fprepos.pp 22 KB

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