Browse Source

* Adapted tests for broken dependencies (packages)
* Reload AddIn-state after an AddIn has been compiled
* Fixed re-compilation of already installed packages, based on the original
sources
* Improved the algorithm to determine which package to use when a package
is being build based on package-name

git-svn-id: trunk@35533 -

joost 8 years ago
parent
commit
2a01a603d8

+ 8 - 1
packages/fppkg/src/fprepos.pp

@@ -365,7 +365,14 @@ end;
 
 function TFPCustomPackagesStructure.GetBuildPathDirectory(APackage: TFPPackage): string;
 begin
-  Result := '';
+  if (APackage.Repository.RepositoryType=fprtInstalled) and (APackage.SourcePath<>'') then
+    begin
+      Result := APackage.SourcePath;
+    end
+  else
+    begin
+      Result := '';
+    end;
 end;
 
 function TFPCustomPackagesStructure.GetPrefix: string;

+ 10 - 3
packages/fppkg/src/pkgcommands.pp

@@ -562,7 +562,7 @@ begin
                 end
               else
                 begin
-                  if PackageManager.PackageIsBroken(InstalledP, InstalledP.Repository) then
+                  if PackageManager.PackageIsBroken(InstalledP, nil) then
                     begin
                       status:='Broken, recompiling';
                       L.Add(D.PackageName);
@@ -610,10 +610,12 @@ procedure TCommandFixBroken.Execute;
 var
   i : integer;
   SL : TStringList;
+  BreakLoop : Boolean;
 begin
   SL:=TStringList.Create;
+  BreakLoop := false;
   repeat
-    FindBrokenPackages(SL);
+    PackageManager.FindBrokenPackages(SL);
     if SL.Count=0 then
       break;
     pkgglobals.Log(llProgres,SProgrReinstallDependent);
@@ -621,8 +623,13 @@ begin
       begin
         ExecuteAction(SL[i],'build');
         ExecuteAction(SL[i],'install-req');
+        if PackageManager.PackageIsBroken(PackageManager.PackageByName(SL[i], pkgpkInstalled), nil) then
+          begin
+            BreakLoop := true;
+            pkgglobals.Log(llWarning, SWarnBrokenAfterReinstall, [SL[i]]);
+          end;
       end;
-  until false;
+  until BreakLoop;
   FreeAndNil(SL);
 end;
 

+ 27 - 3
packages/fppkg/src/pkgfpmake.pp

@@ -23,6 +23,8 @@ type
   { TFPMakeCompiler }
 
   TFPMakeCompiler = Class(TPackagehandler)
+  protected
+    function DeterminePackage: TFPPackage;
   Public
     Procedure Execute;override;
   end;
@@ -30,7 +32,7 @@ type
 
   { TFPMakeRunner }
 
-  TFPMakeRunner = Class(TPackagehandler)
+  TFPMakeRunner = Class(TFPMakeCompiler)
   Protected
     Function RunFPMake(const Command:string):Integer;
   end;
@@ -132,6 +134,28 @@ end;
 
 { TFPMakeCompiler }
 
+function TFPMakeCompiler.DeterminePackage: TFPPackage;
+var
+  PA, PI: TFPPackage;
+begin
+  PA:=PackageManager.FindPackage(PackageName, pkgpkAvailable);
+  PI:=PackageManager.FindPackage(PackageName, pkgpkInstalled);
+  if Assigned(PA) and Assigned(PI) then
+    begin
+    if PA.Version.CompareVersion(PI.Version) > 0 then
+      Result := PA
+    else
+      Result := PI;
+    end
+  else if Assigned(PI) then
+    Result := PI
+  else
+    Result := PA;
+
+  if not Assigned(Result) then
+    Raise EPackage.CreateFmt(SErrMissingPackage,[PackageName]);
+end;
+
 Procedure TFPMakeCompiler.Execute;
 var
   OOptions : string;
@@ -168,7 +192,7 @@ Var
   FPMKUnitDepPackage: TFPPackage;
   P : TFPPackage;
 begin
-  P:=PackageManager.PackageByName(PackageName, pkgpkAvailable);
+  P:=DeterminePackage;
   NeedFPMKUnitSource:=false;
   OOptions:='';
   SetCurrentDir(PackageManager.PackageBuildPath(P));
@@ -323,7 +347,7 @@ begin
   // Does the current package support this CPU-OS?
   if PackageName<>'' then
     begin
-      P:=PackageManager.PackageByName(PackageName, pkgpkAvailable);
+      P := DeterminePackage;
       if (PackageName=CurrentDirPackageName) and (FileExists(ManifestFileName)) then
         ObtainSupportedTargetsFromManifest(p);
     end

+ 119 - 44
packages/fppkg/src/pkgfppkg.pp

