fprepos.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. {
  2. This file is part of the Free Pascal Utilities
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$mode objfpc}
  11. {$H+}
  12. unit fprepos;
  13. interface
  14. uses
  15. classes,sysutils,
  16. contnrs,
  17. {$ifdef ver2_0}
  18. streamcoll20,
  19. {$else}
  20. streamcoll,
  21. {$endif}
  22. fpmktype;
  23. Const
  24. StreamVersion : Integer = 1;
  25. StreamSignature = $FEEF;
  26. Type
  27. { TFPVersion }
  28. TFPVersion = Class(TPersistent)
  29. private
  30. FMajor: Word;
  31. FMinor: Word;
  32. FRelease: Word;
  33. FSuffix: string;
  34. function GetAsString: String;
  35. function GetEmpty: Boolean;
  36. procedure SetAsString(const AValue: String);
  37. Public
  38. Procedure Assign(Source : TPersistent); override;
  39. Property AsString : String Read GetAsString Write SetAsString;
  40. Function CompareVersion(AVersion : TFPVersion) : Integer;
  41. Function SameVersion(AVersion : TFPVersion) : Boolean;
  42. Property Empty : Boolean Read GetEmpty;
  43. Published
  44. Property Release : Word Read FRelease Write FRelease;
  45. Property Major : Word Read FMajor Write FMajor;
  46. Property Minor : Word Read FMinor Write FMinor;
  47. Property Suffix : string Read FSuffix Write FSuffix;
  48. end;
  49. { TFPDependency }
  50. TFPDependency = Class(TStreamCollectionItem)
  51. private
  52. FMinVersion: TFPVersion;
  53. FPackageName: String;
  54. procedure SetMinVersion(const AValue: TFPVersion);
  55. Public
  56. Constructor Create(ACollection : TCollection); override;
  57. Destructor Destroy; override;
  58. Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
  59. Procedure SaveToStream(Stream : TStream); override;
  60. Procedure Assign(Source : TPersistent); override;
  61. Published
  62. Property PackageName : String Read FPackageName Write FPackageName;
  63. Property MinVersion : TFPVersion Read FMinVersion Write SetMinVersion;
  64. end;
  65. { TFPDepencencies }
  66. { TFPDependencies }
  67. TFPDependencies = Class(TStreamCollection)
  68. private
  69. function GetDependency(Index : Integer): TFPDependency;
  70. procedure SetDependency(Index : Integer; const AValue: TFPDependency);
  71. public
  72. Function AddDependency(Const APackageName : String; AMinVersion : String = '') : TFPDependency;
  73. Property Dependencies[Index : Integer] : TFPDependency Read GetDependency Write SetDependency;default;
  74. end;
  75. { TFPPackage }
  76. TFPPackage = Class(TStreamCollectionItem)
  77. private
  78. FAuthor: String;
  79. FDescription: String;
  80. FEmail: String;
  81. FLicense: String;
  82. FName: String;
  83. FURL: String;
  84. FVersion: TFPVersion;
  85. FInstalledVersion: TFPVersion;
  86. FDependencies : TFPDependencies;
  87. FOSes : TOSES;
  88. FCPUs : TCPUS;
  89. function GetDependencies: TFPDependencies;
  90. function GetHasDependencies: Boolean;
  91. procedure SetName(const AValue: String);
  92. procedure SetVersion(const AValue: TFPVersion);
  93. Protected
  94. Function CreateDependencies : TFPDependencies; virtual;
  95. Public
  96. Constructor Create(ACollection : TCollection); override;
  97. Destructor Destroy; override;
  98. Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
  99. Procedure SaveToStream(Stream : TStream); override;
  100. Procedure Assign(Source : TPersistent); override;
  101. Function AddDependency(Const APackageName : String; AMinVersion : String = '') : TFPDependency;
  102. Property HasDependencies : Boolean Read GetHasDependencies;
  103. Property Dependencies : TFPDependencies Read GetDependencies;
  104. Published
  105. Property Name : String Read FName Write SetName;
  106. Property Author : String Read FAuthor Write FAuthor;
  107. Property Version : TFPVersion Read FVersion Write SetVersion;
  108. Property InstalledVersion : TFPVersion Read FInstalledVersion Write FInstalledVersion;
  109. Property License : String Read FLicense Write FLicense;
  110. Property Description : String Read FDescription Write FDescription;
  111. Property URL : String Read FURL Write FURL;
  112. Property Email : String Read FEmail Write FEmail;
  113. Property OSes : TOSes Read FOSes Write FOses;
  114. Property CPUs : TCPUs Read FCPUs Write FCPUs;
  115. end;
  116. { TFPPackages }
  117. TFPPackages = Class(TStreamCollection)
  118. private
  119. FVersion : Integer;
  120. function GetPackage(Index : Integer): TFPPackage;
  121. procedure SetPackage(Index : Integer; const AValue: TFPPackage);
  122. Protected
  123. Function CurrentStreamVersion : Integer; override;
  124. Public
  125. Function IndexOfPackage(PackageName : String) : Integer;
  126. Function FindPackage(PackageName : String) : TFPPackage;
  127. Function PackageByName(PackageName : String) : TFPPackage;
  128. Function AddPackage(PackageName : string) : TFPPackage;
  129. Property StreamVersion : Integer Read FVersion Write FVersion;
  130. Property Packages [Index : Integer] : TFPPackage Read GetPackage Write SetPackage; default;
  131. end;
  132. { TFPRepository }
  133. TFPRepository = Class(TComponent)
  134. Private
  135. FMaxDependencyLevel : Integer;
  136. FBackUpFiles: Boolean;
  137. FFileName: String;
  138. FPackageCount: Integer;
  139. FPackages : TFPPackages;
  140. function GetPackage(Index : Integer): TFPPackage;
  141. function GetPackageCount: Integer;
  142. Protected
  143. Property PackageCollection : TFPPackages Read FPackages;
  144. procedure CreatePackages; virtual;
  145. Procedure BackupFile(AFileName : String); virtual;
  146. Procedure DoGetPackageDependencies(PackageName : String; List : TStringList; Level : Integer); virtual;
  147. Public
  148. Constructor Create(AOwner : TComponent); override;
  149. Destructor Destroy; override;
  150. // Loading and Saving repository. Own format.
  151. Procedure LoadFromStream(Stream : TStream); Virtual;
  152. Procedure SaveToStream(Stream : TStream); Virtual;
  153. Procedure LoadFromFile(AFileName : String);
  154. Procedure SaveToFile(AFileName : String);
  155. Procedure Save;
  156. // Loading and Saving version numbers: List of Name=Value pairs.
  157. Procedure LoadStatusFromStream(Stream : TStream); virtual;
  158. Procedure SaveStatusToStream(Stream : TStream; InstalledStatus : Boolean); virtual;
  159. Procedure LoadStatusFromFile(AFileName : String);
  160. Procedure SaveStatusToFile(AFileName : String; InstalledStatus : Boolean);
  161. // Package management
  162. Function IndexOfPackage(PackageName : String) : Integer;
  163. Function FindPackage(PackageName : String) : TFPPackage;
  164. Function PackageByName(PackageName : String) : TFPPackage;
  165. Procedure DeletePackage(Index : Integer);
  166. Procedure RemovePackage(PackageName : string);
  167. Function AddPackage(PackageName : string) : TFPPackage;
  168. // Dependencies
  169. Procedure GetPackageDependencies(PackageName : String; List : TObjectList; Recurse : Boolean);
  170. // Properties
  171. Property FileName : String Read FFileName;
  172. Property Packages[Index : Integer] : TFPPackage Read GetPackage; default;
  173. Property PackageCount : Integer Read GetPackageCount;
  174. Property BackupFiles : Boolean Read FBackUpFiles Write FBackupFiles;
  175. Property MaxDependencyLevel : Integer Read FMaxDependencyLevel Write FMaxDependencyLevel;
  176. end;
  177. EPackage = Class(Exception);
  178. Const
  179. // Max level of dependency searching before we decide it's a circular dependency.
  180. DefaultMaxDependencyLevel = 15;
  181. Implementation
  182. uses typinfo;
  183. ResourceString
  184. SErrPackageNotFound = 'Package "%s" not found.';
  185. SErrInvalidRepositorySig = 'Invalid repository stream. Stream signature incorrect';
  186. SErrBackupFailed = 'Failed to back up file "%s" to "%s".';
  187. SErrNoFileName = 'No filename for repository specified.';
  188. SErrDuplicatePackageName = 'Duplicate package name : "%s"';
  189. SErrMaxLevelExceeded = 'Maximum number of dependency levels exceeded (%d) at package "%s".';
  190. { TFPVersion }
  191. function TFPVersion.GetAsString: String;
  192. begin
  193. Result:=Format('%d.%d.%d',[Release,Major,Minor]);
  194. If (Suffix<>'') then
  195. Result:=Result+'-'+Suffix;
  196. end;
  197. function TFPVersion.GetEmpty: Boolean;
  198. begin
  199. Result:=(Release=0) and (Major=0) and (Minor=0) and (Suffix='');
  200. end;
  201. procedure TFPVersion.SetAsString(const AValue: String);
  202. Function NextDigit(sep : Char; var V : string) : integer;
  203. Var
  204. P : Integer;
  205. begin
  206. P:=Pos(Sep,V);
  207. If (P=0) then
  208. P:=Length(V)+1;
  209. Result:=StrToIntDef(Copy(V,1,P-1),-1);
  210. If Result<>-1 then
  211. Delete(V,1,P)
  212. else
  213. Result:=0;
  214. end;
  215. Var
  216. P : Integer;
  217. V : String;
  218. begin
  219. Release:=0;
  220. Major:=0;
  221. Minor:=0;
  222. Suffix:='';
  223. V:=AValue;
  224. Release:=NextDigit('.',V);
  225. Major:=NextDigit('.',V);
  226. Minor:=NextDigit('-',V);
  227. P:=Pos('-',V);
  228. If (P<>0) then
  229. Delete(V,1,P);
  230. Suffix:=V;
  231. end;
  232. procedure TFPVersion.Assign(Source: TPersistent);
  233. Var
  234. V : TFPVersion;
  235. begin
  236. if Source is TFPVersion then
  237. begin
  238. V:=Source as TFPVersion;
  239. Release:=V.Release;
  240. Major:=V.Major;
  241. Minor:=V.Minor;
  242. Suffix:=V.Suffix;
  243. end
  244. else
  245. inherited Assign(Source);
  246. end;
  247. function TFPVersion.CompareVersion(AVersion: TFPVersion): Integer;
  248. begin
  249. Result:=Release-AVersion.Release;
  250. If (Result=0) then
  251. begin
  252. Result:=Major-AVersion.Major;
  253. if (Result=0) then
  254. begin
  255. Result:=Minor-AVersion.Minor;
  256. If (Result=0) then
  257. Result:=CompareText(Suffix,AVersion.Suffix);
  258. end;
  259. end;
  260. end;
  261. function TFPVersion.SameVersion(AVersion: TFPVersion): Boolean;
  262. begin
  263. Result:=CompareVersion(AVersion)=0;
  264. end;
  265. { TFPPackage }
  266. procedure TFPPackage.SetVersion(const AValue: TFPVersion);
  267. begin
  268. if FVersion=AValue then
  269. exit;
  270. FVersion.Assign(AValue);
  271. end;
  272. Function TFPPackage.CreateDependencies : TFPDependencies;
  273. begin
  274. Result:=TFPDependencies.Create(TFPDependency);
  275. end;
  276. constructor TFPPackage.Create(ACollection: TCollection);
  277. begin
  278. inherited Create(ACollection);
  279. FVersion:=TFPVersion.Create;
  280. FInstalledVersion:=TFPVersion.Create;
  281. end;
  282. destructor TFPPackage.Destroy;
  283. begin
  284. FreeAndNil(FDependencies);
  285. FreeAndNil(FVersion);
  286. FreeAndNil(FInstalledVersion);
  287. inherited Destroy;
  288. end;
  289. procedure TFPPackage.SetName(const AValue: String);
  290. Var
  291. I : Integer;
  292. begin
  293. If (AValue<>FName) and (AValue<>'') then
  294. If (Collection<>Nil) and (Collection is TFPPackages) then
  295. // do not check while loading, this would slow down a lot !!
  296. if (not TFPPackages(Collection).Streaming) then
  297. If TFPPackages(Collection).IndexOfPackage(AValue)<>-1 then
  298. Raise EPackage.CreateFmt(SErrDuplicatePackageName,[AValue]);
  299. FName:=AValue;
  300. end;
  301. function TFPPackage.GetDependencies: TFPDependencies;
  302. begin
  303. If Not Assigned(FDependencies) then
  304. FDependencies:=CreateDependencies;
  305. Result:=FDependencies;
  306. end;
  307. function TFPPackage.GetHasDependencies: Boolean;
  308. begin
  309. Result:=Assigned(FDependencies) and (FDependencies.Count>0);
  310. end;
  311. procedure TFPPackage.LoadFromStream(Stream: TStream; Streamversion : Integer);
  312. Var
  313. B : Boolean;
  314. O : TOSes;
  315. C : TCPUs;
  316. I,J,Count : Integer;
  317. begin
  318. Version.AsString:=ReadString(Stream);
  319. Name:=ReadString(Stream);
  320. Author:=ReadString(Stream);
  321. License:=ReadString(Stream);
  322. Description:=ReadString(Stream);
  323. URL:=ReadString(Stream);
  324. Email:=ReadString(Stream);
  325. Count:=ReadInteger(Stream);
  326. O:=[];
  327. For I:=1 to Count do
  328. begin
  329. J:=GetEnumValue(TypeInfo(TOS),ReadString(Stream));
  330. If (J<>-1) then
  331. Include(O,TOS(J));
  332. end;
  333. OSEs:=O;
  334. Count:=ReadInteger(Stream);
  335. C:=[];
  336. For I:=1 to Count do
  337. begin
  338. J:=GetEnumValue(TypeInfo(TCPU),ReadString(Stream));
  339. If (J<>-1) then
  340. Include(C,TCPU(J));
  341. end;
  342. CPUS:=C;
  343. FreeAndNil(FDependencies);
  344. B:=ReadBoolean(Stream);
  345. If B then
  346. begin
  347. FDependencies:=CreateDependencies;
  348. FDependencies.LoadFromStream(Stream);
  349. end
  350. end;
  351. procedure TFPPackage.SaveToStream(Stream: TStream);
  352. Var
  353. Count : Integer;
  354. O : TOS;
  355. C : TCPU;
  356. begin
  357. WriteString(Stream,Version.AsString);
  358. WriteString(Stream,Name);
  359. WriteString(Stream,Author);
  360. WriteString(Stream,License);
  361. WriteString(Stream,Description);
  362. WriteString(Stream,URL);
  363. WriteString(Stream,Email);
  364. { Write it like this, makes error checking easier when reading. }
  365. // OSes
  366. Count:=0;
  367. For O:=Low(TOS) to High(TOS) do
  368. If O in OSes then
  369. Inc(Count);
  370. WriteInteger(Stream,Count);
  371. For O:=Low(TOS) to High(TOS) do
  372. If O in OSes then
  373. WriteString(Stream,GetEnumName(TypeInfo(TOS),Ord(O)));
  374. // CPUs
  375. Count:=0;
  376. For C:=Low(TCPU) to High(TCPU) do
  377. If C in CPUS then
  378. Inc(Count);
  379. WriteInteger(Stream,Count);
  380. For C:=Low(TCPU) to High(TCPU) do
  381. If C in CPUS then
  382. WriteString(Stream,GetEnumName(TypeInfo(TCPU),Ord(C)));
  383. WriteBoolean(Stream,HasDependencies);
  384. If HasDependencies then
  385. FDependencies.SaveToStream(Stream);
  386. end;
  387. procedure TFPPackage.Assign(Source: TPersistent);
  388. Var
  389. P : TFPPackage;
  390. begin
  391. if Source is TFPPackage then
  392. begin
  393. P:=Source as TFPPackage;
  394. // This creates trouble if P has the same owning collection !!
  395. If P.Collection<>Collection then
  396. Name:=P.Name;
  397. Author:=P.Author;
  398. Version:=P.Version;
  399. Description:=P.Description;
  400. URL:=P.URL;
  401. InstalledVersion:=P.Installedversion;
  402. If P.HasDependencies then
  403. Dependencies.Assign(P.Dependencies)
  404. else
  405. FreeAndNil(FDependencies);
  406. end
  407. else
  408. inherited Assign(Source);
  409. end;
  410. function TFPPackage.AddDependency(const APackageName: String;
  411. AMinVersion: String): TFPDependency;
  412. begin
  413. Result:=Dependencies.AddDependency(APackageName,AMinVersion);
  414. end;
  415. { TFPPackages }
  416. function TFPPackages.GetPackage(Index : Integer): TFPPackage;
  417. begin
  418. Result:=TFPPackage(Items[Index])
  419. end;
  420. procedure TFPPackages.SetPackage(Index : Integer; const AValue: TFPPackage);
  421. begin
  422. Items[Index]:=AValue;
  423. end;
  424. function TFPPackages.CurrentStreamVersion: Integer;
  425. begin
  426. Result:=FVersion;
  427. end;
  428. function TFPPackages.IndexOfPackage(PackageName: String): Integer;
  429. begin
  430. Result:=Count-1;
  431. While (Result>=0) and (CompareText(GetPackage(Result).Name,PackageName)<>0) do
  432. Dec(Result);
  433. end;
  434. function TFPPackages.FindPackage(PackageName: String): TFPPackage;
  435. Var
  436. I : Integer;
  437. begin
  438. I:=IndexOfPackage(PackageName);
  439. If (I=-1) then
  440. Result:=Nil
  441. else
  442. Result:=GetPackage(I);
  443. end;
  444. function TFPPackages.PackageByName(PackageName: String): TFPPackage;
  445. begin
  446. Result:=FindPackage(PackageName);
  447. If Result=Nil then
  448. Raise EPackage.CreateFmt(SErrPackageNotFound,[PackageName]);
  449. end;
  450. function TFPPackages.AddPackage(PackageName: string): TFPPackage;
  451. begin
  452. Result:=Add as TFPPackage;
  453. Try
  454. Result.Name:=PackageName;
  455. Except
  456. Result.Free;
  457. Raise;
  458. end;
  459. end;
  460. { TFPRepository }
  461. function TFPRepository.GetPackage(Index : Integer): TFPPackage;
  462. begin
  463. Result:=FPackages[Index];
  464. end;
  465. function TFPRepository.GetPackageCount: Integer;
  466. begin
  467. Result:=FPackages.Count;
  468. end;
  469. constructor TFPRepository.Create(AOwner: TComponent);
  470. begin
  471. inherited Create(AOwner);
  472. CreatePackages;
  473. FMaxDependencyLevel:=DefaultMaxDependencyLevel;
  474. end;
  475. procedure TFPRepository.CreatePackages;
  476. begin
  477. FPackages:=TFPPackages.Create(TFPPackage);
  478. FPackages.StreamVersion:=StreamVersion;
  479. end;
  480. procedure TFPRepository.BackupFile(AFileName: String);
  481. Var
  482. S : String;
  483. begin
  484. S:=AFileName+'.bak';
  485. if not RenameFile(AFileName,S) then
  486. Raise EPackage.CreateFmt(SErrBackupFailed,[AFileName,S]);
  487. end;
  488. destructor TFPRepository.Destroy;
  489. begin
  490. FreeAndNil(FPackages);
  491. inherited Destroy;
  492. end;
  493. procedure TFPRepository.LoadFromStream(Stream: TStream);
  494. Var
  495. I : Integer;
  496. V : Integer;
  497. begin
  498. Stream.ReadBuffer(I,SizeOf(Integer));
  499. If (I<>StreamSignature) then
  500. Raise EPackage.Create(SErrInvalidRepositorySig);
  501. Stream.ReadBuffer(V,SizeOf(V));
  502. FPackages.LoadFromStream(Stream);
  503. end;
  504. procedure TFPRepository.SaveToStream(Stream: TStream);
  505. Var
  506. i : Integer;
  507. begin
  508. I:=StreamSignature;
  509. Stream.WriteBuffer(I,SizeOf(Integer));
  510. I:=StreamVersion;
  511. Stream.WriteBuffer(I,SizeOf(Integer));
  512. FPackages.SaveToStream(Stream);
  513. end;
  514. procedure TFPRepository.LoadFromFile(AFileName: String);
  515. Var
  516. F : TFileStream;
  517. begin
  518. F:=TFileStream.Create(AFileName,fmopenRead);
  519. Try
  520. LoadFromStream(F);
  521. FFileName:=AFileName;
  522. Finally
  523. F.Free;
  524. end;
  525. end;
  526. procedure TFPRepository.SaveToFile(AFileName: String);
  527. Var
  528. F : TFileStream;
  529. S : String;
  530. begin
  531. If FileExists(AFileName) and BackupFiles then
  532. BackupFile(AFileName);
  533. F:=TFileStream.Create(AFileName,fmCreate);
  534. Try
  535. SaveToStream(F);
  536. FFileName:=AFileName;
  537. Finally
  538. F.Free;
  539. end;
  540. end;
  541. procedure TFPRepository.Save;
  542. begin
  543. If (FFileName='') then
  544. Raise EPackage.Create(SErrNoFileName);
  545. SaveToFile(FFileName);
  546. end;
  547. procedure TFPRepository.LoadStatusFromStream(Stream: TStream);
  548. Var
  549. L : TStrings;
  550. I : Integer;
  551. N,V : String;
  552. begin
  553. L:=TStringList.Create;
  554. Try
  555. L.LoadFromStream(Stream);
  556. For I:=0 to L.Count-1 do
  557. begin
  558. L.GetNameValue(I,N,V);
  559. If (N<>'') and (V<>'') then
  560. PackageByName(N).InstalledVersion.AsString:=V;
  561. end;
  562. Finally
  563. L.Free;
  564. end;
  565. end;
  566. procedure TFPRepository.SaveStatusToStream(Stream: TStream;InstalledStatus : Boolean);
  567. Var
  568. L : TStrings;
  569. I : Integer;
  570. begin
  571. L:=TStringList.Create;
  572. Try
  573. If InstalledStatus then
  574. For I:=0 to PackageCount-1 do
  575. With Packages[i] do
  576. L.Add(Name+'='+InstalledVersion.AsString)
  577. else
  578. For I:=0 to PackageCount-1 do
  579. With Packages[i] do
  580. L.Add(Name+'='+Version.AsString);
  581. L.SaveToStream(Stream);
  582. Finally
  583. L.Free;
  584. end;
  585. end;
  586. procedure TFPRepository.LoadStatusFromFile(AFileName: String);
  587. Var
  588. F : TFileStream;
  589. begin
  590. F:=TFileStream.Create(AFileName,fmOpenRead);
  591. Try
  592. LoadStatusFromStream(F);
  593. Finally
  594. F.Free;
  595. end;
  596. end;
  597. procedure TFPRepository.SaveStatusToFile(AFileName: String; InstalledStatus : Boolean);
  598. Var
  599. F : TFileStream;
  600. begin
  601. If FileExists(AFileName) and BackupFiles then
  602. BackupFile(AFileName);
  603. F:=TFileStream.Create(AFileName,fmCreate);
  604. Try
  605. SaveStatusToStream(F,InstalledStatus);
  606. Finally
  607. F.Free;
  608. end;
  609. end;
  610. function TFPRepository.IndexOfPackage(PackageName: String): Integer;
  611. begin
  612. Result:=FPackages.IndexOfPackage(PackageName);
  613. end;
  614. function TFPRepository.FindPackage(PackageName: String): TFPPackage;
  615. begin
  616. Result:=FPackages.FindPackage(PackageName);
  617. end;
  618. function TFPRepository.PackageByName(PackageName: String): TFPPackage;
  619. begin
  620. Result:=FPackages.PackageByName(PackageName);
  621. end;
  622. procedure TFPRepository.RemovePackage(PackageName: string);
  623. begin
  624. PackageByName(PackageName).Free;
  625. end;
  626. procedure TFPRepository.DeletePackage(Index : Integer);
  627. begin
  628. GetPackage(Index).Free;
  629. end;
  630. function TFPRepository.AddPackage(PackageName: string): TFPPackage;
  631. begin
  632. Result:=FPackages.AddPackage(PackageName);
  633. end;
  634. procedure TFPRepository.DoGetPackageDependencies(PackageName: String;
  635. List: TStringList; Level: Integer);
  636. Var
  637. P : TFPPackage;
  638. D2,D1 : TFPDependency;
  639. i,J : Integer;
  640. begin
  641. // If too many levels, bail out
  642. If (Level>FMaxDependencyLevel) then
  643. Raise EPackage.CreateFmt(SErrMaxLevelExceeded,[Level,PackageName]);
  644. // Check if it is a known package.
  645. P:=FindPackage(PackageName);
  646. If Assigned(P) and P.HasDependencies then
  647. For I:=0 to P.Dependencies.Count-1 do
  648. begin
  649. D1:=P.Dependencies[i];
  650. J:=List.IndexOf(PackageName);
  651. If J=-1 then
  652. begin
  653. // Dependency not yet in list.
  654. D2:=TFPDependency.Create(Nil);
  655. D2.Assign(D1);
  656. List.AddObject(D2.PackageName,D2);
  657. end
  658. else
  659. begin
  660. // Dependency already in list, compare versions.
  661. D2:=List.Objects[J] as TFPDependency;
  662. If D1.MinVersion.CompareVersion(D2.MinVersion)>0 then
  663. D2.MinVersion.Assign(D1.MinVersion);
  664. end;
  665. // If it was already in the list, we no longer recurse.
  666. If (Level>=0) and (J=-1) Then
  667. DoGetPackageDependencies(D2.PackageName,List,Level+1);
  668. end;
  669. end;
  670. procedure TFPRepository.GetPackageDependencies(PackageName: String;
  671. List: TObjectList; Recurse: Boolean);
  672. Var
  673. L : TStringList;
  674. I : Integer;
  675. begin
  676. L:=TStringList.Create;
  677. Try
  678. L.Sorted:=True;
  679. DoGetPackageDependencies(PackageName,L,Ord(Recurse)-1);
  680. For I:=0 to L.Count-1 do
  681. List.Add(L.Objects[i]);
  682. Finally
  683. // Freeing a stringlist does not free the objects.
  684. L.Free;
  685. end;
  686. end;
  687. { TFPDependency }
  688. procedure TFPDependency.SetMinVersion(const AValue: TFPVersion);
  689. begin
  690. FMinVersion.Assign(AValue);
  691. end;
  692. constructor TFPDependency.Create(ACollection: TCollection);
  693. begin
  694. inherited Create(ACollection);
  695. FMinVersion:=TFPVersion.Create;
  696. end;
  697. destructor TFPDependency.Destroy;
  698. begin
  699. FreeAndNil(FMinVersion);
  700. inherited Destroy;
  701. end;
  702. procedure TFPDependency.LoadFromStream(Stream: TStream; Streamversion: Integer
  703. );
  704. begin
  705. PackageName:=ReadString(Stream);
  706. MinVersion.AsString:=ReadString(Stream)
  707. end;
  708. procedure TFPDependency.SaveToStream(Stream: TStream);
  709. begin
  710. WriteString(Stream,PackageName);
  711. WriteString(Stream,MinVersion.AsString);
  712. end;
  713. procedure TFPDependency.Assign(Source: TPersistent);
  714. begin
  715. If Source is TFPDependency then
  716. With Source as TFPDependency do
  717. begin
  718. Self.PackageName:=PackageName;
  719. Self.MinVersion:=MinVersion;
  720. end
  721. else
  722. inherited Assign(Source);
  723. end;
  724. { TFPDependencies }
  725. function TFPDependencies.GetDependency(Index : Integer): TFPDependency;
  726. begin
  727. Result:=TFPDependency(Items[Index]);
  728. end;
  729. procedure TFPDependencies.SetDependency(Index : Integer;
  730. const AValue: TFPDependency);
  731. begin
  732. Items[Index]:=AValue;
  733. end;
  734. function TFPDependencies.AddDependency(const APackageName: String;
  735. AMinVersion: String): TFPDependency;
  736. begin
  737. Result:=Add as TFPDependency;
  738. Result.PackageName:=APackageName;
  739. If (AMinVersion<>'') then
  740. Result.MinVersion.AsString:=AMinVersion;
  741. end;
  742. end.