Browse Source

Merged revisions 10348,10352-10356,10358-10360,10364-10366,10369-10370,10373-10374,10376-10381,10387-10391,10393-10394,10398,10400,10402-10403,10423,10427,10430,10436,10441,10444-10446,10452,10472,10477,10486,10489-10491,10503,10507,10509-10515,10522,10525-10527,10530-10531,10534,10537-10540,10543,10547,10553,10555,10561-10563,10565-10566,10570,10592-10596,10606,10610 via svnmerge from
svn+ssh://svn.freepascal.org/FPC/svn/fpc/trunk

........
r10348 | Almindor | 2008-02-17 18:04:15 +0100 (Sun, 17 Feb 2008) | 1 line

* fix aspell runtime error in windows if no library (register keys) are present
........
r10394 | peter | 2008-02-26 23:46:42 +0100 (Tue, 26 Feb 2008) | 3 lines

* basic work for checksum on packages to detect if recompile
is needed. Checksum is currently based on the system time
........
r10402 | michael | 2008-02-28 19:22:12 +0100 (Thu, 28 Feb 2008) | 1 line

* Patch from Laurent ([email protected]) to read CMYK files
........
r10427 | peter | 2008-03-02 16:01:08 +0100 (Sun, 02 Mar 2008) | 2 lines

* fixed char constant to formal const
........
r10477 | michael | 2008-03-12 22:08:12 +0100 (Wed, 12 Mar 2008) | 1 line

* Fixed bug in decodesoundexint
........
r10486 | peter | 2008-03-13 22:07:19 +0100 (Thu, 13 Mar 2008) | 3 lines

* simplify compile states
* fix recursive dependency check
........
r10543 | marco | 2008-03-23 19:34:26 +0100 (Sun, 23 Mar 2008) | 2 lines

* fix for 10865
........
r10561 | peter | 2008-03-25 18:14:39 +0100 (Tue, 25 Mar 2008) | 2 lines

* try to compile targets only in neutral state
........
r10562 | peter | 2008-03-25 18:15:26 +0100 (Tue, 25 Mar 2008) | 2 lines

* only parse checksum when available
........
r10563 | peter | 2008-03-25 18:15:41 +0100 (Tue, 25 Mar 2008) | 2 lines

* regenerated
........
r10566 | michael | 2008-03-26 16:33:24 +0100 (Wed, 26 Mar 2008) | 1 line

* Patch for arithmetic overflow from Petr Kristan
........
r10592 | peter | 2008-04-01 23:24:24 +0200 (Tue, 01 Apr 2008) | 2 lines

* avr, armeb added
........
r10593 | peter | 2008-04-01 23:26:20 +0200 (Tue, 01 Apr 2008) | 2 lines

* fixed previous commit
........
r10594 | peter | 2008-04-02 00:32:55 +0200 (Wed, 02 Apr 2008) | 2 lines

* regenerated
........
r10595 | peter | 2008-04-02 00:39:20 +0200 (Wed, 02 Apr 2008) | 10 lines

* detect broken packages, give an error if broken packages are found and the user
needs to run 'fppkg fixbroken' first
* add --broken option to skip the broken package detection at startup
* call fixbroken implicitly after an install command from the commandline has been processed.
This will make sure that all packages depending on the installed package will also be recompiled
and reinstalled.
Warning: Installing a new rtl will recompile everything. Currently this will
give a broken installation because not all packages compile yet.
........
r10596 | peter | 2008-04-02 00:39:52 +0200 (Wed, 02 Apr 2008) | 2 lines

* include fix fixes
........
r10610 | peter | 2008-04-06 23:00:24 +0200 (Sun, 06 Apr 2008) | 4 lines

* split repository in InstalledRepository and AvailableRepository
* replace CurrentPackage by PackageName
* remove obsolete execute arguments
........

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

michael 17 years ago
parent
commit
e8e4e090a5

+ 6 - 5
packages/aspell/src/aspell.pp

@@ -1013,7 +1013,6 @@ uses
 
 
 var
 var
   LibHandle: TLibHandle = 0;
   LibHandle: TLibHandle = 0;
-  AspellInited_: Boolean;
 
 
 {$IFDEF WINDOWS}
 {$IFDEF WINDOWS}
 function RegistryQueryValue (name,sub:shortstring):shortstring;
 function RegistryQueryValue (name,sub:shortstring):shortstring;
@@ -1057,10 +1056,12 @@ begin
   
   
   {$IFDEF windows}
   {$IFDEF windows}
   bversion := RegistryQueryValue('SOFTWARE\Aspell','AspellVersion');
   bversion := RegistryQueryValue('SOFTWARE\Aspell','AspellVersion');
-  move(bversion[1], version, 4);
-  path := RegistryQueryValue('SOFTWARE\Aspell','Path');
-  // will work if they passed %s, won't bork if they passed absolute
-  libname := path + PathDelim + StringReplace(libn, '%s', IntToStr(Version), [rfReplaceAll]);
+  if Length(bversion) >= 4 then begin
+    move(bversion[1], version, 4);
+    path := RegistryQueryValue('SOFTWARE\Aspell','Path');
+    // will work if they passed %s, won't bork if they passed absolute
+    libname := path + PathDelim + StringReplace(libn, '%s', IntToStr(Version), [rfReplaceAll]);
+  end;
   {$ENDIF}
   {$ENDIF}
 
 
   LibHandle := LoadLibrary(libname);
   LibHandle := LoadLibrary(libname);

+ 1 - 0
packages/fcl-base/src/contnrs.pp

@@ -1280,6 +1280,7 @@ begin
       FHashList := nil;
       FHashList := nil;
     end;
     end;
   SetHashCapacity(1);
   SetHashCapacity(1);
+  FHashTable^[0]:=longword(-1); // sethashcapacity does not always call rehash
   if Assigned(FStrs) then
   if Assigned(FStrs) then
     begin
     begin
       FStrCount:=0;
       FStrCount:=0;

+ 22 - 0
packages/fcl-image/src/fpreadjpeg.pas

@@ -201,6 +201,19 @@ var
     end;
     end;
   end;
   end;
 
 
+  function CorrectCMYK(const C: TFPColor): TFPColor;
+  var
+    MinColor: word;
+  begin
+    if C.red<C.green then MinColor:=C.red
+    else MinColor:= C.green;
+    if C.blue<MinColor then MinColor:= C.blue;
+    if MinColor+ C.alpha>$FF then MinColor:=$FF-C.alpha;
+    Result.red:=(C.red-MinColor) shl 8;
+    Result.green:=(C.green-MinColor) shl 8;
+    Result.blue:=(C.blue-MinColor) shl 8;
+    Result.alpha:=alphaOpaque;
+  end;
   procedure ReadPixels;
   procedure ReadPixels;
   var
   var
     Continue: Boolean;
     Continue: Boolean;
@@ -231,6 +244,15 @@ var
       while (FInfo.output_scanline < FInfo.output_height) do begin
       while (FInfo.output_scanline < FInfo.output_height) do begin
         LinesRead := jpeg_read_scanlines(@FInfo, SampArray, 1);
         LinesRead := jpeg_read_scanlines(@FInfo, SampArray, 1);
         if LinesRead<1 then break;
         if LinesRead<1 then break;
+        if (FInfo.jpeg_color_space = JCS_CMYK) then
+        for x:=0 to FInfo.output_width-1 do begin
+          Color.Red:=SampRow^[x*4+0];
+          Color.Green:=SampRow^[x*4+1];
+          Color.Blue:=SampRow^[x*4+2];
+          Color.alpha:=SampRow^[x*4+3];
+          Img.Colors[x,y]:=CorrectCMYK(Color);
+        end
+        else
         for x:=0 to FInfo.output_width-1 do begin
         for x:=0 to FInfo.output_width-1 do begin
           Color.Red:=SampRow^[x*3+0] shl 8;
           Color.Red:=SampRow^[x*3+0] shl 8;
           Color.Green:=SampRow^[x*3+1] shl 8;
           Color.Green:=SampRow^[x*3+1] shl 8;

+ 8 - 4
packages/fcl-image/src/pscanvas.pp

@@ -218,11 +218,13 @@ Resourcestring
 { TPostScriptCanvas ----------------------------------------------------------}
 { TPostScriptCanvas ----------------------------------------------------------}
 
 
 Procedure TPostScriptCanvas.WritePS(const Cmd : String);
 Procedure TPostScriptCanvas.WritePS(const Cmd : String);
-
+var
+  ss : shortstring;
 begin
 begin
   If length(Cmd)>0 then
   If length(Cmd)>0 then
     FStream.Write(Cmd[1],Length(Cmd));
     FStream.Write(Cmd[1],Length(Cmd));
-  FStream.Write(LineEnding,SizeOf(LineEnding));
+  ss:=LineEnding;
+  FStream.Write(ss[1],Length(ss));
 end;
 end;
 
 
 Procedure TPostScriptCanvas.WritePS(Const Fmt : String; Args : Array of Const);
 Procedure TPostScriptCanvas.WritePS(Const Fmt : String; Args : Array of Const);
@@ -586,11 +588,13 @@ begin
 end;
 end;
 
 
 Procedure TPostScript.WritePS(const Cmd : String);
 Procedure TPostScript.WritePS(const Cmd : String);
-
+var
+  ss : shortstring;
 begin
 begin
   If length(Cmd)>0 then
   If length(Cmd)>0 then
     FStream.Write(Cmd[1],Length(Cmd));
     FStream.Write(Cmd[1],Length(Cmd));
-  FStream.Write(LineEnding,SizeOf(LineEnding));
+  ss:=LineEnding;
+  FStream.Write(ss[1],Length(ss));
 end;
 end;
 
 
 Procedure TPostScript.WritePS(Const Fmt : String; Args : Array of Const);
 Procedure TPostScript.WritePS(Const Fmt : String; Args : Array of Const);

+ 178 - 167
packages/fpmkunit/src/fpmkunit.pp

@@ -52,7 +52,7 @@ Type
 
 
   // Please keep this order, see OSCPUSupported below
   // Please keep this order, see OSCPUSupported below
   TCpu=(cpuNone,
   TCpu=(cpuNone,
-    i386,m68k,powerpc,sparc,x86_64,arm,powerpc64
+    i386,m68k,powerpc,sparc,x86_64,arm,powerpc64,avr,armeb
   );
   );
   TCPUS = Set of TCPU;
   TCPUS = Set of TCPU;
 
 
@@ -71,7 +71,7 @@ Type
   TTargetType = (ttProgram,ttUnit,ttImplicitUnit,ttCleanOnlyUnit,ttExampleUnit,ttExampleProgram);
   TTargetType = (ttProgram,ttUnit,ttImplicitUnit,ttCleanOnlyUnit,ttExampleUnit,ttExampleProgram);
   TTargetTypes = set of TTargetType;
   TTargetTypes = set of TTargetType;
 
 
-  TTargetState = (tsNeutral,tsNeedCompile,tsNoCompile,tsCompiling,tsCompiled,tsInstalled,tsNotFound);
+  TTargetState = (tsNeutral,tsConsidering,tsNoCompile,tsCompiled,tsInstalled,tsNotFound);
   TTargetStates = Set of TTargetState;
   TTargetStates = Set of TTargetState;
 
 
   TSourceType = (stDoc,stSrc,stExample,stTest);
   TSourceType = (stDoc,stSrc,stExample,stTest);
@@ -109,35 +109,35 @@ Const
 
 
   { This table is kept OS,Cpu because it is easier to maintain (PFV) }
   { This table is kept OS,Cpu because it is easier to maintain (PFV) }
   OSCPUSupported : array[TOS,TCpu] of boolean = (
   OSCPUSupported : array[TOS,TCpu] of boolean = (
-    { os          none   i386   m68k   ppc    sparc  x86_64 arm    ppc64}
-    { none  }   ( false, false, false, false, false, false, false, false),
-    { linux }   ( false, true,  true,  true,  true,  true,  true,  true ),
-    { go32v2 }  ( false, true,  false, false, false, false, false, false),
-    { win32 }   ( false, true,  false, false, false, false, false, false),
-    { os2 }     ( false, true,  false, false, false, false, false, false),
-    { freebsd } ( false, true,  true,  false, false, true,  false, false),
-    { beos }    ( false, true,  false, false, false, false, false, false),
-    { netbsd }  ( false, false, false, false, false, false, false, false),
-    { amiga }   ( false, false, true,  true,  false, false, false, false),
-    { atari }   ( false, false, false, false, false, false, false, false),
-    { solaris } ( false, true,  false, false, true,  false, false, false),
-    { qnx }     ( false, false, false, false, false, false, false, false),
-    { netware } ( false, true,  false, false, false, false, false, false),
-    { openbsd } ( false, false, false, false, false, false, false, false),
-    { wdosx }   ( false, true,  false, false, false, false, false, false),
-    { palmos }  ( false, false, true,  false, false, false, true,  false),
-    { macos }   ( false, false, false, true,  false, false, false, false),
-    { darwin }  ( false, true,  false, true,  false, true,  false, true ),
-    { emx }     ( false, true,  false, false, false, false, false, false),
-    { watcom }  ( false, true,  false, false, false ,false, false, false),
-    { morphos } ( false, false, false, true,  false ,false, false, false),
-    { netwlibc }( false, true,  false, false, false, false, false, false),
-    { win64   } ( false, false, false, false, false, true,  false, false),
-    { wince    }( false, true,  false, false, false, false, true,  false),
-    { gba    }  ( false, false, false, false, false, false, true,  false),
-    { nds    }  ( false, false, false, false, false, false, true,  false),
-    { embedded }( false, false, false, false, false, false, true,  false),
-    { symbian } ( false, true,  false, false, false, false, true,  false)
+    { os          none   i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb}
+    { none }    ( false, false, false, false, false, false, false, false, false, false),
+    { linux }   ( false, true,  true,  true,  true,  true,  true,  true,  false, true ),
+    { go32v2 }  ( false, true,  false, false, false, false, false, false, false, false),
+    { win32 }   ( false, true,  false, false, false, false, false, false, false, false),
+    { os2 }     ( false, true,  false, false, false, false, false, false, false, false),
+    { freebsd } ( false, true,  true,  false, false, true,  false, false, false, false),
+    { beos }    ( false, true,  false, false, false, false, false, false, false, false),
+    { netbsd }  ( false, true,  true,  true,  true,  false, false, false, false, false),
+    { amiga }   ( false, false, true,  true,  false, false, false, false, false, false),
+    { atari }   ( false, false, true,  false, false, false, false, false, false, false),
+    { solaris } ( false, true,  false, false, true,  false, false, false, false, false),
+    { qnx }     ( false, true,  false, false, false, false, false, false, false, false),
+    { netware } ( false, true,  false, false, false, false, false, false, false, false),
+    { openbsd } ( false, true,  true,  false, false, false, false, false, false, false),
+    { wdosx }   ( false, true,  false, false, false, false, false, false, false, false),
+    { palmos }  ( false, false, true,  false, false, false, true,  false, false, false),
+    { macos }   ( false, false, false, true,  false, false, false, false, false, false),
+    { darwin }  ( false, true,  false, true,  false, true,  true,  true,  false, false),
+    { emx }     ( false, true,  false, false, false, false, false, false, false, false),
+    { watcom }  ( false, true,  false, false, false ,false, false, false, false, false),
+    { morphos } ( false, false, false, true,  false ,false, false, false, false, false),
+    { netwlibc }( false, true,  false, false, false, false, false, false, false, false),
+    { win64   } ( false, false, false, false, false, true,  false, false, false, false),
+    { wince    }( false, true,  false, false, false, false, true,  false, false, false),
+    { gba    }  ( false, false, false, false, false, false, true,  false, false, false),
+    { nds    }  ( false, false, false, false, false, false, true,  false, false, false),
+    { embedded }( false, true,  true,  true,  true,  true,  true,  true,  true,  true ),
+    { symbian } ( false, true,  false, false, false, false, true,  false, false, false)
   );
   );
 
 
   // Useful
   // Useful
@@ -308,6 +308,7 @@ Type
     // Package, Unit
     // Package, Unit
     FTarget : TObject;
     FTarget : TObject;
     FVersion : TFPVersion;
     FVersion : TFPVersion;
+    FRequireChecksum : Cardinal;
     // Filenames, Includes
     // Filenames, Includes
     FTargetFileName : String;
     FTargetFileName : String;
     Function GetVersion : string;
     Function GetVersion : string;
@@ -319,6 +320,7 @@ Type
     Property DependencyType : TDependencyType Read FDependencyType;
     Property DependencyType : TDependencyType Read FDependencyType;
     Property TargetFileName : String Read FTargetFileName Write FTargetFileName;
     Property TargetFileName : String Read FTargetFileName Write FTargetFileName;
     Property Version : String Read GetVersion Write SetVersion;
     Property Version : String Read GetVersion Write SetVersion;
+    Property RequireChecksum : Cardinal Read FRequireChecksum Write FRequireChecksum;
   end;
   end;
 
 
   TDependencies = Class(TConditionalStrings)
   TDependencies = Class(TConditionalStrings)
@@ -524,6 +526,7 @@ Type
     FCommands : TCommands;
     FCommands : TCommands;
     FDescriptionFile : String;
     FDescriptionFile : String;
     FDescription : String;
     FDescription : String;
+    FInstalledChecksum : Cardinal;
     // Cached directory of installed packages
     // Cached directory of installed packages
     FUnitDir : String;
     FUnitDir : String;
     Function GetDescription : string;
     Function GetDescription : string;
@@ -552,6 +555,7 @@ Type
     Property Directory : String Read FDirectory Write FDirectory;
     Property Directory : String Read FDirectory Write FDirectory;
     Property Description : String Read GetDescription Write FDescription;
     Property Description : String Read GetDescription Write FDescription;
     Property DescriptionFile : String Read FDescriptionFile Write FDescriptionFile;
     Property DescriptionFile : String Read FDescriptionFile Write FDescriptionFile;
