IDE: vanished lpk on disk: searching for alternative lpk

git-svn-id: trunk@40222 -
This commit is contained in:
mattias 2013-02-09 12:26:10 +00:00
parent 3022dc2cb1
commit acf679b820
6 changed files with 165 additions and 31 deletions

View File

@ -291,8 +291,14 @@ begin
end else if FileOwner is TLazPackage then begin
// compare disk and package
APackage:=TLazPackage(FileOwner);
if AltFilename<>'' then
Filename:=AltFilename
if AltFilename<>'' then begin
if CompareFilenames(AltFilename,APackage.Filename)<>0 then
Result^.Diff+=Format(lisLpkHasVanishedOnDiskUsingAsAlternative, [
LineEnding
+AltFilename+LineEnding
+LineEnding]);
Filename:=AltFilename;
end
else if APackage.LPKSource<>nil then
Filename:=APackage.LPKSource.Filename
else
@ -310,13 +316,13 @@ begin
DiffOutput:=TDiffOutput.Create(Source,Result^.TxtOnDisk, [], nil);
try
Result^.Diff:=DiffOutput.CreateTextDiff;
Result^.Diff+=DiffOutput.CreateTextDiff;
finally
DiffOutput.Free;
end;
except
On E: Exception do
Result^.Diff:='\ '+Format(lisDiskDiffErrorReadingFile, [E.Message]);
Result^.Diff+='\ '+Format(lisDiskDiffErrorReadingFile, [E.Message]);
end;
FCachedDiffs.Add(Result);
end;

View File

@ -3677,6 +3677,8 @@ resourcestring
// disk diff dialog
lisDiskDiffErrorReadingFile = 'Error reading file: %s';
lisLpkHasVanishedOnDiskUsingAsAlternative = 'lpk has vanished on disk. Using'
+' as alternative%s';
lisDiskDiffSomeFilesHaveChangedOnDisk = 'Some files have changed on disk:';
lisDiskDiffChangedFiles = 'Changed files:';
lisDiskDiffClickOnOneOfTheAboveItemsToSeeTheDiff = 'Click on one of the '

View File

