123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- {$mode objfpc}
- {$h+}
- unit pkghandler;
- {$IFDEF OS2}
- {$DEFINE NO_UNIT_PROCESS}
- {$ENDIF OS2}
- {$IFDEF GO32V2}
- {$DEFINE NO_UNIT_PROCESS}
- {$ENDIF GO32V2}
- {$ifndef NO_UNIT_PROCESS}
- {$define HAS_UNIT_PROCESS}
- {$endif NO_UNIT_PROCESS}
- interface
- uses
- Classes,SysUtils,
- pkgglobals,
- pkgoptions,
- {$ifdef HAS_UNIT_PROCESS}
- process,
- {$endif HAS_UNIT_PROCESS}
- fprepos,
- pkgFppkg;
- type
- { TPackageHandler }
- TPackageHandler = Class(TComponent)
- private
- FPackageName : string;
- FPackageManager: tpkgFPpkg;
- Protected
- Procedure Log(Level: TLogLevel;Msg : String);
- Procedure Log(Level: TLogLevel;Fmt : String; const Args : array of const);
- Procedure Error(Msg : String);
- Procedure Error(Fmt : String; const Args : array of const);
- Function ExecuteProcess(Const Prog,Args:String):Integer;
- Procedure SetCurrentDir(Const ADir:String);
- Property PackageManager:TpkgFPpkg Read FPackageManager;
- Public
- Constructor Create(AOwner:TComponent; APackageManager:TpkgFPpkg; const APackageName:string); virtual;
- function PackageLogPrefix:String;
- procedure ExecuteAction(const APackageName,AAction:string);
- procedure Execute; virtual; abstract;
- Property PackageName:string Read FPackageName;
- end;
- TPackageHandlerClass = class of TPackageHandler;
- EPackageHandler = Class(Exception);
- // Actions/PkgHandler
- procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
- function GetPkgHandler(const AAction:string):TPackageHandlerClass;
- procedure ExecuteAction(const APackageName,AAction:string; PackageManager: TpkgFPpkg);
- function PackageBuildPath(APackage:TFPPackage):String;
- function PackageRemoteArchive(APackage:TFPPackage): String;
- function PackageLocalArchive(APackage:TFPPackage): String;
- function PackageManifestFile(APackage:TFPPackage): String;
- procedure ClearExecutedAction;
- Implementation
- uses
- typinfo,
- contnrs,
- uriparser,
- pkgrepos,
- pkgmessages;
- var
- PkgHandlerList : TFPHashList;
- ExecutedActions : TFPHashList;
- CurrentDir : string;
- procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
- begin
- if PkgHandlerList.Find(AAction)<>nil then
- begin
- Raise EPackageHandler.CreateFmt(SErrActionAlreadyRegistered,[AAction]);
- exit;
- end;
- PkgHandlerList.Add(AAction,pkghandlerclass);
- end;
- function GetPkgHandler(const AAction:string):TPackageHandlerClass;
- begin
- result:=TPackageHandlerClass(PkgHandlerList.Find(AAction));
- if result=nil then
- Raise EPackageHandler.CreateFmt(SErrActionNotFound,[AAction]);
- end;
- procedure ExecuteAction(const APackageName,AAction:string; PackageManager: TpkgFPpkg);
- var
- pkghandlerclass : TPackageHandlerClass;
- FullActionName : string;
- begin
- // Check if we have already executed or are executing the action
- FullActionName:=APackageName+AAction;
- if ExecutedActions.Find(FullActionName)<>nil then
- begin
- Log(llDebug,'Already executed or executing action '+FullActionName);
- exit;
- end;
- ExecutedActions.Add(FullActionName,Pointer(PtrUInt(1)));
- // Create action handler class
- pkghandlerclass:=GetPkgHandler(AAction);
- With pkghandlerclass.Create(nil,PackageManager,APackageName) do
- try
- Log(llDebug,SLogRunAction+' start',[AAction]);
- Execute;
- Log(llDebug,SLogRunAction+' end',[AAction]);
- finally
- Free;
- end;
- end;
- function PackageBuildPath(APackage:TFPPackage):String;
- begin
- if (APackage.Name=CmdLinePackageName) or (APackage.Name=URLPackageName) then
- Result:=GFPpkg.Options.GlobalSection.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'')
- else if Assigned(APackage.PackagesStructure) and (APackage.PackagesStructure.GetBuildPathDirectory(APackage)<>'') then
- Result:=APackage.PackagesStructure.GetBuildPathDirectory(APackage)
- else
- Result:=GFPpkg.Options.GlobalSection.BuildDir+APackage.Name;
- end;
- function PackageRemoteArchive(APackage:TFPPackage): String;
- begin
- if APackage.Name=CurrentDirPackageName then
- Error(SErrNoPackageSpecified)
- else if APackage.Name=CmdLinePackageName then
- Error(SErrPackageIsLocal);
- if APackage.DownloadURL<>'' then
- Result:=APackage.DownloadURL
- else
- Result:=GetRemoteRepositoryURL(APackage.FileName);
- end;
- function PackageLocalArchive(APackage:TFPPackage): String;
- begin
- if APackage.Name=CurrentDirPackageName then
- Error(SErrNoPackageSpecified)
- else if APackage.Name=CmdLinePackageName then
- Result:=APackage.LocalFileName
- else
- Result:=GFPpkg.Options.GlobalSection.ArchivesDir+APackage.FileName;
- end;
- function PackageManifestFile(APackage:TFPPackage): String;
- begin
- Result:=ManifestFileName;
- end;
- procedure ClearExecutedAction;
- begin
- ExecutedActions.Clear;
- end;
- { TPackageHandler }
- Constructor TPackageHandler.Create(AOwner: TComponent; APackageManager: TpkgFPpkg;
- const APackageName: string);
- begin
- inherited Create(AOwner);
- FPackageName:=APackageName;
- FPackageManager:=APackageManager;
- end;
- {$ifdef HAS_UNIT_PROCESS}
- function ExecuteFPC(const Path: string; const ComLine: string): integer;
- var
- P: TProcess;
- ConsoleOutput: TMemoryStream;
- BytesRead: longint;
- function ReadFromStream: longint;
- const
- READ_BYTES = 2048;
- var
- n: longint;
- BuffPos: longint;
- sLine: string;
- ch: char;
- begin
- // make sure we have room
- ConsoleOutput.SetSize(BytesRead + READ_BYTES);
- // try reading it
- n := P.Output.Read((ConsoleOutput.Memory + BytesRead)^, READ_BYTES);
- if n > 0 then
- begin
- Inc(BytesRead, n);
- sLine := '';
- BuffPos := ConsoleOutput.Position;
- //read lines from the stream
- repeat
- ConsoleOutput.Read(ch,1);
- if ch in [#10, #13] then
- begin
- log(llProgres,sLine);
- sLine := '';
- BuffPos := ConsoleOutput.Position;
- end
- else
- sLine := sLine + ch;
- until ConsoleOutput.Position >= BytesRead;
- ConsoleOutput.Position := BuffPos;
- end
- else
- begin
- // no data, wait 100 ms
- Sleep(100);
- end;
- Result := n;
- end;
- begin
- result := -1;
- BytesRead := 0;
- ConsoleOutput := TMemoryStream.Create;
- try
- P := TProcess.Create(nil);
- try
- P.CommandLine := Path + ' ' + ComLine;
- P.Options := [poUsePipes];
- P.Execute;
- while P.Running do
- ReadFromStream;
- // read last part
- repeat
- until ReadFromStream = 0;
- ConsoleOutput.SetSize(BytesRead);
- result := P.ExitStatus;
- finally
- P.Free;
- end;
- finally
- ConsoleOutput.Free;
- end;
- end;
- {$endif HAS_UNIT_PROCESS}
- Function TPackageHandler.ExecuteProcess(Const Prog,Args:String):Integer;
- begin
- Log(llCommands,SLogExecute,[Prog,Args]);
- Flush(StdOut);
- {$ifdef HAS_UNIT_PROCESS}
- Result:=ExecuteFPC(Prog,Args);
- {$else HAS_UNIT_PROCESS}
- Result:=SysUtils.ExecuteProcess(Prog,Args);
- {$endif HAS_UNIT_PROCESS}
- end;
- Procedure TPackageHandler.SetCurrentDir(Const ADir:String);
- begin
- Log(llCommands,SLogChangeDir,[ADir]);
- if not SysUtils.SetCurrentDir(ADir) then
- Error(SErrChangeDirFailed,[ADir]);
- end;
- function TPackageHandler.PackageLogPrefix:String;
- begin
- if PackageName<>'' then
- Result:='['+PackageName+'] '
- else
- Result:='';
- end;
- procedure TPackageHandler.ExecuteAction(const APackageName,AAction:string);
- begin
- pkghandler.ExecuteAction(APackageName,AAction,PackageManager);
- end;
- Procedure TPackageHandler.Log(Level:TLogLevel; Msg:String);
- begin
- pkgglobals.Log(Level,PackageLogPrefix+Msg);
- end;
- Procedure TPackageHandler.Log(Level:TLogLevel; Fmt:String; const Args:array of const);
- begin
- pkgglobals.log(Level,PackageLogPrefix+Fmt,Args);
- end;
- Procedure TPackageHandler.Error(Msg:String);
- begin
- pkgglobals.Error(PackageLogPrefix+Msg);
- end;
- Procedure TPackageHandler.Error(Fmt:String; const Args:array of const);
- begin
- pkgglobals.Error(PackageLogPrefix+Fmt,Args);
- end;
- initialization
- PkgHandlerList:=TFPHashList.Create;
- ExecutedActions:=TFPHashList.Create;
- finalization
- FreeAndNil(PkgHandlerList);
- FreeAndNil(ExecutedActions);
- end.
|