+    Property InstalledChecksum : Cardinal Read FInstalledChecksum Write FInstalledChecksum;
     // Compiler options.
     // Compiler options.
     Property OSes : TOSes Read FOSes Write FOSes;
     Property OSes : TOSes Read FOSes Write FOSes;
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
@@ -957,6 +961,7 @@ ResourceString
   SErrInvalidFPCInfo    = 'Compiler returns invalid information, check if fpc -iV works';
   SErrInvalidFPCInfo    = 'Compiler returns invalid information, check if fpc -iV works';
   SErrDependencyNotFound = 'Could not find unit directory for dependency package "%s"';
   SErrDependencyNotFound = 'Could not find unit directory for dependency package "%s"';
   SErrAlreadyInitialized = 'Installer can only be initialized once';
   SErrAlreadyInitialized = 'Installer can only be initialized once';
+  SErrInvalidState      = 'Invalid state for target %s';
 
 
   SWarnCircularTargetDependency = 'Warning: Circular dependency detected when compiling target %s with target %s';
   SWarnCircularTargetDependency = 'Warning: Circular dependency detected when compiling target %s with target %s';
   SWarnCircularPackageDependency = 'Warning: Circular dependency detected when compiling package %s with package %s';
   SWarnCircularPackageDependency = 'Warning: Circular dependency detected when compiling package %s with package %s';
@@ -1006,6 +1011,7 @@ ResourceString
   SDbgArchivingFile         = 'Archiving "%s"';
   SDbgArchivingFile         = 'Archiving "%s"';
   SDbgSearchPath            = 'Using %s path "%s"';
   SDbgSearchPath            = 'Using %s path "%s"';
   SDbgEnterDir              = 'Entering directory "%s"';
   SDbgEnterDir              = 'Entering directory "%s"';
+  SDbgPackageChecksumChanged = 'Dependent package %s is modified';
 
 
   // Help messages for usage
   // Help messages for usage
   SValue              = 'Value';
   SValue              = 'Value';
@@ -1058,6 +1064,7 @@ Const
   // Keys for unit config
   // Keys for unit config
   KeyName     = 'Name';
   KeyName     = 'Name';
   KeyVersion  = 'Version';
   KeyVersion  = 'Version';
+  KeyChecksum = 'Checksum';
   KeyNeedLibC = 'NeedLibC';
   KeyNeedLibC = 'NeedLibC';
   KeyDepends  = 'Depends';
   KeyDepends  = 'Depends';
 
 
@@ -1854,6 +1861,7 @@ begin
   FCommands:=TCommands.Create(TCommand);
   FCommands:=TCommands.Create(TCommand);
   FCPUs:=AllCPUs;
   FCPUs:=AllCPUs;
   FOSes:=AllOSes;
   FOSes:=AllOSes;
+  FInstalledChecksum:=$ffffffff;
   // Implicit dependency on RTL
   // Implicit dependency on RTL
   FDependencies.Add('rtl');
   FDependencies.Add('rtl');
 end;
 end;
@@ -2064,7 +2072,10 @@ var
   L,L2 : TStrings;
   L,L2 : TStrings;
   VOS : TOS;
   VOS : TOS;
   VCPU : TCPU;
   VCPU : TCPU;
-  i : Integer;
+  i,k : Integer;
+  DepChecksum : Cardinal;
+  DepName : String;
+  D : TDependency;
 begin
 begin
   L:=TStringList.Create;
   L:=TStringList.Create;
   Try
   Try
@@ -2072,6 +2083,7 @@ begin
     With L do
     With L do
       begin
       begin
         Version:=Values[KeyVersion];
         Version:=Values[KeyVersion];
+        InstalledChecksum:=Cardinal(StrToInt64Def(Values[KeyChecksum],$ffffffff));
         VCPU:=StringToCPU(Values[KeyCPU]);
         VCPU:=StringToCPU(Values[KeyCPU]);
         VOS:=StringToOS(Values[KeyOS]);
         VOS:=StringToOS(Values[KeyOS]);
         OSes:=[VOS];
         OSes:=[VOS];
@@ -2079,7 +2091,19 @@ begin
         L2:=TStringList.Create;
         L2:=TStringList.Create;
         L2.CommaText:=Values[KeyDepends];
         L2.CommaText:=Values[KeyDepends];
         for i:=0 to L2.Count-1 do
         for i:=0 to L2.Count-1 do
-          Dependencies.Add(L2[i],CPUs,OSes);
+          begin
+            DepName:=L2[i];
+            k:=Pos('|',DepName);
+            if k>0 then
+              begin
+                DepChecksum:=StrToInt(Copy(DepName,k+1,Length(DepName)-k));
+                DepName:=Copy(DepName,1,k-1);
+              end
+            else
+              DepChecksum:=$ffffffff;
+            D:=Dependencies.Add(DepName,CPUs,OSes);
+            D.RequireChecksum:=DepChecksum;
+          end;
         FreeAndNil(L2);
         FreeAndNil(L2);
         NeedLibC:=Upcase(Values[KeyNeedLibC])='Y';
         NeedLibC:=Upcase(Values[KeyNeedLibC])='Y';
       end;
       end;
@@ -2096,6 +2120,7 @@ Var
   Deps : String;
   Deps : String;
   i : integer;
   i : integer;
   D : TDependency;
   D : TDependency;
+  p : TPackage;
 begin
 begin
   F:=TFileStream.Create(AFileName,fmCreate);
   F:=TFileStream.Create(AFileName,fmCreate);
   L:=TStringList.Create;
   L:=TStringList.Create;
@@ -2104,6 +2129,8 @@ begin
       begin
       begin
         Values[KeyName]:=Name;
         Values[KeyName]:=Name;
         Values[KeyVersion]:=Version;
         Values[KeyVersion]:=Version;
+        // TODO Generate checksum based on PPUs
+        Values[KeyChecksum]:=IntToStr(DateTimeToFileDate(Now));
         Values[KeyCPU]:=CPUToString(ACPU);
         Values[KeyCPU]:=CPUToString(ACPU);
         Values[KeyOS]:=OSToString(AOS);
         Values[KeyOS]:=OSToString(AOS);
         Deps:='';
         Deps:='';
@@ -2112,10 +2139,12 @@ begin
             D:=Dependencies[i];
             D:=Dependencies[i];
             if (ACPU in D.CPUs) and (AOS in D.OSes) then
             if (ACPU in D.CPUs) and (AOS in D.OSes) then
               begin
               begin
-                if Deps='' then
-                  Deps:=D.Value
-                else
-                  Deps:=Deps+','+D.Value;
+                if Deps<>'' then
+                  Deps:=Deps+',';
+                Deps:=Deps+D.Value;
+                P:=TPackage(D.Target);
+                if assigned(P) and (P.InstalledChecksum<>$ffffffff) then
+                  Deps:=Deps+'|'+IntToStr(P.InstalledChecksum);
               end;
               end;
           end;
           end;
         Values[KeyDepends]:=Deps;
         Values[KeyDepends]:=Deps;
@@ -3637,17 +3666,6 @@ Var
   OD,OFN : String;
   OD,OFN : String;
 begin
 begin
   Result:=False;
   Result:=False;
-  case ATarget.State of
-    tsNeedCompile :
-      begin
-        result:=true;
-        exit;
-      end;
-    tsNoCompile,
-    tsCompiling,
-    tsCompiled :
-      exit;
-  end;
 
 
   // Forced recompile?
   // Forced recompile?
   if FForceCompile then
   if FForceCompile then
@@ -3693,7 +3711,7 @@ begin
                       Error(SErrDepUnknownTarget,[ATarget.Name,D.Value]);
                       Error(SErrDepUnknownTarget,[ATarget.Name,D.Value]);
                     // If a dependent package is compiled we always need to recompile
                     // If a dependent package is compiled we always need to recompile
                     Log(vldebug, SDbgDependencyOnUnit, [ATarget.Name,T.Name]);
                     Log(vldebug, SDbgDependencyOnUnit, [ATarget.Name,T.Name]);
-                    Result:=(T.State in [tsNeedCompile,tsCompiling,tsCompiled]) or NeedsCompile(APackage,T);
+                    Result:=(T.State=tsCompiled);
                     if Result then
                     if Result then
                       Log(vldebug, SDbgDependencyUnitRecompiled, [T.Name]);
                       Log(vldebug, SDbgDependencyUnitRecompiled, [T.Name]);
                   end;
                   end;
@@ -3709,14 +3727,8 @@ begin
         end;
         end;
     end;
     end;
 
 
-  // Upate also target state so a second check is faster
   if result then
   if result then
-    begin
-      ATarget.FTargetState:=tsNeedCompile;
-      Log(vlDebug,SDbgMustCompile,[ATarget.Name]);
-    end
-  else
-    ATarget.FTargetState:=tsNoCompile;
+    Log(vlDebug,SDbgMustCompile,[ATarget.Name]);
 end;
 end;
 
 
 
 
@@ -3724,24 +3736,17 @@ procedure TBuildEngine.Compile(APackage: TPackage; ATarget: TTarget);
 Var
 Var
   S : String;
   S : String;
 begin
 begin
-  if ATarget.State in [tsNeutral,tsNeedCompile] then
-    begin
-      Log(vlInfo,SInfoCompilingTarget,[ATarget.Name]);
-      LogIndent;
-      ATarget.FTargetState:=tsCompiling;
-      ExecuteCommands(ATarget.Commands,caBeforeCompile);
-      If Assigned(ATarget.BeforeCompile) then
-        ATarget.BeforeCompile(ATarget);
-      S:=GetCompilerCommand(APackage,ATarget);
-      ExecuteCommand(GetCompiler,S);
-      If Assigned(ATarget.AfterCompile) then
-        ATarget.AfterCompile(ATarget);
-      ExecuteCommands(ATarget.Commands,caAfterCompile);
-      ATarget.FTargetState:=tsCompiled;
-      LogUnIndent;
-    end
-  else if ATarget.State<>tsCompiled then
-    Log(vlWarning, Format(SWarnAttemptingToCompileNonNeutralTarget, [ATarget.Name]));
+  Log(vlInfo,SInfoCompilingTarget,[ATarget.Name]);
+  LogIndent;
+  ExecuteCommands(ATarget.Commands,caBeforeCompile);
+  If Assigned(ATarget.BeforeCompile) then
+    ATarget.BeforeCompile(ATarget);
+  S:=GetCompilerCommand(APackage,ATarget);
+  ExecuteCommand(GetCompiler,S);
+  If Assigned(ATarget.AfterCompile) then
+    ATarget.AfterCompile(ATarget);
+  ExecuteCommands(ATarget.Commands,caAfterCompile);
+  LogUnIndent;
 end;
 end;
 
 
 
 
@@ -3751,8 +3756,6 @@ Var
   T : TTarget;
   T : TTarget;
   D : TDependency;
   D : TDependency;
 begin
 begin
-  if ATarget.State in [tsCompiled,tsCompiling,tsNoCompile] then
-    exit;
   Log(vlDebug, Format(SDbgCompilingDependenciesOfTarget, [ATarget.Name]));
   Log(vlDebug, Format(SDbgCompilingDependenciesOfTarget, [ATarget.Name]));
   LogIndent;
   LogIndent;
   For I:=0 to ATarget.Dependencies.Count-1 do
   For I:=0 to ATarget.Dependencies.Count-1 do
@@ -3770,9 +3773,12 @@ begin
                   // used for dependency checking
                   // used for dependency checking
                   if (T.TargetType<>ttImplicitUnit) then
                   if (T.TargetType<>ttImplicitUnit) then
                     begin
                     begin
-                      if T.State=tsCompiling then
-                        Log(vlWarning,SWarnCircularTargetDependency,[ATarget.Name,T.Name]);
-                      MaybeCompile(APackage,T);
+                      case T.State of
+                        tsNeutral :
+                          MaybeCompile(APackage,T);
+                        tsConsidering :
+                          Log(vlWarning,SWarnCircularTargetDependency,[ATarget.Name,T.Name]);
+                      end;
                     end;
                     end;
                 end
                 end
               else
               else
@@ -3788,14 +3794,20 @@ end;
 
 
 procedure TBuildEngine.MaybeCompile(APackage: TPackage; ATarget: TTarget);
 procedure TBuildEngine.MaybeCompile(APackage: TPackage; ATarget: TTarget);
 begin
 begin
-  if not(ATarget.State in [tsNeutral,tsNeedCompile]) then
-    exit;
+  if ATarget.State<>tsNeutral then
+    Error(SErrInvalidState,[ATarget.Name]);
   Log(vlDebug, Format(SDbgConsideringTarget, [ATarget.Name]));
   Log(vlDebug, Format(SDbgConsideringTarget, [ATarget.Name]));
   LogIndent;
   LogIndent;
+  ATarget.FTargetState:=tsConsidering;
   ResolveDependencies(ATarget.Dependencies,ATarget.Collection as TTargets);
   ResolveDependencies(ATarget.Dependencies,ATarget.Collection as TTargets);
   CompileDependencies(APackage, ATarget);
   CompileDependencies(APackage, ATarget);
   if NeedsCompile(APackage, ATarget) then
   if NeedsCompile(APackage, ATarget) then
-    Compile(APackage,ATarget);
+    begin
+      Compile(APackage,ATarget);
+      ATarget.FTargetState:=tsCompiled;
+    end
+  else
+    ATarget.FTargetState:=tsNoCompile;
   LogUnIndent;
   LogUnIndent;
 end;
 end;
 
 
@@ -3807,19 +3819,6 @@ Var
   D : TDependency;
   D : TDependency;
 begin
 begin
   Result:=False;
   Result:=False;
-  case APackage.State of
-    tsNeedCompile :
-      begin
-        result:=true;
-        exit;
-      end;
-    tsNoCompile,
-    tsNotFound,
-    tsCompiling,
-    tsCompiled,
-    tsInstalled :
-      exit;
-  end;
 
 
   // Forced recompile?
   // Forced recompile?
   if FForceCompile then
   if FForceCompile then
