* 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 -
This commit is contained in:
joost 2011-02-15 15:56:21 +00:00
parent d3afac1736
commit 4d13235ea0
6 changed files with 126 additions and 32 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;