fprepos.pp 26 KB

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