Browse Source

* Store the location of the original source when installing a package
* Store the used options to install a package in fpunits.conf
* When a package is re-installed because of broken dependencies, use the stored
source-path and options if possible
* When installing a package from the current directory, make sure the right
directory is used. It could be changed while installing dependencies.

git-svn-id: trunk@16918 -

joost 14 years ago
parent
commit
4d13235ea0

+ 12 - 3
packages/fpmkunit/src/fpmkunit.pp

@@ -869,6 +869,7 @@ Type
     FRunMode: TRunMode;
     FListMode : Boolean;
     FLogLevels : TVerboseLevels;
+    FFPMakeOptionsString: string;
   Protected
     Procedure Log(Level : TVerboseLevel; Const Msg : String);
     Procedure CreatePackages; virtual;
@@ -891,6 +892,7 @@ Type
     Destructor destroy; override;
     Function AddPackage(Const AName : String) : TPackage;
     Function Run : Boolean;
+    Property FPMakeOptionsString: string read FFPMakeOptionsString;
     //files in package
     Property Packages : TPackages Read GetPackages;
     Property RunMode : TRunMode Read FRunMode;
@@ -1145,6 +1147,8 @@ Const
   KeyNeedLibC = 'NeedLibC';
   KeyDepends  = 'Depends';
   KeyAddIn    = 'FPMakeAddIn';
+  KeySourcePath = 'SourcePath';
+  KeyFPMakeOptions = 'FPMakeOptions';
 
 {****************************************************************************
                                 Helpers
@@ -2553,6 +2557,9 @@ begin
         Values[KeyChecksum]:=IntToStr(DateTimeToFileDate(Now));
         Values[KeyCPU]:=CPUToString(ACPU);
         Values[KeyOS]:=OSToString(AOS);
+        //Installer;
+        Values[KeySourcePath]:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(Installer.BuildEngine.FStartDir)+Directory);
+        Values[KeyFPMakeOptions]:=trim(Installer.FPMakeOptionsString);
         Deps:='';
         for i:=0 to Dependencies.Count-1 do
           begin
@@ -3130,12 +3137,13 @@ end;
 
 procedure TCustomInstaller.AnalyzeOptions;
 
-  Function CheckOption(Index : Integer;const Short,Long : String): Boolean;
+  Function CheckOption(Index : Integer;const Short,Long : String; AddToOptionString: boolean = true): Boolean;
   var
     O : String;
   begin
     O:=Paramstr(Index);
     Result:=(O='-'+short) or (O='--'+long) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
+    if AddToOptionString and Result then FFPMakeOptionsString := FFPMakeOptionsString+' '+O;
   end;
 
   Function CheckCustomOption(Index : Integer; out CustOptName: string): Boolean;
@@ -3154,6 +3162,7 @@ procedure TCustomInstaller.AnalyzeOptions;
     O:=copy(O,3,i-3);
     CustOptName:=O;
     Result:=CustomFpmakeCommandlineOptions.IndexOfName(O)>-1;
+    if Result then FFPMakeOptionsString := FFPMakeOptionsString+' '+Paramstr(Index);
   end;
 
 
@@ -3220,9 +3229,9 @@ begin
   While (I<ParamCount) do
     begin
     Inc(I);
-    if CheckOption(I,'v','verbose') then
+    if CheckOption(I,'v','verbose',false) then
       FLogLevels:=AllMessages
-    else if CheckOption(I,'d','debug') then
+    else if CheckOption(I,'d','debug',false) then
       FLogLevels:=AllMessages+[vlDebug]
     else if CheckCommand(I,'m','compile') then
       FRunMode:=rmCompile

+ 10 - 0
utils/fppkg/fprepos.pp

@@ -113,6 +113,9 @@ type
     FAuthor: String;
     FDescription: String;
     FEmail: String;
+    FFPMakeOptionsString: string;
+    FRecompileBroken: boolean;
+    FSourcePath: string;
     FInstalledLocally: boolean;
     FIsFPMakeAddIn: boolean;
     FLicense: String;
