fprepos.pp 25 KB

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