Просмотр исходного кода

Merged revisions 10182-10184,10187-10188,10191-10192,10200-10201,10203-10204,10206,10214,10220,10232,10234,10238-10241,10243-10244,10247,10251,10253-10254,10264,10266,10271,10273,10276-10280 via svnmerge from
http://svn.freepascal.org/svn/fpc/trunk

........
r10182 | peter | 2008-02-03 16:16:13 +0100 (Sun, 03 Feb 2008) | 2 lines

* basic work to load installed versions from fpunits.conf
........
r10214 | peter | 2008-02-04 22:14:25 +0100 (Mon, 04 Feb 2008) | 3 lines

* find installed versions in local and global install dir
* support Package.fpc for backwards compatibility
........
r10220 | peter | 2008-02-05 00:49:05 +0100 (Tue, 05 Feb 2008) | 4 lines

* check dependencies for os and cpu
* versions changed to major.minor.micro-build
* renamed avail,allavail to showavail,showall
........
r10240 | peter | 2008-02-07 22:23:54 +0100 (Thu, 07 Feb 2008) | 2 lines

* handle duplciate versions in scan
........
r10241 | peter | 2008-02-07 22:55:08 +0100 (Thu, 07 Feb 2008) | 2 lines

* log packages installed both global and local
........
r10244 | peter | 2008-02-08 00:01:28 +0100 (Fri, 08 Feb 2008) | 2 lines

* clean command
........
r10247 | peter | 2008-02-08 01:03:50 +0100 (Fri, 08 Feb 2008) | 2 lines

* disable wrong package not available check
........
r10280 | peter | 2008-02-10 20:06:20 +0100 (Sun, 10 Feb 2008) | 3 lines

* recovery mode added to always use internal fpmkunit
* fix dependency versioning
........

git-svn-id: branches/fixes_2_2@10286 -

peter 17 лет назад
Родитель
Сommit
0307d69da8

Разница между файлами не показана из-за своего большого размера
+ 316 - 291
utils/fppkg/fpmkunitsrc.inc


+ 34 - 63
utils/fppkg/fppkg.lpi

@@ -12,7 +12,7 @@
       <MainUnit Value="0"/>
       <IconPath Value=".\"/>
       <TargetFileExt Value=""/>
-      <ActiveEditorIndexAtStart Value="7"/>
+      <ActiveEditorIndexAtStart Value="4"/>
     </General>
     <VersionInfo>
       <ProjectVersion Value=""/>
@@ -28,17 +28,17 @@
     <RunParams>
       <local>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="build hash"/>
+        <CommandLineParams Value="avail"/>
         <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
       </local>
     </RunParams>
-    <Units Count="38">
+    <Units Count="39">
       <Unit0>
         <Filename Value="fppkg.pp"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="fppkg"/>
-        <CursorPos X="1" Y="246"/>
-        <TopLine Value="228"/>
+        <CursorPos X="1" Y="317"/>
+        <TopLine Value="293"/>
         <EditorIndex Value="7"/>
         <UsageCount Value="86"/>
         <Loaded Value="True"/>
@@ -75,8 +75,8 @@
         <Filename Value="fprepos.pp"/>
         <IsPartOfProject Value="True"/>
         <UnitName Value="fprepos"/>
-        <CursorPos X="1" Y="187"/>
-        <TopLine Value="163"/>
+        <CursorPos X="3" Y="167"/>
+        <TopLine Value="168"/>
         <EditorIndex Value="8"/>
         <UsageCount Value="86"/>
         <Loaded Value="True"/>
@@ -205,8 +205,8 @@
       <Unit22>
         <Filename Value="pkgrepos.pp"/>
         <UnitName Value="pkgrepos"/>
-        <CursorPos X="17" Y="108"/>
-        <TopLine Value="108"/>
+        <CursorPos X="57" Y="242"/>
+        <TopLine Value="210"/>
         <EditorIndex Value="4"/>
         <UsageCount Value="32"/>
         <Loaded Value="True"/>
@@ -276,7 +276,7 @@
       <Unit32>
         <Filename Value="pkglnet.pp"/>
         <UnitName Value="pkglnet"/>
-        <CursorPos X="45" Y="32"/>
+        <CursorPos X="71" Y="10"/>
         <TopLine Value="1"/>
         <EditorIndex Value="9"/>
         <UsageCount Value="17"/>
@@ -321,76 +321,47 @@
         <TopLine Value="1"/>
         <UsageCount Value="10"/>
       </Unit37>
+      <Unit38>
+        <Filename Value="../../../proj/lazarus/lcl/interfaces/gtk/gtkproc.pp"/>
+        <UnitName Value="GTKProc"/>
+        <CursorPos X="11" Y="674"/>
+        <TopLine Value="655"/>
+        <UsageCount Value="10"/>
+      </Unit38>
     </Units>
-    <JumpHistory Count="17" HistoryIndex="16">
+    <JumpHistory Count="8" HistoryIndex="7">
       <Position1>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="128" Column="17" TopLine="111"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="108" Column="17" TopLine="108"/>
       </Position1>
       <Position2>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="47" Column="32" TopLine="28"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="177" Column="16" TopLine="173"/>
       </Position2>
       <Position3>
-        <Filename Value="pkgfpmake.pp"/>
-        <Caret Line="213" Column="18" TopLine="188"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="212" Column="77" TopLine="193"/>
       </Position3>
       <Position4>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="51" Column="54" TopLine="32"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="222" Column="33" TopLine="196"/>
       </Position4>
       <Position5>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="76" Column="25" TopLine="57"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="210" Column="1" TopLine="183"/>
       </Position5>
       <Position6>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="110" Column="56" TopLine="91"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="218" Column="29" TopLine="203"/>
       </Position6>
       <Position7>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="60" Column="31" TopLine="49"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="26" Column="28" TopLine="7"/>
       </Position7>
       <Position8>
-        <Filename Value="pkghandler.pp"/>
-        <Caret Line="160" Column="16" TopLine="134"/>
+        <Filename Value="pkgrepos.pp"/>
+        <Caret Line="229" Column="1" TopLine="208"/>
       </Position8>
-      <Position9>
-        <Filename Value="pkghandler.pp"/>
-        <Caret Line="44" Column="36" TopLine="24"/>
-      </Position9>
-      <Position10>
-        <Filename Value="pkghandler.pp"/>
-        <Caret Line="213" Column="46" TopLine="194"/>
-      </Position10>
-      <Position11>
-        <Filename Value="pkgfpmake.pp"/>
-        <Caret Line="236" Column="12" TopLine="199"/>
-      </Position11>
-      <Position12>
-        <Filename Value="pkgfpmake.pp"/>
-        <Caret Line="200" Column="20" TopLine="181"/>
-      </Position12>
-      <Position13>
-        <Filename Value="fppkg.pp"/>
-        <Caret Line="317" Column="24" TopLine="280"/>
-      </Position13>
-      <Position14>
-        <Filename Value="pkgglobals.pp"/>
-        <Caret Line="159" Column="52" TopLine="147"/>
-      </Position14>
-      <Position15>
-        <Filename Value="fppkg.pp"/>
-        <Caret Line="74" Column="30" TopLine="55"/>
-      </Position15>
-      <Position16>
-        <Filename Value="fppkg.pp"/>
-        <Caret Line="78" Column="32" TopLine="59"/>
-      </Position16>
-      <Position17>
-        <Filename Value="fppkg.pp"/>
-        <Caret Line="245" Column="9" TopLine="224"/>
-      </Position17>
     </JumpHistory>
   </ProjectOptions>
   <CompilerOptions>

+ 17 - 10
utils/fppkg/fppkg.pp

@@ -154,12 +154,15 @@ begin
   Writeln('  -d --debug         Show debugging information');
   Writeln('  -g --global        Force installation to global (system-wide) directory');
   Writeln('  -f --force         Force installation also if the package is already installed');
+  Writeln('  -r --recovery      Recovery mode, use always internal fpmkunit');
   Writeln('Actions:');
   Writeln('  update             Update packages list');
-  Writeln('  avail              List available packages');
+  Writeln('  showavail          List available packages');
+  Writeln('  showall            Show all (including local) packages');
   Writeln('  build              Build package');
   Writeln('  compile            Compile package');
   Writeln('  install            Install package');
+  Writeln('  clean              Clean package');
   Writeln('  archive            Create archive of package');
   Writeln('  download           Download package');
   Writeln('  convertmk          Convert Makefile.fpc to fpmake.pp');
@@ -240,6 +243,8 @@ begin
         LogLevels:=AllLogLevels+[vlDebug]
       else if CheckOption(I,'g','global') then
         GlobalOptions.InstallGlobal:=true
+      else if CheckOption(I,'r','recovery') then
+        GlobalOptions.RecoveryMode:=true
       else if CheckOption(I,'h','help') then
         begin
           ShowUsage;
@@ -292,11 +297,12 @@ begin
       end;
     LoadLocalMirrors;
     LoadLocalRepository;
-    LoadFPMakeLocalStatus;
+    FindInstalledPackages(FPMakeCompilerOptions,true);
+    CheckFPMakeDependencies;
     // We only need to reload the status when we use a different
     // configuration for compiling fpmake
     if GlobalOptions.CompilerConfig<>GlobalOptions.FPMakeCompilerConfig then
-      LoadLocalStatus;
+      FindInstalledPackages(CompilerOptions,true);
 
     if ParaPackages.Count=0 then
       begin
