fpc/utils/fppkg/fprepos.pp
peter 85250cca06 * split repository in InstalledRepository and AvailableRepository
* replace CurrentPackage by PackageName
  * remove obsolete execute arguments

git-svn-id: trunk@10610 -
2008-04-06 21:00:24 +00:00

1072 lines
26 KiB
ObjectPascal

{
This file is part of the Free Pascal Utilities
Copyright (c) 1999-2000 by the Free Pascal development team
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
{$mode objfpc}
{$H+}
unit fprepos;
interface
uses
classes,sysutils,
contnrs,
streamcoll;
Const
StreamVersion : Integer = 1;
StreamSignature = $FEEF;
Type
// Keep syncronized with fpmkunit.pp
TCpu=(cpuNone,
i386,m68k,powerpc,sparc,x86_64,arm,powerpc64
);
TCPUS = Set of TCPU;
// Keep syncronized with fpmkunit.pp
TOS=(osNone,
linux,go32v2,win32,os2,freebsd,beos,netbsd,
amiga,atari, solaris, qnx, netware, openbsd,wdosx,
palmos,macos,darwin,emx,watcom,morphos,netwlibc,
win64,wince,gba,nds,embedded,symbian
);
TOSes = Set of TOS;
const
AllOSes = [Low(TOS)..High(TOS)];
AllCPUs = [Low(TCPU)..High(TCPU)];
type
{ TFPVersion }
TFPVersion = Class(TPersistent)
private
FMajor,
FMinor,
FMicro,
FBuild : Word;
function GetAsString: String;
function GetEmpty: Boolean;
procedure SetAsString(const AValue: String);
Public
Procedure Clear;
Procedure Assign(Source : TPersistent); override;
Property AsString : String Read GetAsString Write SetAsString;
Function CompareVersion(AVersion : TFPVersion) : Integer;
Function SameVersion(AVersion : TFPVersion) : Boolean;
Property Empty : Boolean Read GetEmpty;
Published
Property Major : Word Read FMajor Write FMajor;
Property Minor : Word Read FMinor Write FMinor;
Property Micro : Word Read FMicro Write FMicro;
Property Build : Word Read FBuild Write FBuild;
end;
{ TFPDependency }
TFPDependency = Class(TStreamCollectionItem)
private
FOSes : TOSES;
FCPUs : TCPUS;
FMinVersion: TFPVersion;
FPackageName: String;
FRequireChecksum : cardinal;
procedure SetMinVersion(const AValue: TFPVersion);
Public
Constructor Create(ACollection : TCollection); override;
Destructor Destroy; override;
Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
Procedure SaveToStream(Stream : TStream); override;
Procedure Assign(Source : TPersistent); override;
Published
Property PackageName : String Read FPackageName Write FPackageName;
Property MinVersion : TFPVersion Read FMinVersion Write SetMinVersion;
Property OSes : TOSes Read FOSes Write FOses;
Property CPUs : TCPUs Read FCPUs Write FCPUs;
Property RequireChecksum : Cardinal Read FRequireChecksum Write FRequireChecksum;
end;
{ TFPDepencencies }
TFPDependencies = Class(TStreamCollection)
private
function GetDependency(Index : Integer): TFPDependency;
procedure SetDependency(Index : Integer; const AValue: TFPDependency);
public
Function AddDependency(const APackageName : String; const AMinVersion : String = '') : TFPDependency;
Property Dependencies[Index : Integer] : TFPDependency Read GetDependency Write SetDependency;default;
end;
{ TFPPackage }
TFPPackage = Class(TStreamCollectionItem)
private
FAuthor: String;
FDescription: String;
FEmail: String;
FLicense: String;
FName: String;
FExternalURL: String;
FFileName: String;
FVersion: TFPVersion;
FDependencies : TFPDependencies;
FOSes : TOSES;
FCPUs : TCPUS;
// Installation info
FChecksum : cardinal;
FLocalFileName : String;
function GetFileName: String;
procedure SetName(const AValue: String);
procedure SetVersion(const AValue: TFPVersion);
Public
Constructor Create(ACollection : TCollection); override;
Destructor Destroy; override;
Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
Procedure SaveToStream(Stream : TStream); override;
Procedure Assign(Source : TPersistent); override;
Function AddDependency(Const APackageName : String; const AMinVersion : String = '') : TFPDependency;
Property Dependencies : TFPDependencies Read FDependencies;
Published
Property Name : String Read FName Write SetName;
Property Author : String Read FAuthor Write FAuthor;
Property Version : TFPVersion Read FVersion Write SetVersion;
Property License : String Read FLicense Write FLicense;
Property Description : String Read FDescription Write FDescription;
Property ExternalURL : String Read FExternalURL Write FExternalURL;
Property FileName : String Read GetFileName Write FFileName;
Property Email : String Read FEmail Write FEmail;
Property OSes : TOSes Read FOSes Write FOses;
Property CPUs : TCPUs Read FCPUs Write FCPUs;
Property Checksum : Cardinal Read FChecksum Write FChecksum;
// Manual package from commandline not in official repository
Property LocalFileName : String Read FLocalFileName Write FLocalFileName;
end;
{ TFPPackages }
TFPPackages = Class(TStreamCollection)
private
FVersion : Integer;
function GetPackage(Index : Integer): TFPPackage;
procedure SetPackage(Index : Integer; const AValue: TFPPackage);
Protected
Function CurrentStreamVersion : Integer; override;
Public
Function IndexOfPackage(const APackageName : String) : Integer;
Function FindPackage(const APackageName : String) : TFPPackage;
Function PackageByName(const APackageName : String) : TFPPackage;
Function AddPackage(const APackageName : string) : TFPPackage;
Property StreamVersion : Integer Read FVersion Write FVersion;
Property Packages [Index : Integer] : TFPPackage Read GetPackage Write SetPackage; default;
end;
{ TFPRepository }
TFPRepository = Class(TComponent)
Private
FMaxDependencyLevel : Integer;
FBackUpFiles: Boolean;
FFileName: String;
FPackages : TFPPackages;
function GetPackage(Index : Integer): TFPPackage;
function GetPackageCount: Integer;
Protected
procedure CreatePackages; virtual;
Procedure BackupFile(const AFileName : String); virtual;
Procedure DoGetPackageDependencies(const APackageName : String; List : TStringList; Level : Integer); virtual;
Public
Constructor Create(AOwner : TComponent); override;
Destructor Destroy; override;
// Loading and Saving repository. Own format.
Procedure LoadFromStream(Stream : TStream); Virtual;
Procedure SaveToStream(Stream : TStream); Virtual;
Procedure LoadFromFile(const AFileName : String);
Procedure SaveToFile(const AFileName : String);
Procedure Save;
// Package management
Function IndexOfPackage(const APackageName : String) : Integer;
Function FindPackage(const APackageName : String) : TFPPackage;
Function PackageByName(const APackageName : String) : TFPPackage;
Procedure DeletePackage(Index : Integer);
Procedure RemovePackage(const APackageName : string);
Function AddPackage(const APackageName : string) : TFPPackage;
// Dependencies
Procedure GetPackageDependencies(const APackageName : String; List : TObjectList; Recurse : Boolean);
// Properties
Property FileName : String Read FFileName;
Property Packages[Index : Integer] : TFPPackage Read GetPackage; default;
Property PackageCount : Integer Read GetPackageCount;
Property BackupFiles : Boolean Read FBackUpFiles Write FBackupFiles;
Property MaxDependencyLevel : Integer Read FMaxDependencyLevel Write FMaxDependencyLevel;
Property PackageCollection : TFPPackages Read FPackages;
end;
{ TFPMirror }
TFPMirror = Class(TStreamCollectionItem)
private
FContact: String;
FName: String;
FURL: String;
FWeight: Integer;
Public
Constructor Create(ACollection : TCollection); override;
Destructor Destroy; override;
Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
Procedure SaveToStream(Stream : TStream); override;
Procedure Assign(Source : TPersistent); override;
Published
Property Name : String Read FName Write FName;
Property URL : String Read FURL Write FURL;
Property Contact : String Read FContact Write FContact;
Property Weight : Integer Read FWeight Write FWeight;
end;
{ TFPMirrors }
TFPMirrors = Class(TStreamCollection)
private
FVersion : Integer;
function GetMirror(Index : Integer): TFPMirror;
procedure SetMirror(Index : Integer; const AValue: TFPMirror);
Protected
Function CurrentStreamVersion : Integer; override;
Public
Function IndexOfMirror(const AMirrorName : String) : Integer;
Function FindMirror(const AMirrorName : String) : TFPMirror;
Function MirrorByName(const AMirrorName : String) : TFPMirror;
Function AddMirror(const AMirrorName : string) : TFPMirror;
Property StreamVersion : Integer Read FVersion Write FVersion;
Property Mirrors [Index : Integer] : TFPMirror Read GetMirror Write SetMirror; default;
end;
EPackage = Class(Exception);
EMirror = Class(Exception);
Const
// Max level of dependency searching before we decide it's a circular dependency.
DefaultMaxDependencyLevel = 15;
Function OSToString(OS: TOS) : String;
Function OSesToString(OSes: TOSes) : String;
Function CPUToString(CPU: TCPU) : String;
Function CPUSToString(CPUS: TCPUS) : String;
Function StringToOS(S : String) : TOS;
Function OSesToString(S : String) : TOSes;
Function StringToCPU(S : String) : TCPU;
Function StringToCPUS(S : String) : TCPUS;
Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
Implementation
uses
typinfo,
uriparser;
ResourceString
SErrInvalidCPU = 'Invalid CPU name : "%s"';
SErrInvalidOS = 'Invalid OS name : "%s"';
SErrInvalidMode = 'Invalid compiler mode : "%s"';
SErrInvalidTarget = 'Invalid compiler target: %s';
SErrPackageNotFound = 'Package "%s" not found.';
SErrInvalidRepositorySig = 'Invalid repository stream. Stream signature incorrect';
SErrBackupFailed = 'Failed to back up file "%s" to "%s".';
SErrNoFileName = 'No filename for repository specified.';
SErrDuplicatePackageName = 'Duplicate package name : "%s"';
SErrMaxLevelExceeded = 'Maximum number of dependency levels exceeded (%d) at package "%s".';
SErrMirrorNotFound = 'Mirror "%s" not found.';
Function OSToString(OS: TOS) : String;
begin
Result:=LowerCase(GetenumName(TypeInfo(TOS),Ord(OS)));
end;
Function OSesToString(OSes: TOSes) : String;
begin
Result:=LowerCase(SetToString(PtypeInfo(TypeInfo(TOSes)),Integer(OSes),False));
end;
Function CPUToString(CPU: TCPU) : String;
begin
Result:=LowerCase(GetenumName(TypeInfo(TCPU),Ord(CPU)));
end;
Function CPUSToString(CPUS: TCPUS) : String;
begin
Result:=LowerCase(SetToString(PTypeInfo(TypeInfo(TCPUS)),Integer(CPUS),False));
end;
Function StringToOS(S : String) : TOS;
Var
I : Integer;
begin
I:=GetEnumValue(TypeInfo(TOS),S);
if (I=-1) then
Raise EPackage.CreateFmt(SErrInvalidOS,[S]);
Result:=TOS(I);
end;
Function OSesToString(S : String) : TOSes;
begin
Result:=TOSes(StringToSet(PTypeInfo(TypeInfo(TOSes)),S));
end;
Function StringToCPU(S : String) : TCPU;
Var
I : Integer;
begin
I:=GetEnumValue(TypeInfo(TCPU),S);
if (I=-1) then
Raise EPackage.CreateFmt(SErrInvalidCPU,[S]);
Result:=TCPU(I);
end;
Function StringToCPUS(S : String) : TCPUS;
begin
Result:=TCPUS(StringToSet(PTypeInfo(TypeInfo(TCPUS)),S));
end;
Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
begin
Result:=CPUToString(CPU)+'-'+OSToString(OS);
end;
Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
Var
P : integer;
begin
P:=Pos('-',S);
If (P=0) then
Raise EPackage.CreateFmt(SErrInvalidTarget,[S]);
CPU:=StringToCPU(Copy(S,1,P-1));
OS:=StringToOs(Copy(S,P+1,Length(S)-P));
end;
{ TFPVersion }
function TFPVersion.GetAsString: String;
begin
if Empty then
Result:='<none>'
else
Result:=Format('%d.%d.%d-%d',[Major,Minor,Micro,Build]);
end;
function TFPVersion.GetEmpty: Boolean;
begin
Result:=(Major=0) and (Minor=0) and (Micro=0) and (Build=0);
end;
procedure TFPVersion.SetAsString(const AValue: String);
Function NextDigit(sep : Char; var V : string) : integer;
Var
P : Integer;
begin
P:=Pos(Sep,V);
If (P=0) then
P:=Length(V)+1;
Result:=StrToIntDef(Copy(V,1,P-1),-1);
If Result<>-1 then
Delete(V,1,P)
else
Result:=0;
end;
Var
V : String;
begin
Clear;
// Special support for empty version string
if (AValue='') or (AValue='<none>') then
exit;
V:=AValue;
Major:=NextDigit('.',V);
Minor:=NextDigit('.',V);
Micro:=NextDigit('-',V);
Build:=NextDigit(#0,V);
end;
procedure TFPVersion.Clear;
begin
Micro:=0;
Major:=0;
Minor:=0;
Build:=0;
end;
procedure TFPVersion.Assign(Source: TPersistent);
Var
V : TFPVersion;
begin
if Source is TFPVersion then
begin
V:=Source as TFPVersion;
Major:=V.Major;
Minor:=V.Minor;
Micro:=V.Micro;
Build:=V.Build;
end
else
inherited Assign(Source);
end;
function TFPVersion.CompareVersion(AVersion: TFPVersion): Integer;
begin
Result:=Major-AVersion.Major;
If (Result=0) then
begin
Result:=Minor-AVersion.Minor;
if (Result=0) then
begin
Result:=Micro-AVersion.Micro;
If (Result=0) then
Result:=Build-AVersion.Build;
end;
end;
end;
function TFPVersion.SameVersion(AVersion: TFPVersion): Boolean;
begin
Result:=CompareVersion(AVersion)=0;
end;
{ TFPPackage }
procedure TFPPackage.SetVersion(const AValue: TFPVersion);
begin
if FVersion=AValue then
exit;
FVersion.Assign(AValue);
end;
constructor TFPPackage.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FVersion:=TFPVersion.Create;
FChecksum:=$ffffffff;
FOSes:=AllOSes;
FCPUs:=AllCPUs;
FDependencies:=TFPDependencies.Create(TFPDependency);
end;
destructor TFPPackage.Destroy;
begin
FreeAndNil(FDependencies);
FreeAndNil(FVersion);
inherited Destroy;
end;
procedure TFPPackage.SetName(const AValue: String);
begin
If (AValue<>FName) and (AValue<>'') then
If (Collection<>Nil) and (Collection is TFPPackages) then
// do not check while loading, this would slow down a lot !!
if (not TFPPackages(Collection).Streaming) then
If TFPPackages(Collection).IndexOfPackage(AValue)<>-1 then
Raise EPackage.CreateFmt(SErrDuplicatePackageName,[AValue]);
FName:=AValue;
end;
function TFPPackage.GetFileName: String;
var
URI : TURI;
begin
if FFileName='' then
begin
URI:=ParseURI(ExternalURL);
Result:=URI.Document;
end
else
Result:=FFileName;
end;
procedure TFPPackage.LoadFromStream(Stream: TStream; Streamversion : Integer);
Var
B : Boolean;
O : TOSes;
C : TCPUs;
I,J,Count : Integer;
begin
Version.AsString:=ReadString(Stream);
Name:=ReadString(Stream);
Author:=ReadString(Stream);
License:=ReadString(Stream);
Description:=ReadString(Stream);
ExternalURL:=ReadString(Stream);
FileName:=ReadString(Stream);
Email:=ReadString(Stream);
Count:=ReadInteger(Stream);
O:=[];
For I:=1 to Count do
begin
J:=GetEnumValue(TypeInfo(TOS),ReadString(Stream));
If (J<>-1) then
Include(O,TOS(J));
end;
OSEs:=O;
Count:=ReadInteger(Stream);
C:=[];
For I:=1 to Count do
begin
J:=GetEnumValue(TypeInfo(TCPU),ReadString(Stream));
If (J<>-1) then
Include(C,TCPU(J));
end;
CPUS:=C;
FDependencies.Clear;
B:=ReadBoolean(Stream);
If B then
FDependencies.LoadFromStream(Stream);
end;
procedure TFPPackage.SaveToStream(Stream: TStream);
Var
Count : Integer;
O : TOS;
C : TCPU;
begin
WriteString(Stream,Version.AsString);
WriteString(Stream,Name);
WriteString(Stream,Author);
WriteString(Stream,License);
WriteString(Stream,Description);
WriteString(Stream,ExternalURL);
WriteString(Stream,FileName);
WriteString(Stream,Email);
{ Write it like this, makes error checking easier when reading. }
// OSes
Count:=0;
For O:=Low(TOS) to High(TOS) do
If O in OSes then
Inc(Count);
WriteInteger(Stream,Count);
For O:=Low(TOS) to High(TOS) do
If O in OSes then
WriteString(Stream,GetEnumName(TypeInfo(TOS),Ord(O)));
// CPUs
Count:=0;
For C:=Low(TCPU) to High(TCPU) do
If C in CPUS then
Inc(Count);
WriteInteger(Stream,Count);
For C:=Low(TCPU) to High(TCPU) do
If C in CPUS then
WriteString(Stream,GetEnumName(TypeInfo(TCPU),Ord(C)));
WriteBoolean(Stream,FDependencies.Count>0);
If FDependencies.Count>0 then
FDependencies.SaveToStream(Stream);
end;
procedure TFPPackage.Assign(Source: TPersistent);
Var
P : TFPPackage;
begin
if Source is TFPPackage then
begin
P:=Source as TFPPackage;
// This creates trouble if P has the same owning collection !!
If P.Collection<>Collection then
Name:=P.Name;
Author:=P.Author;
Version:=P.Version;
Description:=P.Description;
ExternalURL:=P.ExternalURL;
FileName:=P.FileName;
Checksum:=P.Checksum;
Dependencies.Clear;
Dependencies.Assign(P.Dependencies);
end
else
inherited Assign(Source);
end;
function TFPPackage.AddDependency(Const APackageName : String; const AMinVersion : String = ''): TFPDependency;
begin
Result:=Dependencies.AddDependency(APackageName,AMinVersion);
end;
{ TFPPackages }
function TFPPackages.GetPackage(Index : Integer): TFPPackage;
begin
Result:=TFPPackage(Items[Index])
end;
procedure TFPPackages.SetPackage(Index : Integer; const AValue: TFPPackage);
begin
Items[Index]:=AValue;
end;
function TFPPackages.CurrentStreamVersion: Integer;
begin
Result:=FVersion;
end;
function TFPPackages.IndexOfPackage(const APackageName: String): Integer;
begin
Result:=Count-1;
While (Result>=0) and (CompareText(GetPackage(Result).Name,APackageName)<>0) do
Dec(Result);
end;
function TFPPackages.FindPackage(const APackageName: String): TFPPackage;
Var
I : Integer;
begin
I:=IndexOfPackage(APackageName);
If (I=-1) then
Result:=Nil
else
Result:=GetPackage(I);
end;
function TFPPackages.PackageByName(const APackageName: String): TFPPackage;
begin
Result:=FindPackage(APackageName);
If Result=Nil then
Raise EPackage.CreateFmt(SErrPackageNotFound,[APackageName]);
end;
function TFPPackages.AddPackage(const APackageName: string): TFPPackage;
begin
Result:=Add as TFPPackage;
Try
Result.Name:=APackageName;
Except
Result.Free;
Raise;
end;
end;
{ TFPRepository }
function TFPRepository.GetPackage(Index : Integer): TFPPackage;
begin
Result:=FPackages[Index];
end;
function TFPRepository.GetPackageCount: Integer;
begin
Result:=FPackages.Count;
end;
constructor TFPRepository.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
CreatePackages;
FMaxDependencyLevel:=DefaultMaxDependencyLevel;
end;
procedure TFPRepository.CreatePackages;
begin
FPackages:=TFPPackages.Create(TFPPackage);
FPackages.StreamVersion:=StreamVersion;
end;
procedure TFPRepository.BackupFile(const AFileName: String);
Var
S : String;
begin
S:=AFileName+'.bak';
if not RenameFile(AFileName,S) then
Raise EPackage.CreateFmt(SErrBackupFailed,[AFileName,S]);
end;
destructor TFPRepository.Destroy;
begin
FreeAndNil(FPackages);
inherited Destroy;
end;
procedure TFPRepository.LoadFromStream(Stream: TStream);
Var
I : Integer;
V : Integer;
begin
Stream.ReadBuffer(I,SizeOf(Integer));
If (I<>StreamSignature) then
Raise EPackage.Create(SErrInvalidRepositorySig);
Stream.ReadBuffer(V,SizeOf(V));
FPackages.LoadFromStream(Stream);
end;
procedure TFPRepository.SaveToStream(Stream: TStream);
Var
i : Integer;
begin
I:=StreamSignature;
Stream.WriteBuffer(I,SizeOf(Integer));
I:=StreamVersion;
Stream.WriteBuffer(I,SizeOf(Integer));
FPackages.SaveToStream(Stream);
end;
procedure TFPRepository.LoadFromFile(const AFileName: String);
Var
F : TFileStream;
begin
F:=TFileStream.Create(AFileName,fmopenRead);
Try
LoadFromStream(F);
FFileName:=AFileName;
Finally
F.Free;
end;
end;
procedure TFPRepository.SaveToFile(const AFileName: String);
Var
F : TFileStream;
begin
If FileExists(AFileName) and BackupFiles then
BackupFile(AFileName);
F:=TFileStream.Create(AFileName,fmCreate);
Try
SaveToStream(F);
FFileName:=AFileName;
Finally
F.Free;
end;
end;
procedure TFPRepository.Save;
begin
If (FFileName='') then
Raise EPackage.Create(SErrNoFileName);
SaveToFile(FFileName);
end;
function TFPRepository.IndexOfPackage(const APackageName: String): Integer;
begin
Result:=FPackages.IndexOfPackage(APackageName);
end;
function TFPRepository.FindPackage(const APackageName: String): TFPPackage;
begin
Result:=FPackages.FindPackage(APackageName);
end;
function TFPRepository.PackageByName(const APackageName: String): TFPPackage;
begin
Result:=FPackages.PackageByName(APackageName);
end;
procedure TFPRepository.RemovePackage(const APackageName: string);
begin
PackageByName(APackageName).Free;
end;
procedure TFPRepository.DeletePackage(Index : Integer);
begin
GetPackage(Index).Free;
end;
function TFPRepository.AddPackage(const APackageName: string): TFPPackage;
begin
Result:=FPackages.AddPackage(APackageName);
end;
procedure TFPRepository.DoGetPackageDependencies(const APackageName: String; List: TStringList; Level: Integer);
Var
P : TFPPackage;
D2,D1 : TFPDependency;
i,J : Integer;
begin
// If too many levels, bail out
If (Level>FMaxDependencyLevel) then
Raise EPackage.CreateFmt(SErrMaxLevelExceeded,[Level,APackageName]);
// Check if it is a known package.
P:=FindPackage(APackageName);
If not Assigned(P) then
exit;
For I:=0 to P.Dependencies.Count-1 do
begin
D1:=P.Dependencies[i];
J:=List.IndexOf(APackageName);
If J=-1 then
begin
// Dependency not yet in list.
D2:=TFPDependency.Create(Nil);
D2.Assign(D1);
List.AddObject(D2.PackageName,D2);
end
else
begin
// Dependency already in list, compare versions.
D2:=List.Objects[J] as TFPDependency;
If D1.MinVersion.CompareVersion(D2.MinVersion)>0 then
D2.MinVersion.Assign(D1.MinVersion);
end;
// If it was already in the list, we no longer recurse.
If (Level>=0) and (J=-1) Then
DoGetPackageDependencies(D2.PackageName,List,Level+1);
end;
end;
procedure TFPRepository.GetPackageDependencies(const APackageName: String; List: TObjectList; Recurse: Boolean);
Var
L : TStringList;
I : Integer;
begin
L:=TStringList.Create;
Try
L.Sorted:=True;
DoGetPackageDependencies(APackageName,L,Ord(Recurse)-1);
For I:=0 to L.Count-1 do
List.Add(L.Objects[i]);
Finally
// Freeing a stringlist does not free the objects.
L.Free;
end;
end;
{ TFPDependency }
procedure TFPDependency.SetMinVersion(const AValue: TFPVersion);
begin
FMinVersion.Assign(AValue);
end;
constructor TFPDependency.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FMinVersion:=TFPVersion.Create;
FOSes:=AllOSes;
FCPUs:=AllCPUs;
FRequireChecksum:=$ffffffff;
end;
destructor TFPDependency.Destroy;
begin
FreeAndNil(FMinVersion);
inherited Destroy;
end;
procedure TFPDependency.LoadFromStream(Stream: TStream; Streamversion: Integer);
begin
PackageName:=ReadString(Stream);
MinVersion.AsString:=ReadString(Stream)
end;
procedure TFPDependency.SaveToStream(Stream: TStream);
begin
WriteString(Stream,PackageName);
WriteString(Stream,MinVersion.AsString);
end;
procedure TFPDependency.Assign(Source: TPersistent);
var
S : TFPDependency;
begin
If Source is TFPDependency then
begin
S:=Source as TFPDependency;
FPackageName:=S.PackageName;
FMinVersion.Assign(S.MinVersion);
FOSes:=S.OSes;
FCPUs:=S.CPUs;
end
else
inherited Assign(Source);
end;
{ TFPDependencies }
function TFPDependencies.GetDependency(Index : Integer): TFPDependency;
begin
Result:=TFPDependency(Items[Index]);
end;
procedure TFPDependencies.SetDependency(Index : Integer; const AValue: TFPDependency);
begin
Items[Index]:=AValue;
end;
function TFPDependencies.AddDependency(const APackageName: String; const AMinVersion: String): TFPDependency;
begin
Result:=Add as TFPDependency;
Result.PackageName:=APackageName;
If (AMinVersion<>'') then
Result.MinVersion.AsString:=AMinVersion;
end;
{ TFPMirror }
constructor TFPMirror.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
Weight:=100;
end;
destructor TFPMirror.Destroy;
begin
inherited Destroy;
end;
procedure TFPMirror.LoadFromStream(Stream: TStream; Streamversion : Integer);
begin
Name:=ReadString(Stream);
URL:=ReadString(Stream);
Contact:=ReadString(Stream);
Weight:=ReadInteger(Stream);
end;
procedure TFPMirror.SaveToStream(Stream: TStream);
begin
WriteString(Stream,Name);
WriteString(Stream,URL);
WriteString(Stream,Contact);
WriteInteger(Stream,Weight);
end;
procedure TFPMirror.Assign(Source: TPersistent);
Var
P : TFPMirror;
begin
if Source is TFPMirror then
begin
P:=Source as TFPMirror;
// This creates trouble if P has the same owning collection !!
If P.Collection<>Collection then
Name:=P.Name;
URL:=P.URL;
Contact:=P.Contact;
Weight:=P.Weight;
end
else
inherited Assign(Source);
end;
{ TFPMirrors }
function TFPMirrors.GetMirror(Index : Integer): TFPMirror;
begin
Result:=TFPMirror(Items[Index])
end;
procedure TFPMirrors.SetMirror(Index : Integer; const AValue: TFPMirror);
begin
Items[Index]:=AValue;
end;
function TFPMirrors.CurrentStreamVersion: Integer;
begin
Result:=FVersion;
end;
function TFPMirrors.IndexOfMirror(const AMirrorName: String): Integer;
begin
Result:=Count-1;
While (Result>=0) and (CompareText(GetMirror(Result).Name,AMirrorName)<>0) do
Dec(Result);
end;
function TFPMirrors.FindMirror(const AMirrorName: String): TFPMirror;
Var
I : Integer;
begin
I:=IndexOfMirror(AMirrorName);
If (I=-1) then
Result:=Nil
else
Result:=GetMirror(I);
end;
function TFPMirrors.MirrorByName(const AMirrorName: String): TFPMirror;
begin
Result:=FindMirror(AMirrorName);
If Result=Nil then
Raise EMirror.CreateFmt(SErrMirrorNotFound,[AMirrorName]);
end;
function TFPMirrors.AddMirror(const AMirrorName: string): TFPMirror;
begin
Result:=Add as TFPMirror;
Try
Result.Name:=AMirrorName;
Except
Result.Free;
Raise;
end;
end;
end.