* Take all repositories into account when searching for broken packages.

The idea that each repository should be compilable by itself is not
   sustainable. Users should be able to install packages at will in 
   repositories with a higher priority. (+tests)

git-svn-id: trunk@36439 -
This commit is contained in:
joost 2017-06-06 18:41:55 +00:00
parent cad2b985d6
commit 9dd1d1a1ea
3 changed files with 225 additions and 51 deletions

View File

@ -354,6 +354,16 @@ begin
begin
// We should only check for dependencies in this repository, or repositories
// with a lower priority.
// This behaviour seems obsolete. The idea behind it was that each repository
// should be useable, only using other repositories with a lower priority.
// In practice this does not work, you have to consider the installation
// as a whole, using all repositories. One specific user might not be able
// to 'fix' the global fpc-repository, and so end up with broken packages
// which he/she can not fix. Or packages may be forced to be installed in
// a specific repository.
// The functionality is kept for now, maybe there is a need for it in the
// future... But for now, ARepository will be always nil.
ThisRepositoryIndex := -1;
for i := RepositoryList.Count -1 downto 0 do
begin

View File

@ -198,7 +198,7 @@ procedure ListPackages(const ShowGlobalAndLocal: boolean);
if Assigned(APackage) then
begin
PackageVersion := APackage.Version.AsString;
if CheckIsBroken and APackage.IsPackageBroken then
if CheckIsBroken and GFPpkg.PackageIsBroken(APackage, nil) then
PackageVersion := PackageVersion + ' (B)';
end
else

View File

