{******************************************************************************* unit helper.pas (only used by main.pas) contains functions that don't need access to a form or another unit of the project, except gvars.pas *******************************************************************************} {******************************************************************************* LazUpdater runs SVN Update/Checkout, Make and Strip for FPC and Lazarus. Copyright (C) 2010 Ingo Steiniger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . *******************************************************************************} unit helper; {$mode objfpc}{$H+} interface uses Classes, SysUtils, AsyncProcess, Process, Dialogs, Forms, extctrls, fileutil; //Helperfuctions function getUpperDir(aPath:String):String; function getLastDir(aPath:String):String; function getCurSvnVer(var LazPath:String):String; function checkPath(aPath:String):Boolean; function checkURL(sURL:String):Boolean; function setPathDelim(aPath:String):String; type {TLUUpdateProcess} TPushDataEvent = procedure(aData:String) of object; TLUUpdateProcess=class(TObject) private FOnPushData:TPushDataEvent; FCommandLine:String; FWorkingDir:String; FBuffer:String; AProcess:TAsyncProcess; function GetOutput():string; procedure ReadData(Sender: TObject); public property OnPushData:TPushDataEvent read FOnPushData write FOnPushData; property CommandLine:String read FCommandLine write FCommandLine; property WorkingDir:String read FWorkingDir write FWorkingDir; constructor Create; destructor Destroy; override; function run:Integer; procedure SendData(aData:String); procedure Stop; end; implementation uses gvars; {******************************************************************************* Helperfunction: Check valid path *******************************************************************************} function checkPath(aPath:String):Boolean; begin Result:=True; if length(aPath)>3 then begin {$ifdef WINDOWS} if aPath[2]<>':' then Result:=False; {$else} if aPath[1]<>'/' then Result:=False; {$endif} end else Result:=False; end; {******************************************************************************* Helperfunction: Check valid URL *******************************************************************************} function checkURL(sURL:String):Boolean; begin Result:=True; if length(sURL)>17 then begin if LowerCase(copy(sURL, 1, 4))+copy(sURL, 5, 3)<>'http://' then Result:=False; end else Result:=False; end; {******************************************************************************* set a trailing pathdelimiter if it doesn't exist *******************************************************************************} function setPathDelim(aPath: String): String; begin if aPath[length(aPath)]<>PathDelim then Result:=aPath+PathDelim else Result:=aPath; end; {******************************************************************************* get current Version from .svn-directory *******************************************************************************} function getCurSvnVer(var LazPath:String):String; var mySL:TStringList; begin Result:='0'; if FileExistsUTF8(LazPath+PathDelim+'.svn'+PathDelim+'entries') then begin mySL:=TStringList.Create; mySL.LoadFromFile(LazPath+PathDelim+'.svn'+PathDelim+'entries'); Result:=mySL[3]; mySL.Free; end; end; {******************************************************************************* Helperfunction: extract the last directoryname from a path *******************************************************************************} function getLastDir(aPath:String):String; begin if aPath[length(aPath)]=PathDelim then aPath:=copy(aPath, 1, length(aPath)-1); while Pos(PathDelim, aPath)<>0 do begin Delete(aPath, 1, Pos(PathDelim, aPath)); end; Result:=aPath; end; {******************************************************************************* Helperfunction: extract the upper directory from a path *******************************************************************************} function getUpperDir(aPath:String):String; begin if aPath[length(aPath)]=PathDelim then aPath:=copy(aPath, 1, length(aPath)-1); Result:=''; while Pos(PathDelim, aPath)<>0 do begin Result:=Result+copy(aPath, 1, Pos(PathDelim, aPath)); Delete(aPath, 1, Pos(PathDelim, aPath)); end; end; {******************************************************************************* Functions of TLUUpdateProcess *******************************************************************************} //read output of process procedure TLUUpdateProcess.ReadData(Sender: TObject); begin if AProcess.Running then begin FOnPushData(GetOutput); end; end; //send data to process procedure TLUUpdateProcess.SendData(aData: String); begin if AProcess.Running then begin AProcess.Input.Write(aData[1], length(aData)); end; end; //kill process procedure TLUUpdateProcess.Stop; begin if AProcess.Running then begin AProcess.Terminate(666); //This is evil! end; end; //Read output of process function TLUUpdateProcess.GetOutput() : string; var Buffer: string; BytesAvailable: DWord; BytesRead:LongInt; begin Result:= ''; if AProcess.Running then begin BytesAvailable := AProcess.Output.NumBytesAvailable; BytesRead := 0; if BytesAvailable>0 then begin SetLength(Buffer, BytesAvailable); BytesRead := AProcess.OutPut.Read(Buffer[1], BytesAvailable); if BytesRead>0 then begin Buffer:=FBuffer+Buffer; while Pos(LineEnding,Buffer)>0 do begin Result:=Result+(copy(Buffer, 1, Pos(LineEnding, Buffer)-1+length(LineEnding))); delete(Buffer, 1, Pos(LineEnding, Buffer)-1+length(LineEnding)); end; FBuffer:=Buffer; end; end; delete(Result, length(Result), 1); //kill last line-break because Memo.Append adds it end; end; //Contructor constructor TLUUpdateProcess.Create; begin inherited Create; FCommandLine:=''; FWorkingDir:=''; AProcess:=TAsyncProcess.Create(nil); AProcess.OnReadData:=@ReadData; end; //Destuctor destructor TLUUpdateProcess.Destroy; begin AProcess.Free; inherited Destroy; end; //Run Process function TLUUpdateProcess.run:Integer; begin //Change Directory if not (WorkingDir='') then begin ForceDirectories(FWorkingDir); ChDir(FWorkingDir); end; //Apply properties AProcess.CommandLine:=FCommandLine; AProcess.Options:=[poUsePipes,poStderrToOutPut]; AProcess.ShowWindow:=swoHIDE; AProcess.Priority:=ppHigh; //Run try AProcess.Execute; except MessageDlg(Format(rsErrorExecuti2, [FCommandLine, LineEnding]), mtError, [ mbOK], 0); end; //Wait for end while AProcess.Running do Application.Idle(True); //Return Exitcode Result:=AProcess.ExitStatus; end; end.