@@ -3836,11 +3835,9 @@ begin
               (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
               (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
              begin
              begin
                P:=TPackage(D.Target);
                P:=TPackage(D.Target);
-               if Assigned(P) and (P<>APackage) then
+               if Assigned(P) then
                  begin
                  begin
-                   If (P.State in [tsCompiling,tsNeedCompile]) then
-                     Log(vlWarning,SWarnCircularPackageDependency,[APackage.Name,P.Name]);
-                   Result:=(P.State in [tsCompiled,tsCompiling,tsNeedCompile]);
+                   Result:=(P.State=tsCompiled);
                    if Result then
                    if Result then
                      break;
                      break;
                  end;
                  end;
@@ -3866,70 +3863,8 @@ begin
       end;
       end;
     end;
     end;
 
 
-  // Upate also target state so a second check is faster
   if result then
   if result then
-    begin
-      APackage.FTargetState:=tsNeedCompile;
-      Log(vlDebug,SDbgMustCompile,[APackage.Name]);
-    end
-  else
-    APackage.FTargetState:=tsNoCompile;
-end;
-
-
-procedure TBuildEngine.Compile(APackage: TPackage);
-Var
-  T : TTarget;
-  I : Integer;
-begin
-  Try
-    Log(vlInfo,SInfoCompilingPackage,[APackage.Name]);
-    APackage.FTargetState:=tsCompiling;
-    If (APackage.Directory<>'') then
-      EnterDir(APackage.Directory);
-    CreateOutputDir(APackage);
-    Dictionary.AddVariable('UNITSOUTPUTDIR',APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS));
-    Dictionary.AddVariable('BINOUTPUTDIR',APackage.GetBinOutputDir(Defaults.CPU,Defaults.OS));
-    DoBeforeCompile(APackage);
-    For I:=0 to APackage.Targets.Count-1 do
-      begin
-        T:=APackage.Targets.TargetItems[i];
-        if (T.TargetType in [ttUnit,ttProgram]) then
-          begin
-            if TargetOK(T) then
-              MaybeCompile(APackage,T)
-            else
-              begin
-                if not(Defaults.CPU in T.CPUs) then
-                  Log(vldebug, Format(SDbgSkippingTargetWrongCPU, [T.Name, CPUsToString(T.CPUs)]));
-                if not(Defaults.OS in T.OSes) then
-                  Log(vldebug, Format(SDbgSkippingTargetWrongOS, [T.Name, OSesToString(T.OSes)]));
-              end;
-          end
-        else
-          log(vldebug, SDbgTargetIsNotAUnitOrProgram,[T.Name]);
-      end;
-    DoAfterCompile(APackage);
-    APackage.FTargetState:=tsCompiled;
-  Finally
-    If (APackage.Directory<>'') then
-      EnterDir('');
-  end;
-end;
-
-
-procedure TBuildEngine.MaybeCompile(APackage: TPackage);
-begin
-  if not(APackage.State in [tsNeutral,tsNeedCompile]) then
-    exit;
-  Log(vlDebug,SDbgConsideringPackage,[APackage.Name]);
-  LogIndent;
-  ResolveDependencies(APackage.Dependencies,(APackage.Collection as TPackages));
-  CompileDependencies(APackage);
-  ResolveFileNames(APackage,Defaults.CPU,Defaults.OS);
-  If NeedsCompile(APackage) then
-    Compile(APackage);
-  LogUnIndent;
+    Log(vlDebug,SDbgMustCompile,[APackage.Name]);
 end;
 end;
 
 
 
 
@@ -3982,16 +3917,92 @@ begin
          (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
          (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
         begin
         begin
           P:=TPackage(D.Target);
           P:=TPackage(D.Target);
-          // If it already was compiled, then State<>tsNeutral, and it won't be compiled again.
-          If Assigned(P) and (P<>APackage) then
-            MaybeCompile(P)
+          If Assigned(P) then
+            begin
+              case P.State of
+                tsNeutral :
+                  MaybeCompile(P);
+                tsConsidering :
+                  Log(vlWarning,SWarnCircularPackageDependency,[APackage.Name,P.Name]);
+              end;
+            end
           else
           else
-            D.Target:=CheckExternalPackage(D.Value);
+            begin
+              D.Target:=CheckExternalPackage(D.Value);
+              P:=TPackage(D.Target);
+            end;
+          if (D.RequireChecksum<>$ffffffff) and
+             (P.InstalledChecksum<>$ffffffff) and
+             (P.InstalledChecksum<>D.RequireChecksum) then
+            Log(vlDebug,SDbgPackageChecksumChanged,[P.Name]);
         end;
         end;
     end;
     end;
 end;
 end;
 
 
 
 
+procedure TBuildEngine.Compile(APackage: TPackage);
+Var
+  T : TTarget;
+  I : Integer;
+begin
+  Try
+    Log(vlInfo,SInfoCompilingPackage,[APackage.Name]);
+    If (APackage.Directory<>'') then
+      EnterDir(APackage.Directory);
+    CreateOutputDir(APackage);
+    Dictionary.AddVariable('UNITSOUTPUTDIR',APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS));
+    Dictionary.AddVariable('BINOUTPUTDIR',APackage.GetBinOutputDir(Defaults.CPU,Defaults.OS));
+    DoBeforeCompile(APackage);
+    For I:=0 to APackage.Targets.Count-1 do
+      begin
+        T:=APackage.Targets.TargetItems[i];
+        if (T.TargetType in [ttUnit,ttProgram]) then
+          begin
+            if TargetOK(T) then
+              begin
+                if T.State=tsNeutral then
+                  MaybeCompile(APackage,T);
+              end
+            else
+              begin
+                if not(Defaults.CPU in T.CPUs) then
+                  Log(vldebug, Format(SDbgSkippingTargetWrongCPU, [T.Name, CPUsToString(T.CPUs)]));
+                if not(Defaults.OS in T.OSes) then
+                  Log(vldebug, Format(SDbgSkippingTargetWrongOS, [T.Name, OSesToString(T.OSes)]));
+              end;
+          end
+        else
+          log(vldebug, SDbgTargetIsNotAUnitOrProgram,[T.Name]);
+      end;
+    DoAfterCompile(APackage);
+  Finally
+    If (APackage.Directory<>'') then
+      EnterDir('');
+  end;
+end;
+
+
+procedure TBuildEngine.MaybeCompile(APackage: TPackage);
+begin
+  if APackage.State<>tsNeutral then
+    Error(SErrInvalidState,[APackage.Name]);
+  Log(vlDebug,SDbgConsideringPackage,[APackage.Name]);
+  LogIndent;
+  APackage.FTargetState:=tsConsidering;
+  ResolveDependencies(APackage.Dependencies,(APackage.Collection as TPackages));
+  CompileDependencies(APackage);
+  ResolveFileNames(APackage,Defaults.CPU,Defaults.OS);
+  If NeedsCompile(APackage) then
+    begin
+      Compile(APackage);
+      APackage.FTargetState:=tsCompiled;
+    end
+  else
+    APackage.FTargetState:=tsNoCompile;
+  LogUnIndent;
+end;
+
+
 Function TBuildEngine.InstallPackageFiles(APAckage : TPackage; tt : TTargetType; Const Dest : String):Boolean;
 Function TBuildEngine.InstallPackageFiles(APAckage : TPackage; tt : TTargetType; Const Dest : String):Boolean;
 Var
 Var
   List : TStringList;
   List : TStringList;
@@ -4033,7 +4044,7 @@ Var
   B : Boolean;
   B : Boolean;
 begin
 begin
   If (Apackage.State<>tsCompiled) then
   If (Apackage.State<>tsCompiled) then
-    Compile(APackage);
+    MaybeCompile(APackage);
   try
   try
     Log(vlInfo,SInfoInstallingPackage,[APackage.Name]);
     Log(vlInfo,SInfoInstallingPackage,[APackage.Name]);
     If (APackage.Directory<>'') then
     If (APackage.Directory<>'') then

+ 35 - 24
rtl/fpmake.pp

@@ -28,7 +28,7 @@ begin
     P.SourcePath.Add('objpas');
     P.SourcePath.Add('objpas');
 
 
     // Where to find the include files using firstmatch
     // Where to find the include files using firstmatch
-    P.IncludePath.Add('$(OS)/$(CPU)',[Linux]+AllBSDOSes);
+    P.IncludePath.Add('$(OS)/$(CPU)',AllUnixOSes);
     P.IncludePath.Add('$(OS)');
     P.IncludePath.Add('$(OS)');
     P.IncludePath.Add('$(CPU)');
     P.IncludePath.Add('$(CPU)');
     P.IncludePath.Add('bsd',AllBSDOSes);
     P.IncludePath.Add('bsd',AllBSDOSes);
@@ -55,6 +55,7 @@ begin
           AddInclude('varianth.inc');
           AddInclude('varianth.inc');
           AddInclude('sysosh.inc');
           AddInclude('sysosh.inc');
           AddInclude('resh.inc');
           AddInclude('resh.inc');
+          AddInclude('currh.inc');
           // Implementations
           // Implementations
           AddInclude('set.inc');
           AddInclude('set.inc');
           AddInclude('int64p.inc');
           AddInclude('int64p.inc');
@@ -63,6 +64,7 @@ begin
           AddInclude('sysheap.inc');
           AddInclude('sysheap.inc');
           AddInclude('sysdir.inc');
           AddInclude('sysdir.inc');
           AddInclude('sysfile.inc');
           AddInclude('sysfile.inc');
+          AddInclude('sysres.inc');
           AddInclude('except.inc');
           AddInclude('except.inc');
           AddInclude('threadvr.inc');
           AddInclude('threadvr.inc');
           AddInclude('filerec.inc');
           AddInclude('filerec.inc');
@@ -70,6 +72,7 @@ begin
           AddInclude('generic.inc');
           AddInclude('generic.inc');
           AddInclude('genset.inc');
           AddInclude('genset.inc');
           AddInclude('genmath.inc');
           AddInclude('genmath.inc');
+          AddInclude('gencurr.inc');
           AddInclude('sstrings.inc');
           AddInclude('sstrings.inc');
           AddInclude('int64.inc');
           AddInclude('int64.inc');
           AddInclude('astrings.inc');
           AddInclude('astrings.inc');
@@ -88,7 +91,7 @@ begin
           AddInclude('innr.inc');
           AddInclude('innr.inc');
           AddInclude('$(CPU).inc');
           AddInclude('$(CPU).inc');
           AddInclude('fastmove.inc',[i386],AllOSes);
           AddInclude('fastmove.inc',[i386],AllOSes);
-          AddInclude('strpas.inc');
+          AddInclude('strpas.inc',[i386,powerpc,powerpc64],AllOSes);
           AddInclude('math.inc');
           AddInclude('math.inc');
           AddInclude('real2str.inc');
           AddInclude('real2str.inc');
           AddInclude('systhrd.inc',AllWindowsOSes+[Netware,Netwlibc,EMX,OS2]);
           AddInclude('systhrd.inc',AllWindowsOSes+[Netware,Netwlibc,EMX,OS2]);
@@ -103,12 +106,12 @@ begin
           AddInclude('ctypes.inc',AllUnixOSes);
           AddInclude('ctypes.inc',AllUnixOSes);
           AddInclude('stat.inc',[Linux]);
           AddInclude('stat.inc',[Linux]);
           AddInclude('signal.inc',AllUnixOSes);
           AddInclude('signal.inc',AllUnixOSes);
-          AddInclude('sighnd.inc',AllUnixOSes);
-          AddInclude('sighndh.inc',AllUnixOSes);
+          AddInclude('sighnd.inc',AllUnixOSes-[Beos]);
+          AddInclude('sighndh.inc',[Linux,Solaris]);
           AddInclude('syscallh.inc',[Linux,Beos,FreeBSD]);
           AddInclude('syscallh.inc',[Linux,Beos,FreeBSD]);
           AddInclude('syscall.inc',[Linux,Beos,FreeBSD]);
           AddInclude('syscall.inc',[Linux,Beos,FreeBSD]);
           AddInclude('sysnr.inc',[Linux,Beos,FreeBSD]);
           AddInclude('sysnr.inc',[Linux,Beos,FreeBSD]);
-          AddInclude('ossysc.inc',AllUnixOSes);
+          AddInclude('ossysc.inc',AllUnixOSes-[Solaris]);
           AddInclude('osmacro.inc',AllUnixOSes);
           AddInclude('osmacro.inc',AllUnixOSes);
           // Windows implementations
           // Windows implementations
           AddInclude('winres.inc',AllWindowsOSes);
           AddInclude('winres.inc',AllWindowsOSes);
@@ -144,7 +147,7 @@ begin
           AddInclude('ostypes.inc');
           AddInclude('ostypes.inc');
           AddInclude('stat.inc',[Linux]);
           AddInclude('stat.inc',[Linux]);
           AddInclude('signal.inc');
           AddInclude('signal.inc');
-          AddInclude('sighndh.inc');
+          AddInclude('sighndh.inc',[Linux,Solaris]);
           AddInclude('bunxh.inc');
           AddInclude('bunxh.inc');
           AddInclude('bunxovlh.inc');
           AddInclude('bunxovlh.inc');
           AddInclude('genfunch.inc');
           AddInclude('genfunch.inc');
@@ -153,8 +156,8 @@ begin
           AddInclude('genfdset.inc');
           AddInclude('genfdset.inc');
           AddInclude('syscallh.inc',[Linux,Beos,FreeBSD]);
           AddInclude('syscallh.inc',[Linux,Beos,FreeBSD]);
           AddInclude('sysnr.inc',[Linux,Beos,FreeBSD]);
           AddInclude('sysnr.inc',[Linux,Beos,FreeBSD]);
-          AddInclude('bsyscall.inc',[Linux,Beos,FreeBSD]);
-          AddInclude('bunxsysc.inc',[Linux,Beos,FreeBSD]);
+          AddInclude('bsyscall.inc',[Linux,FreeBSD]);
+          AddInclude('bunxsysc.inc',[Linux,FreeBSD]);
           AddInclude('settimeo.inc');
           AddInclude('settimeo.inc');
           AddInclude('osmacro.inc');
           AddInclude('osmacro.inc');
           AddInclude('bunxovl.inc');
           AddInclude('bunxovl.inc');
@@ -169,11 +172,11 @@ begin
           AddInclude('aliasptp.inc');
           AddInclude('aliasptp.inc');
           AddInclude('aliasctp.inc');
           AddInclude('aliasctp.inc');
           AddInclude('unxconst.inc');
           AddInclude('unxconst.inc');
-          AddInclude('unxsysch.inc');
+          AddInclude('unxsysch.inc',[Linux,FreeBSD]);
+          AddInclude('unxsysc.inc',[Linux,FreeBSD]);
           AddInclude('unxovlh.inc');
           AddInclude('unxovlh.inc');
           AddInclude('unxovl.inc');
           AddInclude('unxovl.inc');
           AddInclude('syscallh.inc',[Linux,Beos,FreeBSD]);
           AddInclude('syscallh.inc',[Linux,Beos,FreeBSD]);
-          AddInclude('unxsysc.inc',[Linux,Beos,FreeBSD]);
           AddInclude('textrec.inc');
           AddInclude('textrec.inc');
           AddInclude('filerec.inc');
           AddInclude('filerec.inc');
           AddInclude('unxfunc.inc');
           AddInclude('unxfunc.inc');
@@ -189,11 +192,17 @@ begin
           AddInclude('termiosproc.inc');
           AddInclude('termiosproc.inc');
         end;
         end;
     T:=P.Targets.AddUnit('unix/errors.pp',AllUnixOSes);
     T:=P.Targets.AddUnit('unix/errors.pp',AllUnixOSes);
-      T.Dependencies.AddUnit('unixtype');
-      T.Dependencies.AddInclude('errnostr.inc');
-    T:=P.Targets.AddUnit('unix/syscall.pp',AllUnixOSes);
-      T.Dependencies.AddInclude('sysnr.inc');
-      T.Dependencies.AddInclude('syscallh.inc');
+      with T.Dependencies do
+        begin
+          AddUnit('unixtype');
+          AddInclude('errnostr.inc');
+        end;
+    T:=P.Targets.AddUnit('unix/syscall.pp',[Linux,Beos,FreeBSD]);
+      with T.Dependencies do
+        begin
+          AddInclude('sysnr.inc');
+          AddInclude('syscallh.inc');
+        end;
     T:=P.Targets.AddUnit('unix/terminfo.pp',AllUnixOSes);
     T:=P.Targets.AddUnit('unix/terminfo.pp',AllUnixOSes);
       T.Dependencies.AddUnit('baseunix',AllUnixOSes);
       T.Dependencies.AddUnit('baseunix',AllUnixOSes);
     T:=P.Targets.AddUnit('unix/dl.pp',AllUnixOSes);
     T:=P.Targets.AddUnit('unix/dl.pp',AllUnixOSes);
@@ -202,7 +211,7 @@ begin
       With T.Dependencies do
       With T.Dependencies do
         begin
         begin
           AddUnit('baseunix');
           AddUnit('baseunix');
-          AddUnit('syscall');
+          AddUnit('syscall',[Linux,Beos,FreeBSD]);
           AddInclude('ipccall.inc',[Linux]);
           AddInclude('ipccall.inc',[Linux]);
           AddInclude('ipcbsd.inc',[FreeBSD]);
           AddInclude('ipcbsd.inc',[FreeBSD]);
         end;
         end;
@@ -294,11 +303,11 @@ begin
         end;
         end;
 
 
     // Windows units
     // Windows units
-    T:=P.Targets.AddUnit('sysinitcyg.pp',AllWindowsOSes);
+    T:=P.Targets.AddUnit('sysinitcyg.pp',AllWindowsOSes-[WinCE]);
       T.Dependencies.AddUnit('system');
       T.Dependencies.AddUnit('system');
-    T:=P.Targets.AddUnit('sysinitgprof.pp',AllWindowsOSes);
+    T:=P.Targets.AddUnit('sysinitgprof.pp',AllWindowsOSes-[WinCE]);
       T.Dependencies.AddUnit('system');
       T.Dependencies.AddUnit('system');
-    T:=P.Targets.AddUnit('sysinitpas.pp',AllWindowsOSes);
+    T:=P.Targets.AddUnit('sysinitpas.pp',AllWindowsOSes-[WinCE]);
       T.Dependencies.AddUnit('system');
       T.Dependencies.AddUnit('system');
     T:=P.Targets.AddUnit('windows.pp',AllWindowsOSes);
     T:=P.Targets.AddUnit('windows.pp',AllWindowsOSes);
       T.IncludePath.Add('win/wininc');
       T.IncludePath.Add('win/wininc');
@@ -341,7 +350,7 @@ begin
         begin
         begin
           AddUnit('windows');
           AddUnit('windows');
         end;
         end;
-    T:=P.Targets.AddUnit('winsysut.pp',AllWindowsOSes);
+    T:=P.Targets.AddUnit('winsysut.pp',AllWindowsOSes-[WinCE]);
       with T.Dependencies do
       with T.Dependencies do
         begin
         begin
           AddUnit('windows');
           AddUnit('windows');
@@ -352,7 +361,7 @@ begin
         begin
         begin
           AddUnit('system');
           AddUnit('system');
         end;
         end;
-    T:=P.Targets.AddUnit('signals.pp',AllWindowsOSes);
+    T:=P.Targets.AddUnit('signals.pp',[Win32]);
       with T.Dependencies do
       with T.Dependencies do
         begin
         begin
           AddUnit('system');
           AddUnit('system');
@@ -475,6 +484,8 @@ begin
           AddUnit('windows',AllWindowsOSes);
           AddUnit('windows',AllWindowsOSes);
           AddInclude('classesh.inc');
           AddInclude('classesh.inc');
           AddInclude('classes.inc');
           AddInclude('classes.inc');
+          AddInclude('resref.inc');
+          AddInclude('sllist.inc');
           AddInclude('util.inc');
           AddInclude('util.inc');
           AddInclude('bits.inc');
           AddInclude('bits.inc');
           AddInclude('streams.inc');
           AddInclude('streams.inc');
@@ -554,7 +565,7 @@ begin
           AddUnit('unixtype',AllUnixOSes);
           AddUnit('unixtype',AllUnixOSes);
           AddInclude('aliasctp.inc',AllUnixOSes);
           AddInclude('aliasctp.inc',AllUnixOSes);
         end;
         end;
-    T:=P.Targets.AddUnit('initc.pp');
+    T:=P.Targets.AddUnit('initc.pp',AllOSes-[WinCE]);
       T.Dependencies.AddUnit('ctypes');
       T.Dependencies.AddUnit('ctypes');
     T:=P.Targets.AddUnit('cmem.pp');
     T:=P.Targets.AddUnit('cmem.pp');
       T.Dependencies.AddUnit('system');
       T.Dependencies.AddUnit('system');
@@ -660,7 +671,7 @@ begin
            AddInclude('keyscan.inc');
            AddInclude('keyscan.inc');
            AddUnit('mouse');
            AddUnit('mouse');
          end;
          end;
-    T:=P.Targets.AddUnit('sockets.pp');
+    T:=P.Targets.AddUnit('sockets.pp',AllUnixOSes+AllWindowsOSes+[OS2,MorphOS,Netware,Netwlibc]);
       with T.Dependencies do
       with T.Dependencies do
         begin
         begin
           AddUnit('baseunix',AllUnixOSes);
           AddUnit('baseunix',AllUnixOSes);
@@ -672,7 +683,7 @@ begin
           AddInclude('sockovl.inc');
           AddInclude('sockovl.inc');
           AddInclude('sockets.inc');
           AddInclude('sockets.inc');
           AddInclude('unxsockh.inc',AllUnixOSes);
           AddInclude('unxsockh.inc',AllUnixOSes);
-          AddInclude('unixsock.inc',AllUnixOSes);
+          AddInclude('unixsock.inc',AllUnixOSes-[Solaris,Darwin]);
           AddInclude('fpwinsockh.inc',AllWindowsOSes);
           AddInclude('fpwinsockh.inc',AllWindowsOSes);
         end;
         end;
     T:=P.Targets.AddUnit('serial.pp',AllUnixOSes);
     T:=P.Targets.AddUnit('serial.pp',AllUnixOSes);

+ 5 - 3
rtl/objpas/strutils.pp

@@ -836,9 +836,11 @@ begin
     Result:=Chr(Ord0+(AValue mod 7))+Result;
     Result:=Chr(Ord0+(AValue mod 7))+Result;
     AValue:=AValue div 7;
     AValue:=AValue div 7;
     end;
     end;
-  if Len>2 then
-    Result:=IntToStr(AValue mod 26)+Result;
-  AValue:=AValue div 26;
+  if Len>1 then
+    begin
+    Result:=Chr(Ord0+(AValue mod 26))+Result;
+    AValue:=AValue div 26;
+    end;
   Result:=Chr(OrdA+AValue)+Result;
   Result:=Chr(OrdA+AValue)+Result;
 end;
 end;
 
 

+ 1 - 1
rtl/objpas/sysutils/dati.inc

@@ -75,7 +75,7 @@ end;
 function MSecsToTimeStamp(MSecs: comp): TTimeStamp;
 function MSecsToTimeStamp(MSecs: comp): TTimeStamp;
 begin
 begin
   result.Date := Trunc(msecs / msecsperday);
   result.Date := Trunc(msecs / msecsperday);
-  msecs:= comp(msecs-result.date*msecsperday);
+  msecs:= msecs-comp(result.date)*msecsperday;
   result.Time := Round(MSecs);
   result.Time := Round(MSecs);
 end ;
 end ;
 
 

File diff suppressed because it is too large
+ 293 - 287
utils/fppkg/fpmkunitsrc.inc


+ 27 - 19
utils/fppkg/fppkg.pp

@@ -30,7 +30,6 @@ Type
 
 
   TMakeTool = Class(TCustomApplication)
   TMakeTool = Class(TCustomApplication)
   Private
   Private
-    ActionStack  : TActionStack;
     ParaAction   : string;
     ParaAction   : string;
     ParaPackages : TStringList;
     ParaPackages : TStringList;
     procedure MaybeCreateLocalDirs;
     procedure MaybeCreateLocalDirs;
@@ -174,13 +173,11 @@ Constructor TMakeTool.Create;
 begin
 begin
   inherited Create(nil);
   inherited Create(nil);
   ParaPackages:=TStringList.Create;
   ParaPackages:=TStringList.Create;
-  ActionStack:=TActionStack.Create;
 end;
 end;
 
 
 
 
 Destructor TMakeTool.Destroy;
 Destructor TMakeTool.Destroy;
 begin
 begin
-  FreeAndNil(ActionStack);
   FreeAndNil(ParaPackages);
   FreeAndNil(ParaPackages);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
@@ -245,6 +242,8 @@ begin
         GlobalOptions.InstallGlobal:=true
         GlobalOptions.InstallGlobal:=true
       else if CheckOption(I,'r','recovery') then
       else if CheckOption(I,'r','recovery') then
         GlobalOptions.RecoveryMode:=true
         GlobalOptions.RecoveryMode:=true
+      else if CheckOption(I,'b','broken') then
+        GlobalOptions.AllowBroken:=true
       else if CheckOption(I,'h','help') then
       else if CheckOption(I,'h','help') then
         begin
         begin
           ShowUsage;
           ShowUsage;
@@ -273,8 +272,8 @@ procedure TMakeTool.DoRun;
 var
 var
   ActionPackage : TFPPackage;
   ActionPackage : TFPPackage;
   OldCurrDir : String;
   OldCurrDir : String;
-  Res    : Boolean;
   i      : Integer;
   i      : Integer;
+  SL     : TStringList;
 begin
 begin
   OldCurrDir:=GetCurrentDir;
   OldCurrDir:=GetCurrentDir;
   Try
   Try
@@ -289,14 +288,14 @@ begin
     if not FileExists(GlobalOptions.LocalPackagesFile) then
     if not FileExists(GlobalOptions.LocalPackagesFile) then
       begin
       begin
         try
         try
-          pkghandler.ExecuteAction(nil,'update');
+          pkghandler.ExecuteAction('','update');
         except
         except
           on E: Exception do
           on E: Exception do
             Log(vlWarning,E.Message);
             Log(vlWarning,E.Message);
         end;
         end;
       end;
       end;
-    LoadLocalMirrors;
-    LoadLocalRepository;
+    LoadLocalAvailableMirrors;
+    LoadLocalAvailableRepository;
     FindInstalledPackages(FPMakeCompilerOptions,true);
     FindInstalledPackages(FPMakeCompilerOptions,true);
     CheckFPMakeDependencies;
     CheckFPMakeDependencies;
     // We only need to reload the status when we use a different
     // We only need to reload the status when we use a different
@@ -304,10 +303,20 @@ begin
     if GlobalOptions.CompilerConfig<>GlobalOptions.FPMakeCompilerConfig then
     if GlobalOptions.CompilerConfig<>GlobalOptions.FPMakeCompilerConfig then
       FindInstalledPackages(CompilerOptions,true);
       FindInstalledPackages(CompilerOptions,true);
 
 
+    // Check for broken dependencies
+    if not GlobalOptions.AllowBroken and
+       not((ParaPackages.Count=0) and (ParaAction='fixbroken')) then
+      begin
+        SL:=TStringList.Create;
+        if FindBrokenPackages(SL) then
+          Error(SErrBrokenPackagesFound);
+        FreeAndNil(SL);
+      end;
+
     if ParaPackages.Count=0 then
     if ParaPackages.Count=0 then
       begin
       begin
-        Log(vlDebug,SLogCommandLineAction,['[<currentdir>]',ParaAction]);
-        res:=pkghandler.ExecuteAction(nil,ParaAction);
+        ActionPackage:=InstalledRepository.AddPackage(CurrentDirPackageName);
+        pkghandler.ExecuteAction(CurrentDirPackageName,ParaAction);
       end
       end
     else
     else
       begin
       begin
@@ -316,23 +325,22 @@ begin
           begin
           begin
             if FileExists(ParaPackages[i]) then
             if FileExists(ParaPackages[i]) then
               begin
               begin
-                ActionPackage:=LoadOrCreatePackage(ChangeFileExt(ExtractFileName(ParaPackages[i]),''));
-                ActionPackage.FileName:=ExpandFileName(ParaPackages[i]);
-                ActionPackage.IsLocalPackage:=true;
-                res:=pkghandler.ExecuteAction(ActionPackage,ParaAction);
-                FreeAndNil(ActionPackage);
+                ActionPackage:=InstalledRepository.AddPackage(CmdLinePackageName);
+                ActionPackage.LocalFileName:=ExpandFileName(ParaPackages[i]);
+                pkghandler.ExecuteAction(CmdLinePackageName,ParaAction);
               end
               end
             else
             else
               begin
               begin
-                ActionPackage:=CurrentRepository.PackageByName(ParaPackages[i]);
-                Log(vlDebug,SLogCommandLineAction,['['+ActionPackage.Name+']',ParaAction]);
-                res:=pkghandler.ExecuteAction(ActionPackage,ParaAction);
+                Log(vlDebug,SLogCommandLineAction,['['+ParaPackages[i]+']',ParaAction]);
+                pkghandler.ExecuteAction(ParaPackages[i],ParaAction);
               end;
               end;
-            if not res then
-              break;
           end;
           end;
       end;
       end;
 
 
+    // Recompile all packages dependent on this package
+    if (ParaAction='install') then
+      pkghandler.ExecuteAction('','fixbroken');
+
     Terminate;
     Terminate;
 
 
   except
   except

+ 12 - 96
utils/fppkg/fprepos.pp

@@ -79,6 +79,7 @@ type
     FCPUs : TCPUS;
     FCPUs : TCPUS;
     FMinVersion: TFPVersion;
     FMinVersion: TFPVersion;
     FPackageName: String;
     FPackageName: String;
+    FRequireChecksum : cardinal;
     procedure SetMinVersion(const AValue: TFPVersion);
     procedure SetMinVersion(const AValue: TFPVersion);
   Public
   Public
     Constructor Create(ACollection : TCollection); override;
     Constructor Create(ACollection : TCollection); override;
@@ -91,6 +92,7 @@ type
     Property MinVersion : TFPVersion Read FMinVersion Write SetMinVersion;
     Property MinVersion : TFPVersion Read FMinVersion Write SetMinVersion;
     Property OSes : TOSes Read FOSes Write FOses;
     Property OSes : TOSes Read FOSes Write FOses;
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
+    Property RequireChecksum : Cardinal Read FRequireChecksum Write FRequireChecksum;
   end;
   end;
 
 
   { TFPDepencencies }
   { TFPDepencencies }
@@ -116,11 +118,12 @@ type
     FExternalURL: String;
     FExternalURL: String;
     FFileName: String;
     FFileName: String;
     FVersion: TFPVersion;
     FVersion: TFPVersion;
-    FInstalledVersion: TFPVersion;
     FDependencies : TFPDependencies;
     FDependencies : TFPDependencies;
     FOSes : TOSES;
     FOSes : TOSES;
     FCPUs : TCPUS;
     FCPUs : TCPUS;
-    FIsLocalPackage : Boolean;
+    // Installation info
+    FChecksum : cardinal;
+    FLocalFileName : String;
     function GetFileName: String;
     function GetFileName: String;
     procedure SetName(const AValue: String);
     procedure SetName(const AValue: String);
     procedure SetVersion(const AValue: TFPVersion);
     procedure SetVersion(const AValue: TFPVersion);
@@ -130,13 +133,12 @@ type
     Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
     Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
     Procedure SaveToStream(Stream : TStream); override;
     Procedure SaveToStream(Stream : TStream); override;
     Procedure Assign(Source : TPersistent); override;
     Procedure Assign(Source : TPersistent); override;
-    Function AddDependency(Const APackageName : String; AMinVersion : String = '') : TFPDependency;
+    Function AddDependency(Const APackageName : String; const AMinVersion : String = '') : TFPDependency;
     Property Dependencies : TFPDependencies Read FDependencies;
     Property Dependencies : TFPDependencies Read FDependencies;
   Published
   Published
     Property Name : String Read FName Write SetName;
     Property Name : String Read FName Write SetName;
     Property Author : String Read FAuthor Write FAuthor;
     Property Author : String Read FAuthor Write FAuthor;
     Property Version : TFPVersion Read FVersion Write SetVersion;
     Property Version : TFPVersion Read FVersion Write SetVersion;
-    Property InstalledVersion : TFPVersion Read FInstalledVersion Write FInstalledVersion;
     Property License : String Read FLicense Write FLicense;
     Property License : String Read FLicense Write FLicense;
     Property Description : String Read FDescription Write FDescription;
     Property Description : String Read FDescription Write FDescription;
     Property ExternalURL : String Read FExternalURL Write FExternalURL;
     Property ExternalURL : String Read FExternalURL Write FExternalURL;
@@ -144,8 +146,9 @@ type
     Property Email : String Read FEmail Write FEmail;
     Property Email : String Read FEmail Write FEmail;
     Property OSes : TOSes Read FOSes Write FOses;
     Property OSes : TOSes Read FOSes Write FOses;
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
+    Property Checksum : Cardinal Read FChecksum Write FChecksum;
     // Manual package from commandline not in official repository
     // Manual package from commandline not in official repository
-    Property IsLocalPackage : Boolean Read FIsLocalPackage Write FIsLocalPackage;
+    Property LocalFileName : String Read FLocalFileName Write FLocalFileName;
   end;
   end;
 
 
   { TFPPackages }
   { TFPPackages }
@@ -189,14 +192,6 @@ type
     Procedure LoadFromFile(const AFileName : String);
     Procedure LoadFromFile(const AFileName : String);
     Procedure SaveToFile(const AFileName : String);
     Procedure SaveToFile(const AFileName : String);
     Procedure Save;
     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
     // Package management
     Function IndexOfPackage(const APackageName : String) : Integer;
     Function IndexOfPackage(const APackageName : String) : Integer;
     Function FindPackage(const APackageName : String) : TFPPackage;
     Function FindPackage(const APackageName : String) : TFPPackage;
@@ -479,7 +474,7 @@ constructor TFPPackage.Create(ACollection: TCollection);
 begin
 begin
   inherited Create(ACollection);
   inherited Create(ACollection);
   FVersion:=TFPVersion.Create;
   FVersion:=TFPVersion.Create;
-  FInstalledVersion:=TFPVersion.Create;
+  FChecksum:=$ffffffff;
   FOSes:=AllOSes;
   FOSes:=AllOSes;
   FCPUs:=AllCPUs;
   FCPUs:=AllCPUs;
   FDependencies:=TFPDependencies.Create(TFPDependency);
   FDependencies:=TFPDependencies.Create(TFPDependency);
@@ -490,7 +485,6 @@ destructor TFPPackage.Destroy;
 begin
 begin
   FreeAndNil(FDependencies);
   FreeAndNil(FDependencies);
   FreeAndNil(FVersion);
   FreeAndNil(FVersion);
-  FreeAndNil(FInstalledVersion);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -615,7 +609,7 @@ begin
       Description:=P.Description;
       Description:=P.Description;
       ExternalURL:=P.ExternalURL;
       ExternalURL:=P.ExternalURL;
       FileName:=P.FileName;
       FileName:=P.FileName;
-      InstalledVersion.Assign(P.Installedversion);
+      Checksum:=P.Checksum;
       Dependencies.Clear;
       Dependencies.Clear;
       Dependencies.Assign(P.Dependencies);
       Dependencies.Assign(P.Dependencies);
     end
     end
@@ -624,7 +618,7 @@ begin
 end;
 end;
 
 
 
 
-function TFPPackage.AddDependency(const APackageName: String;AMinVersion: String): TFPDependency;
+function TFPPackage.AddDependency(Const APackageName : String; const AMinVersion : String = ''): TFPDependency;
 begin
 begin
   Result:=Dependencies.AddDependency(APackageName,AMinVersion);
   Result:=Dependencies.AddDependency(APackageName,AMinVersion);
 end;
 end;
@@ -802,85 +796,6 @@ begin
 end;
 end;
 
 
 
 
-procedure TFPRepository.ClearStatus;
-Var
-  I : Integer;
-begin
-  For I:=0 to PackageCount-1 do
-    With Packages[i] do
-      InstalledVersion.Clear;
-end;
-
-
-{$ifdef STATUSFILE}
-procedure TFPRepository.LoadStatusFromStream(Stream: TStream);
-Var
-  L : TStrings;
-  I : Integer;
-  N,V : String;
-begin
-  L:=TStringList.Create;
-  Try
-    L.LoadFromStream(Stream);
-    For I:=0 to L.Count-1 do
-      begin
-      L.GetNameValue(I,N,V);
-      If (N<>'') and (V<>'') then
-        PackageByName(N).InstalledVersion.AsString:=V;
-      end;
-  Finally
-    L.Free;
-  end;
-end;
-
-
-procedure TFPRepository.SaveStatusToStream(Stream: TStream);
-Var
-  L : TStrings;
-  I : Integer;
-begin
-  L:=TStringList.Create;
-  Try
-    For I:=0 to PackageCount-1 do
-      With Packages[i] do
-        if not InstalledVersion.Empty then
-          L.Add(Name+'='+InstalledVersion.AsString);
-    L.SaveToStream(Stream);
-  Finally
-    L.Free;
-  end;
-end;
-
-
-procedure TFPRepository.LoadStatusFromFile(const AFileName: String);
-Var
-  F : TFileStream;
-begin
-  F:=TFileStream.Create(AFileName,fmOpenRead);
-  Try
-    LoadStatusFromStream(F);
-  Finally
-    F.Free;
-  end;
-end;
-
-
-procedure TFPRepository.SaveStatusToFile(const AFileName: String);
-Var
-  F : TFileStream;
-begin
-  If FileExists(AFileName) and BackupFiles then
-    BackupFile(AFileName);
-  F:=TFileStream.Create(AFileName,fmCreate);
-  Try
-    SaveStatusToStream(F);
-  Finally
-    F.Free;
-  end;
-end;
-{$endif STATUSFILE}
-
-
 function TFPRepository.IndexOfPackage(const APackageName: String): Integer;
 function TFPRepository.IndexOfPackage(const APackageName: String): Integer;
 begin
 begin
   Result:=FPackages.IndexOfPackage(APackageName);
   Result:=FPackages.IndexOfPackage(APackageName);
@@ -987,6 +902,7 @@ begin
   FMinVersion:=TFPVersion.Create;
   FMinVersion:=TFPVersion.Create;
   FOSes:=AllOSes;
   FOSes:=AllOSes;
   FCPUs:=AllCPUs;
   FCPUs:=AllCPUs;
+  FRequireChecksum:=$ffffffff;
 end;
 end;
 
 
 
 

+ 152 - 95
utils/fppkg/pkgcommands.pp

@@ -23,169 +23,178 @@ type
 
 
   TCommandAddConfig = Class(TPackagehandler)
   TCommandAddConfig = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandUpdate }
   { TCommandUpdate }
 
 
   TCommandUpdate = Class(TPackagehandler)
   TCommandUpdate = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandShowAll }
   { TCommandShowAll }
 
 
   TCommandShowAll = Class(TPackagehandler)
   TCommandShowAll = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandShowAvail }
   { TCommandShowAvail }
 
 
   TCommandShowAvail = Class(TPackagehandler)
   TCommandShowAvail = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandScanPackages }
   { TCommandScanPackages }
 
 
   TCommandScanPackages = Class(TPackagehandler)
   TCommandScanPackages = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandDownload }
   { TCommandDownload }
 
 
   TCommandDownload = Class(TPackagehandler)
   TCommandDownload = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandUnzip }
   { TCommandUnzip }
 
 
   TCommandUnzip = Class(TPackagehandler)
   TCommandUnzip = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandCompile }
   { TCommandCompile }
 
 
   TCommandCompile = Class(TPackagehandler)
   TCommandCompile = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandBuild }
   { TCommandBuild }
 
 
   TCommandBuild = Class(TPackagehandler)
   TCommandBuild = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandInstall }
   { TCommandInstall }
 
 
   TCommandInstall = Class(TPackagehandler)
   TCommandInstall = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandClean }
   { TCommandClean }
 
 
   TCommandClean = Class(TPackagehandler)
   TCommandClean = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandArchive }
   { TCommandArchive }
 
 
   TCommandArchive = Class(TPackagehandler)
   TCommandArchive = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TCommandInstallDependencies }
   { TCommandInstallDependencies }
 
 
   TCommandInstallDependencies = Class(TPackagehandler)
   TCommandInstallDependencies = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
