2
0

pkghandler.pp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. {$mode objfpc}
  2. {$h+}
  3. unit pkghandler;
  4. interface
  5. uses
  6. Classes,SysUtils,
  7. pkgglobals,
  8. pkgoptions,
  9. fprepos;
  10. type
  11. { TActionStack }
  12. TActionArgs = array of string;
  13. TActionStackItem = record
  14. ActionPackage : TFPPackage;
  15. Action : string;
  16. Args : TActionArgs;
  17. end;
  18. PActionStackItem = ^TActionStackItem;
  19. TActionStack = class
  20. private
  21. FList : TFPList;
  22. public
  23. constructor Create;
  24. destructor Destroy;override;
  25. procedure Push(APackage:TFPPackage;const AAction:string;const Args:TActionArgs);
  26. procedure Push(APackage:TFPPackage;const AAction:string;const Args:array of string);
  27. function Pop(out APackage:TFPPackage;out AAction:string;out Args:TActionArgs):boolean;
  28. end;
  29. { TPackageHandler }
  30. TPackageHandler = Class(TComponent)
  31. private
  32. FCurrentPackage : TFPPackage;
  33. Protected
  34. Procedure Log(Level: TVerbosity;Msg : String);
  35. Procedure Log(Level: TVerbosity;Fmt : String; const Args : array of const);
  36. Procedure Error(Msg : String);
  37. Procedure Error(Fmt : String; const Args : array of const);
  38. procedure ExecuteAction(APackage:TFPPackage;const AAction:string;const Args:TActionArgs=nil);
  39. Function ExecuteProcess(Const Prog,Args:String):Integer;
  40. Procedure SetCurrentDir(Const ADir:String);
  41. function PackageBuildPath:String;
  42. function PackageRemoteArchive:String;
  43. function PackageLocalArchive:String;
  44. function PackageManifestFile:String;
  45. Public
  46. Constructor Create(AOwner:TComponent;APackage:TFPPackage); virtual;
  47. function PackageLogPrefix:String;
  48. Function Execute(const Args:TActionArgs):boolean; virtual; abstract;
  49. Property CurrentPackage:TFPPackage Read FCurrentPackage Write FCurrentPackage;
  50. end;
  51. TPackageHandlerClass = class of TPackageHandler;
  52. EPackageHandler = Class(Exception);
  53. // Actions/PkgHandler
  54. procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
  55. function GetPkgHandler(const AAction:string):TPackageHandlerClass;
  56. function ExecuteAction(APackage:TFPPackage;const AAction:string;const Args:TActionArgs=nil):Boolean;
  57. Implementation
  58. uses
  59. typinfo,
  60. contnrs,
  61. uriparser,
  62. pkgmessages;
  63. var
  64. PkgHandlerList : TFPHashList;
  65. ExecutedActions : TFPHashList;
  66. procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
  67. begin
  68. if PkgHandlerList.Find(AAction)<>nil then
  69. begin
  70. Raise EPackageHandler.CreateFmt(SErrActionAlreadyRegistered,[AAction]);
  71. exit;
  72. end;
  73. PkgHandlerList.Add(AAction,pkghandlerclass);
  74. end;
  75. function GetPkgHandler(const AAction:string):TPackageHandlerClass;
  76. begin
  77. result:=TPackageHandlerClass(PkgHandlerList.Find(AAction));
  78. if result=nil then
  79. Raise EPackageHandler.CreateFmt(SErrActionNotFound,[AAction]);
  80. end;
  81. function ExecuteAction(APackage:TFPPackage;const AAction:string;const Args:TActionArgs=nil):Boolean;
  82. var
  83. pkghandlerclass : TPackageHandlerClass;
  84. i : integer;
  85. logargs : string;
  86. FullActionName : string;
  87. begin
  88. result:=false;
  89. // Check if we have already executed or are executing the action
  90. if assigned(Apackage) then
  91. FullActionName:=APackage.Name+AAction
  92. else
  93. FullActionName:=AAction;
  94. if ExecutedActions.Find(FullActionName)<>nil then
  95. begin
  96. Log(vDebug,'Already executed or executing action '+FullActionName);
  97. result:=true;
  98. exit;
  99. end;
  100. ExecutedActions.Add(FullActionName,Pointer(PtrUInt(1)));
  101. // Create action handler class
  102. pkghandlerclass:=GetPkgHandler(AAction);
  103. With pkghandlerclass.Create(nil,APackage) do
  104. try
  105. logargs:='';
  106. for i:=Low(Args) to High(Args) do
  107. begin
  108. if logargs='' then
  109. logargs:=Args[i]
  110. else
  111. logargs:=logargs+','+Args[i];
  112. end;
  113. Log(vDebug,SLogRunAction+' start',[AAction,logargs]);
  114. result:=Execute(Args);
  115. Log(vDebug,SLogRunAction+' end',[AAction,logargs]);
  116. finally
  117. Free;
  118. end;
  119. end;
  120. { TPackageHandler }
  121. constructor TPackageHandler.Create(AOwner:TComponent;APackage:TFPPackage);
  122. begin
  123. inherited Create(AOwner);
  124. FCurrentPackage:=APackage;
  125. end;
  126. Function TPackageHandler.ExecuteProcess(Const Prog,Args:String):Integer;
  127. begin
  128. Log(vCommands,SLogExecute,[Prog,Args]);
  129. Result:=SysUtils.ExecuteProcess(Prog,Args);
  130. end;
  131. Procedure TPackageHandler.SetCurrentDir(Const ADir:String);
  132. begin
  133. Log(vCommands,SLogChangeDir,[ADir]);
  134. if not SysUtils.SetCurrentDir(ADir) then
  135. Error(SErrChangeDirFailed,[ADir]);
  136. end;
  137. function TPackageHandler.PackageBuildPath:String;
  138. begin
  139. if CurrentPackage=nil then
  140. Result:='.'
  141. else
  142. Result:=GlobalOptions.BuildDir+CurrentPackage.Name;
  143. end;
  144. function TPackageHandler.PackageRemoteArchive: String;
  145. begin
  146. if not assigned(CurrentPackage) then
  147. Error(SErrNoPackageSpecified);
  148. if CurrentPackage.ExternalURL<>'' then
  149. Result:=CurrentPackage.ExternalURL
  150. else
  151. Result:=GlobalOptions.RemoteRepository+CurrentPackage.FileName;
  152. end;
  153. function TPackageHandler.PackageLocalArchive: String;
  154. begin
  155. if not assigned(CurrentPackage) then
  156. Error(SErrNoPackageSpecified);
  157. Result:=GlobalOptions.PackagesDir+CurrentPackage.FileName;
  158. end;
  159. function TPackageHandler.PackageManifestFile: String;
  160. begin
  161. Result:=DefaultManifestFile;
  162. end;
  163. function TPackageHandler.PackageLogPrefix:String;
  164. begin
  165. if assigned(CurrentPackage) then
  166. Result:='['+CurrentPackage.Name+'] '
  167. else
  168. // Result:='[<currentdir>] ';
  169. Result:='';
  170. end;
  171. Procedure TPackageHandler.Log(Level:TVerbosity; Msg:String);
  172. begin
  173. pkgglobals.Log(Level,PackageLogPrefix+Msg);
  174. end;
  175. Procedure TPackageHandler.Log(Level:TVerbosity; Fmt:String; const Args:array of const);
  176. begin
  177. pkgglobals.Log(Level,PackageLogPrefix+Fmt,Args);
  178. end;
  179. Procedure TPackageHandler.Error(Msg:String);
  180. begin
  181. pkgglobals.Error(PackageLogPrefix+Msg);
  182. end;
  183. Procedure TPackageHandler.Error(Fmt:String; const Args:array of const);
  184. begin
  185. pkgglobals.Error(PackageLogPrefix+Fmt,Args);
  186. end;
  187. procedure TPackageHandler.ExecuteAction(APackage: TFPPackage; const AAction: string; const Args: TActionArgs=nil);
  188. begin
  189. pkghandler.ExecuteAction(APackage,AAction,Args);
  190. end;
  191. { TActionStack }
  192. constructor TActionStack.Create;
  193. begin
  194. FList:=TFPList.Create;
  195. end;
  196. destructor TActionStack.Destroy;
  197. begin
  198. FreeAndNil(FList);
  199. end;
  200. procedure TActionStack.Push(APackage:TFPPackage;const AAction:string;const Args:TActionArgs);
  201. var
  202. ActionItem : PActionStackItem;
  203. begin
  204. New(ActionItem);
  205. ActionItem^.ActionPackage:=APackage;
  206. ActionItem^.Action:=AAction;
  207. ActionItem^.Args:=Args;
  208. FList.Add(ActionItem);
  209. end;
  210. procedure TActionStack.Push(APackage:TFPPackage;const AAction:string;const Args:array of string);
  211. var
  212. ActionArgs : TActionArgs;
  213. i : integer;
  214. begin
  215. SetLength(ActionArgs,high(Args)+1);
  216. for i:=low(Args) to high(Args) do
  217. ActionArgs[i]:=Args[i];
  218. Push(APackage,AAction,ActionArgs);
  219. end;
  220. function TActionStack.Pop(out APackage:TFPPackage;out AAction:string;out Args:TActionArgs):boolean;
  221. var
  222. ActionItem : PActionStackItem;
  223. Idx : integer;
  224. begin
  225. Result:=false;
  226. if FList.Count=0 then
  227. exit;
  228. // Retrieve Item from stack
  229. Idx:=FList.Count-1;
  230. ActionItem:=PActionStackItem(FList[Idx]);
  231. FList.Delete(Idx);
  232. // Copy contents and dispose stack item
  233. APackage:=ActionItem^.ActionPackage;
  234. AAction:=ActionItem^.Action;
  235. Args:=ActionItem^.Args;
  236. dispose(ActionItem);
  237. Result:=true;
  238. end;
  239. initialization
  240. PkgHandlerList:=TFPHashList.Create;
  241. ExecutedActions:=TFPHashList.Create;
  242. finalization
  243. FreeAndNil(PkgHandlerList);
  244. FreeAndNil(ExecutedActions);
  245. end.