pkgrepos.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. unit pkgrepos;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. SysUtils,Classes,
  6. fprepos,pkgoptions,
  7. fpmkunit;
  8. function GetRemoteRepositoryURL(const AFileName:string):string;
  9. procedure LoadLocalAvailableMirrors;
  10. procedure LoadLocalAvailableRepository;
  11. function LoadManifestFromFile(const AManifestFN:string):TFPPackage;
  12. procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
  13. Procedure AddFPMakeAddIn(APackage: TFPPackage);
  14. function PackageIsBroken(APackage:TFPPackage; MarkForReInstall: boolean):boolean;
  15. function FindBrokenPackages(SL:TStrings):Boolean;
  16. procedure CheckFPMakeDependencies;
  17. function PackageInstalledVersionStr(const AName:String;const ShowUsed: boolean = false;const Local: boolean = false):string;
  18. function PackageInstalledStateStr(const AName:String):string;
  19. function PackageAvailableVersionStr(const AName:String):string;
  20. procedure ListAvailablePackages;
  21. procedure ListPackages(const ShowGlobalAndLocal: boolean);
  22. procedure ListRemoteRepository;
  23. procedure RebuildRemoteRepository;
  24. procedure SaveRemoteRepository;
  25. procedure SetDefaultRepositoryClass(ARepositoryClass: TFPRepositoryClass);
  26. var
  27. AvailableMirrors : TFPMirrors;
  28. AvailableRepository,
  29. InstalledRepository : TFPRepository;
  30. implementation
  31. uses
  32. zipper,
  33. fpxmlrep,
  34. pkgglobals,
  35. pkgmessages;
  36. resourcestring
  37. SErrRepositoryClassAlreadyAssigned = 'Default repository class is already assigned.';
  38. var
  39. CurrentRemoteRepositoryURL : String;
  40. RepositoryClass : TFPRepositoryClass;
  41. procedure SetDefaultRepositoryClass(ARepositoryClass: TFPRepositoryClass);
  42. begin
  43. if assigned(RepositoryClass) then
  44. raise exception.Create(SErrRepositoryClassAlreadyAssigned);
  45. RepositoryClass:=ARepositoryClass;
  46. end;
  47. function GetDefaultRepositoryClass: TFPRepositoryClass;
  48. begin
  49. if not assigned(RepositoryClass) then
  50. SetDefaultRepositoryClass(TFPRepository);
  51. result := RepositoryClass;
  52. end;
  53. {*****************************************************************************
  54. Mirror Selection
  55. *****************************************************************************}
  56. procedure LoadLocalAvailableMirrors;
  57. var
  58. S : String;
  59. X : TFPXMLMirrorHandler;
  60. begin
  61. if assigned(AvailableMirrors) then
  62. AvailableMirrors.Free;
  63. AvailableMirrors:=TFPMirrors.Create(TFPMirror);
  64. // Repository
  65. S:=GlobalOptions.LocalMirrorsFile;
  66. log(llDebug,SLogLoadingMirrorsFile,[S]);
  67. if not FileExists(S) then
  68. exit;
  69. try
  70. X:=TFPXMLMirrorHandler.Create;
  71. With X do
  72. try
  73. LoadFromXml(AvailableMirrors,S);
  74. finally
  75. Free;
  76. end;
  77. except
  78. on E : Exception do
  79. begin
  80. Log(llError,E.Message);
  81. Error(SErrCorruptMirrorsFile,[S]);
  82. end;
  83. end;
  84. end;
  85. function SelectRemoteMirror:string;
  86. var
  87. i,j : Integer;
  88. Bucket,
  89. BucketCnt : Integer;
  90. M : TFPMirror;
  91. begin
  92. Result:='';
  93. M:=nil;
  94. if assigned(AvailableMirrors) then
  95. begin
  96. // Create array for selection
  97. BucketCnt:=0;
  98. for i:=0 to AvailableMirrors.Count-1 do
  99. inc(BucketCnt,AvailableMirrors[i].Weight);
  100. // Select random entry
  101. Bucket:=Random(BucketCnt);
  102. M:=nil;
  103. for i:=0 to AvailableMirrors.Count-1 do
  104. begin
  105. for j:=0 to AvailableMirrors[i].Weight-1 do
  106. begin
  107. if Bucket=0 then
  108. begin
  109. M:=AvailableMirrors[i];
  110. break;
  111. end;
  112. Dec(Bucket);
  113. end;
  114. if assigned(M) then
  115. break;
  116. end;
  117. end;
  118. if assigned(M) then
  119. begin
  120. log(llInfo,SLogSelectedMirror,[M.Name]);
  121. Result:=M.URL;
  122. end
  123. else
  124. Error(SErrFailedToSelectMirror);
  125. end;
  126. function GetRemoteRepositoryURL(const AFileName:string):string;
  127. begin
  128. if CurrentRemoteRepositoryURL='' then
  129. begin
  130. if GlobalOptions.RemoteRepository='auto' then
  131. CurrentRemoteRepositoryURL:=SelectRemoteMirror
  132. else
  133. CurrentRemoteRepositoryURL:=GlobalOptions.RemoteRepository;
  134. end;
  135. result := CurrentRemoteRepositoryURL;
  136. if result[length(result)]<>'/' then
  137. result := result + '/';
  138. Result:=Result+CompilerOptions.CompilerVersion+'/'+AFileName;
  139. end;
  140. {*****************************************************************************
  141. Local Repository
  142. *****************************************************************************}
  143. function LoadManifestFromFile(const AManifestFN:string):TFPPackage;
  144. var
  145. X : TFPXMLRepositoryHandler;
  146. NewPackages : TFPPackages;
  147. NewP,P : TFPPackage;
  148. begin
  149. result:=nil;
  150. NewPackages:=TFPPackages.Create(TFPPackage);
  151. X:=TFPXMLRepositoryHandler.Create;
  152. try
  153. X.LoadFromXml(NewPackages,AManifestFN);
  154. // Update or Add packages to repository
  155. if NewPackages.Count=1 then
  156. begin
  157. NewP:=NewPackages[0];
  158. // Prevent duplicate names
  159. { P:=InstalledRepository.FindPackage(NewP.Name);
  160. if not assigned(P) then
  161. P:=InstalledRepository.AddPackage(NewP.Name); }
  162. result:=TFPPackage.Create(nil);
  163. // Copy contents
  164. result.Assign(NewP);
  165. end
  166. else
  167. Error(SErrManifestNoSinglePackage,[AManifestFN]);
  168. finally
  169. X.Free;
  170. NewPackages.Free;
  171. end;
  172. end;
  173. procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
  174. function AddInstalledPackage(const AName,AFileName: String; const Local: boolean):TFPPackage;
  175. begin
  176. result:=InstalledRepository.FindPackage(AName);
  177. if not assigned(result) then
  178. result:=InstalledRepository.AddPackage(AName)
  179. else
  180. begin
  181. result.UnusedVersion:=result.Version;
  182. // Log packages found in multiple locations (local and global) ?
  183. if showdups then
  184. log(llDebug,SDbgPackageMultipleLocations,[result.Name,ExtractFilePath(AFileName)]);
  185. end;
  186. result.InstalledLocally:=Local;
  187. end;
  188. procedure LoadPackagefpcFromFile(APackage:TFPPackage;const AFileName: String);
  189. Var
  190. L : TStrings;
  191. V : String;
  192. begin
  193. L:=TStringList.Create;
  194. Try
  195. ReadIniFile(AFileName,L);
  196. V:=L.Values['version'];
  197. APackage.Version.AsString:=V;
  198. Finally
  199. L.Free;
  200. end;
  201. end;
  202. function CheckUnitDir(const AUnitDir:string; const Local: boolean):boolean;
  203. var
  204. SR : TSearchRec;
  205. P : TFPPackage;
  206. UD,UF : String;
  207. begin
  208. Result:=false;
  209. if FindFirst(IncludeTrailingPathDelimiter(AUnitDir)+AllFiles,faDirectory,SR)=0 then
  210. begin
  211. log(llDebug,SLogFindInstalledPackages,[AUnitDir]);
  212. repeat
  213. if ((SR.Attr and faDirectory)=faDirectory) and (SR.Name<>'.') and (SR.Name<>'..') then
  214. begin
  215. UD:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(AUnitDir)+SR.Name);
  216. // Try new fpunits.cfg
  217. UF:=UD+UnitConfigFileName;
  218. if FileExistsLog(UF) then
  219. begin
  220. P:=AddInstalledPackage(SR.Name,UF,Local);
  221. P.LoadUnitConfigFromFile(UF);
  222. if P.IsFPMakeAddIn then
  223. AddFPMakeAddIn(P);
  224. end
  225. else
  226. begin
  227. // Try Old style Package.fpc
  228. UF:=UD+'Package.fpc';
  229. if FileExistsLog(UF) then
  230. begin
  231. P:=AddInstalledPackage(SR.Name,UF,Local);
  232. LoadPackagefpcFromFile(P,UF);
  233. end;
  234. end;
  235. end;
  236. until FindNext(SR)<>0;
  237. end;
  238. FindClose(SR);
  239. end;
  240. function CheckInstallDir(AInstallDir:string; const Local: boolean):boolean;
  241. var
  242. SR : TSearchRec;
  243. P : TFPPackage;
  244. UF : String;
  245. begin
  246. Result:=false;
  247. AInstallDir:=IncludeTrailingPathDelimiter(AInstallDir)+'fpmkinst'+PathDelim+ACompilerOptions.CompilerTarget+PathDelim;
  248. if FindFirst(IncludeTrailingPathDelimiter(AInstallDir)+PathDelim+'*'+FpmkExt,faDirectory,SR)=0 then
  249. begin
  250. log(llDebug,SLogFindInstalledPackages,[AInstallDir]);
  251. repeat
  252. if ((SR.Attr and faDirectory)=0) then
  253. begin
  254. // Try new .fpm-file
  255. UF:=AInstallDir+SR.Name;
  256. P:=AddInstalledPackage(ChangeFileExt(SR.Name,''),UF,Local);
  257. P.LoadUnitConfigFromFile(UF);
  258. if P.IsFPMakeAddIn then
  259. AddFPMakeAddIn(P);
  260. end;
  261. until FindNext(SR)<>0;
  262. end;
  263. FindClose(SR);
  264. end;
  265. begin
  266. if assigned(InstalledRepository) then
  267. InstalledRepository.Free;
  268. InstalledRepository:=GetDefaultRepositoryClass.Create(nil);
  269. // First scan the global directory
  270. // The local directory will overwrite the versions
  271. if ACompilerOptions.GlobalInstallDir<>'' then
  272. begin
  273. CheckUnitDir(ACompilerOptions.GlobalUnitDir, False);
  274. CheckInstallDir(ACompilerOptions.GlobalInstallDir, False);
  275. end;
  276. if ACompilerOptions.LocalInstallDir<>'' then
  277. begin
  278. CheckUnitDir(ACompilerOptions.LocalUnitDir, True);
  279. CheckInstallDir(ACompilerOptions.LocalInstallDir, True);
  280. end;
  281. end;
  282. Procedure AddFPMakeAddIn(APackage: TFPPackage);
  283. begin
  284. log(llDebug,SLogFoundFPMakeAddin,[APackage.Name]);
  285. setlength(FPMKUnitDeps,length(FPMKUnitDeps)+1);
  286. FPMKUnitDeps[high(FPMKUnitDeps)].package:=APackage.Name;
  287. FPMKUnitDeps[high(FPMKUnitDeps)].reqver:=APackage.Version.AsString;
  288. FPMKUnitDeps[high(FPMKUnitDeps)].def:='HAS_PACKAGE_'+APackage.Name;
  289. FPMKUnitDeps[high(FPMKUnitDeps)].available:=true;
  290. end;
  291. function PackageIsBroken(APackage:TFPPackage; MarkForReInstall: boolean):boolean;
  292. var
  293. j : integer;
  294. D : TFPDependency;
  295. DepPackage : TFPPackage;
  296. AvailP: TFPPackage;
  297. begin
  298. result:=false;
  299. for j:=0 to APackage.Dependencies.Count-1 do
  300. begin
  301. D:=APackage.Dependencies[j];
  302. if (CompilerOptions.CompilerOS in D.OSes) and
  303. (CompilerOptions.CompilerCPU in D.CPUs) then
  304. begin
  305. DepPackage:=InstalledRepository.FindPackage(D.PackageName);
  306. // Don't stop on missing dependencies
  307. if assigned(DepPackage) then
  308. begin
  309. if (D.RequireChecksum<>$ffffffff) and (DepPackage.Checksum<>D.RequireChecksum) then
  310. begin
  311. log(llInfo,SLogPackageChecksumChanged,[APackage.Name,D.PackageName]);
  312. result:=true;
  313. if MarkForReInstall then
  314. begin
  315. // When the package is re-installed, use the same fpmake-options and sourcepath
  316. // as used during the initial installation. (The AvailableRepository is used to install
  317. // the package so make sure all properties are set there)
  318. AvailP:=AvailableRepository.FindPackage(APackage.Name);
  319. if not assigned(AvailP) then
  320. begin
  321. AvailP := AvailableRepository.AddPackage(APackage.Name);
  322. AvailP.Assign(APackage);
  323. end
  324. else
  325. begin
  326. AvailP.SourcePath := APackage.SourcePath;
  327. AvailP.FPMakeOptionsString := APackage.FPMakeOptionsString;
  328. end;
  329. AvailP.RecompileBroken:=true;
  330. APackage.RecompileBroken:=true;
  331. // If the fpmake.pp of the original installation is not available anymore, do not
  332. // try to use it.
  333. if (AvailP.SourcePath<>'') and not FileExists(IncludeTrailingPathDelimiter(APackage.SourcePath)+'fpmake.pp') then
  334. AvailP.SourcePath:='';
  335. end;
  336. exit;
  337. end;
  338. end
  339. else
  340. log(llDebug,SDbgObsoleteDependency,[D.PackageName]);
  341. end;
  342. end;
  343. end;
  344. function FindBrokenPackages(SL:TStrings):Boolean;
  345. var
  346. i : integer;
  347. P : TFPPackage;
  348. begin
  349. SL.Clear;
  350. for i:=0 to InstalledRepository.PackageCount-1 do
  351. begin
  352. P:=InstalledRepository.Packages[i];
  353. if PackageIsBroken(P,True) then
  354. begin
  355. SL.Add(P.Name);
  356. end;
  357. end;
  358. Result:=(SL.Count>0);
  359. end;
  360. procedure CheckFPMakeDependencies;
  361. var
  362. i : Integer;
  363. P,AvailP : TFPPackage;
  364. AvailVerStr : string;
  365. ReqVer : TFPVersion;
  366. begin
  367. // Reset availability
  368. for i:=0 to high(FPMKUnitDeps) do
  369. FPMKUnitDeps[i].available:=false;
  370. // Not version check needed in Recovery mode, we always need to use
  371. // the internal bootstrap procedure
  372. if GlobalOptions.RecoveryMode then
  373. exit;
  374. // Check for fpmkunit dependencies
  375. for i:=0 to high(FPMKUnitDeps) do
  376. begin
  377. P:=InstalledRepository.FindPackage(FPMKUnitDeps[i].package);
  378. if P<>nil then
  379. begin
  380. AvailP:=AvailableRepository.FindPackage(FPMKUnitDeps[i].package);
  381. if AvailP<>nil then
  382. AvailVerStr:=AvailP.Version.AsString
  383. else
  384. AvailVerStr:='<not available>';
  385. ReqVer:=TFPVersion.Create;
  386. try
  387. ReqVer.AsString:=FPMKUnitDeps[i].ReqVer;
  388. log(llDebug,SLogFPMKUnitDepVersion,[P.Name,ReqVer.AsString,P.Version.AsString,AvailVerStr]);
  389. if ReqVer.CompareVersion(P.Version)<=0 then
  390. FPMKUnitDeps[i].available:=true
  391. else
  392. log(llDebug,SLogFPMKUnitDepTooOld,[FPMKUnitDeps[i].package]);
  393. finally
  394. ReqVer.Free;
  395. end;
  396. end
  397. else
  398. log(llDebug,SLogFPMKUnitDepTooOld,[FPMKUnitDeps[i].package]);
  399. end;
  400. end;
  401. {*****************************************************************************
  402. Local Available Repository
  403. *****************************************************************************}
  404. procedure LoadLocalAvailableRepository;
  405. var
  406. S : String;
  407. X : TFPXMLRepositoryHandler;
  408. begin
  409. if assigned(AvailableRepository) then
  410. AvailableRepository.Free;
  411. AvailableRepository:=GetDefaultRepositoryClass.Create(Nil);
  412. // Repository
  413. S:=GlobalOptions.LocalPackagesFile;
  414. log(llDebug,SLogLoadingPackagesFile,[S]);
  415. if not FileExists(S) then
  416. exit;
  417. try
  418. X:=TFPXMLRepositoryHandler.Create;
  419. With X do
  420. try
  421. LoadFromXml(AvailableRepository,S);
  422. finally
  423. Free;
  424. end;
  425. except
  426. on E : Exception do
  427. begin
  428. Log(llError,E.Message);
  429. Error(SErrCorruptPackagesFile,[S]);
  430. end;
  431. end;
  432. end;
  433. function PackageAvailableVersionStr(const AName:String):string;
  434. var
  435. P : TFPPackage;
  436. begin
  437. P:=AvailableRepository.FindPackage(AName);
  438. if P<>nil then
  439. result:=P.Version.AsString
  440. else
  441. result:='-';
  442. end;
  443. function PackageInstalledVersionStr(const AName:String;const ShowUsed: boolean = false;const Local: boolean = false):string;
  444. var
  445. P : TFPPackage;
  446. begin
  447. P:=InstalledRepository.FindPackage(AName);
  448. if P<>nil then
  449. begin
  450. if not ShowUsed then
  451. result:=P.Version.AsString
  452. else if Local=p.InstalledLocally then
  453. result:=P.Version.AsString
  454. else if not P.UnusedVersion.Empty then
  455. result:=P.UnusedVersion.AsString
  456. else
  457. result:='-';
  458. end
  459. else
  460. result:='-';
  461. end;
  462. function PackageInstalledStateStr(const AName:String):string;
  463. var
  464. P : TFPPackage;
  465. begin
  466. result := '';
  467. P:=InstalledRepository.FindPackage(AName);
  468. if (P<>nil) and PackageIsBroken(P,false) then
  469. result:='B';
  470. end;
  471. procedure ListAvailablePackages;
  472. var
  473. InstalledP,
  474. AvailP : TFPPackage;
  475. i : integer;
  476. SL : TStringList;
  477. begin
  478. SL:=TStringList.Create;
  479. SL.Sorted:=true;
  480. for i:=0 to AvailableRepository.PackageCount-1 do
  481. begin
  482. AvailP:=AvailableRepository.Packages[i];
  483. InstalledP:=InstalledRepository.FindPackage(AvailP.Name);
  484. if not assigned(InstalledP) or
  485. (AvailP.Version.CompareVersion(InstalledP.Version)>0) then
  486. SL.Add(Format('%-20s %-12s %-12s',[AvailP.Name,PackageInstalledVersionStr(AvailP.Name),AvailP.Version.AsString]));
  487. end;
  488. Writeln(Format('%-20s %-12s %-12s',['Name','Installed','Available']));
  489. for i:=0 to SL.Count-1 do
  490. Writeln(SL[i]);
  491. FreeAndNil(SL);
  492. end;
  493. procedure ListPackages(const ShowGlobalAndLocal: boolean);
  494. var
  495. i : integer;
  496. SL : TStringList;
  497. PackageName : String;
  498. begin
  499. SL:=TStringList.Create;
  500. SL.Sorted:=true;
  501. SL.Duplicates:=dupIgnore;
  502. for i:=0 to AvailableRepository.PackageCount-1 do
  503. SL.Add(AvailableRepository.Packages[i].Name);
  504. for i:=0 to InstalledRepository.PackageCount-1 do
  505. SL.Add(InstalledRepository.Packages[i].Name);
  506. if ShowGlobalAndLocal then
  507. Writeln(Format('%-20s %-14s %-14s %-3s %-12s',['Name','Installed (G)','Installed (L)','','Available']))
  508. else
  509. Writeln(Format('%-20s %-12s %-3s %-12s',['Name','Installed','','Available']));
  510. for i:=0 to SL.Count-1 do
  511. begin
  512. PackageName:=SL[i];
  513. if (PackageName<>CmdLinePackageName) and (PackageName<>CurrentDirPackageName) then
  514. begin
  515. if ShowGlobalAndLocal then
  516. Writeln(Format('%-20s %-14s %-14s %-3s %-12s',[PackageName,PackageInstalledVersionStr(PackageName,True,False),PackageInstalledVersionStr(PackageName,True,True),PackageInstalledStateStr(PackageName),PackageAvailableVersionStr(PackageName)]))
  517. else
  518. Writeln(Format('%-20s %-12s %-3s %-12s',[PackageName,PackageInstalledVersionStr(PackageName),PackageInstalledStateStr(PackageName),PackageAvailableVersionStr(PackageName)]));
  519. end;
  520. end;
  521. FreeAndNil(SL);
  522. end;
  523. {*****************************************************************************
  524. Remote Repository
  525. *****************************************************************************}
  526. procedure ListRemoteRepository;
  527. var
  528. P : TFPPackage;
  529. i : integer;
  530. SL : TStringList;
  531. begin
  532. SL:=TStringList.Create;
  533. SL.Sorted:=true;
  534. for i:=0 to InstalledRepository.PackageCount-1 do
  535. begin
  536. P:=InstalledRepository.Packages[i];
  537. SL.Add(Format('%-20s %-12s %-20s',[P.Name,P.Version.AsString,P.FileName]));
  538. end;
  539. Writeln(Format('%-20s %-12s %-20s',['Name','Available','FileName']));
  540. for i:=0 to SL.Count-1 do
  541. Writeln(SL[i]);
  542. FreeAndNil(SL);
  543. end;
  544. procedure RebuildRemoteRepository;
  545. procedure LoadPackageManifest(const AManifestFN:string);
  546. var
  547. X : TFPXMLRepositoryHandler;
  548. i : integer;
  549. DoAdd : Boolean;
  550. P,NewP : TFPPackage;
  551. NewPackages : TFPPackages;
  552. begin
  553. NewPackages:=TFPPackages.Create(TFPPackage);
  554. X:=TFPXMLRepositoryHandler.Create;
  555. try
  556. X.LoadFromXml(NewPackages,AManifestFN);
  557. // Update or Add packages to repository
  558. for i:=0 to NewPackages.Count-1 do
  559. begin
  560. NewP:=NewPackages[i];
  561. DoAdd:=True;
  562. P:=InstalledRepository.FindPackage(NewP.Name);
  563. if assigned(P) then
  564. begin
  565. if NewP.Version.CompareVersion(P.Version)<0 then
  566. begin
  567. Writeln(Format('Ignoring package %s-%s (old %s)',[NewP.Name,NewP.Version.AsString,P.Version.AsString]));
  568. DoAdd:=False;
  569. end
  570. else
  571. Writeln(Format('Updating package %s-%s (old %s)',[NewP.Name,NewP.Version.AsString,P.Version.AsString]));
  572. end
  573. else
  574. P:=InstalledRepository.PackageCollection.AddPackage(NewP.Name);
  575. // Copy contents
  576. if DoAdd then
  577. P.Assign(NewP);
  578. end;
  579. finally
  580. X.Free;
  581. NewPackages.Free;
  582. end;
  583. end;
  584. var
  585. i : integer;
  586. ArchiveSL : TStringList;
  587. ManifestSL : TStringList;
  588. begin
  589. if assigned(InstalledRepository) then
  590. InstalledRepository.Free;
  591. InstalledRepository:=GetDefaultRepositoryClass.Create(Nil);
  592. try
  593. ManifestSL:=TStringList.Create;
  594. ManifestSL.Add(ManifestFileName);
  595. { Find all archives }
  596. ArchiveSL:=TStringList.Create;
  597. SearchFiles(ArchiveSL,'*.zip');
  598. if ArchiveSL.Count=0 then
  599. Error('No archive files found');
  600. { Process all archives }
  601. for i:=0 to ArchiveSL.Count-1 do
  602. begin
  603. Writeln('Processing ',ArchiveSL[i]);
  604. { Unzip manifest.xml }
  605. With TUnZipper.Create do
  606. try
  607. log(llCommands,SLogUnzippping,[ArchiveSL[i]]);
  608. OutputPath:='.';
  609. UnZipFiles(ArchiveSL[i],ManifestSL);
  610. Finally
  611. Free;
  612. end;
  613. { Load manifest.xml }
  614. if FileExists(ManifestFileName) then
  615. begin
  616. LoadPackageManifest(ManifestFileName);
  617. DeleteFile(ManifestFileName);
  618. end
  619. else
  620. Writeln('No manifest found in archive ',ArchiveSL[i]);
  621. end;
  622. finally
  623. ArchiveSL.Free;
  624. ManifestSL.Free;
  625. end;
  626. end;
  627. procedure SaveRemoteRepository;
  628. var
  629. X : TFPXMLRepositoryHandler;
  630. begin
  631. // Repository
  632. Writeln('Saving repository in packages.xml');
  633. X:=TFPXMLRepositoryHandler.Create;
  634. With X do
  635. try
  636. SaveToXml(InstalledRepository,'packages.xml');
  637. finally
  638. Free;
  639. end;
  640. end;
  641. initialization
  642. AvailableRepository := nil;
  643. InstalledRepository := nil;
  644. AvailableMirrors := nil;
  645. finalization
  646. AvailableRepository.Free;
  647. InstalledRepository.Free;
  648. AvailableMirrors.Free;
  649. end.