@@ -143,6 +146,7 @@ type
     // Only for installed packages: (is false for packages which are installed globally)
     Property InstalledLocally : boolean read FInstalledLocally write FInstalledLocally;
     Property UnusedVersion : TFPVersion Read FUnusedVersion Write SetUnusedVersion;
+    Property RecompileBroken : boolean read FRecompileBroken write FRecompileBroken;
   Published
     Property Name : String Read FName Write SetName;
     Property Author : String Read FAuthor Write FAuthor;
@@ -157,6 +161,9 @@ type
     Property CPUs : TCPUs Read FCPUs Write FCPUs;
     Property Checksum : Cardinal Read FChecksum Write FChecksum;
     Property IsFPMakeAddIn : boolean read FIsFPMakeAddIn write FIsFPMakeAddIn;
+    // These properties are used to re-compile the package, when it's dependencies are changed.
+    Property SourcePath : string read FSourcePath write FSourcePath;
+    Property FPMakeOptionsString : string read FFPMakeOptionsString write FFPMakeOptionsString;
     // Manual package from commandline not in official repository
     Property LocalFileName : String Read FLocalFileName Write FLocalFileName;
   end;
@@ -661,6 +668,9 @@ begin
       Description:=P.Description;
       HomepageURL:=P.HomepageURL;
       DownloadURL:=P.DownloadURL;
+      SourcePath:=P.SourcePath;
+      FPMakeOptionsString:=P.FPMakeOptionsString;
+      InstalledLocally:=P.InstalledLocally;
       OSes:=P.OSes;
       CPUs:=P.CPUs;
       FileName:=P.FileName;

+ 28 - 5
utils/fppkg/pkgcommands.pp

@@ -227,6 +227,8 @@ end;
 
 
 procedure TCommandBuild.Execute;
+var
+  P: TFPPackage;
 begin
   if PackageName<>'' then
     begin
@@ -245,7 +247,12 @@ begin
       else
         begin
           ExecuteAction(PackageName,'installdependencies');
-          ExecuteAction(PackageName,'unzip');
+          // Check if the package is not installed but being recompiled because of changed
+          // dependencies while the original source is still available.
+          P := AvailableRepository.FindPackage(PackageName);
+          if not (assigned(P) and P.RecompileBroken and (P.SourcePath<>'')) then
+            // The package is not available locally, download and unzip it.
+            ExecuteAction(PackageName,'unzip');
         end;
     end;
   ExecuteAction(PackageName,'fpmakebuild');
@@ -275,10 +282,26 @@ begin
       P:=InstalledRepository.FindPackage(S);
       if not assigned(P) then
         P:=InstalledRepository.AddPackage(S);
-      if IsSuperUser or GlobalOptions.InstallGlobal then
-        UFN:=CompilerOptions.GlobalUnitDir
+      if P.RecompileBroken then
+        begin
+          // If the package is recompiled, the installation-location is dependent on where
+          // the package was installed originally.
+          if P.InstalledLocally then
+            UFN:=CompilerOptions.LocalUnitDir
+          else
+            UFN:=CompilerOptions.GlobalUnitDir;
+          // Setting RecompileBroken to false is in a strict sense not needed. But it is better
+          // to clean this temporary flag, to avoid problems with changes in the future
+          P.RecompileBroken := false;
+          AvailableRepository.FindPackage(P.Name).RecompileBroken:=false;
+        end
       else
-        UFN:=CompilerOptions.LocalUnitDir;
+        begin
+          if (IsSuperUser or GlobalOptions.InstallGlobal) then
+            UFN:=CompilerOptions.GlobalUnitDir
+          else
+            UFN:=CompilerOptions.LocalUnitDir;
+        end;
       UFN:=IncludeTrailingPathDelimiter(UFN)+S+PathDelim+UnitConfigFileName;
       LoadUnitConfigFromFile(P,UFN);
     end
@@ -352,7 +375,7 @@ begin
             end
           else
             begin
-              if PackageIsBroken(InstalledP) then
+              if PackageIsBroken(InstalledP, True) then
                 begin
                   status:='Broken, recompiling';
                   L.Add(D.PackageName);

+ 28 - 18
utils/fppkg/pkgfpmake.pp