+  { TCommandFixBroken }
 
 
-function TCommandAddConfig.Execute(const Args:TActionArgs):boolean;
+  TCommandFixBroken = Class(TPackagehandler)
+  Public
+    Procedure Execute;override;
+  end;
+
+
+procedure TCommandAddConfig.Execute;
 begin
 begin
 {
 {
   Log(vlInfo,SLogGeneratingCompilerConfig,[S]);
   Log(vlInfo,SLogGeneratingCompilerConfig,[S]);
   Options.InitCompilerDefaults(Args[2]);
   Options.InitCompilerDefaults(Args[2]);
   Options.SaveCompilerToFile(S);
   Options.SaveCompilerToFile(S);
 }
 }
-  Result:=true;
 end;
 end;
 
 
 
 
-function TCommandUpdate.Execute(const Args:TActionArgs):boolean;
+procedure TCommandUpdate.Execute;
 var
 var
   PackagesURL :  String;
   PackagesURL :  String;
 begin
 begin
   // Download mirrors.xml
   // Download mirrors.xml
   Log(vlCommands,SLogDownloading,[GlobalOptions.RemoteMirrorsURL,GlobalOptions.LocalMirrorsFile]);
   Log(vlCommands,SLogDownloading,[GlobalOptions.RemoteMirrorsURL,GlobalOptions.LocalMirrorsFile]);
   DownloadFile(GlobalOptions.RemoteMirrorsURL,GlobalOptions.LocalMirrorsFile);
   DownloadFile(GlobalOptions.RemoteMirrorsURL,GlobalOptions.LocalMirrorsFile);
