fprepos.pp 28 KB

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