@@ -310,17 +316,18 @@ begin
           begin
             if FileExists(ParaPackages[i]) then
               begin
-                ActionPackage:=TFPPackage.Create(nil);
-                ActionPackage.Name:=ChangeFileExt(ExtractFileName(ParaPackages[i]),'');
+                ActionPackage:=LoadOrCreatePackage(ChangeFileExt(ExtractFileName(ParaPackages[i]),''));
                 ActionPackage.FileName:=ExpandFileName(ParaPackages[i]);
                 ActionPackage.IsLocalPackage:=true;
+                res:=pkghandler.ExecuteAction(ActionPackage,ParaAction);
+                FreeAndNil(ActionPackage);
               end
             else
-              ActionPackage:=CurrentRepository.PackageByName(ParaPackages[i]);
-            Log(vlDebug,SLogCommandLineAction,['['+ActionPackage.Name+']',ParaAction]);
-            res:=pkghandler.ExecuteAction(ActionPackage,ParaAction);
-            if ActionPackage.IsLocalPackage then;
-              FreeAndNil(ActionPackage);
+              begin
+                ActionPackage:=CurrentRepository.PackageByName(ParaPackages[i]);
+                Log(vlDebug,SLogCommandLineAction,['['+ActionPackage.Name+']',ParaAction]);
+                res:=pkghandler.ExecuteAction(ActionPackage,ParaAction);
+              end;
             if not res then
               break;
           end;

+ 131 - 143
utils/fppkg/fprepos.pp

@@ -41,14 +41,19 @@ Type
   );
   TOSes = Set of TOS;
 
+const
+  AllOSes = [Low(TOS)..High(TOS)];
+  AllCPUs = [Low(TCPU)..High(TCPU)];
+
+type
   { TFPVersion }
 
   TFPVersion = Class(TPersistent)
   private
-    FMajor: Word;
-    FMinor: Word;
-    FRelease: Word;
-    FSuffix: string;
+    FMajor,
+    FMinor,
+    FMicro,
+    FBuild    : Word;
     function GetAsString: String;
     function GetEmpty: Boolean;
     procedure SetAsString(const AValue: String);
@@ -60,16 +65,18 @@ Type
    Function SameVersion(AVersion : TFPVersion) : Boolean;
    Property Empty : Boolean Read GetEmpty;
   Published
-   Property Release : Word Read FRelease Write FRelease;
    Property Major : Word Read FMajor Write FMajor;
    Property Minor : Word Read FMinor Write FMinor;
-   Property Suffix : string Read FSuffix Write FSuffix;
+   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;
     procedure SetMinVersion(const AValue: TFPVersion);
@@ -82,6 +89,8 @@ Type
   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;
   end;
 
   { TFPDepencencies }
@@ -112,13 +121,9 @@ Type
     FOSes : TOSES;
     FCPUs : TCPUS;
     FIsLocalPackage : Boolean;
-    function GetDependencies: TFPDependencies;
-    function GetHasDependencies: Boolean;
     function GetFileName: String;
     procedure SetName(const AValue: String);
     procedure SetVersion(const AValue: TFPVersion);
-  Protected
-    Function CreateDependencies : TFPDependencies; virtual;
   Public
     Constructor Create(ACollection : TCollection); override;
     Destructor Destroy; override;
@@ -126,8 +131,7 @@ Type
     Procedure SaveToStream(Stream : TStream); override;
     Procedure Assign(Source : TPersistent); override;
     Function AddDependency(Const APackageName : String; AMinVersion : String = '') : TFPDependency;
-    Property HasDependencies : Boolean Read GetHasDependencies;
-    Property Dependencies : TFPDependencies Read GetDependencies;
+    Property Dependencies : TFPDependencies Read FDependencies;
   Published
     Property Name : String Read FName Write SetName;
     Property Author : String Read FAuthor Write FAuthor;
@@ -187,10 +191,12 @@ Type
     Procedure Save;
     // Loading and Saving version numbers: List of Name=Value pairs.
     procedure ClearStatus;
+{$ifdef STATUSFILE}
     Procedure LoadStatusFromStream(Stream : TStream); virtual;
     Procedure SaveStatusToStream(Stream : TStream); virtual;
     Procedure LoadStatusFromFile(const AFileName : String);
     Procedure SaveStatusToFile(const AFileName : String);
+{$endif STATUSFILE}
     // Package management
     Function IndexOfPackage(const APackageName : String) : Integer;
     Function FindPackage(const APackageName : String) : TFPPackage;
@@ -289,34 +295,32 @@ ResourceString
 
 
 Function OSToString(OS: TOS) : String;
-
 begin
   Result:=LowerCase(GetenumName(TypeInfo(TOS),Ord(OS)));
 end;
 
-Function OSesToString(OSes: TOSes) : String;
 
+Function OSesToString(OSes: TOSes) : String;
 begin
   Result:=LowerCase(SetToString(PtypeInfo(TypeInfo(TOSes)),Integer(OSes),False));
 end;
 
-Function CPUToString(CPU: TCPU) : String;
 
+Function CPUToString(CPU: TCPU) : String;
 begin
   Result:=LowerCase(GetenumName(TypeInfo(TCPU),Ord(CPU)));
 end;
 
-Function CPUSToString(CPUS: TCPUS) : String;
 
+Function CPUSToString(CPUS: TCPUS) : String;
 begin
   Result:=LowerCase(SetToString(PTypeInfo(TypeInfo(TCPUS)),Integer(CPUS),False));
 end;
 
-Function StringToOS(S : String) : TOS;
 
+Function StringToOS(S : String) : TOS;
 Var
   I : Integer;
-
 begin
   I:=GetEnumValue(TypeInfo(TOS),S);
   if (I=-1) then
@@ -326,16 +330,14 @@ end;
 
 
 Function OSesToString(S : String) : TOSes;
-
 begin
   Result:=TOSes(StringToSet(PTypeInfo(TypeInfo(TOSes)),S));
 end;
 
-Function StringToCPU(S : String) : TCPU;
 
+Function StringToCPU(S : String) : TCPU;
 Var
   I : Integer;
-
 begin
   I:=GetEnumValue(TypeInfo(TCPU),S);
   if (I=-1) then
@@ -343,23 +345,22 @@ begin
   Result:=TCPU(I);
 end;
 
-Function StringToCPUS(S : String) : TCPUS;
 
+Function StringToCPUS(S : String) : TCPUS;
 begin
   Result:=TCPUS(StringToSet(PTypeInfo(TypeInfo(TCPUS)),S));
 end;
 
-Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
 
+Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
 begin
   Result:=CPUToString(CPU)+'-'+OSToString(OS);
 end;
 
-Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
 
+Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
 Var
   P : integer;
-
 begin
   P:=Pos('-',S);
   If (P=0) then
@@ -376,25 +377,21 @@ begin
   if Empty then
     Result:='<none>'
   else
-    begin
-      Result:=Format('%d.%d.%d',[Release,Major,Minor]);
-      If (Suffix<>'') then
-        Result:=Result+'-'+Suffix;
-    end;
+    Result:=Format('%d.%d.%d-%d',[Major,Minor,Micro,Build]);
 end;
 
+
 function TFPVersion.GetEmpty: Boolean;
 begin
-  Result:=(Release=0) and (Major=0) and (Minor=0) and (Suffix='');
+  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
@@ -407,65 +404,62 @@ procedure TFPVersion.SetAsString(const AValue: String);
   end;
 
 Var
-  P : Integer;
   V : String;
-
 begin
   Clear;
   // Special support for empty version string
   if (AValue='') or (AValue='<none>') then
     exit;
   V:=AValue;
-  Release:=NextDigit('.',V);
   Major:=NextDigit('.',V);
-  Minor:=NextDigit('-',V);
-  P:=Pos('-',V);
-  If (P<>0) then
-    Delete(V,1,P);
-  Suffix:=V;
+  Minor:=NextDigit('.',V);
+  Micro:=NextDigit('-',V);
+  Build:=NextDigit(#0,V);
 end;
 
+
 procedure TFPVersion.Clear;
 begin
-  Release:=0;
+  Micro:=0;
   Major:=0;
   Minor:=0;
-  Suffix:='';
+  Build:=0;
 end;
 
-procedure TFPVersion.Assign(Source: TPersistent);
 
+procedure TFPVersion.Assign(Source: TPersistent);
 Var
   V : TFPVersion;
-
 begin
   if Source is TFPVersion then
     begin
-    V:=Source as TFPVersion;
-    Release:=V.Release;
-    Major:=V.Major;
-    Minor:=V.Minor;
-    Suffix:=V.Suffix;
+      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:=Release-AVersion.Release;
+  Result:=Major-AVersion.Major;
   If (Result=0) then
     begin
-    Result:=Major-AVersion.Major;
-    if (Result=0) then
-      begin
       Result:=Minor-AVersion.Minor;
-      If (Result=0) then
-        Result:=CompareText(Suffix,AVersion.Suffix);
-      end;
+      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;
@@ -480,16 +474,15 @@ begin
   FVersion.Assign(AValue);
 end;
 
-Function TFPPackage.CreateDependencies : TFPDependencies;
-begin
-  Result:=TFPDependencies.Create(TFPDependency);
-end;
 
 constructor TFPPackage.Create(ACollection: TCollection);
 begin
   inherited Create(ACollection);
   FVersion:=TFPVersion.Create;
   FInstalledVersion:=TFPVersion.Create;
+  FOSes:=AllOSes;
+  FCPUs:=AllCPUs;
+  FDependencies:=TFPDependencies.Create(TFPDependency);
 end;
 
 
@@ -501,8 +494,8 @@ begin
   inherited Destroy;
 end;
 
-procedure TFPPackage.SetName(const AValue: String);
 
+procedure TFPPackage.SetName(const AValue: String);
 begin
   If (AValue<>FName) and (AValue<>'') then
     If (Collection<>Nil) and (Collection is TFPPackages) then
@@ -513,17 +506,6 @@ begin
   FName:=AValue;
 end;
 
-function TFPPackage.GetDependencies: TFPDependencies;
-begin
-  If Not Assigned(FDependencies) then
-    FDependencies:=CreateDependencies;
-  Result:=FDependencies;
-end;
-
-function TFPPackage.GetHasDependencies: Boolean;
-begin
-  Result:=(Dependencies<>nil) and (FDependencies.Count>0);
-end;
 
 function TFPPackage.GetFileName: String;
 var
@@ -538,14 +520,13 @@ begin
     Result:=FFileName;
 end;
 
-procedure TFPPackage.LoadFromStream(Stream: TStream; Streamversion : Integer);
 
+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);
@@ -559,36 +540,32 @@ begin
   O:=[];
   For I:=1 to Count do
     begin
