fprepos.pp 29 KB

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