-  LoadLocalMirrors;
+  LoadLocalAvailableMirrors;
   // Download packages.xml
   // Download packages.xml
   PackagesURL:=GetRemoteRepositoryURL(PackagesFileName);
   PackagesURL:=GetRemoteRepositoryURL(PackagesFileName);
   Log(vlCommands,SLogDownloading,[PackagesURL,GlobalOptions.LocalPackagesFile]);
   Log(vlCommands,SLogDownloading,[PackagesURL,GlobalOptions.LocalPackagesFile]);
   DownloadFile(PackagesURL,GlobalOptions.LocalPackagesFile);
   DownloadFile(PackagesURL,GlobalOptions.LocalPackagesFile);
   // Read the repository again
   // Read the repository again
-  LoadLocalRepository;
+  LoadLocalAvailableRepository;
   // no need to log errors again
   // no need to log errors again
   FindInstalledPackages(CompilerOptions,False);
   FindInstalledPackages(CompilerOptions,False);
-  Result:=true;
 end;
 end;
 
 
 
 
-function TCommandShowAll.Execute(const Args:TActionArgs):boolean;
+procedure TCommandShowAll.Execute;
 begin
 begin
-  ListLocalRepository(true);
-  Result:=true;
+  ListInstalledPackages;
 end;
 end;
 
 
 
 
-function TCommandShowAvail.Execute(const Args:TActionArgs):boolean;
+procedure TCommandShowAvail.Execute;
 begin
 begin
-  ListLocalRepository(false);
-  Result:=true;
+  ListAvailablePackages;
 end;
 end;
 
 
 
 
-function TCommandScanPackages.Execute(const Args:TActionArgs):boolean;
+procedure TCommandScanPackages.Execute;
 begin
 begin
   RebuildRemoteRepository;
   RebuildRemoteRepository;
   ListRemoteRepository;
   ListRemoteRepository;
   SaveRemoteRepository;
   SaveRemoteRepository;
-  Result:=true;
 end;
 end;
 
 
 
 
-function TCommandDownload.Execute(const Args:TActionArgs):boolean;
+procedure TCommandDownload.Execute;
+var
+  P : TFPPackage;
 begin
 begin
-  if not assigned(CurrentPackage) then
+  if PackageName='' then
     Error(SErrNoPackageSpecified);
     Error(SErrNoPackageSpecified);
-  if not FileExists(PackageLocalArchive) then
-    ExecuteAction(CurrentPackage,'downloadpackage',Args);
-  Result:=true;
+  P:=AvailableRepository.PackageByName(PackageName);
+  if not FileExists(PackageLocalArchive(P)) then
+    ExecuteAction(PackageName,'downloadpackage');
 end;
 end;
 
 
 
 
-function TCommandUnzip.Execute(const Args:TActionArgs):boolean;
+procedure TCommandUnzip.Execute;
 Var
 Var
   BuildDir : string;
   BuildDir : string;
   ArchiveFile : String;
   ArchiveFile : String;
+  P : TFPPackage;
 begin
 begin
-  BuildDir:=PackageBuildPath;
-  ArchiveFile:=PackageLocalArchive;
-  if not assigned(CurrentPackage) then
+  if PackageName='' then
     Error(SErrNoPackageSpecified);
     Error(SErrNoPackageSpecified);
+  if IsLocalPackage then
+    P:=InstalledRepository.PackageByName(PackageName)
+  else
+    P:=AvailableRepository.PackageByName(PackageName);
+  BuildDir:=PackageBuildPath(P);
+  ArchiveFile:=PackageLocalArchive(P);
   if not FileExists(ArchiveFile) then
   if not FileExists(ArchiveFile) then
-    ExecuteAction(CurrentPackage,'downloadpackage');
+    ExecuteAction(PackageName,'downloadpackage');
   { Create builddir, remove it first if needed }
   { Create builddir, remove it first if needed }
   if DirectoryExists(BuildDir) then
   if DirectoryExists(BuildDir) then
     DeleteDir(BuildDir);
     DeleteDir(BuildDir);
@@ -195,121 +204,141 @@ begin
   With TUnZipper.Create do
   With TUnZipper.Create do
     try
     try
       Log(vlCommands,SLogUnzippping,[ArchiveFile]);
       Log(vlCommands,SLogUnzippping,[ArchiveFile]);
-      OutputPath:=PackageBuildPath;
+      OutputPath:=PackageBuildPath(P);
       UnZipAllFiles(ArchiveFile);
       UnZipAllFiles(ArchiveFile);
     Finally
     Finally
       Free;
       Free;
     end;
     end;
-  Result:=true;
 end;
 end;
 
 
 
 
-function TCommandCompile.Execute(const Args:TActionArgs):boolean;
+procedure TCommandCompile.Execute;
 begin
 begin
-  if assigned(CurrentPackage) then
+  if PackageName<>'' then
     begin
     begin
       // For local files we need the information inside the zip to get the
       // For local files we need the information inside the zip to get the
       // dependencies
       // dependencies
-      if CurrentPackage.IsLocalPackage then
+      if IsLocalPackage then
         begin
         begin
-          ExecuteAction(CurrentPackage,'unzip',Args);
-          ExecuteAction(CurrentPackage,'installdependencies',Args);
+          ExecuteAction(PackageName,'unzip');
+          ExecuteAction(PackageName,'installdependencies');
         end
         end
       else
       else
         begin
         begin
-          ExecuteAction(CurrentPackage,'installdependencies',Args);
-          ExecuteAction(CurrentPackage,'unzip',Args);
+          ExecuteAction(PackageName,'installdependencies');
+          ExecuteAction(PackageName,'unzip');
         end;
         end;
     end;
     end;
-  ExecuteAction(CurrentPackage,'fpmakecompile',Args);
-  Result:=true;
+  ExecuteAction(PackageName,'fpmakecompile');
 end;
 end;
 
 
 
 
-function TCommandBuild.Execute(const Args:TActionArgs):boolean;
+procedure TCommandBuild.Execute;
 begin
 begin
-  if assigned(CurrentPackage) then
+  if PackageName<>'' then
     begin
     begin
       // For local files we need the information inside the zip to get the
       // For local files we need the information inside the zip to get the
       // dependencies
       // dependencies
-      if CurrentPackage.IsLocalPackage then
+      if IsLocalPackage then
         begin
         begin
-          ExecuteAction(CurrentPackage,'unzip',Args);
-          ExecuteAction(CurrentPackage,'installdependencies',Args);
+          ExecuteAction(PackageName,'unzip');
+          ExecuteAction(PackageName,'installdependencies');
         end
         end
       else
       else
         begin
         begin
-          ExecuteAction(CurrentPackage,'installdependencies',Args);
-          ExecuteAction(CurrentPackage,'unzip',Args);
+          ExecuteAction(PackageName,'installdependencies');
+          ExecuteAction(PackageName,'unzip');
         end;
         end;
     end;
     end;
-  ExecuteAction(CurrentPackage,'fpmakebuild',Args);
-  Result:=true;
+  ExecuteAction(PackageName,'fpmakebuild');
 end;
 end;
 
 
 
 
-function TCommandInstall.Execute(const Args:TActionArgs):boolean;
+procedure TCommandInstall.Execute;
+var
+  UFN,S : String;
+  P   : TFPPackage;
 begin
 begin
-  if assigned(CurrentPackage) then
-    ExecuteAction(CurrentPackage,'build',Args);
-  ExecuteAction(CurrentPackage,'fpmakeinstall',Args);
-  // Update local status file
-  if assigned(CurrentPackage) then
-    CurrentPackage.InstalledVersion.Assign(CurrentPackage.Version);
-  Result:=true;
+  if PackageName<>'' then
+    begin
+      ExecuteAction(PackageName,'build');
+      ExecuteAction(PackageName,'fpmakeinstall');
+      if IsLocalPackage then
+        begin
+          // Load package name from manifest
+          if not FileExists(ManifestFileName) then
+            ExecuteAction(PackageName,'fpmakemanifest');
+          P:=LoadManifestFromFile(ManifestFileName);
+          S:=P.Name;
+          FreeAndNil(P);
+        end
+      else
+        S:=PackageName;
+      P:=InstalledRepository.FindPackage(S);
+      if not assigned(P) then
+        P:=InstalledRepository.AddPackage(S);
+      if GlobalOptions.InstallGlobal then
+        UFN:=CompilerOptions.GlobalUnitDir
+      else
+        UFN:=CompilerOptions.LocalUnitDir;
+      UFN:=IncludeTrailingPathDelimiter(UFN)+S+PathDelim+UnitConfigFileName;
+      LoadUnitConfigFromFile(P,UFN);
+    end
+  else
+    ExecuteAction(PackageName,'fpmakeinstall');
 end;
 end;
 
 
 
 
-function TCommandClean.Execute(const Args:TActionArgs):boolean;
+procedure TCommandClean.Execute;
 begin
 begin
-  ExecuteAction(CurrentPackage,'fpmakeclean',Args);
-  Result:=true;
+  ExecuteAction(PackageName,'fpmakeclean');
 end;
 end;
 
 
 
 
-function TCommandArchive.Execute(const Args:TActionArgs):boolean;
+procedure TCommandArchive.Execute;
 begin
 begin
-  ExecuteAction(CurrentPackage,'fpmakearchive',Args);
-  Result:=true;
+  ExecuteAction(PackageName,'fpmakearchive');
 end;
 end;
 
 
 
 
-function TCommandInstallDependencies.Execute(const Args:TActionArgs):boolean;
+procedure TCommandInstallDependencies.Execute;
 var
 var
   i : Integer;
   i : Integer;
   MissingDependency,
   MissingDependency,
   D : TFPDependency;
   D : TFPDependency;
   P,
   P,
-  DepPackage : TFPPackage;
+  InstalledP,
+  AvailP : TFPPackage;
   L : TStringList;
   L : TStringList;
   status : string;
   status : string;
 begin
 begin
-  if not assigned(CurrentPackage) then
+  if PackageName='' then
     Error(SErrNoPackageSpecified);
     Error(SErrNoPackageSpecified);
   // Load dependencies for local packages
   // Load dependencies for local packages
-  if CurrentPackage.IsLocalPackage then
+  if IsLocalPackage then
     begin
     begin
-      ExecuteAction(CurrentPackage,'fpmakemanifest',Args);
-      P:=LoadPackageManifest(ManifestFileName);
-      // Update CurrentPackage
-      CurrentPackage.Assign(P);
-      CurrentPackage.IsLocalPackage:=true;
-    end;
+      ExecuteAction(PackageName,'fpmakemanifest');
+      P:=LoadManifestFromFile(ManifestFileName);
+    end
+  else
+    P:=AvailableRepository.PackageByName(PackageName);
   // Find and List dependencies
   // Find and List dependencies
   MissingDependency:=nil;
   MissingDependency:=nil;
   L:=TStringList.Create;
   L:=TStringList.Create;
-  for i:=0 to CurrentPackage.Dependencies.Count-1 do
+  for i:=0 to P.Dependencies.Count-1 do
     begin
     begin
-      D:=CurrentPackage.Dependencies[i];
+      D:=P.Dependencies[i];
       if (CompilerOptions.CompilerOS in D.OSes) and
       if (CompilerOptions.CompilerOS in D.OSes) and
          (CompilerOptions.CompilerCPU in D.CPUs) then
          (CompilerOptions.CompilerCPU in D.CPUs) then
         begin
         begin
-          DepPackage:=CurrentRepository.PackageByName(D.PackageName);
+          InstalledP:=InstalledRepository.FindPackage(D.PackageName);
           // Need installation?
           // Need installation?
-          if (DepPackage.InstalledVersion.Empty) or
-             (DepPackage.InstalledVersion.CompareVersion(D.MinVersion)<0) then
+          if not assigned(InstalledP) or
+             (InstalledP.Version.CompareVersion(D.MinVersion)<0) then
             begin
             begin
-              if DepPackage.Version.CompareVersion(D.MinVersion)<0 then
+              AvailP:=AvailableRepository.FindPackage(D.PackageName);
+              if not assigned(AvailP) or
+                 (AvailP.Version.CompareVersion(D.MinVersion)<0) then
                 begin
                 begin
                   status:='Not Available!';
                   status:='Not Available!';
                   MissingDependency:=D;
                   MissingDependency:=D;
@@ -317,13 +346,22 @@ begin
               else
               else
                 begin
                 begin
                   status:='Updating';
                   status:='Updating';
-                  L.Add(DepPackage.Name);
+                  L.Add(D.PackageName);
                 end;
                 end;
             end
             end
           else
           else
-            status:='OK';
+            begin
+              if PackageIsBroken(InstalledP) then
+                begin
+                  status:='Broken, recompiling';
+                  L.Add(D.PackageName);
+                end
+              else
+                status:='OK';
+            end;
           Log(vlInfo,SLogPackageDependency,
           Log(vlInfo,SLogPackageDependency,
-              [D.PackageName,D.MinVersion.AsString,DepPackage.InstalledVersion.AsString,DepPackage.Version.AsString,status]);
+              [D.PackageName,D.MinVersion.AsString,PackageInstalledVersionStr(D.PackageName),
+               PackageAvailableVersionStr(D.PackageName),status]);
         end
         end
       else
       else
         Log(vlDebug,SDbgPackageDependencyOtherTarget,[D.PackageName,MakeTargetString(CompilerOptions.CompilerCPU,CompilerOptions.CompilerOS)]);
         Log(vlDebug,SDbgPackageDependencyOtherTarget,[D.PackageName,MakeTargetString(CompilerOptions.CompilerCPU,CompilerOptions.CompilerOS)]);
@@ -333,12 +371,30 @@ begin
     Error(SErrNoPackageAvailable,[MissingDependency.PackageName,MissingDependency.MinVersion.AsString]);
     Error(SErrNoPackageAvailable,[MissingDependency.PackageName,MissingDependency.MinVersion.AsString]);
   // Install needed updates
   // Install needed updates
   for i:=0 to L.Count-1 do
   for i:=0 to L.Count-1 do
-    begin
-      DepPackage:=CurrentRepository.PackageByName(L[i]);
-      ExecuteAction(DepPackage,'install');
-    end;
+    ExecuteAction(L[i],'install');
   FreeAndNil(L);
   FreeAndNil(L);
-  Result:=true;
+  if IsLocalPackage then
+    FreeAndNil(P);
+end;
+
+
+procedure TCommandFixBroken.Execute;
+var
+  i : integer;
+  SL : TStringList;
+begin
+  SL:=TStringList.Create;
+  repeat
+    FindBrokenPackages(SL);
+    if SL.Count=0 then
+      break;
+    for i:=0 to SL.Count-1 do
+      begin
+        ExecuteAction(SL[i],'build');
+        ExecuteAction(SL[i],'install');
+      end;
+  until false;
+  FreeAndNil(SL);
 end;
 end;
 
 
 
 
@@ -355,4 +411,5 @@ initialization
   RegisterPkgHandler('clean',TCommandClean);
   RegisterPkgHandler('clean',TCommandClean);
   RegisterPkgHandler('archive',TCommandArchive);
   RegisterPkgHandler('archive',TCommandArchive);
   RegisterPkgHandler('installdependencies',TCommandInstallDependencies);
   RegisterPkgHandler('installdependencies',TCommandInstallDependencies);
+  RegisterPkgHandler('fixbroken',TCommandFixBroken);
 end.
 end.

+ 9 - 5
utils/fppkg/pkgdownload.pp

@@ -30,7 +30,7 @@ Type
 
 
   TDownloadPackage = Class(TPackagehandler)
   TDownloadPackage = Class(TPackagehandler)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
 procedure RegisterDownloader(const AName:string;Downloaderclass:TBaseDownloaderClass);
 procedure RegisterDownloader(const AName:string;Downloaderclass:TBaseDownloaderClass);
@@ -44,9 +44,11 @@ implementation
 uses
 uses
   contnrs,
   contnrs,
   uriparser,
   uriparser,
+  fprepos,
   pkgglobals,
   pkgglobals,
   pkgoptions,
   pkgoptions,
-  pkgmessages;
+  pkgmessages,
+  pkgrepos;
 
 
 var
 var
   DownloaderList  : TFPHashList;
   DownloaderList  : TFPHashList;