@@ -21,6 +21,9 @@ type
   TpkgPackageKind = (pkgpkInstalled, pkgpkAvailable, pkgpkBoth);
   TpkgFPpkg = class(TComponent)
   private
+    FInsideFindBrokenPackages: Integer;
+    FBrokenPackagesDictionary: TFPHashList;
+
     FFPMakeRepositoryList: TComponentList;
     FRepositoryList: TComponentList;
     FOptions: TFppkgOptions;
@@ -35,6 +38,8 @@ type
     function  FindPackage(ARepositoryList: TComponentList; APackageName: string; APackageKind: TpkgPackageKind): TFPPackage;
 
     function  SelectRemoteMirror:string;
+    procedure EnterFindBrokenPackages;
+    procedure LeaveFindBrokenpackages;
   public
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
@@ -63,6 +68,7 @@ type
 
     procedure ScanInstalledPackagesForAvailablePackages;
     procedure CheckFPMakeDependencies;
+    function  FindBrokenPackages(SL:TStrings):Boolean;
 
     property Options: TFppkgOptions read FOptions;
     property CompilerOptions: TCompilerOptions read FCompilerOptions;
@@ -90,10 +96,12 @@ begin
   FFpmakeCompilerOptions := TCompilerOptions.Create;
   FRepositoryList := TComponentList.Create(False);
   FFPMakeRepositoryList := TComponentList.Create(False);
+  FBrokenPackagesDictionary := TFPHashList.Create;
 end;
 
 destructor TpkgFPpkg.Destroy;
 begin
+  FBrokenPackagesDictionary.Free;
   FFPMakeRepositoryList.Free;
   FRepositoryList.Free;
   FCompilerOptions.Free;
@@ -321,57 +329,82 @@ var
   Dependency: TFPDependency;
   Repository: TFPRepository;
   DepPackage: TFPPackage;
+  HashPtr: PtrInt;
 begin
   result:=false;
 
-  if not Assigned(ARepository) then
-    begin
-    // Check with all repositories
-    ThisRepositoryIndex := RepositoryList.Count -1;
-    end
-  else
-    begin
-    // We should only check for dependencies in this repository, or repositories
-    // with a lower priority.
-    ThisRepositoryIndex := -1;
-    for i := RepositoryList.Count -1 downto 0 do
+  EnterFindBrokenPackages;
+  try
+    HashPtr := PtrInt(FBrokenPackagesDictionary.Find(APackage.Name));
+    if HashPtr<>0 then
       begin
-        if RepositoryList.Items[i] = ARepository then
-          ThisRepositoryIndex := i;
+        // Package is already evaluated
+        Result := (HashPtr = 1);
+        Exit;
       end;
-    end;
-
-  for j:=0 to APackage.Dependencies.Count-1 do
-    begin
-      Dependency:=APackage.Dependencies[j];
-      if (CompilerOptions.CompilerOS in Dependency.OSes) and
-         (CompilerOptions.CompilerCPU in Dependency.CPUs) then
+    if not Assigned(ARepository) then
+      begin
+      // Check with all repositories
+      ThisRepositoryIndex := RepositoryList.Count -1;
+      end
+    else
+      begin
+      // We should only check for dependencies in this repository, or repositories
+      // with a lower priority.
+      ThisRepositoryIndex := -1;
+      for i := RepositoryList.Count -1 downto 0 do
         begin
-          for i := ThisRepositoryIndex downto 0 do
-            begin
-              Repository := RepositoryList.Items[i] as TFPRepository;
-              DepPackage := Repository.FindPackage(Dependency.PackageName);
-              if Assigned(DepPackage) then
-                Break;
-            end;
-
-          if assigned(DepPackage) then
-            begin
-              if (Dependency.RequireChecksum<>$ffffffff) and (DepPackage.Checksum<>Dependency.RequireChecksum) then
-                begin
-                  log(llInfo,SLogPackageChecksumChanged,[APackage.Name,APackage.Repository.RepositoryName,Dependency.PackageName,Repository.RepositoryName]);
-                  result:=true;
-                  exit;
-                end;
-            end
-          else
-            begin
-              log(llDebug,SDbgObsoleteDependency,[APackage.Name,Dependency.PackageName]);
-              result:=true;
-              exit;
-            end;
+          if RepositoryList.Items[i] = ARepository then
+            ThisRepositoryIndex := i;
         end;