-    J:=GetEnumValue(TypeInfo(TOS),ReadString(Stream));
-    If (J<>-1) then
-      Include(O,TOS(J));
+      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));
+      J:=GetEnumValue(TypeInfo(TCPU),ReadString(Stream));
+      If (J<>-1) then
+        Include(C,TCPU(J));
     end;
   CPUS:=C;
-  FreeAndNil(FDependencies);
+  FDependencies.Clear;
   B:=ReadBoolean(Stream);
   If B then
-    begin
-    FDependencies:=CreateDependencies;
     FDependencies.LoadFromStream(Stream);
-    end
 end;
 
-procedure TFPPackage.SaveToStream(Stream: TStream);
 
+procedure TFPPackage.SaveToStream(Stream: TStream);
 Var
   Count : Integer;
   O : TOS;
   C : TCPU;
-
 begin
   WriteString(Stream,Version.AsString);
   WriteString(Stream,Name);
@@ -617,44 +594,42 @@ begin
   For C:=Low(TCPU) to High(TCPU) do
     If C in CPUS then
       WriteString(Stream,GetEnumName(TypeInfo(TCPU),Ord(C)));
-  WriteBoolean(Stream,HasDependencies);
-  If HasDependencies then
+  WriteBoolean(Stream,FDependencies.Count>0);
+  If FDependencies.Count>0 then
     FDependencies.SaveToStream(Stream);
 end;
 
-procedure TFPPackage.Assign(Source: TPersistent);
 
+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;
-    InstalledVersion:=P.Installedversion;
-    If P.HasDependencies then
-      Dependencies.Assign(P.Dependencies)
-    else
-      FreeAndNil(FDependencies);
+      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;
+      InstalledVersion.Assign(P.Installedversion);
+      Dependencies.Clear;
+      Dependencies.Assign(P.Dependencies);
     end
   else
     inherited Assign(Source);
 end;
 
-function TFPPackage.AddDependency(const APackageName: String;
-  AMinVersion: String): TFPDependency;
+
+function TFPPackage.AddDependency(const APackageName: String;AMinVersion: String): TFPDependency;
 begin
   Result:=Dependencies.AddDependency(APackageName,AMinVersion);
 end;
 
+
 { TFPPackages }
 
 function TFPPackages.GetPackage(Index : Integer): TFPPackage;
@@ -837,13 +812,12 @@ begin
 end;
 
 
+{$ifdef STATUSFILE}
 procedure TFPRepository.LoadStatusFromStream(Stream: TStream);
-
 Var
   L : TStrings;
   I : Integer;
   N,V : String;
-
 begin
   L:=TStringList.Create;
   Try
@@ -859,12 +833,11 @@ begin
   end;
 end;
 
-procedure TFPRepository.SaveStatusToStream(Stream: TStream);
 
+procedure TFPRepository.SaveStatusToStream(Stream: TStream);
 Var
   L : TStrings;
   I : Integer;
-
 begin
   L:=TStringList.Create;
   Try
@@ -878,11 +851,10 @@ begin
   end;
 end;
 
-procedure TFPRepository.LoadStatusFromFile(const AFileName: String);
 
+procedure TFPRepository.LoadStatusFromFile(const AFileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(AFileName,fmOpenRead);
   Try
@@ -892,11 +864,10 @@ begin
   end;
 end;
 
-procedure TFPRepository.SaveStatusToFile(const AFileName: String);
 
+procedure TFPRepository.SaveStatusToFile(const AFileName: String);
 Var
   F : TFileStream;
-
 begin
   If FileExists(AFileName) and BackupFiles then
     BackupFile(AFileName);
@@ -907,83 +878,87 @@ begin
     F.Free;
   end;
 end;
+{$endif STATUSFILE}
+
 
 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;
 
+function TFPRepository.AddPackage(const APackageName: string): TFPPackage;
 begin
   Result:=FPackages.AddPackage(APackageName);
 end;
 
-procedure TFPRepository.DoGetPackageDependencies(const APackageName: String;
-  List: TStringList; Level: Integer);
+
+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 Assigned(P) and P.HasDependencies then
-    For I:=0 to P.Dependencies.Count-1 do
-      begin
+  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);
+          // 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);
+          // 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;
 end;
 
-procedure TFPRepository.GetPackageDependencies(const APackageName: String;
-  List: TObjectList; Recurse: Boolean);
 
+procedure TFPRepository.GetPackageDependencies(const APackageName: String; List: TObjectList; Recurse: Boolean);
 Var
   L : TStringList;
   I : Integer;
-
 begin
   L:=TStringList.Create;
   Try
@@ -1005,43 +980,54 @@ begin
   FMinVersion.Assign(AValue);
 end;
 
+
 constructor TFPDependency.Create(ACollection: TCollection);
 begin
   inherited Create(ACollection);
   FMinVersion:=TFPVersion.Create;
+  FOSes:=AllOSes;
+  FCPUs:=AllCPUs;
 end;
 
+
 destructor TFPDependency.Destroy;
 begin
   FreeAndNil(FMinVersion);
   inherited Destroy;
 end;
 
-procedure TFPDependency.LoadFromStream(Stream: TStream; Streamversion: Integer
-  );
+
+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
-    With Source as TFPDependency do
-      begin
-      Self.PackageName:=PackageName;
-      Self.MinVersion:=MinVersion;
-      end
+    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;
@@ -1049,12 +1035,13 @@ begin
   Result:=TFPDependency(Items[Index]);
 end;
 
-procedure TFPDependencies.SetDependency(Index : Integer;
-  const AValue: TFPDependency);
+
+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;
@@ -1063,6 +1050,7 @@ begin
     Result.MinVersion.AsString:=AMinVersion;
 end;
 
+
 { TFPMirror }
 
 constructor TFPMirror.Create(ACollection: TCollection);

+ 168 - 175
utils/fppkg/fpxmlrep.pp