@@ -157,15 +159,17 @@ end;
 
 
 { TDownloadPackage }
 { TDownloadPackage }
 
 
-function TDownloadPackage.Execute(const Args:TActionArgs):boolean;
+procedure TDownloadPackage.Execute;
 var
 var
   DownloaderClass : TBaseDownloaderClass;
   DownloaderClass : TBaseDownloaderClass;
+  P : TFPPackage;
 begin
 begin
+  P:=AvailableRepository.PackageByName(PackageName);
   DownloaderClass:=GetDownloader(GlobalOptions.Downloader);
   DownloaderClass:=GetDownloader(GlobalOptions.Downloader);
   with DownloaderClass.Create(nil) do
   with DownloaderClass.Create(nil) do
     try
     try
-      Log(vlCommands,SLogDownloading,[PackageRemoteArchive,PackageLocalArchive]);
-      Download(PackageRemoteArchive,PackageLocalArchive);
+      Log(vlCommands,SLogDownloading,[PackageRemoteArchive(P),PackageLocalArchive(P)]);
+      Download(PackageRemoteArchive(P),PackageLocalArchive(P));
     finally
     finally
       Free;
       Free;
     end;
     end;

+ 42 - 42
utils/fppkg/pkgfpmake.pp

@@ -13,16 +13,15 @@ uses
   fprepos,
   fprepos,
   pkgoptions,
   pkgoptions,
   pkgglobals,
   pkgglobals,
-  pkgmessages;
+  pkgmessages,
+  pkgrepos;
 
 
 type
 type
   { TFPMakeCompiler }
   { TFPMakeCompiler }
 
 
   TFPMakeCompiler = Class(TPackagehandler)
   TFPMakeCompiler = Class(TPackagehandler)
-  Private
-    Procedure CompileFPMake;
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
 
 
@@ -38,7 +37,7 @@ type
 
 
   TFPMakeRunnerCompile = Class(TFPMakeRunner)
   TFPMakeRunnerCompile = Class(TFPMakeRunner)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
 
 
@@ -46,7 +45,7 @@ type
 
 
   TFPMakeRunnerBuild = Class(TFPMakeRunner)
   TFPMakeRunnerBuild = Class(TFPMakeRunner)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
 
 
@@ -54,7 +53,7 @@ type
 
 
   TFPMakeRunnerInstall = Class(TFPMakeRunner)
   TFPMakeRunnerInstall = Class(TFPMakeRunner)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
 
 
@@ -62,21 +61,21 @@ type
 
 
   TFPMakeRunnerClean = Class(TFPMakeRunner)
   TFPMakeRunnerClean = Class(TFPMakeRunner)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TFPMakeRunnerManifest }
   { TFPMakeRunnerManifest }
 
 
   TFPMakeRunnerManifest = Class(TFPMakeRunner)
   TFPMakeRunnerManifest = Class(TFPMakeRunner)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
   { TFPMakeRunnerArchive }
   { TFPMakeRunnerArchive }
 
 
   TFPMakeRunnerArchive = Class(TFPMakeRunner)
   TFPMakeRunnerArchive = Class(TFPMakeRunner)
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
    TMyMemoryStream=class(TMemoryStream)
    TMyMemoryStream=class(TMemoryStream)
@@ -120,7 +119,7 @@ end;
 
 
 { TFPMakeCompiler }
 { TFPMakeCompiler }
 
 
-Procedure TFPMakeCompiler.CompileFPMake;
+Procedure TFPMakeCompiler.Execute;
 var
 var
   OOptions : string;
   OOptions : string;
 
 
@@ -161,9 +160,11 @@ Var
   FPMakeSrc : string;
   FPMakeSrc : string;
   NeedFPMKUnitSource,
   NeedFPMKUnitSource,
   HaveFpmake : boolean;
   HaveFpmake : boolean;
+  P : TFPPackage;
 begin
 begin
+  P:=InstalledRepository.PackageByName(PackageName);
   OOptions:='';
   OOptions:='';
-  SetCurrentDir(PackageBuildPath);
+  SetCurrentDir(PackageBuildPath(P));
   // Check for fpmake source
   // Check for fpmake source
   FPMakeBin:='fpmake'+ExeExt;
   FPMakeBin:='fpmake'+ExeExt;
   FPMakeSrc:='fpmake.pp';
   FPMakeSrc:='fpmake.pp';
@@ -222,7 +223,12 @@ begin
         CreateFPMKUnitSource(TempBuildDir+PathDelim+'fpmkunit.pp');
         CreateFPMKUnitSource(TempBuildDir+PathDelim+'fpmkunit.pp');
       // Call compiler
       // Call compiler
       If ExecuteProcess(FPMakeCompilerOptions.Compiler,OOptions+' '+FPmakeSrc)<>0 then
       If ExecuteProcess(FPMakeCompilerOptions.Compiler,OOptions+' '+FPmakeSrc)<>0 then
-        Error(SErrFailedToCompileFPCMake);
+        begin
+          if not GlobalOptions.RecoveryMode then
+            Error(SErrCompileFailureFPMakeTryRecovery)
+          else
+            Error(SErrCompileFailureFPMake);
+        end;
       // Cleanup units
       // Cleanup units
       DeleteDir(TempBuildDir);
       DeleteDir(TempBuildDir);
     end
     end
@@ -231,18 +237,11 @@ begin
 end;
 end;
 
 
 
 
-function TFPMakeCompiler.Execute(const Args:TActionArgs):boolean;
-begin
-{$warning TODO Check arguments}
-  CompileFPMake;
-  result:=true;
-end;
-
-
 { TFPMakeRunner }
 { TFPMakeRunner }
 
 
 Function TFPMakeRunner.RunFPMake(const Command:string) : Integer;
 Function TFPMakeRunner.RunFPMake(const Command:string) : Integer;
 Var
 Var
+  P : TFPPackage;
   FPMakeBin,
   FPMakeBin,
   OOptions : string;
   OOptions : string;
 
 
@@ -256,15 +255,18 @@ Var
 begin
 begin
   OOptions:='';
   OOptions:='';
   // Does the current package support this CPU-OS?
   // Does the current package support this CPU-OS?
-  if assigned(CurrentPackage) then
+  if PackageName<>'' then
+    P:=InstalledRepository.PackageByName(PackageName)
+  else
+    P:=nil;
+  if assigned(P) then
     begin
     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)]);
+      if not(CompilerOptions.CompilerOS in P.OSes) or
+         not(CompilerOptions.CompilerCPU in P.CPUs) then
+        Error(SErrPackageDoesNotSupportTarget,[P.Name,MakeTargetString(CompilerOptions.CompilerCPU,CompilerOptions.CompilerOS)]);
     end;
     end;
   { Maybe compile fpmake executable? }
   { Maybe compile fpmake executable? }
-  ExecuteAction(CurrentPackage,'compilefpmake');
+  ExecuteAction(PackageName,'compilefpmake');
   { Create options }
   { Create options }
   AddOption('--nofpccfg');
   AddOption('--nofpccfg');
   if vlInfo in LogLevels then
   if vlInfo in LogLevels then
@@ -281,51 +283,49 @@ begin
   AddOption('--globalunitdir='+CompilerOptions.GlobalUnitDir);
   AddOption('--globalunitdir='+CompilerOptions.GlobalUnitDir);
   { Run FPMake }
   { Run FPMake }
   FPMakeBin:='fpmake'+ExeExt;
   FPMakeBin:='fpmake'+ExeExt;
-  SetCurrentDir(PackageBuildPath);
+  SetCurrentDir(PackageBuildPath(P));
   Result:=ExecuteProcess(FPMakeBin,Command+' '+OOptions);
   Result:=ExecuteProcess(FPMakeBin,Command+' '+OOptions);
   if Result<>0 then
   if Result<>0 then
     Error(SErrExecutionFPMake,[Command]);
     Error(SErrExecutionFPMake,[Command]);
 end;
 end;
 
 
 
 
-function TFPMakeRunnerCompile.Execute(const Args:TActionArgs):boolean;
+procedure TFPMakeRunnerCompile.Execute;
 begin
 begin
-  result:=(RunFPMake('compile')=0);
+  RunFPMake('compile');
 end;
 end;
 
 
 
 
-function TFPMakeRunnerBuild.Execute(const Args:TActionArgs):boolean;
+procedure TFPMakeRunnerBuild.Execute;
 begin
 begin
-  result:=(RunFPMake('build')=0);
+  RunFPMake('build');
 end;
 end;
 
 
 
 
-function TFPMakeRunnerInstall.Execute(const Args:TActionArgs):boolean;
+procedure TFPMakeRunnerInstall.Execute;
 begin
 begin
-  result:=(RunFPMake('install')=0);
+  RunFPMake('install');
 end;
 end;
 
 
 
 
-function TFPMakeRunnerClean.Execute(const Args:TActionArgs):boolean;
+procedure TFPMakeRunnerClean.Execute;
 begin
 begin
-  result:=(RunFPMake('clean')=0);
+  RunFPMake('clean');
 end;
 end;
 
 
 
 
-function TFPMakeRunnerManifest.Execute(const Args:TActionArgs):boolean;
+procedure TFPMakeRunnerManifest.Execute;
 begin
 begin
-  result:=(RunFPMake('manifest')=0);
+  RunFPMake('manifest');
 end;
 end;
 
 
 
 
-function TFPMakeRunnerArchive.Execute(const Args:TActionArgs):boolean;
+procedure TFPMakeRunnerArchive.Execute;
 begin
 begin
-  result:=(RunFPMake('archive')=0);
+  RunFPMake('archive');
 end;
 end;
 
 
 
 
-
-
 initialization
 initialization
   RegisterPkgHandler('compilefpmake',TFPMakeCompiler);
   RegisterPkgHandler('compilefpmake',TFPMakeCompiler);
   RegisterPkgHandler('fpmakecompile',TFPMakeRunnerCompile);
   RegisterPkgHandler('fpmakecompile',TFPMakeRunnerCompile);

+ 74 - 156
utils/fppkg/pkghandler.pp

@@ -10,52 +10,31 @@ uses
   pkgoptions,
   pkgoptions,
   fprepos;
   fprepos;
 
 
-type
-  { TActionStack }
-
-  TActionArgs = array of string;
-
-  TActionStackItem = record
-    ActionPackage : TFPPackage;
-    Action : string;
-    Args   : TActionArgs;
-  end;
-  PActionStackItem = ^TActionStackItem;
-
-  TActionStack = class
-  private
-    FList : TFPList;
-  public
-    constructor Create;
-    destructor Destroy;override;
-    procedure Push(APackage:TFPPackage;const AAction:string;const Args:TActionArgs);
-    procedure Push(APackage:TFPPackage;const AAction:string;const Args:array of string);
-    function  Pop(out APackage:TFPPackage;out AAction:string;out Args:TActionArgs):boolean;
-  end;
-
+const
+  CmdLinePackageName='<cmdline>';
+  CurrentDirPackageName='<currentdir>';
 
 
+type
   { TPackageHandler }
   { TPackageHandler }
 
 
   TPackageHandler = Class(TComponent)
   TPackageHandler = Class(TComponent)
   private
   private
-    FCurrentPackage : TFPPackage;
+    FPackageName : string;
+    FIsLocalPackage : boolean;
   Protected
   Protected
     Procedure Log(Level: TLogLevel;Msg : String);
     Procedure Log(Level: TLogLevel;Msg : String);
     Procedure Log(Level: TLogLevel;Fmt : String; const Args : array of const);
     Procedure Log(Level: TLogLevel;Fmt : String; const Args : array of const);
     Procedure Error(Msg : String);
     Procedure Error(Msg : String);
     Procedure Error(Fmt : String; const Args : array of const);
     Procedure Error(Fmt : String; const Args : array of const);
-    procedure ExecuteAction(APackage:TFPPackage;const AAction:string;const Args:TActionArgs=nil);
     Function ExecuteProcess(Const Prog,Args:String):Integer;
     Function ExecuteProcess(Const Prog,Args:String):Integer;
     Procedure SetCurrentDir(Const ADir:String);
     Procedure SetCurrentDir(Const ADir:String);
-    function PackageBuildPath:String;
-    function PackageRemoteArchive:String;
-    function PackageLocalArchive:String;
-    function PackageManifestFile:String;
   Public
   Public
-    Constructor Create(AOwner:TComponent;APackage:TFPPackage); virtual;
+    Constructor Create(AOwner:TComponent;const APackageName:string); virtual;
     function PackageLogPrefix:String;
     function PackageLogPrefix:String;
-    Function Execute(const Args:TActionArgs):boolean; virtual; abstract;
-    Property CurrentPackage:TFPPackage Read FCurrentPackage Write FCurrentPackage;
+    procedure ExecuteAction(const APackageName,AAction:string);
+    procedure Execute; virtual; abstract;
+    Property PackageName:string Read FPackageName;
+    Property IsLocalPackage:boolean Read FIsLocalPackage Write FIsLocalPackage;
   end;
   end;
   TPackageHandlerClass = class of TPackageHandler;
   TPackageHandlerClass = class of TPackageHandler;
 
 
@@ -64,7 +43,12 @@ type
 // Actions/PkgHandler
 // Actions/PkgHandler
 procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
 procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
 function GetPkgHandler(const AAction:string):TPackageHandlerClass;
 function GetPkgHandler(const AAction:string):TPackageHandlerClass;
-function ExecuteAction(APackage:TFPPackage;const AAction:string;const Args:TActionArgs=nil):Boolean;
+procedure ExecuteAction(const APackageName,AAction:string);
+
+function PackageBuildPath(APackage:TFPPackage):String;
+function PackageRemoteArchive(APackage:TFPPackage): String;
+function PackageLocalArchive(APackage:TFPPackage): String;
+function PackageManifestFile(APackage:TFPPackage): String;
 
 
 
 
 Implementation
 Implementation
@@ -99,203 +83,137 @@ begin
 end;
 end;
 
 
 
 
-function ExecuteAction(APackage:TFPPackage;const AAction:string;const Args:TActionArgs=nil):Boolean;
+procedure ExecuteAction(const APackageName,AAction:string);
 var
 var
   pkghandlerclass : TPackageHandlerClass;
   pkghandlerclass : TPackageHandlerClass;
-  i : integer;
-  logargs : string;
   FullActionName : string;
   FullActionName : string;
 begin
 begin
-  result:=false;
   // Check if we have already executed or are executing the action
   // Check if we have already executed or are executing the action
-  if assigned(Apackage) then
-    FullActionName:=APackage.Name+AAction
-  else
-    FullActionName:=AAction;
+  FullActionName:=APackageName+AAction;
   if ExecutedActions.Find(FullActionName)<>nil then
   if ExecutedActions.Find(FullActionName)<>nil then
     begin
     begin
       Log(vlDebug,'Already executed or executing action '+FullActionName);
       Log(vlDebug,'Already executed or executing action '+FullActionName);
-      result:=true;
       exit;
       exit;
     end;
     end;
   ExecutedActions.Add(FullActionName,Pointer(PtrUInt(1)));
   ExecutedActions.Add(FullActionName,Pointer(PtrUInt(1)));
   // Create action handler class
   // Create action handler class
   pkghandlerclass:=GetPkgHandler(AAction);
   pkghandlerclass:=GetPkgHandler(AAction);
-  With pkghandlerclass.Create(nil,APackage) do
+  With pkghandlerclass.Create(nil,APackageName) do
     try
     try
-      logargs:='';
-      for i:=Low(Args) to High(Args) do
-        begin
-          if logargs='' then
-            logargs:=Args[i]
-          else
-            logargs:=logargs+','+Args[i];
-        end;
-      Log(vlDebug,SLogRunAction+' start',[AAction,logargs]);
-      result:=Execute(Args);
-      Log(vlDebug,SLogRunAction+' end',[AAction,logargs]);
+      if (APackageName=CmdLinePackageName) or
+         (APackageName=CurrentDirPackageName) then
+        IsLocalPackage:=true;
+      Log(vlDebug,SLogRunAction+' start',[AAction]);
+      Execute;
+      Log(vlDebug,SLogRunAction+' end',[AAction]);
     finally
     finally
       Free;
       Free;
     end;
     end;
 end;
 end;
 
 
 
 
-{ TPackageHandler }
-
-constructor TPackageHandler.Create(AOwner:TComponent;APackage:TFPPackage);
-begin
-  inherited Create(AOwner);
-  FCurrentPackage:=APackage;
-end;
-
-Function TPackageHandler.ExecuteProcess(Const Prog,Args:String):Integer;
-begin
-  Log(vlCommands,SLogExecute,[Prog,Args]);
-  Result:=SysUtils.ExecuteProcess(Prog,Args);
-end;
-
-
-Procedure TPackageHandler.SetCurrentDir(Const ADir:String);
+function PackageBuildPath(APackage:TFPPackage):String;
 begin
 begin
-  Log(vlCommands,SLogChangeDir,[ADir]);
-  if not SysUtils.SetCurrentDir(ADir) then
-    Error(SErrChangeDirFailed,[ADir]);
-end;
-
-
-function TPackageHandler.PackageBuildPath:String;
-begin
-  if CurrentPackage=nil then
+  if APackage.Name=CurrentDirPackageName then
     Result:='.'
     Result:='.'
+  else if APackage.Name=CmdLinePackageName then
+    Result:=GlobalOptions.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'')
   else
   else
-    Result:=GlobalOptions.BuildDir+CurrentPackage.Name;
+    Result:=GlobalOptions.BuildDir+APackage.Name;
 end;
 end;
 
 
-function TPackageHandler.PackageRemoteArchive: String;
+
+function PackageRemoteArchive(APackage:TFPPackage): String;
 begin
 begin
-  if not assigned(CurrentPackage) then
-    Error(SErrNoPackageSpecified);
-  if CurrentPackage.IsLocalPackage then
+  if APackage.Name=CurrentDirPackageName then
+    Error(SErrNoPackageSpecified)
+  else if APackage.Name=CmdLinePackageName then
     Error(SErrPackageIsLocal);
     Error(SErrPackageIsLocal);