@ -1,4 +1,3 @@
{ $Id$ }
{
/***************************************************************************
basepkgmanager.pas

View File

@ -431,6 +431,7 @@ begin
License:='';
Description:='';
PkgType:=lptRunAndDesignTime;
Version.Clear;
if FilenameIsAbsolute(LPKFilename) and FileExistsUTF8(LPKFilename) then begin
// load the package file
try

View File

@ -138,7 +138,7 @@ type
function FindLeftMostNode(LinkTree: TAvgLvlTree;
const PkgName: string): TAvgLvlTreeNode;
function FindLinkWithPkgNameInTree(LinkTree: TAvgLvlTree;
const PkgName: string): TPackageLink;
const PkgName: string; IgnoreFiles: TFilenameToStringTree): TPackageLink;
function FindLinkWithDependencyInTree(LinkTree: TAvgLvlTree;
Dependency: TPkgDependency; IgnoreFiles: TFilenameToStringTree): TPackageLink;
function FindLinkWithPackageIDInTree(LinkTree: TAvgLvlTree;
@ -166,9 +166,12 @@ type
procedure SaveUserLinks;
function NeedSaveUserLinks(const ConfigFilename: string): boolean;
procedure WriteLinkTree(LinkTree: TAvgLvlTree);
function FindLinkWithPkgName(const PkgName: string): TPackageLink;
function FindLinkWithPkgName(const PkgName: string;
IgnoreFiles: TFilenameToStringTree = nil;
FirstUserLinks: boolean = true): TPackageLink;
function FindLinkWithDependency(Dependency: TPkgDependency;
IgnoreFiles: TFilenameToStringTree = nil): TPackageLink;
IgnoreFiles: TFilenameToStringTree = nil;
FirstUserLinks: boolean = true): TPackageLink;
function FindLinkWithPackageID(APackageID: TLazPackageID): TPackageLink;
procedure IteratePackages(MustExist: boolean; Event: TIteratePackagesEvent;
Origins: TPkgLinkOrigins = AllPkgLinkOrigins);
@ -765,16 +768,36 @@ begin
end;
function TPackageLinks.FindLinkWithPkgNameInTree(LinkTree: TAvgLvlTree;
const PkgName: string): TPackageLink;
const PkgName: string; IgnoreFiles: TFilenameToStringTree): TPackageLink;
// find left most link with PkgName
var
CurNode: TAvgLvlTreeNode;
Link: TPackageLink;
begin
Result:=nil;
if PkgName='' then exit;
CurNode:=FindLeftMostNode(LinkTree,PkgName);
if CurNode=nil then exit;
Result:=TPackageLink(CurNode.Data);
while CurNode<>nil do begin
Link:=TPackageLink(CurNode.Data);
if (CompareText(PkgName,Link.Name)=0)
and ((IgnoreFiles=nil) or (not IgnoreFiles.Contains(Link.GetEffectiveFilename)))
then begin
if Result=nil then
Result:=Link
else begin
// there are two packages fitting
if ((Link.LastUsed>Result.LastUsed)
or (Link.Version.Compare(Result.Version)>0))
and FileExistsCached(Link.GetEffectiveFilename) then
Result:=Link; // this one is better
end;
end;
CurNode:=LinkTree.FindSuccessor(CurNode);
if CurNode=nil then break;
if CompareText(TPackageLink(CurNode.Data).Name,PkgName)<>0
then
break;
end;
end;
function TPackageLinks.FindLinkWithDependencyInTree(LinkTree: TAvgLvlTree;
@ -809,10 +832,8 @@ begin
CurNode:=LinkTree.FindSuccessor(CurNode);
if CurNode=nil then break;
if CompareText(TPackageLink(CurNode.Data).Name,Dependency.PackageName)<>0
then begin
CurNode:=nil;
then
break;
end;
end;
end;
@ -860,19 +881,28 @@ begin
IncreaseChangeStamp;
end;
function TPackageLinks.FindLinkWithPkgName(const PkgName: string): TPackageLink;
function TPackageLinks.FindLinkWithPkgName(const PkgName: string;
IgnoreFiles: TFilenameToStringTree; FirstUserLinks: boolean): TPackageLink;
begin
Result:=FindLinkWithPkgNameInTree(FUserLinksSortID,PkgName);
Result:=nil;
if FirstUserLinks then
Result:=FindLinkWithPkgNameInTree(FUserLinksSortID,PkgName,IgnoreFiles);
if Result=nil then
Result:=FindLinkWithPkgNameInTree(FGlobalLinks,PkgName);
Result:=FindLinkWithPkgNameInTree(FGlobalLinks,PkgName,IgnoreFiles);
if (Result=nil) and (not FirstUserLinks) then
Result:=FindLinkWithPkgNameInTree(FUserLinksSortID,PkgName,IgnoreFiles);
end;
function TPackageLinks.FindLinkWithDependency(Dependency: TPkgDependency;
IgnoreFiles: TFilenameToStringTree): TPackageLink;
IgnoreFiles: TFilenameToStringTree; FirstUserLinks: boolean): TPackageLink;
begin
Result:=FindLinkWithDependencyInTree(FUserLinksSortID,Dependency,IgnoreFiles);
Result:=nil;
if FirstUserLinks then
Result:=FindLinkWithDependencyInTree(FUserLinksSortID,Dependency,IgnoreFiles);
if Result=nil then
Result:=FindLinkWithDependencyInTree(FGlobalLinks,Dependency,IgnoreFiles);
if (Result=nil) and (not FirstUserLinks) then
Result:=FindLinkWithDependencyInTree(FUserLinksSortID,Dependency,IgnoreFiles);
//if Result=nil then begin
//debugln('TPackageLinks.FindLinkWithDependency A ',Dependency.AsString);
// WriteLinkTree(FGlobalLinks);

View File

@ -4516,7 +4516,7 @@ begin
continue;
end else begin
// lpk has vanished -> search alternative
NewFilename:=PackageGraph.FindAlternativeLPK(APackage);
end;
if ListOfPackages=nil then
ListOfPackages:=TStringList.Create;
@ -4976,19 +4976,115 @@ end;
function TLazPackageGraph.FindAlternativeLPK(APackage: TLazPackage): string;
var
Dependency: TPkgDependency;
begin
Result:='';
// first check for preferred dependencies
Dependency:=APackage.FirstUsedByDependency;
while Dependency<>nil do begin
if (Dependency.DefaultFilename<>'') and Dependency.PreferDefaultFilename
then begin
//PreferredFilename:=Dependency.FindDefaultFilename;
IgnoreFiles: TFilenameToStringTree;
end;
Dependency:=Dependency.NextUsedByDependency;
procedure IgnoreLPK(LPKFilename: string);
begin
IgnoreFiles[LPKFilename]:='1';
end;
function ParseLPK(var LPKFilename: string; Version: TPkgVersion): boolean;
var
Code: TCodeBuffer;
XMLConfig: TXMLConfig;
Path: String;
FileVersion: Integer;
begin
Result:=false;
LPKFilename:=TrimFilename(LPKFilename);
if IgnoreFiles[LPKFilename]='1' then exit;
IgnoreLPK(LPKFilename);
if not FilenameIsAbsolute(LPKFilename) then exit;
Code:=CodeToolBoss.LoadFile(LPKFilename,true,false);
if Code=nil then exit;
try
XMLConfig:=TXMLConfig.CreateWithSource(LPKFilename,Code.Source);
try
Path:='Package/';
FileVersion:=XMLConfig.GetValue(Path+'Version',0);
PkgVersionLoadFromXMLConfig(Version,XMLConfig,Path+'Version/',FileVersion);
Result:=true;
finally
XMLConfig.Free;
end;
except
on E: Exception do begin
debugln(['ParseLPK "'+LPKFilename+'": '+E.Message]);
end;
end;
end;
var
Dependency: TPkgDependency;
Version: TPkgVersion;
PkgLink: TPackageLink;
Filename: String;
BaseDir: String;
begin
Version:=TPkgVersion.Create;
IgnoreFiles:=TFilenameToStringTree.Create(false);
try
// first check for preferred filenames in dependencies
Dependency:=APackage.FirstUsedByDependency;
while Dependency<>nil do begin
if (Dependency.DefaultFilename<>'') and Dependency.PreferDefaultFilename
then begin
Result:=Dependency.FindDefaultFilename;
if ParseLPK(Result,Version) then
exit;
end;
Dependency:=Dependency.NextUsedByDependency;
end;
// find nearest package link to old lpk
// for example
// if old was /path/to/lazarus/comp/bla.lpk
// then a /path/to/lazarus/comp/design/bla.lpk
// is better than a /path/to/other/lazarus/comp/bla.lpk
Dependency:=APackage.FirstUsedByDependency;
if Dependency<>nil then begin
Result:='';
BaseDir:=TrimFilename(APackage.Directory);
repeat
PkgLink:=PkgLinks.FindLinkWithDependency(Dependency,IgnoreFiles);
if PkgLink=nil then break;
Filename:=PkgLink.GetEffectiveFilename;
if ParseLPK(Filename,Version) then begin
// candidate found
if (Result='')
or (length(CreateRelativePath(Filename,BaseDir))<length(CreateRelativePath(Result,BaseDir)))
then
Result:=Filename;
end;
until false;
if Result<>'' then exit;
end;
// last check for default filenames in dependencies
Dependency:=APackage.FirstUsedByDependency;
while Dependency<>nil do begin
if (Dependency.DefaultFilename<>'')
and (not Dependency.PreferDefaultFilename) then
begin
Result:=Dependency.FindDefaultFilename;
if ParseLPK(Result,Version) then
exit;
end;
Dependency:=Dependency.NextUsedByDependency;
end;
// nothing found via dependencies
// search in links
PkgLink:=PkgLinks.FindLinkWithPkgName(APackage.Name,IgnoreFiles,true);
if PkgLink<>nil then begin
Result:=PkgLink.GetEffectiveFilename;
exit;
end;
finally
IgnoreFiles.Free;
Version.Free;
end;
Result:='';
end;
procedure TLazPackageGraph.OpenInstalledDependency(Dependency: TPkgDependency;