@@ -53,6 +53,8 @@ Type
   Public
     // Saving
     Function VersionToXML(V : TFPVersion; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
+    function OSesToXML(OSes:TOSes; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement; virtual;
+    function CPUsToXML(CPUs:TCPUs; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement; virtual;
     Function DependencyToXML(D : TFPDependency; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
     Function DependenciesToXML(DS : TFPDependencies; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
     Function PackageToXML(P : TFPPackage; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
@@ -134,16 +136,14 @@ Const
   SAttrName         = 'name';
   SAttrPackageName  = 'packagename';
   SAttrMinVersion   = 'minversion';
-  SAttrRelease      = 'release';
   SAttrMajor        = 'major';
   SAttrMinor        = 'minor';
-  SAttrSuffix       = 'suffix';
+  SAttrMicro        = 'micro';
+  SAttrBuild        = 'build';
 
 ResourceString
   SErrInvalidXMLDocument = 'Wrong root tag in XML document. Expected "%s", got "%s".';
-  SErrUnknownPackageNode = 'Unknown XML tag ("%s") encountered while reading package "%s".';
-  SErrInvalidDependencyXML = 'Invalid XMl encountered when reading dependency.';
-  SErrUnknownMirrorNode = 'Unknown XML tag ("%s") encountered while reading mirror "%s".';
+  SErrUnknownNode = 'Unknown XML tag ("%s") encountered while reading %s "%s".';
 
 
 {****************************************************************************
@@ -151,7 +151,6 @@ ResourceString
 ****************************************************************************}
 
 function TFPXMLHandler.AddTextNode(Const NodeName,NodeContent : String; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement;
-
 begin
   Result:=XML.CreateElement(NodeName);
   Try
@@ -165,8 +164,8 @@ begin
   end;
 end;
 
-function TFPXMLHandler.GetNextElement(Start: TDomNode): TDomElement;
 
+function TFPXMLHandler.GetNextElement(Start: TDomNode): TDomElement;
 begin
   Result:=Nil;
   While (Start<>Nil) and (Start.NodeType<>ELEMENT_NODE) do
@@ -175,25 +174,25 @@ begin
     Result:=Start as TDomElement;
 end;
 
+
 function TFPXMLHandler.FindNextElement(Start: TDomNode; NodeName: String): TDomElement;
 begin
   Result:=GetNextElement(Start);
   While (Result<>Nil) and (Result.NodeName<>NodeName) do
-    Result:=GetNextElement(Result);
+    Result:=GetNextElement(Result.NextSibling);
 end;
 
-procedure TFPXMLHandler.CheckNodeType(E : TDomElement; NodeName : String);
 
+procedure TFPXMLHandler.CheckNodeType(E : TDomElement; NodeName : String);
 begin
   If (E.NodeName<>NodeName) then
     Raise EXMLPackage.CreateFmt(SErrInvalidXMLDocument,[NodeName,E.NodeName]);
 end;
 
-Function TFPXMLHandler.NodeText(E : TDomElement) : String;
 
+Function TFPXMLHandler.NodeText(E : TDomElement) : String;
 Var
   N : TDomNode;
-
 begin
   N:=E.FirstChild;
   While (N<>Nil) and (N.NodeType<>TEXT_NODE) do
@@ -207,18 +206,17 @@ end;
                         TFPXMLRepositoryHandler
 ****************************************************************************}
 
-function TFPXMLRepositoryHandler.VersionToXML(V : TFPVersion;
-  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+function TFPXMLRepositoryHandler.VersionToXML(V : TFPVersion; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 begin
   Result:=XML.CreateElement(SNodeVersion);
   try
     If Not Assigned(Parent) then
       Parent:=XML;
     Parent.AppendChild(Result);
-    Result[SAttrRelease]:=IntToStr(V.Release);
     Result[SAttrMajor]:=IntToStr(V.Major);
     Result[SAttrMinor]:=IntToStr(V.Minor);
-    Result[SAttrSuffix]:=V.Suffix;
+    Result[SAttrMicro]:=IntToStr(V.Micro);
+    Result[SAttrBuild]:=IntToStr(V.Build);
   except
     Parent.RemoveChild(Result);
     Result.Free;
@@ -226,12 +224,10 @@ begin
   end;
 end;
 
-function TFPXMLRepositoryHandler.DependencyToXML(D: TFPDependency;
-  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 
+function TFPXMLRepositoryHandler.DependencyToXML(D: TFPDependency; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 Var
   E : TDOMElement;
-
 begin
   Result:=XML.CreateElement(SNodeDependency);
   Try
@@ -240,9 +236,13 @@ begin
     Parent.AppendChild(Result);
     E:=XML.CreateElement(SNodePackage);
     E[SAttrPackageName]:=D.PackageName;
-    If Not D.MinVersion.Empty then
-      E[SAttrMinVersion]:=D.MinVersion.AsString;
     Result.AppendChild(E);
+    if not D.MinVersion.Empty then
+      VersionToXML(D.MinVersion,XML,Result);
+    if D.OSes<>AllOSes then
+      OSesToXML(D.OSes,XML,Result);
+    if D.CPUs<>AllCPUs then
+      CPUsToXML(D.CPUs,XML,Result);
   Except
     Parent.RemoveChild(Result);
     Result.Free;
@@ -250,12 +250,10 @@ begin
   end;
 end;
 
-function TFPXMLRepositoryHandler.DependenciesToXML(DS: TFPDependencies;
-  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 
+function TFPXMLRepositoryHandler.DependenciesToXML(DS: TFPDependencies; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 Var
   I : Integer;
-
 begin
   If (DS.Count>0) then
     begin
@@ -274,14 +272,42 @@ begin
     end;
 end;
 
-function TFPXMLRepositoryHandler.PackageToXML(P: TFPPackage;
-  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 
+function TFPXMLRepositoryHandler.OSesToXML(OSes:TOSes; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 Var
-  E,ES : TDomElement;
+  ES : TDomElement;
   O : TOS;
+begin
+  Result:=XML.CreateElement(SNodeOSes);
+  Parent.AppendChild(Result);
+  For O:=Low(TOS) to High(TOS) do
+    If (O in OSes) then
+      begin
+        ES:=XML.CreateElement(SNodeOS);
+        ES[SAttrName]:=GetEnumName(TypeInfo(TOS),Ord(O));
+        Result.AppendChild(ES);
+      end;
+end;
+
+
+function TFPXMLRepositoryHandler.CPUsToXML(CPUs:TCPUs; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+Var
+  ES : TDomElement;
   C : TCPU;
+begin
+  Result:=XML.CreateElement(SNodeCPUs);
+  Parent.AppendChild(Result);
+  For C:=Low(TCPU) to High(TCPU) do
+    If (C in CPUs) then
+      begin
+        ES:=XML.CreateElement(SNodeCPU);
+        ES[SAttrName]:=GetEnumName(TypeInfo(TCPU),Ord(C));
+        Result.AppendChild(ES);
+      end;
+end;
+
 
+function TFPXMLRepositoryHandler.PackageToXML(P: TFPPackage; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 begin
   Result:=XML.CreateElement(SNodePackage);
   Try
@@ -297,27 +323,11 @@ begin
     AddTextNode(SNodeEmail,P.Email,XML,Result);
     AddTextNode(SNodeDescription,P.Description,XML,Result);
     AddTextNode(SNodeLicense,P.License,XML,Result);
-    // OSes
-    E:=XML.CreateElement(SNodeOSes);
-    Result.AppendChild(E);
-    For O:=Low(TOS) to High(TOS) do
-      If (O in P.OSes) then
-        begin
-        ES:=XML.CreateElement(SNodeOS);
-        ES[SAttrName]:=GetEnumName(TypeInfo(TOS),Ord(O));
-        E.AppendChild(ES);
-        end;
-    // CPUs
-    E:=XML.CreateElement(SNodeCPUs);
-    Result.AppendChild(E);
-    For C:=Low(TCPU) to High(TCPU) do
-      If (C in P.CPUS) then
-        begin
-        ES:=XML.CreateElement(SNodeCPU);
-        ES[SAttrName]:=GetEnumName(TypeInfo(TCPU),Ord(C));
-        E.AppendChild(ES);
-        end;
-    If P.HasDependencies then
+    if P.OSes<>AllOSes then
+      OSesToXML(P.OSes,XML,Result);
+    if P.CPUs<>AllCPUs then
+      CPUsToXML(P.CPUs,XML,Result);
+    If P.Dependencies.Count>0 then
       DependenciesToXML(P.Dependencies,XML,Result);
   Except
     Parent.RemoveChild(Result);
@@ -326,12 +336,10 @@ begin
   end;
 end;
 
-function TFPXMLRepositoryHandler.PackagesToXML(PS: TFPPackages;
-  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 
+function TFPXMLRepositoryHandler.PackagesToXML(PS: TFPPackages; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 Var
   I : Integer;
-
 begin
   Result:=XML.CreateElement(SNodePackages);
   Try
@@ -348,13 +356,10 @@ begin
 end;
 
 
-function TFPXMLRepositoryHandler.RepositoryToXML(R: TFPRepository;
-  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
-
+function TFPXMLRepositoryHandler.RepositoryToXML(R: TFPRepository; XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
 Var
   I : Integer;
   P : TDomElement;
-
 begin
   Result:=XML.CreateElement(sNodeRepository);
   Try
@@ -381,11 +386,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(D: TFPDependency; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(D: TFPDependency; Stream: TStream);
 Var
   X : TXMLDocument;
-
 begin
   X:=TXMLDocument.Create;
   Try
@@ -396,11 +400,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(DS: TFPDependencies; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(DS: TFPDependencies; Stream: TStream);
 Var
   D : TXMLDocument;
-
 begin
   D:=TXMLDocument.Create;
   Try
@@ -411,11 +414,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(P: TFPPackage; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(P: TFPPackage; Stream: TStream);
 Var
   D : TXMLDocument;
-
 begin
   D:=TXMLDocument.Create;
   Try
@@ -426,11 +428,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(PS: TFPPackages; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(PS: TFPPackages; Stream: TStream);
 Var
   D : TXMLDocument;
-
 begin
   D:=TXMLDocument.Create;
   Try
@@ -441,11 +442,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(R: TFPRepository; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(R: TFPRepository; Stream: TStream);
 Var
   D : TXMLDocument;
-
 begin
   D:=TXMLDocument.Create;
   Try
@@ -456,11 +456,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(D: TFPDependency; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(D: TFPDependency; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmCreate);
   try
@@ -470,11 +469,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(DS: TFPDependencies; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(DS: TFPDependencies; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmCreate);
   try
@@ -484,11 +482,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(P: TFPPackage; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(P: TFPPackage; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmCreate);
   try
@@ -498,11 +495,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(PS: TFPPackages; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(PS: TFPPackages; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmCreate);
   try
@@ -512,11 +508,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.SaveToXml(R: TFPRepository; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.SaveToXml(R: TFPRepository; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmCreate);
   try
@@ -526,77 +521,90 @@ begin
   end;
 end;
 
+
 procedure TFPXMLRepositoryHandler.XMLToVersion(E: TDomElement; V: TFPVersion);
 begin
   CheckNodeType(E,SNodeVersion);
   DoXMLToVersion(E,V);
 end;
 
+
 procedure TFPXMLRepositoryHandler.DoXMLToVersion(E: TDomElement; V: TFPVersion);
 begin
-  V.Release:=Abs(StrToIntDef(E[SAttrRelease],0));
   V.Major:=Abs(StrToIntDef(E[SAttrMajor],0));
   V.Minor:=Abs(StrToIntDef(E[SAttrMinor],0));
-  V.Suffix:=E[SAttrSuffix];
+  V.Micro:=Abs(StrToIntDef(E[SAttrMicro],0));
+  V.Build:=Abs(StrToIntDef(E[SAttrBuild],0));
 end;
 
+
 procedure TFPXMLRepositoryHandler.XMLToDependency(E: TDomElement; D: TFPDependency);
 begin
   CheckNodeType(E,SNodeDependency);
   DoXMLToDependency(E,D);
 end;
 
+
 procedure TFPXMLRepositoryHandler.DoXMLToDependency(E: TDomElement; D: TFPDependency);
+var
+  N : TDomElement;
 begin
-  E:=FindNextElement(E.FirstChild,SNodePackage);
-  If (E=Nil) then
-    Raise EXMLpackage.Create(SErrInvalidDependencyXML);
-  D.PackageName:=E[SAttrPackageName];
-  D.MinVersion.AsString:=E[SAttrMinVersion];
+  N:=GetNextElement(E.FirstChild);
+  While (N<>Nil) do
+    begin
+      if (N.NodeName=sNodePackage) then
+        D.PackageName:=N[SAttrPackageName]
+      else if (N.NodeName=sNodeVersion) then
+        DoXMlToVersion(N,D.MinVersion)
+      else if (N.NodeName=sNodeOSes) then
+        D.OSes:=DoXMLToOSes(N)
+      else if (N.NodeName=sNodeCPUS) then
+        D.CPUs:=DoXMLToCPUs(N)
+      else if Not IgnoreUnknownNodes then
+        Raise EXMLPackage.CreateFmt(SErrUnknownNode,[N.NodeName,sNodeDependency,'']);
+      N:=GetNextElement(N.NextSibling);
+    end;
 end;
 
-procedure TFPXMLRepositoryHandler.XMLToDependencies(E: TDomElement; DS: TFPDependencies);
 
+procedure TFPXMLRepositoryHandler.XMLToDependencies(E: TDomElement; DS: TFPDependencies);
 begin
   CheckNodeType(E,SNodeDependencies);
   DoXMLToDependencies(E,DS)
 end;
 
-procedure TFPXMLRepositoryHandler.DoXMLToDependencies(E: TDomElement;
-  DS: TFPDependencies);
 
+procedure TFPXMLRepositoryHandler.DoXMLToDependencies(E: TDomElement; DS: TFPDependencies);
 Var
   DN : TDomElement;
   D : TFPDependency;
-
 begin
   DN:=FindNextElement(E.FirstChild,SNodeDependency);
   While (DN<>Nil) do
     begin
-    D:=DS.AddDependency('','');
-    Try
-      DoXMLToDependency(DN,D);
-    except
-      D.Free;
-      Raise;
-    end;
-    DN:=FindNextElement(DN.NextSibling,SNodeDependency);
+      D:=DS.AddDependency('','');
+      Try
+        DoXMLToDependency(DN,D);
+      except
+        D.Free;
+        Raise;
+      end;
+      DN:=FindNextElement(DN.NextSibling,SNodeDependency);
     end;
 end;
 
-procedure TFPXMLRepositoryHandler.XMLToPackage(E: TDomElement; P: TFPPackage);
 
+procedure TFPXMLRepositoryHandler.XMLToPackage(E: TDomElement; P: TFPPackage);
 begin
   CheckNodeType(E,sNodePackage);
   DoXMLToPackage(E,P);
 end;
 
-Function TFPXMLRepositoryHandler.DoXMLToOSes(N : TDomElement) : TOSes;
 
+Function TFPXMLRepositoryHandler.DoXMLToOSes(N : TDomElement) : TOSes;
 Var
   E : TDomElement;
   J : Integer;
-
 begin
   Result:=[];
   E:=FindNextElement(N.FirstChild,SNodeOS);
@@ -609,125 +617,120 @@ begin
     end;
 end;
 
-Function TFPXMLRepositoryHandler.DoXMLToCPUs(N : TDomElement) : TCPUS;
 
+Function TFPXMLRepositoryHandler.DoXMLToCPUs(N : TDomElement) : TCPUS;
 Var
   E : TDomElement;
   J : Integer;
-
 begin
   Result:=[];
   E:=FindNextElement(N.FirstChild,SNodeCPU);
   While (E<>Nil) do
     begin
-    J:=GetEnumValue(TypeInfo(TCPU),E[SAttrName]);
-    If (J<>-1) then
-      Include(Result,TCPU(J));
-    E:=FindNextElement(E.NextSibling,SNodeCPU);
+      J:=GetEnumValue(TypeInfo(TCPU),E[SAttrName]);
+      If (J<>-1) then
+        Include(Result,TCPU(J));
+      E:=FindNextElement(E.NextSibling,SNodeCPU);
     end;
 end;
 
-procedure TFPXMLRepositoryHandler.DoXMLToPackage(E: TDomElement; P: TFPPackage);
 
+procedure TFPXMLRepositoryHandler.DoXMLToPackage(E: TDomElement; P: TFPPackage);
 Var
   N : TDomElement;
-
 begin
   P.Name:=E[sAttrName];
   N:=GetNextElement(E.FirstChild);
   While (N<>Nil) do
     begin
-    if (N.NodeName=sNodeAuthor) then
-      P.Author:=NodeText(N)
-    else if (N.NodeName=sNodeExternalURL) then
-      P.ExternalURL:=NodeText(N)
-    else if (N.NodeName=sNodeFileName) then
-      P.FileName:=NodeText(N)
-    else if (N.NodeName=sNodeEmail) then
-      P.Email:=NodeText(N)
-    else if (N.NodeName=sNodeDescription) then
-      P.Description:=NodeText(N)
-    else if (N.NodeName=sNodeLicense) then
-      P.License:=NodeText(N)
-    else if (N.NodeName=sNodeVersion) then
-      DoXMlToVersion(N,P.Version)
-    else if (N.NodeName=sNodeOSes) then
-      P.OSes:=DoXMLToOSes(N)
-    else if (N.NodeName=sNodeCPUS) then
-      P.CPUs:=DoXMLToCPUs(N)
-    else if (N.NodeName=sNodeDependencies) then
-      DoXMlToDependencies(N,P.Dependencies)
-    else if Not IgnoreUnknownNodes then
-      Raise EXMLPackage.CreateFmt(SErrUnknownPackageNode,[N.NodeName,P.Name]);
-    N:=GetNextElement(N.NextSibling);
+      if (N.NodeName=sNodeAuthor) then
+        P.Author:=NodeText(N)
+      else if (N.NodeName=sNodeExternalURL) then
+        P.ExternalURL:=NodeText(N)
+      else if (N.NodeName=sNodeFileName) then
+        P.FileName:=NodeText(N)
+      else if (N.NodeName=sNodeEmail) then
+        P.Email:=NodeText(N)
+      else if (N.NodeName=sNodeDescription) then
+        P.Description:=NodeText(N)
+      else if (N.NodeName=sNodeLicense) then
+        P.License:=NodeText(N)
+      else if (N.NodeName=sNodeVersion) then
+        DoXMlToVersion(N,P.Version)
+      else if (N.NodeName=sNodeOSes) then
+        P.OSes:=DoXMLToOSes(N)
+      else if (N.NodeName=sNodeCPUS) then
+        P.CPUs:=DoXMLToCPUs(N)
+      else if (N.NodeName=sNodeDependencies) then
+        DoXMlToDependencies(N,P.Dependencies)
+      else if Not IgnoreUnknownNodes then
+        Raise EXMLPackage.CreateFmt(SErrUnknownNode,[N.NodeName,sNodePackage,P.Name]);
+      N:=GetNextElement(N.NextSibling);
     end;
 end;
 
-procedure TFPXMLRepositoryHandler.XMLToPackages(E: TDomElement; PS: TFPPackages);
 
+procedure TFPXMLRepositoryHandler.XMLToPackages(E: TDomElement; PS: TFPPackages);
 begin
   CheckNodeType(E,SNodePackages);
   DoXMLToPackages(E,PS);
 end;
 
-procedure TFPXMLRepositoryHandler.DoXMLToPackages(E: TDomElement; PS: TFPPackages);
 
+procedure TFPXMLRepositoryHandler.DoXMLToPackages(E: TDomElement; PS: TFPPackages);
 Var
   PN : TDomElement;
   P : TFPPackage;
-
 begin
   PN:=FindNextElement(E.FirstChild,SNodePackage);
   While (PN<>Nil) do
     begin
-    P:=PS.AddPackage('');
-    try
-      DoXMLToPackage(PN,P);
-    except
-      P.Free;
-      Raise;
-    end;
-    PN:=FindNextElement(PN.NextSibling,SNodePackage);
+      P:=PS.AddPackage('');
+      try
+        DoXMLToPackage(PN,P);
+      except
+        P.Free;
+        Raise;
+      end;
+      PN:=FindNextElement(PN.NextSibling,SNodePackage);
     end;
 end;
 
-procedure TFPXMLRepositoryHandler.XMLToRepository(E: TDomElement; R: TFPRepository);
 
+procedure TFPXMLRepositoryHandler.XMLToRepository(E: TDomElement; R: TFPRepository);
 begin
   CheckNodeType(E,SNodeRepository);
   DoXMLToRepository(E,R);
 end;
 
-procedure TFPXMLRepositoryHandler.DoXMLToRepository(E: TDomElement; R: TFPRepository);
 
+procedure TFPXMLRepositoryHandler.DoXMLToRepository(E: TDomElement; R: TFPRepository);
 Var
   PSN,PN : TDomElement;
   P : TFPPackage;
-
 begin
   PSN:=FindNextElement(E.FirstChild,SNodePackages);
   If (PSN<>Nil) then
     begin
-    PN:=FindNextElement(PSN.FirstChild,SNodePackage);
-    While (PN<>Nil) do
-      begin
-      P:=R.AddPackage('');
-      try
-        DoXMLToPackage(PN,P);
-      except
-        P.Free;
-        Raise;
-      end;
-      PN:=FindNextElement(PN.NextSibling,SNodePackage);
-      end;
+      PN:=FindNextElement(PSN.FirstChild,SNodePackage);
+      While (PN<>Nil) do
+        begin
+          P:=R.AddPackage('');
+          try
+            DoXMLToPackage(PN,P);
+          except
+            P.Free;
+            Raise;
+          end;
+          PN:=FindNextElement(PN.NextSibling,SNodePackage);
+        end;
     end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(D: TFPDependency; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(D: TFPDependency; Stream: TStream);
 Var
   XML : TXMLDocument;
-
 begin
   XML:=TXMLDocument.Create;
   try
@@ -738,12 +741,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(DS: TFPDependencies;
-  Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(DS: TFPDependencies; Stream: TStream);
 Var
   XML : TXMLDocument;
-
 begin
   XML:=TXMLDocument.Create;
   try
@@ -754,11 +755,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(P: TFPPackage; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(P: TFPPackage; Stream: TStream);
 Var
   XML : TXMLDocument;
-
 begin
   XML:=TXMLDocument.Create;
   try
@@ -769,11 +769,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(PS: TFPPackages; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(PS: TFPPackages; Stream: TStream);
 Var
   XML : TXMLDocument;
-
 begin
   XML:=TXMLDocument.Create;
   try
@@ -784,11 +783,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(R: TFPRepository; Stream: TStream);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(R: TFPRepository; Stream: TStream);
 Var
   XML : TXMLDocument;
-
 begin
   XML:=TXMLDocument.Create;
   try
@@ -799,11 +797,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(D: TFPDependency; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(D: TFPDependency; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmOpenRead);
   try
@@ -813,11 +810,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(DS: TFPDependencies; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(DS: TFPDependencies; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmOpenRead);
   try
@@ -827,11 +823,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(P: TFPPackage; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(P: TFPPackage; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmOpenRead);
   try
@@ -841,11 +836,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(PS: TFPPackages; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(PS: TFPPackages; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmOpenRead);
   try
@@ -855,11 +849,10 @@ begin
   end;
 end;
 
-procedure TFPXMLRepositoryHandler.LoadFromXml(R: TFPRepository; const FileName: String);
 
+procedure TFPXMLRepositoryHandler.LoadFromXml(R: TFPRepository; const FileName: String);
 Var
   F : TFileStream;
-
 begin
   F:=TFileStream.Create(FileName,fmOpenRead);
   try
@@ -889,7 +882,7 @@ begin
       else if (N.NodeName=sNodeWeight) then
         P.Weight:=StrToInt(NodeText(N))
       else if Not IgnoreUnknownNodes then
-        Raise EXMLPackage.CreateFmt(SErrUnknownMirrorNode,[N.NodeName,P.Name]);
+        Raise EXMLPackage.CreateFmt(SErrUnknownNode,[N.NodeName,sNodeMirror,P.Name]);
       N:=GetNextElement(N.NextSibling);
     end;
 end;

+ 88 - 31
utils/fppkg/pkgcommands.pp

@@ -33,16 +33,16 @@ type
     Function Execute(const Args:TActionArgs):boolean;override;
   end;
 
-  { TCommandAllAvail }
+  { TCommandShowAll }
 
-  TCommandAllAvail = Class(TPackagehandler)
+  TCommandShowAll = Class(TPackagehandler)
   Public
     Function Execute(const Args:TActionArgs):boolean;override;
   end;
 
-  { TCommandAvail }
+  { TCommandShowAvail }
 
-  TCommandAvail = Class(TPackagehandler)
+  TCommandShowAvail = Class(TPackagehandler)
   Public
     Function Execute(const Args:TActionArgs):boolean;override;
   end;
@@ -89,6 +89,13 @@ type
     Function Execute(const Args:TActionArgs):boolean;override;
   end;
 
+  { TCommandClean }
+
+  TCommandClean = Class(TPackagehandler)
+  Public
+    Function Execute(const Args:TActionArgs):boolean;override;
+  end;
+
   { TCommandArchive }
 
   TCommandArchive = Class(TPackagehandler)
@@ -129,19 +136,20 @@ begin
   DownloadFile(PackagesURL,GlobalOptions.LocalPackagesFile);
   // Read the repository again
   LoadLocalRepository;
-  LoadLocalStatus;
+  // no need to log errors again
+  FindInstalledPackages(CompilerOptions,False);
   Result:=true;
 end;
 
 
-function TCommandAllAvail.Execute(const Args:TActionArgs):boolean;
+function TCommandShowAll.Execute(const Args:TActionArgs):boolean;
 begin
   ListLocalRepository(true);
   Result:=true;
 end;
 
 
-function TCommandAvail.Execute(const Args:TActionArgs):boolean;
+function TCommandShowAvail.Execute(const Args:TActionArgs):boolean;
 begin
   ListLocalRepository(false);
   Result:=true;
@@ -200,8 +208,18 @@ function TCommandCompile.Execute(const Args:TActionArgs):boolean;
 begin
   if assigned(CurrentPackage) then
     begin
-      ExecuteAction(CurrentPackage,'installdependencies',Args);
-      ExecuteAction(CurrentPackage,'unzip',Args);
+      // For local files we need the information inside the zip to get the
+      // dependencies
+      if CurrentPackage.IsLocalPackage then
+        begin
+          ExecuteAction(CurrentPackage,'unzip',Args);
+          ExecuteAction(CurrentPackage,'installdependencies',Args);
+        end
+      else
+        begin
+          ExecuteAction(CurrentPackage,'installdependencies',Args);
+          ExecuteAction(CurrentPackage,'unzip',Args);
+        end;
     end;
   ExecuteAction(CurrentPackage,'fpmakecompile',Args);
   Result:=true;
@@ -212,8 +230,18 @@ function TCommandBuild.Execute(const Args:TActionArgs):boolean;
 begin
   if assigned(CurrentPackage) then
     begin
-      ExecuteAction(CurrentPackage,'installdependencies',Args);
-      ExecuteAction(CurrentPackage,'unzip',Args);
+      // For local files we need the information inside the zip to get the
+      // dependencies
+      if CurrentPackage.IsLocalPackage then
+        begin
+          ExecuteAction(CurrentPackage,'unzip',Args);
+          ExecuteAction(CurrentPackage,'installdependencies',Args);
+        end
+      else
+        begin
+          ExecuteAction(CurrentPackage,'installdependencies',Args);
+          ExecuteAction(CurrentPackage,'unzip',Args);
+        end;
     end;
   ExecuteAction(CurrentPackage,'fpmakebuild',Args);
   Result:=true;
@@ -227,10 +255,14 @@ begin
   ExecuteAction(CurrentPackage,'fpmakeinstall',Args);
   // Update local status file
   if assigned(CurrentPackage) then
-    begin
-      CurrentPackage.InstalledVersion.Assign(CurrentPackage.Version);
-      SaveLocalStatus;
-    end;
+    CurrentPackage.InstalledVersion.Assign(CurrentPackage.Version);
+  Result:=true;
+end;
+
+
+function TCommandClean.Execute(const Args:TActionArgs):boolean;
+begin
+  ExecuteAction(CurrentPackage,'fpmakeclean',Args);
   Result:=true;
 end;
 
@@ -245,40 +277,64 @@ end;
 function TCommandInstallDependencies.Execute(const Args:TActionArgs):boolean;
 var
   i : Integer;
+  MissingDependency,
   D : TFPDependency;
+  P,
   DepPackage : TFPPackage;
   L : TStringList;
   status : string;
 begin
   if not assigned(CurrentPackage) then
     Error(SErrNoPackageSpecified);
-  // List dependencies
+  // Load dependencies for local packages
+  if CurrentPackage.IsLocalPackage then
+    begin
+      ExecuteAction(CurrentPackage,'fpmakemanifest',Args);
+      P:=LoadPackageManifest(ManifestFileName);
+      // Update CurrentPackage
+      CurrentPackage.Assign(P);
+      CurrentPackage.IsLocalPackage:=true;
+    end;
+  // Find and List dependencies
+  MissingDependency:=nil;
   L:=TStringList.Create;
   for i:=0 to CurrentPackage.Dependencies.Count-1 do
     begin
       D:=CurrentPackage.Dependencies[i];
-      DepPackage:=CurrentRepository.PackageByName(D.PackageName);
-      // Need installation?
-      if (DepPackage.InstalledVersion.Empty) or
-         (DepPackage.InstalledVersion.CompareVersion(D.MinVersion)<0) then
+      if (CompilerOptions.CompilerOS in D.OSes) and
+         (CompilerOptions.CompilerCPU in D.CPUs) then
         begin
-          if DepPackage.Version.CompareVersion(D.MinVersion)<0 then
-            status:='Not Available!'
+          DepPackage:=CurrentRepository.PackageByName(D.PackageName);
+          // Need installation?
+          if (DepPackage.InstalledVersion.Empty) or
+             (DepPackage.InstalledVersion.CompareVersion(D.MinVersion)<0) then
+            begin
+              if DepPackage.Version.CompareVersion(D.MinVersion)<0 then
+                begin
+                  status:='Not Available!';
+                  MissingDependency:=D;
+                end
+              else
+                begin
+                  status:='Updating';
+                  L.Add(DepPackage.Name);
+                end;
+            end
           else
-            status:='Updating';
-          L.Add(DepPackage.Name);
+            status:='OK';
+          Log(vlInfo,SLogPackageDependency,
+              [D.PackageName,D.MinVersion.AsString,DepPackage.InstalledVersion.AsString,DepPackage.Version.AsString,status]);
         end
       else
-        status:='OK';
-      Log(vlDebug,SDbgPackageDependency,
-          [D.PackageName,D.MinVersion.AsString,DepPackage.InstalledVersion.AsString,DepPackage.Version.AsString,status]);
+        Log(vlDebug,SDbgPackageDependencyOtherTarget,[D.PackageName,MakeTargetString(CompilerOptions.CompilerCPU,CompilerOptions.CompilerOS)]);
     end;
+  // Give error on first missing dependency
+  if assigned(MissingDependency) then
+    Error(SErrNoPackageAvailable,[MissingDependency.PackageName,MissingDependency.MinVersion.AsString]);
   // Install needed updates
   for i:=0 to L.Count-1 do
     begin
       DepPackage:=CurrentRepository.PackageByName(L[i]);
-      if DepPackage.Version.CompareVersion(D.MinVersion)<0 then
-        Error(SErrNoPackageAvailable,[D.PackageName,D.MinVersion.AsString]);
       ExecuteAction(DepPackage,'install');
     end;
   FreeAndNil(L);
@@ -288,14 +344,15 @@ end;
 
 initialization
   RegisterPkgHandler('update',TCommandUpdate);
-  RegisterPkgHandler('allavail',TCommandAllAvail);
-  RegisterPkgHandler('avail',TCommandAvail);
+  RegisterPkgHandler('showall',TCommandShowAll);
+  RegisterPkgHandler('showavail',TCommandShowAvail);
   RegisterPkgHandler('scan',TCommandScanPackages);
   RegisterPkgHandler('download',TCommandDownload);
   RegisterPkgHandler('unzip',TCommandUnzip);
   RegisterPkgHandler('compile',TCommandCompile);
   RegisterPkgHandler('build',TCommandBuild);
   RegisterPkgHandler('install',TCommandInstall);
+  RegisterPkgHandler('clean',TCommandClean);
   RegisterPkgHandler('archive',TCommandArchive);
   RegisterPkgHandler('installdependencies',TCommandInstallDependencies);
 end.

+ 22 - 0
utils/fppkg/pkgfpmake.pp

@@ -58,6 +58,13 @@ type
   end;
 
 
+  { TFPMakeRunnerClean }
+
+  TFPMakeRunnerClean = Class(TFPMakeRunner)
+  Public
+    Function Execute(const Args:TActionArgs):boolean;override;
+  end;
+
   { TFPMakeRunnerManifest }
 
   TFPMakeRunnerManifest = Class(TFPMakeRunner)
@@ -248,6 +255,14 @@ Var
 
 begin
   OOptions:='';
+  // Does the current package support this CPU-OS?
+  if assigned(CurrentPackage) then
+    begin
+      if not(CompilerOptions.CompilerOS in CurrentPackage.OSes) or
+         not(CompilerOptions.CompilerCPU in CurrentPackage.CPUs) then
+        Error(SErrPackageDoesNotSupportTarget,[CurrentPackage.Name,
+            MakeTargetString(CompilerOptions.CompilerCPU,CompilerOptions.CompilerOS)]);
+    end;
   { Maybe compile fpmake executable? }
   ExecuteAction(CurrentPackage,'compilefpmake');
   { Create options }
@@ -291,6 +306,12 @@ begin
 end;
 
 
+function TFPMakeRunnerClean.Execute(const Args:TActionArgs):boolean;
+begin
+  result:=(RunFPMake('clean')=0);
+end;
+
+
 function TFPMakeRunnerManifest.Execute(const Args:TActionArgs):boolean;
 begin
   result:=(RunFPMake('manifest')=0);
@@ -310,6 +331,7 @@ initialization
   RegisterPkgHandler('fpmakecompile',TFPMakeRunnerCompile);
   RegisterPkgHandler('fpmakebuild',TFPMakeRunnerBuild);
   RegisterPkgHandler('fpmakeinstall',TFPMakeRunnerInstall);
+  RegisterPkgHandler('fpmakeclean',TFPMakeRunnerClean);
   RegisterPkgHandler('fpmakemanifest',TFPMakeRunnerManifest);
   RegisterPkgHandler('fpmakearchive',TFPMakeRunnerArchive);
 end.

+ 4 - 4
utils/fppkg/pkgglobals.pp

@@ -32,16 +32,16 @@ Const
   FPMKUnitDepCount=4;
   FPMKUnitDeps : array[1..4] of TFPMKUnitDep = (
     (package: 'hash';
-     reqver : '2.0.0';
+     reqver : '2.2.1';
      undef  : 'NO_UNIT_ZIPPER'),
     (package: 'paszlib';
-     reqver : '2.2.0';
+     reqver : '2.2.1';
      undef  : 'NO_UNIT_ZIPPER'),
     (package: 'fcl-process';
-     reqver : '2.0.0';
+     reqver : '2.2.1';
      undef  : 'NO_UNIT_PROCESS'),
     (package: 'fpmkunit';
-     reqver : '2.2.0';
+     reqver : '2.2.1';
      undef  : '')
   );
 

+ 5 - 3
utils/fppkg/pkgmessages.pp

@@ -42,7 +42,7 @@ Resourcestring
   SErrConvertFPMakeExists    = 'Found existing fpmake.pp, aborting conversion';
   SErrFailedToSelectMirror   = 'Could not select a mirror, run update and retry';
   SErrUnsupportedConfigVersion = 'Configuration file "%s" is too old, delete file manual and retry';
-
+  SErrPackageDoesNotSupportTarget = 'Package %s does not support %s';
   SErrHTTPGetFailed          = 'HTTP Download failed.';
   SErrLoginFailed            = 'FTP LOGIN command failed.';
   SErrCWDFailed              = 'FTP CWD "%s" command failed.';
@@ -66,19 +66,21 @@ Resourcestring
   SLogGeneratingCompilerConfig  = 'Generating default compiler configuration in "%s"';
   SLogLoadingPackagesFile    = 'Loading available packages from "%s"';
   SLogLoadingMirrorsFile     = 'Loading available mirrors from "%s"';
-  SLogLoadingStatusFile      = 'Loading local status from "%s"';
+  SLogFindInstalledPackages  = 'Finding installed packages in "%s"';
   SLogSavingStatusFile       = 'Saving local status to "%s"';
   SLogFPMKUnitDepVersion     = 'Checking for %s %s, installed %s, available %s';
   SLogFPMKUnitDepTooOld      = 'Minimum version of %s is not installed, using internal fpmkunit with limited functionality';
   SLogSelectedMirror         = 'Selected mirror "%s"';
   SLogUpgradingConfig        = 'Configuration file "%s" is updated with new configuration settings';
+  SLogPackageDependency      = 'Dependency on package %s %s, installed %s, available %s  (%s)';
 
   SDbgFound                  = 'Found';
   SDbgNotFound               = 'Not Found';
   SDbgDirectoryExists        = 'Directory "%s" %s';
   SDbgFileExists             = 'File "%s" %s';
   SDbgBackupFile             = 'Creating Backup File "%s"';
-  SDbgPackageDependency      = 'Dependency on package %s %s, installed %s, available %s  (%s)';
+  SDbgPackageMultipleLocations = 'Multiple installations found for package %s, using installation "%s"';
+  SDbgPackageDependencyOtherTarget  = 'Dependency on package %s is not for %s';
 
 implementation
 

+ 1 - 1
utils/fppkg/pkgmkconv.pp

@@ -502,7 +502,7 @@ begin
         Res:=R.IndexOfName(N)<>-1;
       GetOSCPU(V,OS,CPU);
       Pre[1]:=Upcase(Pre[1]);
-      Src.Add('    T:=P.Targets.Add'+Pre+'('''+Prefix+N+''');');
+      Src.Add('    T:=P.Targets.Add'+Pre+'('''+Prefix+N+'.pp'');');
       If (CPU<>'') then
         Src.Add('    T.CPU:=['+CPU+'];');
       If (OS<>'') then

+ 5 - 1
utils/fppkg/pkgoptions.pp

@@ -19,6 +19,7 @@ interface
 uses Classes, Sysutils, Inifiles, fprepos;
 
 Const
+  UnitConfigFileName   = 'fpunits.conf';
   ManifestFileName     = 'manifest.xml';
   MirrorsFileName      = 'mirrors.xml';
   PackagesFileName     = 'packages.xml';
@@ -44,7 +45,8 @@ Type
     FFPMakeCompilerConfig : String;
     // Parameter options
     FCompilerConfig : String;
-    FInstallGlobal  : Boolean;
+    FInstallGlobal,
+    FRecoveryMode   : Boolean;
     function  GetOptString(Index: integer): String;
     procedure SetOptString(Index: integer; const AValue: String);
   Public
@@ -71,6 +73,7 @@ Type
     // Parameters
     Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
     Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
+    Property RecoveryMode : Boolean Read FRecoveryMode Write FRecoveryMode;
   end;
 
 
@@ -257,6 +260,7 @@ begin
   // Parameter defaults
   FCompilerConfig:=FDefaultCompilerConfig;
   FInstallGlobal:=False;
+  FRecoveryMode:=False;
 end;
 
 

+ 174 - 35
utils/fppkg/pkgrepos.pp

@@ -5,16 +5,17 @@ unit pkgrepos;
 interface
 
 uses
-  Classes,SysUtils,
-  fprepos;
+  SysUtils,Classes,
+  fprepos,pkgoptions;
 
 function GetRemoteRepositoryURL(const AFileName:string):string;
 
 procedure LoadLocalMirrors;
 procedure LoadLocalRepository;
-procedure LoadLocalStatus;
-procedure SaveLocalStatus;
-procedure LoadFPMakeLocalStatus;
+function  LoadOrCreatePackage(const AName:string):TFPPackage;
+function  LoadPackageManifest(const AManifestFN:string):TFPPackage;
+procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
+procedure CheckFPMakeDependencies;
 procedure ListLocalRepository(all:boolean=false);
 
 procedure ListRemoteRepository;
@@ -32,7 +33,6 @@ uses
   zipper,
   fpxmlrep,
   pkgglobals,
-  pkgoptions,
   pkgmessages;
 
 {*****************************************************************************
@@ -134,6 +134,32 @@ end;
                            Local Repository
 *****************************************************************************}
 
+procedure ReadIniFile(Const AFileName: String;L:TStrings);
+Var
+  F : TFileStream;
+  Line : String;
+  I,P,PC : Integer;
+begin
+  F:=TFileStream.Create(AFileName,fmOpenRead);
+  Try
+    L.LoadFromStream(F);
+    // Fix lines.
+    For I:=L.Count-1 downto 0 do
+      begin
+        Line:=L[I];
+        P:=Pos('=',Line);
+        PC:=Pos(';',Line);  // Comment line.
+        If (P=0) or ((PC<>0) and (PC<P)) then
+          L.Delete(I)
+        else
+          L[i]:=Trim(System.Copy(Line,1,P-1)+'='+Trim(System.Copy(Line,P+1,Length(Line)-P)));
+      end;
+  Finally
+    F.Free;
+  end;
+end;
+
+
 procedure LoadLocalRepository;
 var
   S : String;
@@ -165,44 +191,162 @@ begin
 end;
 
 
-procedure LoadLocalStatus;
-var
-  S : String;
+function LoadOrCreatePackage(const AName:string):TFPPackage;
 begin
-  S:=GlobalOptions.LocalVersionsFile(GlobalOptions.CompilerConfig);
-  Log(vlDebug,SLogLoadingStatusFile,[S]);
-  CurrentRepository.ClearStatus;
-  if FileExists(S) then
-    CurrentRepository.LoadStatusFromFile(S);
+  result:=CurrentRepository.FindPackage(AName);
+  if not assigned(result) then
+    begin
+      result:=CurrentRepository.AddPackage(AName);
+      result.IsLocalPackage:=true;
+    end;
 end;
 
 
-procedure SaveLocalStatus;
+function LoadPackageManifest(const AManifestFN:string):TFPPackage;
 var
-  S : String;
+  X : TFPXMLRepositoryHandler;
+  i : integer;
+  DoAdd : Boolean;
+  NewP : TFPPackage;
+  NewPackages : TFPPackages;
 begin
-  S:=GlobalOptions.LocalVersionsFile(GlobalOptions.CompilerConfig);
-  Log(vlDebug,SLogSavingStatusFile,[S]);
-  CurrentRepository.SaveStatusToFile(S);
+  result:=nil;
+  NewPackages:=TFPPackages.Create(TFPPackage);
+  X:=TFPXMLRepositoryHandler.Create;
+  try
+    X.LoadFromXml(NewPackages,AManifestFN);
+    // Update or Add packages to repository
+    for i:=0 to NewPackages.Count-1 do
+      begin
+        NewP:=NewPackages[i];
+        DoAdd:=True;
+        result:=CurrentRepository.FindPackage(NewP.Name);
+        if assigned(result) then
+          begin
+            if NewP.Version.CompareVersion(result.Version)<0 then
+              begin
+                Writeln(Format('Ignoring package %s-%s (old %s)',[NewP.Name,NewP.Version.AsString,result.Version.AsString]));
+                DoAdd:=False;
+              end
+            else
+              Writeln(Format('Updating package %s-%s (old %s)',[NewP.Name,NewP.Version.AsString,result.Version.AsString]));
+          end
+        else
+          result:=CurrentRepository.PackageCollection.AddPackage(NewP.Name);
+        // Copy contents
+        if DoAdd then
+          result.Assign(NewP);
+      end;
+  finally
+    X.Free;
+    NewPackages.Free;
+  end;
 end;
 
 
-procedure LoadFPMakeLocalStatus;
+procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
+
+  procedure LoadUnitConfigFromFile(APackage:TFPPackage;const AFileName: String);
+  Var
+    L : TStrings;
+    V : String;
+  begin
+    L:=TStringList.Create;
+    Try
+      ReadIniFile(AFileName,L);
+{$warning TODO Maybe check also CPU-OS}
+{$warning TODO Add date to check recompile}
+      V:=L.Values['version'];
+      APackage.InstalledVersion.AsString:=V;
+      // Log packages found in multiple locations (local and global) ?
+      if not APackage.InstalledVersion.Empty then
+        begin
+          if showdups then
+            Log(vlDebug,SDbgPackageMultipleLocations,[APackage.Name,ExtractFilePath(AFileName)]);
+        end;
+    Finally
+      L.Free;
+    end;
+  end;
+
+  procedure LoadPackagefpcFromFile(APackage:TFPPackage;const AFileName: String);
+  Var
+    L : TStrings;
+    V : String;
+  begin
+    L:=TStringList.Create;
+    Try
+      ReadIniFile(AFileName,L);
+      V:=L.Values['version'];
+      APackage.InstalledVersion.AsString:=V;
+    Finally
+      L.Free;
+    end;
+  end;
+
+  function CheckUnitDir(const AUnitDir:string):boolean;
+  var
+    SR : TSearchRec;
+    P  : TFPPackage;
+    UD,UF : String;
+  begin
+    Result:=false;
+    if FindFirst(IncludeTrailingPathDelimiter(AUnitDir)+AllFiles,faDirectory,SR)=0 then
+      begin
+        Log(vlDebug,SLogFindInstalledPackages,[AUnitDir]);
+        repeat
+          if ((SR.Attr and faDirectory)=faDirectory) and (SR.Name<>'.') and (SR.Name<>'..') then
+            begin
+              UD:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(AUnitDir)+SR.Name);
+              // Try new fpunits.conf
+              UF:=UD+UnitConfigFileName;
+              if FileExistsLog(UF) then
+                begin
+                  P:=LoadOrCreatePackage(SR.Name);
+                  LoadUnitConfigFromFile(P,UF)
+                end
+              else
+                begin
+                  // Try Old style Package.fpc
+                  UF:=UD+'Package.fpc';
+                  if FileExistsLog(UF) then
+                    begin
+                      P:=LoadOrCreatePackage(SR.Name);
+                      LoadPackagefpcFromFile(P,UF);
+                    end;
+                end;
+            end;
+        until FindNext(SR)<>0;
+      end;
+  end;
+
+begin
+  CurrentRepository.ClearStatus;
+  // First scan the global directory
+  // The local directory will overwrite the versions
+  if ACompilerOptions.GlobalUnitDir<>'' then
+    CheckUnitDir(ACompilerOptions.GlobalUnitDir);
+  if ACompilerOptions.LocalUnitDir<>'' then
+    CheckUnitDir(ACompilerOptions.LocalUnitDir);
+end;
+
+
+procedure CheckFPMakeDependencies;
 var
   i : Integer;
-  S : String;
   P : TFPPackage;
   ReqVer : TFPVersion;
 begin
-  S:=GlobalOptions.LocalVersionsFile(GlobalOptions.FPMakeCompilerConfig);
-  Log(vlDebug,SLogLoadingStatusFile,[S]);
-  CurrentRepository.ClearStatus;
-  if FileExists(S) then
-    CurrentRepository.LoadStatusFromFile(S);
+  // Reset availability
+  for i:=1 to FPMKUnitDepCount do
+    FPMKUnitDepAvailable[i]:=false;
+  // Not version check needed in Recovery mode, we always need to use
+  // the internal bootstrap procedure
+  if GlobalOptions.RecoveryMode then
+    exit;
   // Check for fpmkunit dependencies
   for i:=1 to FPMKUnitDepCount do
     begin
-      FPMKUnitDepAvailable[i]:=false;
       P:=CurrentRepository.FindPackage(FPMKUnitDeps[i].package);
       if P<>nil then
         begin
@@ -256,8 +400,8 @@ end;
 
 
 procedure RebuildRemoteRepository;
+
 var
-  X : TFPXMLRepositoryHandler;
   i : integer;
   ArchiveSL : TStringList;
   ManifestSL : TStringList;
@@ -289,17 +433,12 @@ begin
         { Load manifest.xml }
         if FileExists(ManifestFileName) then
           begin
-            X:=TFPXMLRepositoryHandler.Create;
-            With X do
-              try
-                LoadFromXml(CurrentRepository.PackageCollection,ManifestFileName);
-              finally
-                Free;
-              end;
+            LoadPackageManifest(ManifestFileName);
             DeleteFile(ManifestFileName);
           end
         else
           Writeln('No manifest found in archive ',ArchiveSL[i]);
+
       end;
   finally
     ArchiveSL.Free;

Некоторые файлы не были показаны из-за большого количества измененных файлов