-    end;
+      end;
+
+    for j:=0 to APackage.Dependencies.Count-1 do
+      begin
+        Dependency:=APackage.Dependencies[j];
+        if (CompilerOptions.CompilerOS in Dependency.OSes) and
+           (CompilerOptions.CompilerCPU in Dependency.CPUs) then
+          begin
+            DepPackage := nil;
+            for i := ThisRepositoryIndex downto 0 do
+              begin
+                Repository := RepositoryList.Items[i] as TFPRepository;
+                if Repository.RepositoryType=fprtInstalled then
+                  DepPackage := Repository.FindPackage(Dependency.PackageName);
+                if Assigned(DepPackage) then
+                  Break;
+              end;
+
+            if assigned(DepPackage) then
+              begin
+                if PackageIsBroken(DepPackage, ARepository) then
+                  begin
+                    log(llInfo,SLogPackageDepBroken,[APackage.Name,APackage.Repository.RepositoryName,Dependency.PackageName,Repository.RepositoryName]);
+                    result:=true;
+                    FBrokenPackagesDictionary.Add(APackage.Name, Pointer(1));
+                    exit;
+                  end;
+                if (Dependency.RequireChecksum<>$ffffffff) and (DepPackage.Checksum<>Dependency.RequireChecksum) then
+                  begin
+                    log(llInfo,SLogPackageChecksumChanged,[APackage.Name,APackage.Repository.RepositoryName,Dependency.PackageName,Repository.RepositoryName]);
+                    result:=true;
+                    FBrokenPackagesDictionary.Add(APackage.Name, Pointer(1));
+                    exit;
+                  end;
+              end
+            else
+              begin
+                log(llInfo,SDbgObsoleteDependency,[APackage.Name,Dependency.PackageName]);
+                result:=true;
+                FBrokenPackagesDictionary.Add(APackage.Name, Pointer(1));
+                exit;
+              end;
+          end;
+      end;
+    FBrokenPackagesDictionary.Add(APackage.Name, Pointer(2));
+  finally
+    LeaveFindBrokenpackages;
+  end;
 end;
 
 function TpkgFPpkg.FPMakeRepoFindPackage(APackageName: string;
@@ -446,6 +479,20 @@ begin
     Error(SErrFailedToSelectMirror);
 end;
 
+procedure TpkgFPpkg.EnterFindBrokenPackages;
+begin
+  Assert((FInsideFindBrokenPackages>0) or (FBrokenPackagesDictionary.Count=0));
+  Inc(FInsideFindBrokenPackages)
+end;
+
+procedure TpkgFPpkg.LeaveFindBrokenpackages;
+begin
+  Assert(FInsideFindBrokenPackages>0);
+  Dec(FInsideFindBrokenPackages);
+  if FInsideFindBrokenPackages=0 then
+    FBrokenPackagesDictionary.Clear;
+end;
+
 function TpkgFPpkg.PackageByName(APackageName: string; APackageKind: TpkgPackageKind): TFPPackage;
 var
   ErrStr: string;
@@ -578,6 +625,34 @@ begin
     end;
 end;
 
+function TpkgFPpkg.FindBrokenPackages(SL: TStrings): Boolean;
+var
+  i,j,k : integer;
+  P : TFPPackage;
+  Repo: TFPRepository;
+begin
+  SL.Clear;
+  EnterFindBrokenPackages;
+  try
+    for i:=0 to RepositoryList.Count-1 do
+      begin
+        Repo := TFPRepository(RepositoryList[i]);
+        if Repo.RepositoryType = fprtInstalled then
+          begin
+            for j := 0 to Repo.PackageCount-1 do
+              begin
+                P := Repo.Packages[j];
+                if (P = FindPackage(P.Name, pkgpkInstalled)) and PackageIsBroken(P, nil) then
+                  SL.Add(P.Name);
+              end;
+          end;
+      end;
+  finally
+    LeaveFindBrokenpackages;
+  end;
+  Result:=(SL.Count>0);
+end;
+
 function TpkgFPpkg.PackageBuildPath(APackage: TFPPackage): String;
 begin
   if (APackage.Name=CmdLinePackageName) or (APackage.Name=URLPackageName) then

+ 5 - 1
packages/fppkg/src/pkgmessages.pp

@@ -20,7 +20,7 @@ Resourcestring
   SErrMissingCompilerConfig  = 'Could not find compiler configuration "%s"';
   SErrMissingInstallPackage  = 'Package "%s" is not installed';
   SErrMissingAvailablePackage= 'Package "%s" is not available';
-  SErrMissingPackage         = 'Could not fin package "%s"';
+  SErrMissingPackage         = 'Could not find package "%s"';
   SErrMissingInstallRepo     = 'Could not find repository "%s"';
   SErrNoPackageSpecified     = 'No package specified';
   SErrNoPackageAvailable     = 'Package %s %s is not available';
@@ -80,6 +80,7 @@ Resourcestring
   SLogLoadingMirrorsFile     = 'Loading available mirrors from "%s"';
   SLogFindInstalledPackages  = 'Searching for installed packages in "%s"';
   SLogFoundFPMakeAddin       = 'Found FPMake-AddIn "%s"';
+  SLogUpdateFPMakeAddin      = 'FPMake-AddIn "%s" updated';
   SLogSavingStatusFile       = 'Saving local status to "%s"';
   SLogFPMKUnitDepVersion     = 'Checking for %s %s, installed %s, available %s';
   SLogFPMKUnitDepTooOld      = 'Minimum version of %s is not installed, using internal fpmkunit with limited functionality';
@@ -89,6 +90,7 @@ Resourcestring
   SLogOldConfigFileFormat    = 'Configuration file is in an old format';
   SLogPackageDependency      = 'Dependency on package %s %s, installed %s, available %s  (%s)';
   SLogPackageChecksumChanged = 'Package %s (%s) needs to be rebuild, dependency %s (%s) is modified';
+  SLogPackageDepBroken       = 'Package %s (%s) needs to be rebuild, dependency %s (%s) is broken';
   SLogCheckBrokenDependenvies= 'Checking for broken dependencies';
   SLogFailedToCreateManifest = 'Failed to create manifest from fpmake.pp-file (%s) while scanning for available packages: %s';
   SLogUseInternalFpmkunit    = 'Fpmkunit not available, fallback to internal version.';
@@ -146,6 +148,8 @@ Resourcestring
   SDbgPackageDependencyOtherTarget  = 'Dependency on package %s is not for %s';
   SDbgObsoleteDependency     = 'Package %s depends on package %s which is not installed anymore';
 
+  SWarnBrokenAfterReinstall  = 'Package %s is still broken, even after re-installation.';
+
   SProgrReinstallDependent   = 'Re-install packages which are dependent on just installed packages';
   SProgrInstallDependencies  = 'Install dependencies';
   SProgrDependenciesInstalled= 'Dependencies installed';

+ 25 - 35
packages/fppkg/src/pkgrepos.pp

@@ -145,47 +145,37 @@ end;
 
 
 Procedure AddFPMakeAddIn(APackage: TFPPackage);
-begin
-  log(llDebug,SLogFoundFPMakeAddin,[APackage.Name]);
-  setlength(FPMKUnitDeps,length(FPMKUnitDeps)+1);
-  FPMKUnitDeps[high(FPMKUnitDeps)].package:=APackage.Name;
-  FPMKUnitDeps[high(FPMKUnitDeps)].reqver:=APackage.Version.AsString;
-  FPMKUnitDeps[high(FPMKUnitDeps)].def:='HAS_PACKAGE_'+APackage.Name;
-  FPMKUnitDeps[high(FPMKUnitDeps)].PluginUnit:=APackage.FPMakePluginUnits;
-  FPMKUnitDeps[high(FPMKUnitDeps)].available:=true;
-end;
-
-
-function FindBrokenPackages(SL:TStrings):Boolean;
 var
-  i,j,k : integer;
-  P : TFPPackage;
-  Repo: TFPRepository;
+  SelectedDep, i: Integer;
 begin
-  SL.Clear;
-  for i:=0 to GFPpkg.RepositoryList.Count-1 do
+  SelectedDep := -1;
+  for i := 0 to high(FPMKUnitDeps) do
     begin
-      Repo := TFPRepository(GFPpkg.RepositoryList[i]);
-      if Repo.RepositoryType = fprtInstalled then
+      if FPMKUnitDeps[i].package = APackage.Name then
         begin
-          for j := 0 to Repo.PackageCount-1 do
-            begin
-              P := Repo.Packages[j];
-              if P.IsPackageBroken then
-                SL.Add(P.Name)
-              else
-                begin
-                  // It could be that a package is broken in one repository,
-                  // but that this problem is 'fixed' in a repository with an higher
-                  // priority
-                  k := SL.IndexOf(P.Name);
-                  if k > -1 then
-                    SL.Delete(k);
-                end;
-            end;
+          log(llDebug,SLogUpdateFPMakeAddin,[APackage.Name]);
+          SelectedDep := i;
+          break;
         end;
     end;
-  Result:=(SL.Count>0);
+
+  if SelectedDep = -1 then
+    begin
+      log(llDebug,SLogFoundFPMakeAddin,[APackage.Name]);
+      setlength(FPMKUnitDeps,length(FPMKUnitDeps)+1);
+      SelectedDep := high(FPMKUnitDeps);
+    end;
+  FPMKUnitDeps[SelectedDep].package:=APackage.Name;
+  FPMKUnitDeps[SelectedDep].reqver:=APackage.Version.AsString;
+  FPMKUnitDeps[SelectedDep].def:='HAS_PACKAGE_'+APackage.Name;
+  FPMKUnitDeps[SelectedDep].PluginUnit:=APackage.FPMakePluginUnits;
+  FPMKUnitDeps[SelectedDep].available:=true;
+end;
+
+
+function FindBrokenPackages(SL:TStrings):Boolean;
+begin
+  Result := GFPpkg.FindBrokenPackages(SL);
 end;