@@ -295,32 +295,42 @@ begin
   { Maybe compile fpmake executable? }
   ExecuteAction(PackageName,'compilefpmake');
   { Create options }
-  AddOption('--nofpccfg');
   if vlDebug in LogLevels then
     AddOption('--debug')
   else if vlInfo in LogLevels then
     AddOption('--verbose');
-  AddOption('--compiler='+CompilerOptions.Compiler);
-  AddOption('--cpu='+CPUToString(CompilerOptions.CompilerCPU));
-  AddOption('--os='+OSToString(CompilerOptions.CompilerOS));
-  if CompilerOptions.HasOptions then
-    AddOption('--options='+CompilerOptions.Options.DelimitedText);
-  if IsSuperUser or GlobalOptions.InstallGlobal then
+  if P.RecompileBroken and
+     (P.FPMakeOptionsString<>'') then // Check for a empty FPMakeOptionString for packages being installed with an old fpmkunit
     begin
-      CondAddOption('--prefix',CompilerOptions.GlobalPrefix);
-      CondAddOption('--baseinstalldir',CompilerOptions.GlobalInstallDir);
+      // When the package is being reinstalled because of broken dependencies, use the same fpmake-options
+      // as were used to compile the package in the first place.
+      OOptions:=P.FPMakeOptionsString;
     end
   else
     begin
-      CondAddOption('--prefix',CompilerOptions.LocalPrefix);
-      CondAddOption('--baseinstalldir',CompilerOptions.LocalInstallDir);
-    end;
-  CondAddOption('--localunitdir',CompilerOptions.LocalUnitDir);
-  CondAddOption('--globalunitdir',CompilerOptions.GlobalUnitDir);
-  if GlobalOptions.CustomFPMakeOptions<>'' then
-    begin
-    AddOption('--ignoreinvalidoption');
-    AddOption(GlobalOptions.CustomFPMakeOptions);
+      AddOption('--nofpccfg');
+      AddOption('--compiler='+CompilerOptions.Compiler);
+      AddOption('--cpu='+CPUToString(CompilerOptions.CompilerCPU));
+      AddOption('--os='+OSToString(CompilerOptions.CompilerOS));
+      if CompilerOptions.HasOptions then
+        AddOption('--options='+CompilerOptions.Options.DelimitedText);
+      if IsSuperUser or GlobalOptions.InstallGlobal then
+        begin
+          CondAddOption('--prefix',CompilerOptions.GlobalPrefix);
+          CondAddOption('--baseinstalldir',CompilerOptions.GlobalInstallDir);
+        end
+      else
+        begin
+          CondAddOption('--prefix',CompilerOptions.LocalPrefix);
+          CondAddOption('--baseinstalldir',CompilerOptions.LocalInstallDir);
+        end;
+      CondAddOption('--localunitdir',CompilerOptions.LocalUnitDir);
+      CondAddOption('--globalunitdir',CompilerOptions.GlobalUnitDir);
+      if GlobalOptions.CustomFPMakeOptions<>'' then
+        begin
+        AddOption('--ignoreinvalidoption');
+        AddOption(GlobalOptions.CustomFPMakeOptions);
+        end;
     end;
   { Run FPMake }
   FPMakeBin:='fpmake'+ExeExt;

+ 15 - 1
utils/fppkg/pkghandler.pp

@@ -57,6 +57,7 @@ uses
 var
   PkgHandlerList  : TFPHashList;
   ExecutedActions : TFPHashList;
+  CurrentDir      : string;
 
 procedure RegisterPkgHandler(const AAction:string;pkghandlerclass:TPackageHandlerClass);
 begin
@@ -106,9 +107,22 @@ end;
 function PackageBuildPath(APackage:TFPPackage):String;
 begin
   if APackage.Name=CurrentDirPackageName then
-    Result:='.'
+    begin
+      // It could be that to resolve some dependencies, the current directory changes. The first time
+      // PackageBuildPath is called the dependencies are not resolved yet, so store the current directory
+      // for later calls.
+      if CurrentDir='' then
+        begin
+          Result:='.';
+          CurrentDir := SysUtils.GetCurrentDir;
+        end
+      else
+        Result:=CurrentDir;
+    end
   else if APackage.Name=CmdLinePackageName then
     Result:=GlobalOptions.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'')