-  if CurrentPackage.ExternalURL<>'' then
-    Result:=CurrentPackage.ExternalURL
+  if APackage.ExternalURL<>'' then
+    Result:=APackage.ExternalURL
   else
   else
-    Result:=GetRemoteRepositoryURL(CurrentPackage.FileName);
+    Result:=GetRemoteRepositoryURL(APackage.FileName);
 end;
 end;
 
 
-function TPackageHandler.PackageLocalArchive: String;
+
+function PackageLocalArchive(APackage:TFPPackage): String;
 begin
 begin
-  if not assigned(CurrentPackage) then
-    Error(SErrNoPackageSpecified);
-  if CurrentPackage.IsLocalPackage then
-    Result:=CurrentPackage.FileName
+  if APackage.Name=CurrentDirPackageName then
+    Error(SErrNoPackageSpecified)
+  else if APackage.Name=CmdLinePackageName then
+    Result:=APackage.LocalFileName
   else
   else
-    Result:=GlobalOptions.ArchivesDir+CurrentPackage.FileName;
+    Result:=GlobalOptions.ArchivesDir+APackage.FileName;
 end;
 end;
 
 
 
 
-function TPackageHandler.PackageManifestFile: String;
+function PackageManifestFile(APackage:TFPPackage): String;
 begin
 begin
   Result:=ManifestFileName;
   Result:=ManifestFileName;
 end;
 end;
 
 
 
 
-function TPackageHandler.PackageLogPrefix:String;
-begin
-  if assigned(CurrentPackage) then
-    Result:='['+CurrentPackage.Name+'] '
-  else
-//    Result:='[<currentdir>] ';
-    Result:='';
-end;
-
-
-Procedure TPackageHandler.Log(Level:TLogLevel; Msg:String);
-begin
-  pkgglobals.Log(Level,PackageLogPrefix+Msg);
-end;
 
 
+{ TPackageHandler }
 
 
-Procedure TPackageHandler.Log(Level:TLogLevel; Fmt:String; const Args:array of const);
+constructor TPackageHandler.Create(AOwner:TComponent;const APackageName:string);
 begin
 begin
-  pkgglobals.Log(Level,PackageLogPrefix+Fmt,Args);
+  inherited Create(AOwner);
+  FPackageName:=APackageName;
 end;
 end;
 
 
-
-Procedure TPackageHandler.Error(Msg:String);
+Function TPackageHandler.ExecuteProcess(Const Prog,Args:String):Integer;
 begin
 begin
-  pkgglobals.Error(PackageLogPrefix+Msg);
+  Log(vlCommands,SLogExecute,[Prog,Args]);
+  Result:=SysUtils.ExecuteProcess(Prog,Args);
 end;
 end;
 
 
 
 
-Procedure TPackageHandler.Error(Fmt:String; const Args:array of const);
+Procedure TPackageHandler.SetCurrentDir(Const ADir:String);
 begin
 begin
-  pkgglobals.Error(PackageLogPrefix+Fmt,Args);
+  Log(vlCommands,SLogChangeDir,[ADir]);
+  if not SysUtils.SetCurrentDir(ADir) then
+    Error(SErrChangeDirFailed,[ADir]);
 end;
 end;
 
 
 
 
-procedure TPackageHandler.ExecuteAction(APackage: TFPPackage; const AAction: string; const Args: TActionArgs=nil);
+function TPackageHandler.PackageLogPrefix:String;
 begin
 begin
-  pkghandler.ExecuteAction(APackage,AAction,Args);
+  if PackageName<>'' then
+    Result:='['+PackageName+'] '
+  else
+    Result:='';
 end;
 end;
 
 
 
 
-{ TActionStack }
-
-constructor TActionStack.Create;
+procedure TPackageHandler.ExecuteAction(const APackageName,AAction:string);
 begin
 begin
-  FList:=TFPList.Create;
+  // Needed to override TComponent.ExecuteAction method
+  pkghandler.ExecuteAction(APackageName,AAction);
 end;
 end;
 
 
 
 
-destructor TActionStack.Destroy;
+Procedure TPackageHandler.Log(Level:TLogLevel; Msg:String);
 begin
 begin
-  FreeAndNil(FList);
+  pkgglobals.Log(Level,PackageLogPrefix+Msg);
 end;
 end;
 
 
 
 
-procedure TActionStack.Push(APackage:TFPPackage;const AAction:string;const Args:TActionArgs);
-var
-  ActionItem : PActionStackItem;
+Procedure TPackageHandler.Log(Level:TLogLevel; Fmt:String; const Args:array of const);
 begin
 begin
-  New(ActionItem);
-  ActionItem^.ActionPackage:=APackage;
-  ActionItem^.Action:=AAction;
-  ActionItem^.Args:=Args;
-  FList.Add(ActionItem);
+  pkgglobals.Log(Level,PackageLogPrefix+Fmt,Args);
 end;
 end;
 
 
 
 
-procedure TActionStack.Push(APackage:TFPPackage;const AAction:string;const Args:array of string);
-var
-  ActionArgs : TActionArgs;
-  i : integer;
+Procedure TPackageHandler.Error(Msg:String);
 begin
 begin
-  SetLength(ActionArgs,high(Args)+1);
-  for i:=low(Args) to high(Args) do
-    ActionArgs[i]:=Args[i];
-  Push(APackage,AAction,ActionArgs);
+  pkgglobals.Error(PackageLogPrefix+Msg);
 end;
 end;
 
 
 
 
-function TActionStack.Pop(out APackage:TFPPackage;out AAction:string;out Args:TActionArgs):boolean;
-var
-  ActionItem : PActionStackItem;
-  Idx : integer;
+Procedure TPackageHandler.Error(Fmt:String; const Args:array of const);
 begin
 begin
-  Result:=false;
-  if FList.Count=0 then
-    exit;
-  // Retrieve Item from stack
-  Idx:=FList.Count-1;
-  ActionItem:=PActionStackItem(FList[Idx]);
-  FList.Delete(Idx);
-  // Copy contents and dispose stack item
-  APackage:=ActionItem^.ActionPackage;
-  AAction:=ActionItem^.Action;
-  Args:=ActionItem^.Args;
-  dispose(ActionItem);
-  Result:=true;
+  pkgglobals.Error(PackageLogPrefix+Fmt,Args);
 end;
 end;
 
 
 
 

+ 8 - 2
utils/fppkg/pkgmessages.pp

@@ -26,7 +26,8 @@ Resourcestring
   SErrException              = 'The FPC Package tool encountered the following error:';
   SErrException              = 'The FPC Package tool encountered the following error:';
   SErrActionAlreadyRegistered= 'Action "%s" is already registered';
   SErrActionAlreadyRegistered= 'Action "%s" is already registered';
   SErrActionNotFound         = 'Action "%s" is not supported';
   SErrActionNotFound         = 'Action "%s" is not supported';
-  SErrFailedToCompileFPCMake = 'Could not compile fpmake driver program';
+  SErrCompileFailureFPMake   = 'Could not compile fpmake driver program';
+  SErrCompileFailureFPMakeTryRecovery = 'Could not compile fpmake driver program, try adding "--recovery"';
   SErrNoFTPDownload          = 'This binary has no support for FTP downloads.';
   SErrNoFTPDownload          = 'This binary has no support for FTP downloads.';
   SErrNoHTTPDownload         = 'This binary has no support for HTTP downloads.';
   SErrNoHTTPDownload         = 'This binary has no support for HTTP downloads.';
   SErrBackupFailed           = 'Backup of file "%s" to file "%s" failed.';
   SErrBackupFailed           = 'Backup of file "%s" to file "%s" failed.';
@@ -47,11 +48,13 @@ Resourcestring
   SErrLoginFailed            = 'FTP LOGIN command failed.';
   SErrLoginFailed            = 'FTP LOGIN command failed.';
   SErrCWDFailed              = 'FTP CWD "%s" command failed.';
   SErrCWDFailed              = 'FTP CWD "%s" command failed.';
   SErrGETFailed              = 'FTP GET "%s" command failed.';
   SErrGETFailed              = 'FTP GET "%s" command failed.';
+  SErrBrokenPackagesFound    = 'Found broken packages, run "fppkg fixbroken" first';
+  SErrManifestNoSinglePackage = 'Manifest file "%s" does not contain exactly one package';
 
 
   SLogGeneratingFPMake       = 'Generating fpmake.pp';
   SLogGeneratingFPMake       = 'Generating fpmake.pp';
   SLogNotCompilingFPMake     = 'Skipping compiling of fpmake.pp, fpmake executable already exists';
   SLogNotCompilingFPMake     = 'Skipping compiling of fpmake.pp, fpmake executable already exists';
   SLogCommandLineAction      = 'Adding action from commandline: "%s %s"';
   SLogCommandLineAction      = 'Adding action from commandline: "%s %s"';
-  SLogRunAction              = 'Action: "%s %s"';
+  SLogRunAction              = 'Action: "%s"';
   SLogExecute                = 'Executing: "%s %s"';
   SLogExecute                = 'Executing: "%s %s"';
   SLogChangeDir              = 'CurrentDir: "%s"';
   SLogChangeDir              = 'CurrentDir: "%s"';
   SLogDownloading            = 'Downloading "%s" to "%s"';
   SLogDownloading            = 'Downloading "%s" to "%s"';
@@ -73,6 +76,7 @@ Resourcestring
   SLogSelectedMirror         = 'Selected mirror "%s"';
   SLogSelectedMirror         = 'Selected mirror "%s"';
   SLogUpgradingConfig        = 'Configuration file "%s" is updated with new configuration settings';
   SLogUpgradingConfig        = 'Configuration file "%s" is updated with new configuration settings';
   SLogPackageDependency      = 'Dependency on package %s %s, installed %s, available %s  (%s)';
   SLogPackageDependency      = 'Dependency on package %s %s, installed %s, available %s  (%s)';
+  SLogPackageChecksumChanged = 'Package %s needs to be rebuild, dependency %s is modified';
 
 
   SDbgFound                  = 'Found';
   SDbgFound                  = 'Found';
   SDbgNotFound               = 'Not Found';
   SDbgNotFound               = 'Not Found';
@@ -81,6 +85,8 @@ Resourcestring
   SDbgBackupFile             = 'Creating Backup File "%s"';
   SDbgBackupFile             = 'Creating Backup File "%s"';
   SDbgPackageMultipleLocations = 'Multiple installations found for package %s, using installation "%s"';
   SDbgPackageMultipleLocations = 'Multiple installations found for package %s, using installation "%s"';
   SDbgPackageDependencyOtherTarget  = 'Dependency on package %s is not for %s';
   SDbgPackageDependencyOtherTarget  = 'Dependency on package %s is not for %s';
+  SDbgObsoleteDependency     = 'Obsolete dependency found on package %s';
+
 
 
 implementation
 implementation
 
 

+ 2 - 3
utils/fppkg/pkgmkconv.pp

@@ -42,7 +42,7 @@ Type
     procedure ConvertFile(const AFileName: String; Src: TStrings; Dir,OS : String);
     procedure ConvertFile(const AFileName: String; Src: TStrings; Dir,OS : String);
     Procedure ConvertFile(Const Source,Dest: String);
     Procedure ConvertFile(Const Source,Dest: String);
   Public
   Public
-    Function Execute(const Args:TActionArgs):boolean;override;
+    Procedure Execute;override;
   end;
   end;
 
 
 
 
@@ -696,13 +696,12 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TMakeFileConverter.Execute(const Args:TActionArgs):boolean;
+procedure TMakeFileConverter.Execute;
 begin
 begin
   if not FileExists('fpmake.pp') then
   if not FileExists('fpmake.pp') then
     ConvertFile('Makefile.fpc','fpmake.pp')
     ConvertFile('Makefile.fpc','fpmake.pp')
   else
   else
     Error(SErrConvertFPMakeExists);
     Error(SErrConvertFPMakeExists);
-  result:=true;
 end;
 end;
 
 
 begin
 begin

+ 3 - 0
utils/fppkg/pkgoptions.pp

@@ -45,6 +45,7 @@ Type
     FFPMakeCompilerConfig : String;
     FFPMakeCompilerConfig : String;
     // Parameter options
     // Parameter options
     FCompilerConfig : String;
     FCompilerConfig : String;
+    FAllowBroken,
     FInstallGlobal,
     FInstallGlobal,
     FRecoveryMode   : Boolean;
     FRecoveryMode   : Boolean;
     function  GetOptString(Index: integer): String;
     function  GetOptString(Index: integer): String;
@@ -74,6 +75,7 @@ Type
     Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
     Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
     Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
     Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
     Property RecoveryMode : Boolean Read FRecoveryMode Write FRecoveryMode;
     Property RecoveryMode : Boolean Read FRecoveryMode Write FRecoveryMode;
+    Property AllowBroken : Boolean Read FAllowBroken Write FAllowBroken;
   end;
   end;
 
 
 
 
@@ -261,6 +263,7 @@ begin
   FCompilerConfig:=FDefaultCompilerConfig;
   FCompilerConfig:=FDefaultCompilerConfig;
   FInstallGlobal:=False;
   FInstallGlobal:=False;
   FRecoveryMode:=False;
   FRecoveryMode:=False;
+  FAllowBroken:=False;
 end;
 end;
 
 
 
 

+ 314 - 129
utils/fppkg/pkgrepos.pp

@@ -10,21 +10,27 @@ uses
 
 
 function GetRemoteRepositoryURL(const AFileName:string):string;
 function GetRemoteRepositoryURL(const AFileName:string):string;
 
 
-procedure LoadLocalMirrors;
-procedure LoadLocalRepository;
-function  LoadOrCreatePackage(const AName:string):TFPPackage;
-function  LoadPackageManifest(const AManifestFN:string):TFPPackage;
+procedure LoadLocalAvailableMirrors;
+procedure LoadLocalAvailableRepository;
+procedure LoadUnitConfigFromFile(APackage:TFPPackage;const AFileName: String);
+function LoadManifestFromFile(const AManifestFN:string):TFPPackage;
 procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
 procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
+function  PackageIsBroken(APackage:TFPPackage):boolean;
+function  FindBrokenPackages(SL:TStrings):Boolean;
 procedure CheckFPMakeDependencies;
 procedure CheckFPMakeDependencies;
-procedure ListLocalRepository(all:boolean=false);
+function  PackageInstalledVersionStr(const AName:String):string;
+function  PackageAvailableVersionStr(const AName:String):string;
+procedure ListAvailablePackages;
+procedure ListInstalledPackages;
 
 
 procedure ListRemoteRepository;
 procedure ListRemoteRepository;
 procedure RebuildRemoteRepository;
 procedure RebuildRemoteRepository;
 procedure SaveRemoteRepository;
 procedure SaveRemoteRepository;
 
 
 var
 var
-  CurrentMirrors    : TFPMirrors;
-  CurrentRepository : TFPRepository;
+  AvailableMirrors    : TFPMirrors;
+  AvailableRepository,
+  InstalledRepository : TFPRepository;
 
 
 
 
 implementation
 implementation
@@ -42,14 +48,14 @@ uses
 var
 var
   CurrentRemoteRepositoryURL : String;
   CurrentRemoteRepositoryURL : String;
 
 
-procedure LoadLocalMirrors;
+procedure LoadLocalAvailableMirrors;
 var
 var
   S : String;
   S : String;
   X : TFPXMLMirrorHandler;
   X : TFPXMLMirrorHandler;
 begin
 begin
-  if assigned(CurrentMirrors) then
-    CurrentMirrors.Free;
-  CurrentMirrors:=TFPMirrors.Create(TFPMirror);
+  if assigned(AvailableMirrors) then
+    AvailableMirrors.Free;
+  AvailableMirrors:=TFPMirrors.Create(TFPMirror);
 
 
   // Repository
   // Repository
   S:=GlobalOptions.LocalMirrorsFile;
   S:=GlobalOptions.LocalMirrorsFile;
@@ -60,7 +66,7 @@ begin
     X:=TFPXMLMirrorHandler.Create;
     X:=TFPXMLMirrorHandler.Create;
     With X do
     With X do
       try
       try
-        LoadFromXml(CurrentMirrors,S);
+        LoadFromXml(AvailableMirrors,S);
       finally
       finally
         Free;
         Free;
       end;
       end;
@@ -83,22 +89,22 @@ var
 begin
 begin
   Result:='';
   Result:='';
   M:=nil;
   M:=nil;
-  if assigned(CurrentMirrors) then
+  if assigned(AvailableMirrors) then
    begin
    begin
      // Create array for selection
      // Create array for selection
      BucketCnt:=0;
      BucketCnt:=0;
-     for i:=0 to CurrentMirrors.Count-1 do
-       inc(BucketCnt,CurrentMirrors[i].Weight);
+     for i:=0 to AvailableMirrors.Count-1 do
+       inc(BucketCnt,AvailableMirrors[i].Weight);
      // Select random entry
      // Select random entry
      Bucket:=Random(BucketCnt);
      Bucket:=Random(BucketCnt);
      M:=nil;
      M:=nil;
-     for i:=0 to CurrentMirrors.Count-1 do
+     for i:=0 to AvailableMirrors.Count-1 do
        begin
        begin
-         for j:=0 to CurrentMirrors[i].Weight-1 do
+         for j:=0 to AvailableMirrors[i].Weight-1 do
            begin
            begin
              if Bucket=0 then
              if Bucket=0 then
                begin
                begin
-                 M:=CurrentMirrors[i];
+                 M:=AvailableMirrors[i];
                  break;
                  break;
                end;
                end;
              Dec(Bucket);
              Dec(Bucket);
@@ -160,55 +166,11 @@ begin
 end;
 end;
 
 
 
 
