fprepos.pp 26 KB

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