+  else if (APackage.RecompileBroken) and (APackage.SourcePath<>'') then
+    Result:=APackage.SourcePath
   else
     Result:=GlobalOptions.BuildDir+APackage.Name;
 end;

+ 33 - 5
utils/fppkg/pkgrepos.pp

@@ -15,7 +15,7 @@ procedure LoadLocalAvailableRepository;
 procedure LoadUnitConfigFromFile(APackage:TFPPackage;const AFileName: String);
 function LoadManifestFromFile(const AManifestFN:string):TFPPackage;
 procedure FindInstalledPackages(ACompilerOptions:TCompilerOptions;showdups:boolean=true);
-function  PackageIsBroken(APackage:TFPPackage):boolean;
+function  PackageIsBroken(APackage:TFPPackage; MarkForReInstall: boolean):boolean;
 function  FindBrokenPackages(SL:TStrings):Boolean;
 procedure CheckFPMakeDependencies;
 function  PackageInstalledVersionStr(const AName:String;const ShowUsed: boolean = false;const Local: boolean = false):string;
@@ -216,6 +216,8 @@ begin
     V:=L.Values['version'];
     APackage.Version.AsString:=V;
     APackage.IsFPMakeAddIn:=Upcase(L.Values['FPMakeAddIn'])='Y';
+    APackage.SourcePath:=L.Values['SourcePath'];
+    APackage.FPMakeOptionsString:=L.Values['FPMakeOptions'];
     V:=L.Values['checksum'];
     if V<>'' then
       APackage.Checksum:=StrToInt(V)
@@ -347,11 +349,12 @@ begin
 end;
 
 
-function PackageIsBroken(APackage:TFPPackage):boolean;
+function PackageIsBroken(APackage:TFPPackage; MarkForReInstall: boolean):boolean;
 var
   j : integer;
   D : TFPDependency;
   DepPackage : TFPPackage;
+  AvailP: TFPPackage;
 begin
   result:=false;
   for j:=0 to APackage.Dependencies.Count-1 do
@@ -368,6 +371,29 @@ begin
                 begin
                   Log(vlInfo,SLogPackageChecksumChanged,[APackage.Name,D.PackageName]);
                   result:=true;
+                  if MarkForReInstall then
+                    begin
+                      // When the package is re-installed, use the same fpmake-options and sourcepath
+                      // as used during the initial installation. (The AvailableRepository is used to install
+                      // the package so make sure all properties are set there)
+                      AvailP:=AvailableRepository.FindPackage(APackage.Name);
+                      if not assigned(AvailP) then
+                        begin
+                          AvailP := AvailableRepository.AddPackage(APackage.Name);
+                          AvailP.Assign(APackage);
+                        end
+                      else
+                        begin
+                          AvailP.SourcePath := APackage.SourcePath;
+                          AvailP.FPMakeOptionsString := APackage.FPMakeOptionsString;
+                        end;
+                      AvailP.RecompileBroken:=true;
+                      APackage.RecompileBroken:=true;
+                      // If the fpmake.pp of the original installation is not available anymore, do not
+                      // try to use it.
+                      if (AvailP.SourcePath<>'') and not FileExists(IncludeTrailingPathDelimiter(APackage.SourcePath)+'fpmake.pp') then
+                        AvailP.SourcePath:='';
+                    end;
                   exit;
                 end;
             end
@@ -387,8 +413,10 @@ begin
   for i:=0 to InstalledRepository.PackageCount-1 do
     begin
       P:=InstalledRepository.Packages[i];
-      if PackageIsBroken(P) then
-        SL.Add(P.Name);
+      if PackageIsBroken(P,True) then
+        begin
+          SL.Add(P.Name);
+        end;
     end;
   Result:=(SL.Count>0);
 end;
@@ -507,7 +535,7 @@ var
 begin
   result := '';
   P:=InstalledRepository.FindPackage(AName);
-  if (P<>nil) and PackageIsBroken(P) then
+  if (P<>nil) and PackageIsBroken(P,false) then
     result:='B';
 end;