@ -25,6 +25,9 @@ type
protected
procedure SetUp; override;
procedure TearDown; override;
procedure AlterChecksumOfPackageFPM(FPMFileName: string);
procedure AlterChecksumOfDependencyInFPM(FPMFileName: string);
procedure CheckBrokenPackages(ExpectBrokenPackages: Boolean);
published
procedure TestListPackages;
procedure IntTestListPackages;
@ -44,6 +47,9 @@ type
procedure TestSourceRepositoryInstallLocation;
procedure TestConfiguredInstallLocation;
procedure TestInstallationLocationOriginalSource;
procedure TestUninstalledRepository;
procedure TestBrokenPackagesBetweenRepos;
procedure TestPackageDependenciesBetweenRepos;
end;
{ TFullFPCInstallationSetup }
@ -331,6 +337,76 @@ begin
end;
procedure TFullFPCInstallationTests.AlterChecksumOfPackageFPM(FPMFileName: string);
var
SL: TStringList;
Checksum: Int64;
begin
// Break packageb on purpose, by changing the checksum of packagea
SL := TStringList.Create;
try
SL.LoadFromFile(FPMFilename);
Checksum := StrToInt64Def(SL.Values['Checksum'], -1);
Check(Checksum>-1, 'Determine checksum package');
SL.Values['Checksum'] := IntToStr(Checksum+1);
SL.SaveToFile(FPMFilename);
finally
SL.Free;
end;
end;
procedure TFullFPCInstallationTests.AlterChecksumOfDependencyInFPM(FPMFileName: string);
var
SL: TStringList;
Dependencies: string;
begin
// Break packageb on purpose, by changing the checksum of packagea
SL := TStringList.Create;
try
SL.LoadFromFile(FPMFilename);
Dependencies := SL.Values['Depends'];
SL.Values['Depends'] := copy(Dependencies, 1, length(Dependencies)-2);
SL.SaveToFile(FPMFilename);
finally
SL.Free;
end;
end;
procedure TFullFPCInstallationTests.CheckBrokenPackages(ExpectBrokenPackages: Boolean);
var
SL: TStringList;
FPpkg: TpkgFPpkg;
begin
FPpkg := TpkgFPpkg.Create(nil);
try
FPpkg.InitializeGlobalOptions(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath,'etc','fppkg.cfg']));
FPpkg.Options.GlobalSection.Downloader := 'FPC';
FPpkg.InitializeCompilerOptions;
FPpkg.CompilerOptions.InitCompilerDefaults;
FPpkg.FpmakeCompilerOptions.InitCompilerDefaults;
FPpkg.CompilerOptions.CheckCompilerValues;
FPpkg.FpmakeCompilerOptions.CheckCompilerValues;
FPpkg.LoadLocalAvailableMirrors;
FPpkg.ScanAvailablePackages;
FPpkg.ScanPackages;
SL := TStringList.Create;
try
FPpkg.FindBrokenPackages(SL);
if ExpectBrokenPackages then
check(SL.Count>0, 'There should be broken packages')
else
check(SL.Count=0, 'There should not be any broken packages');
finally
SL.Free;
end;
finally
FPpkg.Free;
end;
end;
procedure TFullFPCInstallationTests.TestFpmakePluginDependencies;
begin
// A fpmake-plugin could have it's own dependencies. These dependencies have
@ -346,44 +422,7 @@ end;
procedure TFullFPCInstallationTests.TestInstallationLocationOriginalSource;
var
SL: TStringList;
Checksum: Int64;
FPMFilename, S: string;
procedure CheckBrokenPackages(ExpectBrokenPackages: Boolean);
var
FPpkg: TpkgFPpkg;
begin
FPpkg := TpkgFPpkg.Create(nil);
try
FPpkg.InitializeGlobalOptions(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath,'etc','fppkg.cfg']));
FPpkg.Options.GlobalSection.Downloader := 'FPC';
FPpkg.InitializeCompilerOptions;
FPpkg.CompilerOptions.InitCompilerDefaults;
FPpkg.FpmakeCompilerOptions.InitCompilerDefaults;
FPpkg.CompilerOptions.CheckCompilerValues;
FPpkg.FpmakeCompilerOptions.CheckCompilerValues;
FPpkg.LoadLocalAvailableMirrors;
FPpkg.ScanAvailablePackages;
FPpkg.ScanPackages;
SL := TStringList.Create;
try
FPpkg.FindBrokenPackages(SL);
if ExpectBrokenPackages then
check(SL.Count>0, 'There should be broken packages')
else
check(SL.Count=0, 'There should not be any broken packages');
finally
SL.Free;
end;
finally
FPpkg.Free;
end;
end;
S: string;
begin
// Test whether a once installed package on a re-install is installed into the
// right (original) location.
@ -397,17 +436,7 @@ begin
CheckBrokenPackages(False);
// Break packageb on purpose, by changing the checksum of packagea
SL := TStringList.Create;
try
FPMFilename := ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'user', 'lib', 'fpc', TFullFPCInstallationSetup.GetCompilerVersion, 'fpmkinst', TFullFPCInstallationSetup.GetTargetString, 'packagea.fpm']);
SL.LoadFromFile(FPMFilename);
Checksum := StrToInt64Def(SL.Values['Checksum'], -1);
Check(Checksum>-1, 'Determine checksum packagea');
SL.Values['Checksum'] := IntToStr(Checksum+1);
SL.SaveToFile(FPMFilename);
finally
SL.Free;
end;
AlterChecksumOfPackageFPM(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'user', 'lib', 'fpc', TFullFPCInstallationSetup.GetCompilerVersion, 'fpmkinst', TFullFPCInstallationSetup.GetTargetString, 'packagea.fpm']));
CheckBrokenPackages(True);
@ -417,6 +446,142 @@ begin
CheckBrokenPackages(False);
end;
procedure TFullFPCInstallationTests.TestUninstalledRepository;
var
LocalPackagesRepoCfgFilename: String;
ConfigFile: TIniFile;
FPpkg: TpkgFPpkg;
PackageA: TFPPackage;
begin
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packagea');
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packageb');
// Create a setup with two repositories, one with the source of the packages,
// and one repository where the packages are installed into. The trick is that
// both repositories use the same location, which effectively means that there
// is no need to install the packages. As soon as they are build, they are
// installed.
LocalPackagesRepoCfgFilename := ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'user', 'config', 'conf.d', 'uninstalledrepo.conf']);
ConfigFile := TIniFile.Create(LocalPackagesRepoCfgFilename);
try
ConfigFile.WriteString('UninstalledSourceRepository', 'Name', 'localpackages');
ConfigFile.WriteString('UninstalledSourceRepository', 'Description', 'Local packages');
ConfigFile.WriteString('UninstalledSourceRepository', 'Path', ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'packages']));
ConfigFile.WriteString('UninstalledSourceRepository', 'InstallRepository', 'installedlocalpackages');
ConfigFile.WriteString('UninstalledRepository', 'Name', 'installedlocalpackages');
ConfigFile.WriteString('UninstalledRepository', 'Description', 'Installed local packages');
ConfigFile.WriteString('UninstalledRepository', 'Path', ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'packages']));
ConfigFile.WriteString('UninstalledRepository', 'SourceRepository', 'localpackages');
ConfigFile.UpdateFile;
finally
ConfigFile.Free;
end;
// Should install into fpc, as it is installed from the localpackages repository
// which has fpc as install-repository
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestPath, ['build', 'packagea'], 'Build package A, which will show as installed');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestPath, ['build', 'packageb'], 'Build package B, which will show as installed');
// Check if packagea is installed
FPpkg := TpkgFPpkg.Create(nil);
try
FPpkg.InitializeGlobalOptions(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath,'etc','fppkg.cfg']));
FPpkg.Options.GlobalSection.Downloader := 'FPC';
FPpkg.InitializeCompilerOptions;
FPpkg.CompilerOptions.InitCompilerDefaults;
FPpkg.FpmakeCompilerOptions.InitCompilerDefaults;
FPpkg.CompilerOptions.CheckCompilerValues;
FPpkg.FpmakeCompilerOptions.CheckCompilerValues;
FPpkg.LoadLocalAvailableMirrors;
FPpkg.ScanAvailablePackages;
FPpkg.ScanPackages;
PackageA := FPpkg.FindPackage('packagea', pkgpkInstalled);
CheckNotNull(PackageA, 'Installed packagea found');
CheckEquals('installedlocalpackages', PackageA.Repository.RepositoryName, 'Package is ''installed'' in local-repository');
AlterChecksumOfPackageFPM(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'packages', 'packagea', 'packagea-'+TFullFPCInstallationSetup.GetTargetString+'.fpm']));
CheckBrokenPackages(True);
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestPath, ['fixbroken'], 'Fix PackageB by only re-compiling it, without installation');
CheckBrokenPackages(False);
PackageA := FPpkg.FindPackage('packagea', pkgpkInstalled);
CheckNotNull(PackageA, 'Installed packagea found');
CheckEquals('installedlocalpackages', PackageA.Repository.RepositoryName, 'Package is ''installed'' in local-repository');
Check(not Assigned(FPpkg.FindRepository('user').FindPackage('packagea')),'PackageA should not be installed in user-repository');
Check(not Assigned(FPpkg.FindRepository('user').FindPackage('PackageB')),'PackageB should not be installed in user-repository');
Check(not Assigned(FPpkg.FindRepository('fpc').FindPackage('packagea')),'PackageA should not be installed in user-repository');
Check(not Assigned(FPpkg.FindRepository('fpc').FindPackage('PackageB')),'PackageB should not be installed in user-repository');
Check(Assigned(FPpkg.FindRepository('installedlocalpackages').FindPackage('packagea')),'PackageA should be installed in installedlocalpackages-repository');
Check(Assigned(FPpkg.FindRepository('installedlocalpackages').FindPackage('PackageB')),'PackageB should be installed in installedlocalpackages-repository');
finally
FPpkg.Free;
end;
end;
procedure TFullFPCInstallationTests.TestBrokenPackagesBetweenRepos;
var
s: String;
begin
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packagea');
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packageb');
// Make sure that PackageB is not reported broken. (It could be that it marks
// it as broken, because packages in the 'user'-repository could not be found
// by the 'fpc'-repository. All wrong, but this was the case in earlier
// versions.)
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packagea', ['install'], 'install PackageA');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packageb', ['install', '-i', 'fpc'], 'install PackageB');
CheckBrokenPackages(False);
s := RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath, ['list', '-l'], 'List all packages, none should be broken');
Check(pos('(B)',s) = 0, 'There are no broken packages, fppkg should report so.');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packageb', ['install'], 'install PackageB into user-repository');
// Now break the package in the fpc-repository on purpose. This package should
// now be broken, but the 'whole' repository should not, because the
// package in the 'user'-repository has precedence.
AlterChecksumOfDependencyInFPM(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'lib', 'fpc', TFullFPCInstallationSetup.GetCompilerVersion, 'fpmkinst', TFullFPCInstallationSetup.GetTargetString, 'PackageB.fpm']));
CheckBrokenPackages(False);
s := RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath, ['list', '-l'], 'List all packages, one should be broken');
Check(pos('(B)',s) > 0, 'The PackageB in the fpc-repository should be broken.');
end;
procedure TFullFPCInstallationTests.TestPackageDependenciesBetweenRepos;
var
s: String;
begin
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packagea');
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packageb');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packagea', ['install'], 'install PackageA');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packageb', ['install'], 'install PackageB');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packagea', ['install', '-i', 'fpc'], 'install PackageA in fpc-repository');
RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath + 'packageb', ['install', '-i', 'fpc'], 'install PackageB in fpc-repository');
CheckBrokenPackages(False);
// Although Package-A's checksum in the fpc-repo is modified, there should not
// be any packages reported as being broken, because the user-version of
// PackageA should be used.
AlterChecksumOfPackageFPM(ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'lib', 'fpc', TFullFPCInstallationSetup.GetCompilerVersion, 'fpmkinst', TFullFPCInstallationSetup.GetTargetString, 'packagea.fpm']));
s := RunFppkgIndir(TFullFPCInstallationSetup.GetCurrentTestBasePackagesPath, ['list', '-l'], 'List all packages, none should be broken');
Check(pos('(B)',s) = 0, 'There are no broken packages, fppkg should report so.');
end;
procedure TFullFPCInstallationTests.TestCleanupOfTemporaryBuildpath;
var
SR: TSearchRec;
@ -473,7 +638,6 @@ begin
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packagea');
TFullFPCInstallationSetup.SyncPackageIntoCurrentTest('packageb');
// Remove the installrepository setting from fppkg.cfg
LocalPackagesRepoCfgFilename := ConcatPaths([TFullFPCInstallationSetup.GetCurrentTestPath, 'user', 'config', 'conf.d', 'lazaruspackagesrepo.conf']);
ConfigFile := TIniFile.Create(LocalPackagesRepoCfgFilename);
try