fprepos.pp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  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; NonNumerisIsSep : boolean; var V : string; aDefault : integer = 0) : integer;
  329. Var
  330. P : Integer;
  331. i : Integer;
  332. begin
  333. P:=Pos(Sep,V);
  334. If (P=0) then
  335. P:=Length(V)+1;
  336. If NonNumerisIsSep then
  337. for i := 1 to P-1 do
  338. if not (V[i] in ['0','1','2','3','4','5','6','7','8','9']) then
  339. begin
  340. P := i;
  341. Break;
  342. end;
  343. Result:=StrToIntDef(Copy(V,1,P-1),-1);
  344. If Result<>-1 then
  345. Delete(V,1,P)
  346. else
  347. Result:=aDefault;
  348. end;
  349. Var
  350. V : String;
  351. b : integer;
  352. begin
  353. Clear;
  354. // Special support for empty version string
  355. if (AValue='') or (AValue='<none>') then
  356. exit;
  357. V:=AValue;
  358. // Supported version-format is x.y.z-b
  359. // x,y,z and b are all optional and are set to 0 if they are not provided
  360. // except for b which has a default of 1.
  361. // x and y must be numeric. z or b may contain a non-numeric suffix which
  362. // will be stripped. If there is any non-numeric character in z or b and
  363. // there is no value supplied for b, build will be set to 0
  364. // examples:
  365. // 2 -> 2.0.0-1
  366. // 2.2 -> 2.2.0-1
  367. // 2.2.4 -> 2.2.4-1
  368. // 2.2.4-0 -> 2.2.4-0
  369. // 2.2.4rc1 -> 2.2.4-0
  370. // 2.2.4-0rc1 -> 2.2.4-0
  371. // 2.2.4-2rc1 -> 2.2.4-2
  372. Major:=NextDigit('.',False,V);
  373. Minor:=NextDigit('.',False,V);
  374. Micro:=NextDigit('-',True,V);
  375. b := NextDigit(#0,True,V,-1);
  376. if b<0 then
  377. if V <> '' then
  378. Build := 0
  379. else
  380. Build := 1
  381. else
  382. Build := b;
  383. end;
  384. procedure TFPVersion.Clear;
  385. begin
  386. Micro:=0;
  387. Major:=0;
  388. Minor:=0;
  389. Build:=0;
  390. end;
  391. procedure TFPVersion.Assign(Source: TPersistent);
  392. Var
  393. V : TFPVersion;
  394. begin
  395. if Source is TFPVersion then
  396. begin
  397. V:=Source as TFPVersion;
  398. Major:=V.Major;
  399. Minor:=V.Minor;
  400. Micro:=V.Micro;
  401. Build:=V.Build;
  402. end
  403. else
  404. inherited Assign(Source);
  405. end;
  406. function TFPVersion.CompareVersion(AVersion: TFPVersion): Integer;
  407. begin
  408. Result:=Major-AVersion.Major;
  409. If (Result=0) then
  410. begin
  411. Result:=Minor-AVersion.Minor;
  412. if (Result=0) then
  413. begin
  414. Result:=Micro-AVersion.Micro;
  415. If (Result=0) then
  416. Result:=Build-AVersion.Build;
  417. end;
  418. end;
  419. end;
  420. function TFPVersion.SameVersion(AVersion: TFPVersion): Boolean;
  421. begin
  422. Result:=CompareVersion(AVersion)=0;
  423. end;
  424. { TFPPackage }
  425. procedure TFPPackage.SetVersion(const AValue: TFPVersion);
  426. begin
  427. if FVersion=AValue then
  428. exit;
  429. FVersion.Assign(AValue);
  430. end;
  431. constructor TFPPackage.Create(ACollection: TCollection);
  432. begin
  433. inherited Create(ACollection);
  434. FVersion:=TFPVersion.Create;
  435. FChecksum:=$ffffffff;
  436. FOSes:=AllOSes;
  437. FCPUs:=AllCPUs;
  438. FDependencies:=TFPDependencies.Create(TFPDependency);
  439. end;
  440. destructor TFPPackage.Destroy;
  441. begin
  442. FreeAndNil(FDependencies);
  443. FreeAndNil(FVersion);
  444. inherited Destroy;
  445. end;
  446. procedure TFPPackage.SetName(const AValue: String);
  447. begin
  448. If (AValue<>FName) and (AValue<>'') then
  449. If (Collection<>Nil) and (Collection is TFPPackages) then
  450. // do not check while loading, this would slow down a lot !!
  451. if (not TFPPackages(Collection).Streaming) then
  452. If TFPPackages(Collection).IndexOfPackage(AValue)<>-1 then
  453. Raise EPackage.CreateFmt(SErrDuplicatePackageName,[AValue]);
  454. FName:=AValue;
  455. end;
  456. function TFPPackage.GetFileName: String;
  457. var
  458. URI : TURI;
  459. begin
  460. if FFileName='' then
  461. begin
  462. URI:=ParseURI(DownloadURL);
  463. Result:=URI.Document;
  464. end
  465. else
  466. Result:=FFileName;
  467. end;
  468. procedure TFPPackage.LoadFromStream(Stream: TStream; Streamversion : Integer);
  469. Var
  470. B : Boolean;
  471. O : TOSes;
  472. C : TCPUs;
  473. I,J,Count : Integer;
  474. begin
  475. Version.AsString:=ReadString(Stream);
  476. Name:=ReadString(Stream);
  477. Author:=ReadString(Stream);
  478. License:=ReadString(Stream);
  479. Description:=ReadString(Stream);
  480. HomepageURL:=ReadString(Stream);
  481. DownloadURL:=ReadString(Stream);
  482. FileName:=ReadString(Stream);
  483. Email:=ReadString(Stream);
  484. Count:=ReadInteger(Stream);
  485. O:=[];
  486. For I:=1 to Count do
  487. begin
  488. J:=GetEnumValue(TypeInfo(TOS),ReadString(Stream));
  489. If (J<>-1) then
  490. Include(O,TOS(J));
  491. end;
  492. OSEs:=O;
  493. Count:=ReadInteger(Stream);
  494. C:=[];
  495. For I:=1 to Count do
  496. begin
  497. J:=GetEnumValue(TypeInfo(TCPU),ReadString(Stream));
  498. If (J<>-1) then
  499. Include(C,TCPU(J));
  500. end;
  501. CPUS:=C;
  502. FDependencies.Clear;
  503. B:=ReadBoolean(Stream);
  504. If B then
  505. FDependencies.LoadFromStream(Stream);
  506. end;
  507. procedure TFPPackage.SaveToStream(Stream: TStream);
  508. Var
  509. Count : Integer;
  510. O : TOS;
  511. C : TCPU;
  512. begin
  513. WriteString(Stream,Version.AsString);
  514. WriteString(Stream,Name);
  515. WriteString(Stream,Author);
  516. WriteString(Stream,License);
  517. WriteString(Stream,Description);
  518. WriteString(Stream,HomepageURL);
  519. WriteString(Stream,DownloadURL);
  520. WriteString(Stream,FileName);
  521. WriteString(Stream,Email);
  522. { Write it like this, makes error checking easier when reading. }
  523. // OSes
  524. Count:=0;
  525. For O:=Low(TOS) to High(TOS) do
  526. If O in OSes then
  527. Inc(Count);
  528. WriteInteger(Stream,Count);
  529. For O:=Low(TOS) to High(TOS) do
  530. If O in OSes then
  531. WriteString(Stream,GetEnumName(TypeInfo(TOS),Ord(O)));
  532. // CPUs
  533. Count:=0;
  534. For C:=Low(TCPU) to High(TCPU) do
  535. If C in CPUS then
  536. Inc(Count);
  537. WriteInteger(Stream,Count);
  538. For C:=Low(TCPU) to High(TCPU) do
  539. If C in CPUS then
  540. WriteString(Stream,GetEnumName(TypeInfo(TCPU),Ord(C)));
  541. WriteBoolean(Stream,FDependencies.Count>0);
  542. If FDependencies.Count>0 then
  543. FDependencies.SaveToStream(Stream);
  544. end;
  545. procedure TFPPackage.Assign(Source: TPersistent);
  546. Var
  547. P : TFPPackage;
  548. begin
  549. if Source is TFPPackage then
  550. begin
  551. P:=Source as TFPPackage;
  552. // This creates trouble if P has the same owning collection !!
  553. If P.Collection<>Collection then
  554. Name:=P.Name;
  555. Author:=P.Author;
  556. Version:=P.Version;
  557. Description:=P.Description;
  558. HomepageURL:=P.HomepageURL;
  559. DownloadURL:=P.DownloadURL;
  560. FileName:=P.FileName;
  561. Checksum:=P.Checksum;
  562. Dependencies.Clear;
  563. Dependencies.Assign(P.Dependencies);
  564. end
  565. else
  566. inherited Assign(Source);
  567. end;
  568. function TFPPackage.AddDependency(Const APackageName : String; const AMinVersion : String = ''): TFPDependency;
  569. begin
  570. Result:=Dependencies.AddDependency(APackageName,AMinVersion);
  571. end;
  572. { TFPPackages }
  573. function TFPPackages.GetPackage(Index : Integer): TFPPackage;
  574. begin
  575. Result:=TFPPackage(Items[Index])
  576. end;
  577. procedure TFPPackages.SetPackage(Index : Integer; const AValue: TFPPackage);
  578. begin
  579. Items[Index]:=AValue;
  580. end;
  581. function TFPPackages.CurrentStreamVersion: Integer;
  582. begin
  583. Result:=FVersion;
  584. end;
  585. function TFPPackages.IndexOfPackage(const APackageName: String): Integer;
  586. begin
  587. Result:=Count-1;
  588. While (Result>=0) and (CompareText(GetPackage(Result).Name,APackageName)<>0) do
  589. Dec(Result);
  590. end;
  591. function TFPPackages.FindPackage(const APackageName: String): TFPPackage;
  592. Var
  593. I : Integer;
  594. begin
  595. I:=IndexOfPackage(APackageName);
  596. If (I=-1) then
  597. Result:=Nil
  598. else
  599. Result:=GetPackage(I);
  600. end;
  601. function TFPPackages.PackageByName(const APackageName: String): TFPPackage;
  602. begin
  603. Result:=FindPackage(APackageName);
  604. If Result=Nil then
  605. Raise EPackage.CreateFmt(SErrPackageNotFound,[APackageName]);
  606. end;
  607. function TFPPackages.AddPackage(const APackageName: string): TFPPackage;
  608. begin
  609. Result:=Add as TFPPackage;
  610. Try
  611. Result.Name:=APackageName;
  612. Except
  613. Result.Free;
  614. Raise;
  615. end;
  616. end;
  617. { TFPRepository }
  618. function TFPRepository.GetPackage(Index : Integer): TFPPackage;
  619. begin
  620. Result:=FPackages[Index];
  621. end;
  622. function TFPRepository.GetPackageCount: Integer;
  623. begin
  624. Result:=FPackages.Count;
  625. end;
  626. constructor TFPRepository.Create(AOwner: TComponent);
  627. begin
  628. inherited Create(AOwner);
  629. CreatePackages;
  630. FMaxDependencyLevel:=DefaultMaxDependencyLevel;
  631. end;
  632. procedure TFPRepository.CreatePackages;
  633. begin
  634. FPackages:=TFPPackages.Create(TFPPackage);
  635. FPackages.StreamVersion:=StreamVersion;
  636. end;
  637. procedure TFPRepository.BackupFile(const AFileName: String);
  638. Var
  639. S : String;
  640. begin
  641. S:=AFileName+'.bak';
  642. if not RenameFile(AFileName,S) then
  643. Raise EPackage.CreateFmt(SErrBackupFailed,[AFileName,S]);
  644. end;
  645. destructor TFPRepository.Destroy;
  646. begin
  647. FreeAndNil(FPackages);
  648. inherited Destroy;
  649. end;
  650. procedure TFPRepository.LoadFromStream(Stream: TStream);
  651. Var
  652. I : Integer;
  653. V : Integer;
  654. begin
  655. Stream.ReadBuffer(I,SizeOf(Integer));
  656. If (I<>StreamSignature) then
  657. Raise EPackage.Create(SErrInvalidRepositorySig);
  658. Stream.ReadBuffer(V,SizeOf(V));
  659. FPackages.LoadFromStream(Stream);
  660. end;
  661. procedure TFPRepository.SaveToStream(Stream: TStream);
  662. Var
  663. i : Integer;
  664. begin
  665. I:=StreamSignature;
  666. Stream.WriteBuffer(I,SizeOf(Integer));
  667. I:=StreamVersion;
  668. Stream.WriteBuffer(I,SizeOf(Integer));
  669. FPackages.SaveToStream(Stream);
  670. end;
  671. procedure TFPRepository.LoadFromFile(const AFileName: String);
  672. Var
  673. F : TFileStream;
  674. begin
  675. F:=TFileStream.Create(AFileName,fmopenRead);
  676. Try
  677. LoadFromStream(F);
  678. FFileName:=AFileName;
  679. Finally
  680. F.Free;
  681. end;
  682. end;
  683. procedure TFPRepository.SaveToFile(const AFileName: String);
  684. Var
  685. F : TFileStream;
  686. begin
  687. If FileExists(AFileName) and BackupFiles then
  688. BackupFile(AFileName);
  689. F:=TFileStream.Create(AFileName,fmCreate);
  690. Try
  691. SaveToStream(F);
  692. FFileName:=AFileName;
  693. Finally
  694. F.Free;
  695. end;
  696. end;
  697. procedure TFPRepository.Save;
  698. begin
  699. If (FFileName='') then
  700. Raise EPackage.Create(SErrNoFileName);
  701. SaveToFile(FFileName);
  702. end;
  703. function TFPRepository.IndexOfPackage(const APackageName: String): Integer;
  704. begin
  705. Result:=FPackages.IndexOfPackage(APackageName);
  706. end;
  707. function TFPRepository.FindPackage(const APackageName: String): TFPPackage;
  708. begin
  709. Result:=FPackages.FindPackage(APackageName);
  710. end;
  711. function TFPRepository.PackageByName(const APackageName: String): TFPPackage;
  712. begin
  713. Result:=FPackages.PackageByName(APackageName);
  714. end;
  715. procedure TFPRepository.RemovePackage(const APackageName: string);
  716. begin
  717. PackageByName(APackageName).Free;
  718. end;
  719. procedure TFPRepository.DeletePackage(Index : Integer);
  720. begin
  721. GetPackage(Index).Free;
  722. end;
  723. function TFPRepository.AddPackage(const APackageName: string): TFPPackage;
  724. begin
  725. Result:=FPackages.AddPackage(APackageName);
  726. end;
  727. procedure TFPRepository.DoGetPackageDependencies(const APackageName: String; List: TStringList; Level: Integer);
  728. Var
  729. P : TFPPackage;
  730. D2,D1 : TFPDependency;
  731. i,J : Integer;
  732. begin
  733. // If too many levels, bail out
  734. If (Level>FMaxDependencyLevel) then
  735. Raise EPackage.CreateFmt(SErrMaxLevelExceeded,[Level,APackageName]);
  736. // Check if it is a known package.
  737. P:=FindPackage(APackageName);
  738. If not Assigned(P) then
  739. exit;
  740. For I:=0 to P.Dependencies.Count-1 do
  741. begin
  742. D1:=P.Dependencies[i];
  743. J:=List.IndexOf(APackageName);
  744. If J=-1 then
  745. begin
  746. // Dependency not yet in list.
  747. D2:=TFPDependency.Create(Nil);
  748. D2.Assign(D1);
  749. List.AddObject(D2.PackageName,D2);
  750. end
  751. else
  752. begin
  753. // Dependency already in list, compare versions.
  754. D2:=List.Objects[J] as TFPDependency;
  755. If D1.MinVersion.CompareVersion(D2.MinVersion)>0 then
  756. D2.MinVersion.Assign(D1.MinVersion);
  757. end;
  758. // If it was already in the list, we no longer recurse.
  759. If (Level>=0) and (J=-1) Then
  760. DoGetPackageDependencies(D2.PackageName,List,Level+1);
  761. end;
  762. end;
  763. procedure TFPRepository.GetPackageDependencies(const APackageName: String; List: TObjectList; Recurse: Boolean);
  764. Var
  765. L : TStringList;
  766. I : Integer;
  767. begin
  768. L:=TStringList.Create;
  769. Try
  770. L.Sorted:=True;
  771. DoGetPackageDependencies(APackageName,L,Ord(Recurse)-1);
  772. For I:=0 to L.Count-1 do
  773. List.Add(L.Objects[i]);
  774. Finally
  775. // Freeing a stringlist does not free the objects.
  776. L.Free;
  777. end;
  778. end;
  779. { TFPDependency }
  780. procedure TFPDependency.SetMinVersion(const AValue: TFPVersion);
  781. begin
  782. FMinVersion.Assign(AValue);
  783. end;
  784. constructor TFPDependency.Create(ACollection: TCollection);
  785. begin
  786. inherited Create(ACollection);
  787. FMinVersion:=TFPVersion.Create;
  788. FOSes:=AllOSes;
  789. FCPUs:=AllCPUs;
  790. FRequireChecksum:=$ffffffff;
  791. end;
  792. destructor TFPDependency.Destroy;
  793. begin
  794. FreeAndNil(FMinVersion);
  795. inherited Destroy;
  796. end;
  797. procedure TFPDependency.LoadFromStream(Stream: TStream; Streamversion: Integer);
  798. begin
  799. PackageName:=ReadString(Stream);
  800. MinVersion.AsString:=ReadString(Stream)
  801. end;
  802. procedure TFPDependency.SaveToStream(Stream: TStream);
  803. begin
  804. WriteString(Stream,PackageName);
  805. WriteString(Stream,MinVersion.AsString);
  806. end;
  807. procedure TFPDependency.Assign(Source: TPersistent);
  808. var
  809. S : TFPDependency;
  810. begin
  811. If Source is TFPDependency then
  812. begin
  813. S:=Source as TFPDependency;
  814. FPackageName:=S.PackageName;
  815. FMinVersion.Assign(S.MinVersion);
  816. FOSes:=S.OSes;
  817. FCPUs:=S.CPUs;
  818. end
  819. else
  820. inherited Assign(Source);
  821. end;
  822. { TFPDependencies }
  823. function TFPDependencies.GetDependency(Index : Integer): TFPDependency;
  824. begin
  825. Result:=TFPDependency(Items[Index]);
  826. end;
  827. procedure TFPDependencies.SetDependency(Index : Integer; const AValue: TFPDependency);
  828. begin
  829. Items[Index]:=AValue;
  830. end;
  831. function TFPDependencies.AddDependency(const APackageName: String; const AMinVersion: String): TFPDependency;
  832. begin
  833. Result:=Add as TFPDependency;
  834. Result.PackageName:=APackageName;
  835. If (AMinVersion<>'') then
  836. Result.MinVersion.AsString:=AMinVersion;
  837. end;
  838. { TFPMirror }
  839. constructor TFPMirror.Create(ACollection: TCollection);
  840. begin
  841. inherited Create(ACollection);
  842. Weight:=100;
  843. end;
  844. destructor TFPMirror.Destroy;
  845. begin
  846. inherited Destroy;
  847. end;
  848. procedure TFPMirror.LoadFromStream(Stream: TStream; Streamversion : Integer);
  849. begin
  850. Name:=ReadString(Stream);
  851. URL:=ReadString(Stream);
  852. Contact:=ReadString(Stream);
  853. Weight:=ReadInteger(Stream);
  854. end;
  855. procedure TFPMirror.SaveToStream(Stream: TStream);
  856. begin
  857. WriteString(Stream,Name);
  858. WriteString(Stream,URL);
  859. WriteString(Stream,Contact);
  860. WriteInteger(Stream,Weight);
  861. end;
  862. procedure TFPMirror.Assign(Source: TPersistent);
  863. Var
  864. P : TFPMirror;
  865. begin
  866. if Source is TFPMirror then
  867. begin
  868. P:=Source as TFPMirror;
  869. // This creates trouble if P has the same owning collection !!
  870. If P.Collection<>Collection then
  871. Name:=P.Name;
  872. URL:=P.URL;
  873. Contact:=P.Contact;
  874. Weight:=P.Weight;
  875. end
  876. else
  877. inherited Assign(Source);
  878. end;
  879. { TFPMirrors }
  880. function TFPMirrors.GetMirror(Index : Integer): TFPMirror;
  881. begin
  882. Result:=TFPMirror(Items[Index])
  883. end;
  884. procedure TFPMirrors.SetMirror(Index : Integer; const AValue: TFPMirror);
  885. begin
  886. Items[Index]:=AValue;
  887. end;
  888. function TFPMirrors.CurrentStreamVersion: Integer;
  889. begin
  890. Result:=FVersion;
  891. end;
  892. function TFPMirrors.IndexOfMirror(const AMirrorName: String): Integer;
  893. begin
  894. Result:=Count-1;
  895. While (Result>=0) and (CompareText(GetMirror(Result).Name,AMirrorName)<>0) do
  896. Dec(Result);
  897. end;
  898. function TFPMirrors.FindMirror(const AMirrorName: String): TFPMirror;
  899. Var
  900. I : Integer;
  901. begin
  902. I:=IndexOfMirror(AMirrorName);
  903. If (I=-1) then
  904. Result:=Nil
  905. else
  906. Result:=GetMirror(I);
  907. end;
  908. function TFPMirrors.MirrorByName(const AMirrorName: String): TFPMirror;
  909. begin
  910. Result:=FindMirror(AMirrorName);
  911. If Result=Nil then
  912. Raise EMirror.CreateFmt(SErrMirrorNotFound,[AMirrorName]);
  913. end;
  914. function TFPMirrors.AddMirror(const AMirrorName: string): TFPMirror;
  915. begin
  916. Result:=Add as TFPMirror;
  917. Try
  918. Result.Name:=AMirrorName;
  919. Except
  920. Result.Free;
  921. Raise;
  922. end;
  923. end;
  924. end.