fprepos.pp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  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. // Keep syncronized with fpmkunit.pp
  23. TCpu=(cpuNone,
  24. i386,m68k,powerpc,sparc,x86_64,arm,powerpc64
  25. );
  26. TCPUS = Set of TCPU;
  27. // Keep syncronized with fpmkunit.pp
  28. TOS=(osNone,
  29. linux,go32v2,win32,os2,freebsd,beos,netbsd,
  30. amiga,atari, solaris, qnx, netware, openbsd,wdosx,
  31. palmos,macos,darwin,emx,watcom,morphos,netwlibc,
  32. win64,wince,gba,nds,embedded,symbian
  33. );
  34. TOSes = Set of TOS;
  35. const
  36. AllOSes = [Low(TOS)..High(TOS)];
  37. AllCPUs = [Low(TCPU)..High(TCPU)];
  38. type
  39. { TFPVersion }
  40. TFPVersion = Class(TPersistent)
  41. private
  42. FMajor,
  43. FMinor,
  44. FMicro,
  45. FBuild : Word;
  46. function GetAsString: String;
  47. function GetEmpty: Boolean;
  48. procedure SetAsString(const AValue: String);
  49. Public
  50. Procedure Clear;
  51. Procedure Assign(Source : TPersistent); override;
  52. Property AsString : String Read GetAsString Write SetAsString;
  53. Function CompareVersion(AVersion : TFPVersion) : Integer;
  54. Function SameVersion(AVersion : TFPVersion) : Boolean;
  55. Property Empty : Boolean Read GetEmpty;
  56. Published
  57. Property Major : Word Read FMajor Write FMajor;
  58. Property Minor : Word Read FMinor Write FMinor;
  59. Property Micro : Word Read FMicro Write FMicro;
  60. Property Build : Word Read FBuild Write FBuild;
  61. end;
  62. { TFPDependency }
  63. TFPDependency = Class(TStreamCollectionItem)
  64. private
  65. FOSes : TOSES;
  66. FCPUs : TCPUS;
  67. FMinVersion: TFPVersion;
  68. FPackageName: String;
  69. FRequireChecksum : cardinal;
  70. procedure SetMinVersion(const AValue: TFPVersion);
  71. Public
  72. Constructor Create(ACollection : TCollection); override;
  73. Destructor Destroy; override;
  74. Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
  75. Procedure SaveToStream(Stream : TStream); override;
  76. Procedure Assign(Source : TPersistent); override;
  77. Published
  78. Property PackageName : String Read FPackageName Write FPackageName;
  79. Property MinVersion : TFPVersion Read FMinVersion Write SetMinVersion;
  80. Property OSes : TOSes Read FOSes Write FOses;
  81. Property CPUs : TCPUs Read FCPUs Write FCPUs;
  82. Property RequireChecksum : Cardinal Read FRequireChecksum Write FRequireChecksum;
  83. end;
  84. { TFPDepencencies }
  85. TFPDependencies = Class(TStreamCollection)
  86. private
  87. function GetDependency(Index : Integer): TFPDependency;
  88. procedure SetDependency(Index : Integer; const AValue: TFPDependency);
  89. public
  90. Function AddDependency(const APackageName : String; const AMinVersion : String = '') : TFPDependency;
  91. Property Dependencies[Index : Integer] : TFPDependency Read GetDependency Write SetDependency;default;
  92. end;
  93. { TFPPackage }
  94. TFPPackage = Class(TStreamCollectionItem)
  95. private
  96. FAuthor: String;
  97. FDescription: String;
  98. FEmail: String;
  99. FInstalledLocally: boolean;
  100. FIsFPMakeAddIn: boolean;
  101. FLicense: String;
  102. FName: String;
  103. FHomepageURL: String;
  104. FDownloadURL: String;
  105. FFileName: String;
  106. FUnusedVersion: TFPVersion;
  107. FVersion: TFPVersion;
  108. FDependencies : TFPDependencies;
  109. FOSes : TOSES;
  110. FCPUs : TCPUS;
  111. // Installation info
  112. FChecksum : cardinal;
  113. FLocalFileName : String;
  114. function GetFileName: String;
  115. procedure SetName(const AValue: String);
  116. procedure SetUnusedVersion(const AValue: TFPVersion);
  117. procedure SetVersion(const AValue: TFPVersion);
  118. Public
  119. Constructor Create(ACollection : TCollection); override;
  120. Destructor Destroy; override;
  121. Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
  122. Procedure SaveToStream(Stream : TStream); override;
  123. Procedure Assign(Source : TPersistent); override;
  124. Function AddDependency(Const APackageName : String; const AMinVersion : String = '') : TFPDependency;
  125. Property Dependencies : TFPDependencies Read FDependencies;
  126. // Only for installed packages: (is false for packages which are installed globally)
  127. Property InstalledLocally : boolean read FInstalledLocally write FInstalledLocally;
  128. Property UnusedVersion : TFPVersion Read FUnusedVersion Write SetUnusedVersion;
  129. Published
  130. Property Name : String Read FName Write SetName;
  131. Property Author : String Read FAuthor Write FAuthor;
  132. Property Version : TFPVersion Read FVersion Write SetVersion;
  133. Property License : String Read FLicense Write FLicense;
  134. Property Description : String Read FDescription Write FDescription;
  135. Property HomepageURL : String Read FHomepageURL Write FHomepageURL;
  136. Property DownloadURL : String Read FDownloadURL Write FDownloadURL;
  137. Property FileName : String Read GetFileName Write FFileName;
  138. Property Email : String Read FEmail Write FEmail;
  139. Property OSes : TOSes Read FOSes Write FOses;
  140. Property CPUs : TCPUs Read FCPUs Write FCPUs;
  141. Property Checksum : Cardinal Read FChecksum Write FChecksum;
  142. Property IsFPMakeAddIn : boolean read FIsFPMakeAddIn write FIsFPMakeAddIn;
  143. // Manual package from commandline not in official repository
  144. Property LocalFileName : String Read FLocalFileName Write FLocalFileName;
  145. end;
  146. { TFPPackages }
  147. TFPPackages = Class(TStreamCollection)
  148. private
  149. FVersion : Integer;
  150. function GetPackage(Index : Integer): TFPPackage;
  151. procedure SetPackage(Index : Integer; const AValue: TFPPackage);
  152. Protected
  153. Function CurrentStreamVersion : Integer; override;
  154. Public
  155. Function IndexOfPackage(const APackageName : String) : Integer;
  156. Function FindPackage(const APackageName : String) : TFPPackage;
  157. Function PackageByName(const APackageName : String) : TFPPackage;
  158. Function AddPackage(const APackageName : string) : TFPPackage;
  159. Property StreamVersion : Integer Read FVersion Write FVersion;
  160. Property Packages [Index : Integer] : TFPPackage Read GetPackage Write SetPackage; default;
  161. end;
  162. { TFPRepository }
  163. TFPRepository = Class(TComponent)
  164. Private
  165. FMaxDependencyLevel : Integer;
  166. FBackUpFiles: Boolean;
  167. FFileName: String;
  168. FPackages : TFPPackages;
  169. function GetPackage(Index : Integer): TFPPackage;
  170. function GetPackageCount: Integer;
  171. Protected
  172. procedure CreatePackages; virtual;
  173. Procedure BackupFile(const AFileName : String); virtual;
  174. Procedure DoGetPackageDependencies(const APackageName : String; List : TStringList; Level : Integer); virtual;
  175. Public
  176. Constructor Create(AOwner : TComponent); override;
  177. Destructor Destroy; override;
  178. // Loading and Saving repository. Own format.
  179. Procedure LoadFromStream(Stream : TStream); Virtual;
  180. Procedure SaveToStream(Stream : TStream); Virtual;
  181. Procedure LoadFromFile(const AFileName : String);
  182. Procedure SaveToFile(const AFileName : String);
  183. Procedure Save;
  184. // Package management
  185. Function IndexOfPackage(const APackageName : String) : Integer;
  186. Function FindPackage(const APackageName : String) : TFPPackage;
  187. Function PackageByName(const APackageName : String) : TFPPackage;
  188. Procedure DeletePackage(Index : Integer);
  189. Procedure RemovePackage(const APackageName : string);
  190. Function AddPackage(const APackageName : string) : TFPPackage;
  191. // Dependencies
  192. Procedure GetPackageDependencies(const APackageName : String; List : TObjectList; Recurse : Boolean);
  193. // Properties
  194. Property FileName : String Read FFileName;
  195. Property Packages[Index : Integer] : TFPPackage Read GetPackage; default;
  196. Property PackageCount : Integer Read GetPackageCount;
  197. Property BackupFiles : Boolean Read FBackUpFiles Write FBackupFiles;
  198. Property MaxDependencyLevel : Integer Read FMaxDependencyLevel Write FMaxDependencyLevel;
  199. Property PackageCollection : TFPPackages Read FPackages;
  200. end;
  201. { TFPMirror }
  202. TFPMirror = Class(TStreamCollectionItem)
  203. private
  204. FContact: String;
  205. FName: String;
  206. FURL: String;
  207. FWeight: Integer;
  208. Public
  209. Constructor Create(ACollection : TCollection); override;
  210. Destructor Destroy; override;
  211. Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
  212. Procedure SaveToStream(Stream : TStream); override;
  213. Procedure Assign(Source : TPersistent); override;
  214. Published
  215. Property Name : String Read FName Write FName;
  216. Property URL : String Read FURL Write FURL;
  217. Property Contact : String Read FContact Write FContact;
  218. Property Weight : Integer Read FWeight Write FWeight;
  219. end;
  220. { TFPMirrors }
  221. TFPMirrors = Class(TStreamCollection)
  222. private
  223. FVersion : Integer;
  224. function GetMirror(Index : Integer): TFPMirror;
  225. procedure SetMirror(Index : Integer; const AValue: TFPMirror);
  226. Protected
  227. Function CurrentStreamVersion : Integer; override;
  228. Public
  229. Function IndexOfMirror(const AMirrorName : String) : Integer;
  230. Function FindMirror(const AMirrorName : String) : TFPMirror;
  231. Function MirrorByName(const AMirrorName : String) : TFPMirror;
  232. Function AddMirror(const AMirrorName : string) : TFPMirror;
  233. Property StreamVersion : Integer Read FVersion Write FVersion;
  234. Property Mirrors [Index : Integer] : TFPMirror Read GetMirror Write SetMirror; default;
  235. end;
  236. EPackage = Class(Exception);
  237. EMirror = Class(Exception);
  238. Const
  239. // Max level of dependency searching before we decide it's a circular dependency.
  240. DefaultMaxDependencyLevel = 15;
  241. Function OSToString(OS: TOS) : String;
  242. Function OSesToString(OSes: TOSes) : String;
  243. Function CPUToString(CPU: TCPU) : String;
  244. Function CPUSToString(CPUS: TCPUS) : String;
  245. Function StringToOS(S : String) : TOS;
  246. Function OSesToString(S : String) : TOSes;
  247. Function StringToCPU(S : String) : TCPU;
  248. Function StringToCPUS(S : String) : TCPUS;
  249. Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
  250. Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
  251. Implementation
  252. uses
  253. typinfo,
  254. uriparser;
  255. ResourceString
  256. SErrInvalidCPU = 'Invalid CPU name : "%s"';
  257. SErrInvalidOS = 'Invalid OS name : "%s"';
  258. SErrInvalidMode = 'Invalid compiler mode : "%s"';
  259. SErrInvalidTarget = 'Invalid compiler target: %s';
  260. SErrPackageNotFound = 'Package "%s" not found.';
  261. SErrInvalidRepositorySig = 'Invalid repository stream. Stream signature incorrect';
  262. SErrBackupFailed = 'Failed to back up file "%s" to "%s".';
  263. SErrNoFileName = 'No filename for repository specified.';
  264. SErrDuplicatePackageName = 'Duplicate package name : "%s"';
  265. SErrMaxLevelExceeded = 'Maximum number of dependency levels exceeded (%d) at package "%s".';
  266. SErrMirrorNotFound = 'Mirror "%s" not found.';
  267. Function OSToString(OS: TOS) : String;
  268. begin
  269. Result:=LowerCase(GetenumName(TypeInfo(TOS),Ord(OS)));
  270. end;
  271. Function OSesToString(OSes: TOSes) : String;
  272. begin
  273. Result:=LowerCase(SetToString(PtypeInfo(TypeInfo(TOSes)),Integer(OSes),False));
  274. end;
  275. Function CPUToString(CPU: TCPU) : String;
  276. begin
  277. Result:=LowerCase(GetenumName(TypeInfo(TCPU),Ord(CPU)));
  278. end;
  279. Function CPUSToString(CPUS: TCPUS) : String;
  280. begin
  281. Result:=LowerCase(SetToString(PTypeInfo(TypeInfo(TCPUS)),Integer(CPUS),False));
  282. end;
  283. Function StringToOS(S : String) : TOS;
  284. Var
  285. I : Integer;
  286. begin
  287. I:=GetEnumValue(TypeInfo(TOS),S);
  288. if (I=-1) then
  289. Raise EPackage.CreateFmt(SErrInvalidOS,[S]);
  290. Result:=TOS(I);
  291. end;
  292. Function OSesToString(S : String) : TOSes;
  293. begin
  294. Result:=TOSes(StringToSet(PTypeInfo(TypeInfo(TOSes)),S));
  295. end;
  296. Function StringToCPU(S : String) : TCPU;
  297. Var
  298. I : Integer;
  299. begin
  300. I:=GetEnumValue(TypeInfo(TCPU),S);
  301. if (I=-1) then
  302. Raise EPackage.CreateFmt(SErrInvalidCPU,[S]);
  303. Result:=TCPU(I);
  304. end;
  305. Function StringToCPUS(S : String) : TCPUS;
  306. begin
  307. Result:=TCPUS(StringToSet(PTypeInfo(TypeInfo(TCPUS)),S));
  308. end;
  309. Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
  310. begin
  311. Result:=CPUToString(CPU)+'-'+OSToString(OS);
  312. end;
  313. Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
  314. Var
  315. P : integer;
  316. begin
  317. P:=Pos('-',S);
  318. If (P=0) then
  319. Raise EPackage.CreateFmt(SErrInvalidTarget,[S]);
  320. CPU:=StringToCPU(Copy(S,1,P-1));
  321. OS:=StringToOs(Copy(S,P+1,Length(S)-P));
  322. end;
  323. { TFPVersion }
  324. function TFPVersion.GetAsString: String;
  325. begin
  326. if Empty then
  327. Result:='<none>'
  328. else
  329. Result:=Format('%d.%d.%d-%d',[Major,Minor,Micro,Build]);
  330. end;
  331. function TFPVersion.GetEmpty: Boolean;
  332. begin
  333. Result:=(Major=0) and (Minor=0) and (Micro=0) and (Build=0);
  334. end;
  335. procedure TFPVersion.SetAsString(const AValue: String);
  336. Function NextDigit(sep : Char; NonNumerisIsSep : boolean; var V : string; aDefault : integer = 0) : integer;
  337. Var
  338. P : Integer;
  339. i : Integer;
  340. begin
  341. P:=Pos(Sep,V);
  342. If (P=0) then
  343. P:=Length(V)+1;
  344. If NonNumerisIsSep then
  345. for i := 1 to P-1 do
  346. if not (V[i] in ['0','1','2','3','4','5','6','7','8','9']) then
  347. begin
  348. P := i;
  349. Break;
  350. end;
  351. Result:=StrToIntDef(Copy(V,1,P-1),-1);
  352. If Result<>-1 then
  353. Delete(V,1,P)
  354. else
  355. Result:=aDefault;
  356. end;
  357. Var
  358. V : String;
  359. b : integer;
  360. begin
  361. Clear;
  362. // Special support for empty version string
  363. if (AValue='') or (AValue='<none>') then
  364. exit;
  365. V:=AValue;
  366. // Supported version-format is x.y.z-b
  367. // x,y,z and b are all optional and are set to 0 if they are not provided
  368. // except for b which has a default of 1.
  369. // x and y must be numeric. z or b may contain a non-numeric suffix which
  370. // will be stripped. If there is any non-numeric character in z or b and
  371. // there is no value supplied for b, build will be set to 0
  372. // examples:
  373. // 2 -> 2.0.0-1
  374. // 2.2 -> 2.2.0-1
  375. // 2.2.4 -> 2.2.4-1
  376. // 2.2.4-0 -> 2.2.4-0
  377. // 2.2.4rc1 -> 2.2.4-0
  378. // 2.2.4-0rc1 -> 2.2.4-0
  379. // 2.2.4-2rc1 -> 2.2.4-2
  380. Major:=NextDigit('.',False,V);
  381. Minor:=NextDigit('.',False,V);
  382. Micro:=NextDigit('-',True,V);
  383. b := NextDigit(#0,True,V,-1);
  384. if b<0 then
  385. if V <> '' then
  386. Build := 0
  387. else
  388. Build := 1
  389. else
  390. Build := b;
  391. end;
  392. procedure TFPVersion.Clear;
  393. begin
  394. Micro:=0;
  395. Major:=0;
  396. Minor:=0;
  397. Build:=0;
  398. end;
  399. procedure TFPVersion.Assign(Source: TPersistent);
  400. Var
  401. V : TFPVersion;
  402. begin
  403. if Source is TFPVersion then
  404. begin
  405. V:=Source as TFPVersion;
  406. Major:=V.Major;
  407. Minor:=V.Minor;
  408. Micro:=V.Micro;
  409. Build:=V.Build;
  410. end
  411. else
  412. inherited Assign(Source);
  413. end;
  414. function TFPVersion.CompareVersion(AVersion: TFPVersion): Integer;
  415. begin
  416. Result:=Major-AVersion.Major;
  417. If (Result=0) then
  418. begin
  419. Result:=Minor-AVersion.Minor;
  420. if (Result=0) then
  421. begin
  422. Result:=Micro-AVersion.Micro;
  423. If (Result=0) then
  424. Result:=Build-AVersion.Build;
  425. end;
  426. end;
  427. end;
  428. function TFPVersion.SameVersion(AVersion: TFPVersion): Boolean;
  429. begin
  430. Result:=CompareVersion(AVersion)=0;
  431. end;
  432. { TFPPackage }
  433. procedure TFPPackage.SetVersion(const AValue: TFPVersion);
  434. begin
  435. if FVersion=AValue then
  436. exit;
  437. FVersion.Assign(AValue);
  438. end;
  439. constructor TFPPackage.Create(ACollection: TCollection);
  440. begin
  441. inherited Create(ACollection);
  442. FVersion:=TFPVersion.Create;
  443. FUnusedVersion:=TFPVersion.Create;
  444. FChecksum:=$ffffffff;
  445. FOSes:=AllOSes;
  446. FCPUs:=AllCPUs;
  447. FDependencies:=TFPDependencies.Create(TFPDependency);
  448. end;
  449. destructor TFPPackage.Destroy;
  450. begin
  451. FreeAndNil(FDependencies);
  452. FreeAndNil(FVersion);
  453. FreeAndNil(FUnusedVersion);
  454. inherited Destroy;
  455. end;
  456. procedure TFPPackage.SetName(const AValue: String);
  457. begin
  458. If (AValue<>FName) and (AValue<>'') then
  459. If (Collection<>Nil) and (Collection is TFPPackages) then
  460. // do not check while loading, this would slow down a lot !!
  461. if (not TFPPackages(Collection).Streaming) then
  462. If TFPPackages(Collection).IndexOfPackage(AValue)<>-1 then
  463. Raise EPackage.CreateFmt(SErrDuplicatePackageName,[AValue]);
  464. FName:=AValue;
  465. end;
  466. procedure TFPPackage.SetUnusedVersion(const AValue: TFPVersion);
  467. begin
  468. if FUnusedVersion=AValue then
  469. exit;
  470. FUnusedVersion.Assign(AValue);
  471. end;
  472. function TFPPackage.GetFileName: String;
  473. var
  474. URI : TURI;
  475. begin
  476. if FFileName='' then
  477. begin
  478. URI:=ParseURI(DownloadURL);
  479. Result:=URI.Document;
  480. end
  481. else
  482. Result:=FFileName;
  483. end;
  484. procedure TFPPackage.LoadFromStream(Stream: TStream; Streamversion : Integer);
  485. Var
  486. B : Boolean;
  487. O : TOSes;
  488. C : TCPUs;
  489. I,J,Count : Integer;
  490. begin
  491. Version.AsString:=ReadString(Stream);
  492. Name:=ReadString(Stream);
  493. Author:=ReadString(Stream);
  494. License:=ReadString(Stream);
  495. Description:=ReadString(Stream);
  496. HomepageURL:=ReadString(Stream);
  497. DownloadURL:=ReadString(Stream);
  498. FileName:=ReadString(Stream);
  499. Email:=ReadString(Stream);
  500. Count:=ReadInteger(Stream);
  501. O:=[];
  502. For I:=1 to Count do
  503. begin
  504. J:=GetEnumValue(TypeInfo(TOS),ReadString(Stream));
  505. If (J<>-1) then
  506. Include(O,TOS(J));
  507. end;
  508. OSEs:=O;
  509. Count:=ReadInteger(Stream);
  510. C:=[];
  511. For I:=1 to Count do
  512. begin
  513. J:=GetEnumValue(TypeInfo(TCPU),ReadString(Stream));
  514. If (J<>-1) then
  515. Include(C,TCPU(J));
  516. end;
  517. CPUS:=C;
  518. FDependencies.Clear;
  519. B:=ReadBoolean(Stream);
  520. If B then
  521. FDependencies.LoadFromStream(Stream);
  522. end;
  523. procedure TFPPackage.SaveToStream(Stream: TStream);
  524. Var
  525. Count : Integer;
  526. O : TOS;
  527. C : TCPU;
  528. begin
  529. WriteString(Stream,Version.AsString);
  530. WriteString(Stream,Name);
  531. WriteString(Stream,Author);
  532. WriteString(Stream,License);
  533. WriteString(Stream,Description);
  534. WriteString(Stream,HomepageURL);
  535. WriteString(Stream,DownloadURL);
  536. WriteString(Stream,FileName);
  537. WriteString(Stream,Email);
  538. { Write it like this, makes error checking easier when reading. }
  539. // OSes
  540. Count:=0;
  541. For O:=Low(TOS) to High(TOS) do
  542. If O in OSes then
  543. Inc(Count);
  544. WriteInteger(Stream,Count);
  545. For O:=Low(TOS) to High(TOS) do
  546. If O in OSes then
  547. WriteString(Stream,GetEnumName(TypeInfo(TOS),Ord(O)));
  548. // CPUs
  549. Count:=0;
  550. For C:=Low(TCPU) to High(TCPU) do
  551. If C in CPUS then
  552. Inc(Count);
  553. WriteInteger(Stream,Count);
  554. For C:=Low(TCPU) to High(TCPU) do
  555. If C in CPUS then
  556. WriteString(Stream,GetEnumName(TypeInfo(TCPU),Ord(C)));
  557. WriteBoolean(Stream,FDependencies.Count>0);
  558. If FDependencies.Count>0 then
  559. FDependencies.SaveToStream(Stream);
  560. end;
  561. procedure TFPPackage.Assign(Source: TPersistent);
  562. Var
  563. P : TFPPackage;
  564. begin
  565. if Source is TFPPackage then
  566. begin
  567. P:=Source as TFPPackage;
  568. // This creates trouble if P has the same owning collection !!
  569. If P.Collection<>Collection then
  570. Name:=P.Name;
  571. Author:=P.Author;
  572. Version:=P.Version;
  573. Description:=P.Description;
  574. HomepageURL:=P.HomepageURL;
  575. DownloadURL:=P.DownloadURL;
  576. OSes:=P.OSes;
  577. CPUs:=P.CPUs;
  578. FileName:=P.FileName;
  579. Checksum:=P.Checksum;
  580. Dependencies.Clear;
  581. Dependencies.Assign(P.Dependencies);
  582. end
  583. else
  584. inherited Assign(Source);
  585. end;
  586. function TFPPackage.AddDependency(Const APackageName : String; const AMinVersion : String = ''): TFPDependency;
  587. begin
  588. Result:=Dependencies.AddDependency(APackageName,AMinVersion);
  589. end;
  590. { TFPPackages }
  591. function TFPPackages.GetPackage(Index : Integer): TFPPackage;
  592. begin
  593. Result:=TFPPackage(Items[Index])
  594. end;
  595. procedure TFPPackages.SetPackage(Index : Integer; const AValue: TFPPackage);
  596. begin
  597. Items[Index]:=AValue;
  598. end;
  599. function TFPPackages.CurrentStreamVersion: Integer;
  600. begin
  601. Result:=FVersion;
  602. end;
  603. function TFPPackages.IndexOfPackage(const APackageName: String): Integer;
  604. begin
  605. Result:=Count-1;
  606. While (Result>=0) and (CompareText(GetPackage(Result).Name,APackageName)<>0) do
  607. Dec(Result);
  608. end;
  609. function TFPPackages.FindPackage(const APackageName: String): TFPPackage;
  610. Var
  611. I : Integer;
  612. begin
  613. I:=IndexOfPackage(APackageName);
  614. If (I=-1) then
  615. Result:=Nil
  616. else
  617. Result:=GetPackage(I);
  618. end;
  619. function TFPPackages.PackageByName(const APackageName: String): TFPPackage;
  620. begin
  621. Result:=FindPackage(APackageName);
  622. If Result=Nil then
  623. Raise EPackage.CreateFmt(SErrPackageNotFound,[APackageName]);
  624. end;
  625. function TFPPackages.AddPackage(const APackageName: string): TFPPackage;
  626. begin
  627. Result:=Add as TFPPackage;
  628. Try
  629. Result.Name:=APackageName;
  630. Except
  631. Result.Free;
  632. Raise;
  633. end;
  634. end;
  635. { TFPRepository }
  636. function TFPRepository.GetPackage(Index : Integer): TFPPackage;
  637. begin
  638. Result:=FPackages[Index];
  639. end;
  640. function TFPRepository.GetPackageCount: Integer;
  641. begin
  642. Result:=FPackages.Count;
  643. end;
  644. constructor TFPRepository.Create(AOwner: TComponent);
  645. begin
  646. inherited Create(AOwner);
  647. CreatePackages;
  648. FMaxDependencyLevel:=DefaultMaxDependencyLevel;
  649. end;
  650. procedure TFPRepository.CreatePackages;
  651. begin
  652. FPackages:=TFPPackages.Create(TFPPackage);
  653. FPackages.StreamVersion:=StreamVersion;
  654. end;
  655. procedure TFPRepository.BackupFile(const AFileName: String);
  656. Var
  657. S : String;
  658. begin
  659. S:=AFileName+'.bak';
  660. if not RenameFile(AFileName,S) then
  661. Raise EPackage.CreateFmt(SErrBackupFailed,[AFileName,S]);
  662. end;
  663. destructor TFPRepository.Destroy;
  664. begin
  665. FreeAndNil(FPackages);
  666. inherited Destroy;
  667. end;
  668. procedure TFPRepository.LoadFromStream(Stream: TStream);
  669. Var
  670. I : Integer;
  671. V : Integer;
  672. begin
  673. Stream.ReadBuffer(I,SizeOf(Integer));
  674. If (I<>StreamSignature) then
  675. Raise EPackage.Create(SErrInvalidRepositorySig);
  676. Stream.ReadBuffer(V,SizeOf(V));
  677. FPackages.LoadFromStream(Stream);
  678. end;
  679. procedure TFPRepository.SaveToStream(Stream: TStream);
  680. Var
  681. i : Integer;
  682. begin
  683. I:=StreamSignature;
  684. Stream.WriteBuffer(I,SizeOf(Integer));
  685. I:=StreamVersion;
  686. Stream.WriteBuffer(I,SizeOf(Integer));
  687. FPackages.SaveToStream(Stream);
  688. end;
  689. procedure TFPRepository.LoadFromFile(const AFileName: String);
  690. Var
  691. F : TFileStream;
  692. begin
  693. F:=TFileStream.Create(AFileName,fmopenRead);
  694. Try
  695. LoadFromStream(F);
  696. FFileName:=AFileName;
  697. Finally
  698. F.Free;
  699. end;
  700. end;
  701. procedure TFPRepository.SaveToFile(const AFileName: String);
  702. Var
  703. F : TFileStream;
  704. begin
  705. If FileExists(AFileName) and BackupFiles then
  706. BackupFile(AFileName);
  707. F:=TFileStream.Create(AFileName,fmCreate);
  708. Try
  709. SaveToStream(F);
  710. FFileName:=AFileName;
  711. Finally
  712. F.Free;
  713. end;
  714. end;
  715. procedure TFPRepository.Save;
  716. begin
  717. If (FFileName='') then
  718. Raise EPackage.Create(SErrNoFileName);
  719. SaveToFile(FFileName);
  720. end;
  721. function TFPRepository.IndexOfPackage(const APackageName: String): Integer;
  722. begin
  723. Result:=FPackages.IndexOfPackage(APackageName);
  724. end;
  725. function TFPRepository.FindPackage(const APackageName: String): TFPPackage;
  726. begin
  727. Result:=FPackages.FindPackage(APackageName);
  728. end;
  729. function TFPRepository.PackageByName(const APackageName: String): TFPPackage;
  730. begin
  731. Result:=FPackages.PackageByName(APackageName);
  732. end;
  733. procedure TFPRepository.RemovePackage(const APackageName: string);
  734. begin
  735. PackageByName(APackageName).Free;
  736. end;
  737. procedure TFPRepository.DeletePackage(Index : Integer);
  738. begin
  739. GetPackage(Index).Free;
  740. end;
  741. function TFPRepository.AddPackage(const APackageName: string): TFPPackage;
  742. begin
  743. Result:=FPackages.AddPackage(APackageName);
  744. end;
  745. procedure TFPRepository.DoGetPackageDependencies(const APackageName: String; List: TStringList; Level: Integer);
  746. Var
  747. P : TFPPackage;
  748. D2,D1 : TFPDependency;
  749. i,J : Integer;
  750. begin
  751. // If too many levels, bail out
  752. If (Level>FMaxDependencyLevel) then
  753. Raise EPackage.CreateFmt(SErrMaxLevelExceeded,[Level,APackageName]);
  754. // Check if it is a known package.
  755. P:=FindPackage(APackageName);
  756. If not Assigned(P) then
  757. exit;
  758. For I:=0 to P.Dependencies.Count-1 do
  759. begin
  760. D1:=P.Dependencies[i];
  761. J:=List.IndexOf(APackageName);
  762. If J=-1 then
  763. begin
  764. // Dependency not yet in list.
  765. D2:=TFPDependency.Create(Nil);
  766. D2.Assign(D1);
  767. List.AddObject(D2.PackageName,D2);
  768. end
  769. else
  770. begin
  771. // Dependency already in list, compare versions.
  772. D2:=List.Objects[J] as TFPDependency;
  773. If D1.MinVersion.CompareVersion(D2.MinVersion)>0 then
  774. D2.MinVersion.Assign(D1.MinVersion);
  775. end;
  776. // If it was already in the list, we no longer recurse.
  777. If (Level>=0) and (J=-1) Then
  778. DoGetPackageDependencies(D2.PackageName,List,Level+1);
  779. end;
  780. end;
  781. procedure TFPRepository.GetPackageDependencies(const APackageName: String; List: TObjectList; Recurse: Boolean);
  782. Var
  783. L : TStringList;
  784. I : Integer;
  785. begin
  786. L:=TStringList.Create;
  787. Try
  788. L.Sorted:=True;
  789. DoGetPackageDependencies(APackageName,L,Ord(Recurse)-1);
  790. For I:=0 to L.Count-1 do
  791. List.Add(L.Objects[i]);
  792. Finally
  793. // Freeing a stringlist does not free the objects.
  794. L.Free;
  795. end;
  796. end;
  797. { TFPDependency }
  798. procedure TFPDependency.SetMinVersion(const AValue: TFPVersion);
  799. begin
  800. FMinVersion.Assign(AValue);
  801. end;
  802. constructor TFPDependency.Create(ACollection: TCollection);
  803. begin
  804. inherited Create(ACollection);
  805. FMinVersion:=TFPVersion.Create;
  806. FOSes:=AllOSes;
  807. FCPUs:=AllCPUs;
  808. FRequireChecksum:=$ffffffff;
  809. end;
  810. destructor TFPDependency.Destroy;
  811. begin
  812. FreeAndNil(FMinVersion);
  813. inherited Destroy;
  814. end;
  815. procedure TFPDependency.LoadFromStream(Stream: TStream; Streamversion: Integer);
  816. begin
  817. PackageName:=ReadString(Stream);
  818. MinVersion.AsString:=ReadString(Stream)
  819. end;
  820. procedure TFPDependency.SaveToStream(Stream: TStream);
  821. begin
  822. WriteString(Stream,PackageName);
  823. WriteString(Stream,MinVersion.AsString);
  824. end;
  825. procedure TFPDependency.Assign(Source: TPersistent);
  826. var
  827. S : TFPDependency;
  828. begin
  829. If Source is TFPDependency then
  830. begin
  831. S:=Source as TFPDependency;
  832. FPackageName:=S.PackageName;
  833. FMinVersion.Assign(S.MinVersion);
  834. FOSes:=S.OSes;
  835. FCPUs:=S.CPUs;
  836. end
  837. else
  838. inherited Assign(Source);
  839. end;
  840. { TFPDependencies }
  841. function TFPDependencies.GetDependency(Index : Integer): TFPDependency;
  842. begin
  843. Result:=TFPDependency(Items[Index]);
  844. end;
  845. procedure TFPDependencies.SetDependency(Index : Integer; const AValue: TFPDependency);
  846. begin
  847. Items[Index]:=AValue;
  848. end;
  849. function TFPDependencies.AddDependency(const APackageName: String; const AMinVersion: String): TFPDependency;
  850. begin
  851. Result:=Add as TFPDependency;
  852. Result.PackageName:=APackageName;
  853. If (AMinVersion<>'') then
  854. Result.MinVersion.AsString:=AMinVersion;
  855. end;
  856. { TFPMirror }
  857. constructor TFPMirror.Create(ACollection: TCollection);
  858. begin
  859. inherited Create(ACollection);
  860. Weight:=100;
  861. end;
  862. destructor TFPMirror.Destroy;
  863. begin
  864. inherited Destroy;
  865. end;
  866. procedure TFPMirror.LoadFromStream(Stream: TStream; Streamversion : Integer);
  867. begin
  868. Name:=ReadString(Stream);
  869. URL:=ReadString(Stream);
  870. Contact:=ReadString(Stream);
  871. Weight:=ReadInteger(Stream);
  872. end;
  873. procedure TFPMirror.SaveToStream(Stream: TStream);
  874. begin
  875. WriteString(Stream,Name);
  876. WriteString(Stream,URL);
  877. WriteString(Stream,Contact);
  878. WriteInteger(Stream,Weight);
  879. end;
  880. procedure TFPMirror.Assign(Source: TPersistent);
  881. Var
  882. P : TFPMirror;
  883. begin
  884. if Source is TFPMirror then
  885. begin
  886. P:=Source as TFPMirror;
  887. // This creates trouble if P has the same owning collection !!
  888. If P.Collection<>Collection then
  889. Name:=P.Name;
  890. URL:=P.URL;
  891. Contact:=P.Contact;
  892. Weight:=P.Weight;
  893. end
  894. else
  895. inherited Assign(Source);
  896. end;
  897. { TFPMirrors }
  898. function TFPMirrors.GetMirror(Index : Integer): TFPMirror;
  899. begin
  900. Result:=TFPMirror(Items[Index])
  901. end;
  902. procedure TFPMirrors.SetMirror(Index : Integer; const AValue: TFPMirror);
  903. begin
  904. Items[Index]:=AValue;
  905. end;
  906. function TFPMirrors.CurrentStreamVersion: Integer;
  907. begin
  908. Result:=FVersion;
  909. end;
  910. function TFPMirrors.IndexOfMirror(const AMirrorName: String): Integer;
  911. begin
  912. Result:=Count-1;
  913. While (Result>=0) and (CompareText(GetMirror(Result).Name,AMirrorName)<>0) do
  914. Dec(Result);
  915. end;
  916. function TFPMirrors.FindMirror(const AMirrorName: String): TFPMirror;
  917. Var
  918. I : Integer;
  919. begin
  920. I:=IndexOfMirror(AMirrorName);
  921. If (I=-1) then
  922. Result:=Nil
  923. else
  924. Result:=GetMirror(I);
  925. end;
  926. function TFPMirrors.MirrorByName(const AMirrorName: String): TFPMirror;
  927. begin
  928. Result:=FindMirror(AMirrorName);
  929. If Result=Nil then
  930. Raise EMirror.CreateFmt(SErrMirrorNotFound,[AMirrorName]);
  931. end;
  932. function TFPMirrors.AddMirror(const AMirrorName: string): TFPMirror;
  933. begin
  934. Result:=Add as TFPMirror;
  935. Try
  936. Result.Name:=AMirrorName;
  937. Except
  938. Result.Free;
  939. Raise;
  940. end;
  941. end;
  942. end.