-procedure LoadLocalRepository;
-var
-  S : String;
-  X : TFPXMLRepositoryHandler;
-begin
-  if assigned(CurrentRepository) then
-    CurrentRepository.Free;
-  CurrentRepository:=TFPRepository.Create(Nil);
-  // Repository
-  S:=GlobalOptions.LocalPackagesFile;
-  Log(vlDebug,SLogLoadingPackagesFile,[S]);
-  if not FileExists(S) then
-    exit;
-  try
-    X:=TFPXMLRepositoryHandler.Create;
-    With X do
-      try
-        LoadFromXml(CurrentRepository,S);
-      finally
-        Free;
-      end;
-  except
-    on E : Exception do
-      begin
-        Log(vlError,E.Message);
-        Error(SErrCorruptPackagesFile,[S]);
-      end;
-  end;
-end;
-
-
-function LoadOrCreatePackage(const AName:string):TFPPackage;
-begin
-  result:=CurrentRepository.FindPackage(AName);
-  if not assigned(result) then
-    begin
-      result:=CurrentRepository.AddPackage(AName);
-      result.IsLocalPackage:=true;
-    end;
-end;
-
-
-function LoadPackageManifest(const AManifestFN:string):TFPPackage;
+function LoadManifestFromFile(const AManifestFN:string):TFPPackage;
 var
 var
   X : TFPXMLRepositoryHandler;
   X : TFPXMLRepositoryHandler;
-  i : integer;
-  DoAdd : Boolean;
-  NewP : TFPPackage;
   NewPackages : TFPPackages;
   NewPackages : TFPPackages;
+  NewP,P : TFPPackage;
 begin
 begin
   result:=nil;
   result:=nil;
   NewPackages:=TFPPackages.Create(TFPPackage);
   NewPackages:=TFPPackages.Create(TFPPackage);
@@ -216,27 +178,19 @@ begin
   try
   try
     X.LoadFromXml(NewPackages,AManifestFN);
     X.LoadFromXml(NewPackages,AManifestFN);
     // Update or Add packages to repository
     // Update or Add packages to repository
-    for i:=0 to NewPackages.Count-1 do
+    if NewPackages.Count=1 then
       begin
       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);
+        NewP:=NewPackages[0];
+        // Prevent duplicate names
+{        P:=InstalledRepository.FindPackage(NewP.Name);
+        if not assigned(P) then
+          P:=InstalledRepository.AddPackage(NewP.Name); }
+        result:=TFPPackage.Create(nil);
         // Copy contents
         // Copy contents
-        if DoAdd then
-          result.Assign(NewP);
-      end;
+        result.Assign(NewP);
+      end
+    else
+      Error(SErrManifestNoSinglePackage,[AManifestFN]);
   finally
   finally
     X.Free;
     X.Free;
     NewPackages.Free;
     NewPackages.Free;
@@ -244,29 +198,74 @@ begin
 end;
 end;
 
 
 
 
+procedure LoadUnitConfigFromFile(APackage:TFPPackage;const AFileName: String);
+Var
+  L,DepSL : TStrings;
+  DepName,
+  V : String;
+  DepChecksum : Cardinal;
+  i,j,k : integer;
+  D : TFPDependency;
+begin
+  L:=TStringList.Create;
+  Try
+    ReadIniFile(AFileName,L);
+{$warning TODO Maybe check also CPU-OS}
+    // Read fpunits.conf
+    V:=L.Values['version'];
+    APackage.Version.AsString:=V;
+    V:=L.Values['checksum'];
+    if V<>'' then
+      APackage.Checksum:=StrToInt(V)
+    else
+      APackage.Checksum:=$ffffffff;
+    // Load dependencies
+    V:=L.Values['depends'];
+    DepSL:=TStringList.Create;
+    DepSL.CommaText:=V;
+    for i:=0 to DepSL.Count-1 do
+      begin
+        DepName:=DepSL[i];
+        k:=Pos('|',DepName);
+        if k>0 then
+          begin
+            DepChecksum:=StrToInt(Copy(DepName,k+1,Length(DepName)-k));
+            DepName:=Copy(DepName,1,k-1);
+          end
+        else
+          DepChecksum:=$ffffffff;
+        D:=nil;
+        for j:=0 to APackage.Dependencies.Count-1 do
+          begin
+            D:=APackage.Dependencies[j];
+            if D.PackageName=DepName then
+              break;
+            D:=nil;
+          end;
+        if not assigned(D) then
+          D:=APackage.AddDependency(DepName,'');
+        D.RequireChecksum:=DepChecksum;
+      end;
+    DepSL.Free;
+  Finally
+    L.Free;
+  end;
+end;
+
+
 procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
 procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
 
 
-  procedure LoadUnitConfigFromFile(APackage:TFPPackage;const AFileName: String);
-  Var
-    L : TStrings;
-    V : String;
+  function AddInstalledPackage(const AName,AFileName: String):TFPPackage;
   begin
   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;
+    result:=InstalledRepository.FindPackage(AName);
+    if not assigned(result) then
+      result:=InstalledRepository.AddPackage(AName)
+    else
+      begin
+        // Log packages found in multiple locations (local and global) ?
+        if showdups then
+          Log(vlDebug,SDbgPackageMultipleLocations,[result.Name,ExtractFilePath(AFileName)]);
+      end;
   end;
   end;
 
 
   procedure LoadPackagefpcFromFile(APackage:TFPPackage;const AFileName: String);
   procedure LoadPackagefpcFromFile(APackage:TFPPackage;const AFileName: String);
@@ -278,7 +277,7 @@ procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boole
     Try
     Try
       ReadIniFile(AFileName,L);
       ReadIniFile(AFileName,L);
       V:=L.Values['version'];
       V:=L.Values['version'];
-      APackage.InstalledVersion.AsString:=V;
+      APackage.Version.AsString:=V;
     Finally
     Finally
       L.Free;
       L.Free;
     end;
     end;
@@ -302,7 +301,7 @@ procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boole
               UF:=UD+UnitConfigFileName;
               UF:=UD+UnitConfigFileName;
               if FileExistsLog(UF) then
               if FileExistsLog(UF) then
                 begin
                 begin
-                  P:=LoadOrCreatePackage(SR.Name);
+                  P:=AddInstalledPackage(SR.Name,UF);
                   LoadUnitConfigFromFile(P,UF)
                   LoadUnitConfigFromFile(P,UF)
                 end
                 end
               else
               else
@@ -311,7 +310,7 @@ procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boole
                   UF:=UD+'Package.fpc';
                   UF:=UD+'Package.fpc';
                   if FileExistsLog(UF) then
                   if FileExistsLog(UF) then
                     begin
                     begin
-                      P:=LoadOrCreatePackage(SR.Name);
+                      P:=AddInstalledPackage(SR.Name,UF);
                       LoadPackagefpcFromFile(P,UF);
                       LoadPackagefpcFromFile(P,UF);
                     end;
                     end;
                 end;
                 end;
@@ -321,7 +320,9 @@ procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boole
   end;
   end;
 
 
 begin
 begin
-  CurrentRepository.ClearStatus;
+  if assigned(InstalledRepository) then
+    InstalledRepository.Free;
+  InstalledRepository:=TFPRepository.Create(nil);
   // First scan the global directory
   // First scan the global directory
   // The local directory will overwrite the versions
   // The local directory will overwrite the versions
   if ACompilerOptions.GlobalUnitDir<>'' then
   if ACompilerOptions.GlobalUnitDir<>'' then
@@ -331,10 +332,58 @@ begin
 end;
 end;
 
 
 
 
+function PackageIsBroken(APackage:TFPPackage):boolean;
+var
+  j : integer;
+  D : TFPDependency;
+  DepPackage : TFPPackage;
+begin
+  result:=false;
+  for j:=0 to APackage.Dependencies.Count-1 do
+    begin
+      D:=APackage.Dependencies[j];
+      if (CompilerOptions.CompilerOS in D.OSes) and
+         (CompilerOptions.CompilerCPU in D.CPUs) then
+        begin
+          DepPackage:=InstalledRepository.FindPackage(D.PackageName);
+          // Don't stop on missing dependencies
+          if assigned(DepPackage) then
+            begin
+              if (DepPackage.Checksum<>D.RequireChecksum) then
+                begin
+                  Log(vlInfo,SLogPackageChecksumChanged,[APackage.Name,D.PackageName]);
+                  result:=true;
+                  exit;
+                end;
+            end
+          else
+            Log(vlDebug,SDbgObsoleteDependency,[D.PackageName]);
+        end;
+    end;
+end;
+
+
+function FindBrokenPackages(SL:TStrings):Boolean;
+var
+  i : integer;
+  P : TFPPackage;
+begin
+  SL.Clear;
+  for i:=0 to InstalledRepository.PackageCount-1 do
+    begin
+      P:=InstalledRepository.Packages[i];
+      if PackageIsBroken(P) then
+        SL.Add(P.Name);
+    end;
+  Result:=(SL.Count>0);
+end;
+
+
 procedure CheckFPMakeDependencies;
 procedure CheckFPMakeDependencies;
 var
 var
   i : Integer;
   i : Integer;
-  P : TFPPackage;
+  P,AvailP : TFPPackage;
+  AvailVerStr : string;
   ReqVer : TFPVersion;
   ReqVer : TFPVersion;
 begin
 begin
   // Reset availability
   // Reset availability
@@ -347,13 +396,18 @@ begin
   // Check for fpmkunit dependencies
   // Check for fpmkunit dependencies
   for i:=1 to FPMKUnitDepCount do
   for i:=1 to FPMKUnitDepCount do
     begin
     begin
-      P:=CurrentRepository.FindPackage(FPMKUnitDeps[i].package);
+      P:=InstalledRepository.FindPackage(FPMKUnitDeps[i].package);
       if P<>nil then
       if P<>nil then
         begin
         begin
+          AvailP:=AvailableRepository.FindPackage(FPMKUnitDeps[i].package);
+          if P<>nil then
+            AvailVerStr:=AvailP.Version.AsString
+          else
+            AvailVerStr:='<not available>';
           ReqVer:=TFPVersion.Create;
           ReqVer:=TFPVersion.Create;
           ReqVer.AsString:=FPMKUnitDeps[i].ReqVer;
           ReqVer.AsString:=FPMKUnitDeps[i].ReqVer;
-          Log(vlDebug,SLogFPMKUnitDepVersion,[P.Name,ReqVer.AsString,P.InstalledVersion.AsString,P.Version.AsString]);
-          if ReqVer.CompareVersion(P.InstalledVersion)<=0 then
+          Log(vlDebug,SLogFPMKUnitDepVersion,[P.Name,ReqVer.AsString,P.Version.AsString,AvailVerStr]);
+          if ReqVer.CompareVersion(P.Version)<=0 then
             FPMKUnitDepAvailable[i]:=true
             FPMKUnitDepAvailable[i]:=true
           else
           else
             Log(vlDebug,SLogFPMKUnitDepTooOld,[FPMKUnitDeps[i].package]);
             Log(vlDebug,SLogFPMKUnitDepTooOld,[FPMKUnitDeps[i].package]);
@@ -364,20 +418,107 @@ begin
 end;
 end;
 
 
 
 
-procedure ListLocalRepository(all:boolean=false);
+{*****************************************************************************
+                           Local Available Repository
+*****************************************************************************}
+
+procedure LoadLocalAvailableRepository;
+var
+  S : String;
+  X : TFPXMLRepositoryHandler;
+begin
+  if assigned(AvailableRepository) then
+    AvailableRepository.Free;
+  AvailableRepository:=TFPRepository.Create(Nil);
+  // Repository
+  S:=GlobalOptions.LocalPackagesFile;
+  Log(vlDebug,SLogLoadingPackagesFile,[S]);
+  if not FileExists(S) then
+    exit;
+  try
+    X:=TFPXMLRepositoryHandler.Create;
+    With X do
+      try
+        LoadFromXml(AvailableRepository,S);
+      finally
+        Free;
+      end;
+  except
+    on E : Exception do
+      begin
+        Log(vlError,E.Message);
+        Error(SErrCorruptPackagesFile,[S]);
+      end;
+  end;
+end;
+
+
+function PackageAvailableVersionStr(const AName:String):string;
 var
 var
   P : TFPPackage;
   P : TFPPackage;
+begin
+  P:=InstalledRepository.FindPackage(AName);
+  if P<>nil then
+    result:=P.Version.AsString
+  else
+    result:='-';
+end;
+
+
+function PackageInstalledVersionStr(const AName:String):string;
+var
+  P : TFPPackage;
+begin
+  P:=InstalledRepository.FindPackage(AName);
+  if P<>nil then
+    result:=P.Version.AsString
+  else
+    result:='-';
+end;
+
+
+
+procedure ListAvailablePackages;
+var
+  InstalledP,
+  AvailP : TFPPackage;
   i : integer;
   i : integer;
+  SL : TStringList;
 begin
 begin
+  SL:=TStringList.Create;
+  SL.Sorted:=true;
+  for i:=0 to AvailableRepository.PackageCount-1 do
+    begin
+      AvailP:=AvailableRepository.Packages[i];
+      InstalledP:=InstalledRepository.FindPackage(AvailP.Name);
+      if not assigned(InstalledP) or
+         (AvailP.Version.CompareVersion(InstalledP.Version)>0) then
+        SL.Add(Format('%-20s %-12s %-12s',[AvailP.Name,PackageInstalledVersionStr(AvailP.Name),AvailP.Version.AsString]));
+    end;
   Writeln(Format('%-20s %-12s %-12s',['Name','Installed','Available']));
   Writeln(Format('%-20s %-12s %-12s',['Name','Installed','Available']));
-  for i:=0 to CurrentRepository.PackageCount-1 do
+  for i:=0 to SL.Count-1 do
+    Writeln(SL[i]);
+  FreeAndNil(SL);
+end;
+
+
+procedure ListInstalledPackages;
+var
+  P : TFPPackage;
+  i : integer;
+  SL : TStringList;
+begin
+  SL:=TStringList.Create;
+  SL.Sorted:=true;
+  for i:=0 to InstalledRepository.PackageCount-1 do
     begin
     begin
-      P:=CurrentRepository.Packages[i];
-      if all or (P.Version.CompareVersion(P.InstalledVersion)>0) then
-        begin
-          Writeln(Format('%-20s %-12s %-12s',[P.Name,P.InstalledVersion.AsString,P.Version.AsString]));
-        end;
+      P:=InstalledRepository.Packages[i];
+      SL.Add(Format('%-20s %-12s %-12s',[P.Name,P.Version.AsString,PackageAvailableVersionStr(P.Name)]));
     end;
     end;
+  Writeln(Format('%-20s %-12s %-12s',['Name','Installed','Available']));
+  for i:=0 to SL.Count-1 do
+    Writeln(SL[i]);
+  FreeAndNil(SL);
 end;
 end;
 
 
 
 
@@ -385,30 +526,77 @@ end;
                            Remote Repository
                            Remote Repository
 *****************************************************************************}
 *****************************************************************************}
 
 
+
 procedure ListRemoteRepository;
 procedure ListRemoteRepository;
 var
 var
   P : TFPPackage;
   P : TFPPackage;
   i : integer;
   i : integer;
+  SL : TStringList;
 begin
 begin
-  Writeln(Format('%-20s %-12s %-20s',['Name','Available','FileName']));
-  for i:=0 to CurrentRepository.PackageCount-1 do
+  SL:=TStringList.Create;
+  SL.Sorted:=true;
+  for i:=0 to InstalledRepository.PackageCount-1 do
     begin
     begin
-      P:=CurrentRepository.Packages[i];
-      Writeln(Format('%-20s %-12s %-20s',[P.Name,P.Version.AsString,P.FileName]));
+      P:=InstalledRepository.Packages[i];
+      SL.Add(Format('%-20s %-12s %-20s',[P.Name,P.Version.AsString,P.FileName]));
     end;
     end;
+  Writeln(Format('%-20s %-12s %-20s',['Name','Available','FileName']));
+  for i:=0 to SL.Count-1 do
+    Writeln(SL[i]);
+  FreeAndNil(SL);
 end;
 end;
 
 
 
 
 procedure RebuildRemoteRepository;
 procedure RebuildRemoteRepository;
 
 
+  procedure LoadPackageManifest(const AManifestFN:string);
+  var
+    X : TFPXMLRepositoryHandler;
+    i : integer;
+    DoAdd : Boolean;
+    P,NewP : TFPPackage;
+    NewPackages : TFPPackages;
+  begin
+    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;
+          P:=InstalledRepository.FindPackage(NewP.Name);
+          if assigned(P) then
+            begin
+              if NewP.Version.CompareVersion(P.Version)<0 then
+                begin
+                  Writeln(Format('Ignoring package %s-%s (old %s)',[NewP.Name,NewP.Version.AsString,P.Version.AsString]));
+                  DoAdd:=False;
+                end
+              else
+                Writeln(Format('Updating package %s-%s (old %s)',[NewP.Name,NewP.Version.AsString,P.Version.AsString]));
+            end
+          else
+            P:=InstalledRepository.PackageCollection.AddPackage(NewP.Name);
+          // Copy contents
+          if DoAdd then
+            P.Assign(NewP);
+        end;
+    finally
+      X.Free;
+      NewPackages.Free;
+    end;
+  end;
+
 var
 var
   i : integer;
   i : integer;
   ArchiveSL : TStringList;
   ArchiveSL : TStringList;
   ManifestSL : TStringList;
   ManifestSL : TStringList;
 begin
 begin
-  if assigned(CurrentRepository) then
-    CurrentRepository.Free;
-  CurrentRepository:=TFPRepository.Create(Nil);
+  if assigned(InstalledRepository) then
+    InstalledRepository.Free;
+  InstalledRepository:=TFPRepository.Create(Nil);
   try
   try
     ManifestSL:=TStringList.Create;
     ManifestSL:=TStringList.Create;
     ManifestSL.Add(ManifestFileName);
     ManifestSL.Add(ManifestFileName);
@@ -456,13 +644,10 @@ begin
   X:=TFPXMLRepositoryHandler.Create;
   X:=TFPXMLRepositoryHandler.Create;
   With X do
   With X do
     try
     try
-      SaveToXml(CurrentRepository,'packages.xml');
+      SaveToXml(InstalledRepository,'packages.xml');
     finally
     finally
       Free;
       Free;
     end;
     end;
 end;
 end;
 
 
-
-
-initialization
 end.
 end.

Some files were not shown because too many files changed in this diff