pkghandler.pp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. {$mode objfpc}
  2. {$h+}
  3. unit pkghandler;
  4. interface
  5. uses
  6. Classes,SysUtils,
  7. pkgglobals,
  8. pkgoptions,
  9. fprepos;
  10. type
  11. { TPackageHandler }
  12. TPackageHandler = Class(TComponent)
  13. private
  14. FPackageName : string;
  15. Protected
  16. Procedure Log(Level: TLogLevel;Msg : String);
  17. Procedure Log(Level: TLogLevel;Fmt : String; const Args : array of const);
  18. Procedure Error(Msg : String);
  19. Procedure Error(Fmt : String; const Args : array of const);
  20. Function ExecuteProcess(Const Prog,Args:String):Integer;
  21. Procedure SetCurrentDir(Const ADir:String);
  22. Public
  23. Constructor Create(AOwner:TComponent;const APackageName:string); virtual;
  24. function PackageLogPrefix:String;
  25. procedure ExecuteAction(const APackageName,AAction:string);
  26. procedure Execute; virtual; abstract;
  27. Property PackageName:string Read FPackageName;
  28. end;
  29. TPackageHandlerClass = class of TPackageHandler;
  30. EPackageHandler = Class(Exception);
  31. // Actions/PkgHandler
  32. procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
  33. function GetPkgHandler(const AAction:string):TPackageHandlerClass;
  34. procedure ExecuteAction(const APackageName,AAction:string);
  35. function PackageBuildPath(APackage:TFPPackage):String;
  36. function PackageRemoteArchive(APackage:TFPPackage): String;
  37. function PackageLocalArchive(APackage:TFPPackage): String;
  38. function PackageManifestFile(APackage:TFPPackage): String;
  39. Implementation
  40. uses
  41. typinfo,
  42. contnrs,
  43. uriparser,
  44. pkgrepos,
  45. pkgmessages;
  46. var
  47. PkgHandlerList : TFPHashList;
  48. ExecutedActions : TFPHashList;
  49. CurrentDir : string;
  50. procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
  51. begin
  52. if PkgHandlerList.Find(AAction)<>nil then
  53. begin
  54. Raise EPackageHandler.CreateFmt(SErrActionAlreadyRegistered,[AAction]);
  55. exit;
  56. end;
  57. PkgHandlerList.Add(AAction,pkghandlerclass);
  58. end;
  59. function GetPkgHandler(const AAction:string):TPackageHandlerClass;
  60. begin
  61. result:=TPackageHandlerClass(PkgHandlerList.Find(AAction));
  62. if result=nil then
  63. Raise EPackageHandler.CreateFmt(SErrActionNotFound,[AAction]);
  64. end;
  65. procedure ExecuteAction(const APackageName,AAction:string);
  66. var
  67. pkghandlerclass : TPackageHandlerClass;
  68. FullActionName : string;
  69. begin
  70. // Check if we have already executed or are executing the action
  71. FullActionName:=APackageName+AAction;
  72. if ExecutedActions.Find(FullActionName)<>nil then
  73. begin
  74. Log(vlDebug,'Already executed or executing action '+FullActionName);
  75. exit;
  76. end;
  77. ExecutedActions.Add(FullActionName,Pointer(PtrUInt(1)));
  78. // Create action handler class
  79. pkghandlerclass:=GetPkgHandler(AAction);
  80. With pkghandlerclass.Create(nil,APackageName) do
  81. try
  82. Log(vlDebug,SLogRunAction+' start',[AAction]);
  83. Execute;
  84. Log(vlDebug,SLogRunAction+' end',[AAction]);
  85. finally
  86. Free;
  87. end;
  88. end;
  89. function PackageBuildPath(APackage:TFPPackage):String;
  90. begin
  91. if APackage.Name=CurrentDirPackageName then
  92. begin
  93. // It could be that to resolve some dependencies, the current directory changes. The first time
  94. // PackageBuildPath is called the dependencies are not resolved yet, so store the current directory
  95. // for later calls.
  96. if CurrentDir='' then
  97. begin
  98. Result:='.';
  99. CurrentDir := SysUtils.GetCurrentDir;
  100. end
  101. else
  102. Result:=CurrentDir;
  103. end
  104. else if APackage.Name=CmdLinePackageName then
  105. Result:=GlobalOptions.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'')
  106. else if (APackage.RecompileBroken) and (APackage.SourcePath<>'') then
  107. Result:=APackage.SourcePath
  108. else
  109. Result:=GlobalOptions.BuildDir+APackage.Name;
  110. end;
  111. function PackageRemoteArchive(APackage:TFPPackage): String;
  112. begin
  113. if APackage.Name=CurrentDirPackageName then
  114. Error(SErrNoPackageSpecified)
  115. else if APackage.Name=CmdLinePackageName then
  116. Error(SErrPackageIsLocal);
  117. if APackage.DownloadURL<>'' then
  118. Result:=APackage.DownloadURL
  119. else
  120. Result:=GetRemoteRepositoryURL(APackage.FileName);
  121. end;
  122. function PackageLocalArchive(APackage:TFPPackage): String;
  123. begin
  124. if APackage.Name=CurrentDirPackageName then
  125. Error(SErrNoPackageSpecified)
  126. else if APackage.Name=CmdLinePackageName then
  127. Result:=APackage.LocalFileName
  128. else
  129. Result:=GlobalOptions.ArchivesDir+APackage.FileName;
  130. end;
  131. function PackageManifestFile(APackage:TFPPackage): String;
  132. begin
  133. Result:=ManifestFileName;
  134. end;
  135. { TPackageHandler }
  136. constructor TPackageHandler.Create(AOwner:TComponent;const APackageName:string);
  137. begin
  138. inherited Create(AOwner);
  139. FPackageName:=APackageName;
  140. end;
  141. Function TPackageHandler.ExecuteProcess(Const Prog,Args:String):Integer;
  142. begin
  143. Log(vlCommands,SLogExecute,[Prog,Args]);
  144. Flush(StdOut);
  145. Result:=SysUtils.ExecuteProcess(Prog,Args);
  146. end;
  147. Procedure TPackageHandler.SetCurrentDir(Const ADir:String);
  148. begin
  149. Log(vlCommands,SLogChangeDir,[ADir]);
  150. if not SysUtils.SetCurrentDir(ADir) then
  151. Error(SErrChangeDirFailed,[ADir]);
  152. end;
  153. function TPackageHandler.PackageLogPrefix:String;
  154. begin
  155. if PackageName<>'' then
  156. Result:='['+PackageName+'] '
  157. else
  158. Result:='';
  159. end;
  160. procedure TPackageHandler.ExecuteAction(const APackageName,AAction:string);
  161. begin
  162. // Needed to override TComponent.ExecuteAction method
  163. pkghandler.ExecuteAction(APackageName,AAction);
  164. end;
  165. Procedure TPackageHandler.Log(Level:TLogLevel; Msg:String);
  166. begin
  167. pkgglobals.Log(Level,PackageLogPrefix+Msg);
  168. end;
  169. Procedure TPackageHandler.Log(Level:TLogLevel; Fmt:String; const Args:array of const);
  170. begin
  171. pkgglobals.Log(Level,PackageLogPrefix+Fmt,Args);
  172. end;
  173. Procedure TPackageHandler.Error(Msg:String);
  174. begin
  175. pkgglobals.Error(PackageLogPrefix+Msg);
  176. end;
  177. Procedure TPackageHandler.Error(Fmt:String; const Args:array of const);
  178. begin
  179. pkgglobals.Error(PackageLogPrefix+Fmt,Args);
  180. end;
  181. initialization
  182. PkgHandlerList:=TFPHashList.Create;
  183. ExecutedActions:=TFPHashList.Create;
  184. finalization
  185. FreeAndNil(PkgHandlerList);
  186. FreeAndNil(ExecutedActions);
  187. end.