mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-13 23:49:13 +02:00
implemented replacing package
git-svn-id: trunk@4057 -
This commit is contained in:
parent
29fb14b1f9
commit
af6fab6c95
@ -499,6 +499,8 @@ function FindLowestPkgDependencyWithName(const PkgName: string): TPkgDependency;
|
|||||||
function FindLowestPkgDependencyNodeWithName(const PkgName: string): TAVLTreeNode;
|
function FindLowestPkgDependencyNodeWithName(const PkgName: string): TAVLTreeNode;
|
||||||
function FindNextPkgDependecyNodeWithSameName(Node: TAVLTreeNode): TAVLTreeNode;
|
function FindNextPkgDependecyNodeWithSameName(Node: TAVLTreeNode): TAVLTreeNode;
|
||||||
|
|
||||||
|
function PackageFileNameIsValid(const AFilename: string): boolean;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -667,6 +669,17 @@ begin
|
|||||||
Result:=nil;
|
Result:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function PackageFileNameIsValid(const AFilename: string): boolean;
|
||||||
|
var
|
||||||
|
PkgName: String;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
if CompareFileExt(AFilename,'.lpk',false)<>0 then exit;
|
||||||
|
PkgName:=ExtractFileNameOnly(AFilename);
|
||||||
|
if (PkgName='') or (not IsValidIdent(PkgName)) then exit;
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
function FindLowestPkgDependencyWithName(const PkgName: string): TPkgDependency;
|
function FindLowestPkgDependencyWithName(const PkgName: string): TPkgDependency;
|
||||||
var
|
var
|
||||||
ANode: TAVLTreeNode;
|
ANode: TAVLTreeNode;
|
||||||
|
@ -63,6 +63,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
function MakeSense: boolean;
|
||||||
public
|
public
|
||||||
property Origin: TPkgLinkOrigin read FOrigin write SetOrigin;
|
property Origin: TPkgLinkOrigin read FOrigin write SetOrigin;
|
||||||
property Filename: string read FFilename write SetFilename;
|
property Filename: string read FFilename write SetFilename;
|
||||||
@ -190,6 +191,13 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPackageLink.MakeSense: boolean;
|
||||||
|
begin
|
||||||
|
Result:=(Name<>'') and IsValidIdent(Name)
|
||||||
|
and PackageFileNameIsValid(Filename)
|
||||||
|
and (AnsiCompareText(Name,ExtractFileNameOnly(Filename))=0);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPackageLinks }
|
{ TPackageLinks }
|
||||||
|
|
||||||
function TPackageLinks.FindLeftMostNode(LinkTree: TAVLTree;
|
function TPackageLinks.FindLeftMostNode(LinkTree: TAVLTree;
|
||||||
@ -337,7 +345,7 @@ begin
|
|||||||
NewPkgLink.Name:=NewPkgName;
|
NewPkgLink.Name:=NewPkgName;
|
||||||
NewPkgLink.Version.Assign(PkgVersion);
|
NewPkgLink.Version.Assign(PkgVersion);
|
||||||
NewPkgLink.Filename:=NewFilename;
|
NewPkgLink.Filename:=NewFilename;
|
||||||
if IsValidIdent(NewPkgLink.Name) then
|
if NewPkgLink.MakeSense then
|
||||||
FGlobalLinks.Add(NewPkgLink)
|
FGlobalLinks.Add(NewPkgLink)
|
||||||
else
|
else
|
||||||
NewPkgLink.Free;
|
NewPkgLink.Free;
|
||||||
@ -385,7 +393,8 @@ begin
|
|||||||
NewPkgLink.Version.LoadFromXMLConfig(XMLConfig,ItemPath+'Version/',
|
NewPkgLink.Version.LoadFromXMLConfig(XMLConfig,ItemPath+'Version/',
|
||||||
LazPkgXMLFileVersion);
|
LazPkgXMLFileVersion);
|
||||||
NewPkgLink.Filename:=XMLConfig.GetValue(ItemPath+'Filename/Value','');
|
NewPkgLink.Filename:=XMLConfig.GetValue(ItemPath+'Filename/Value','');
|
||||||
if IsValidIdent(NewPkgLink.Name) then
|
|
||||||
|
if NewPkgLink.MakeSense then
|
||||||
FUserLinks.Add(NewPkgLink)
|
FUserLinks.Add(NewPkgLink)
|
||||||
else
|
else
|
||||||
NewPkgLink.Free;
|
NewPkgLink.Free;
|
||||||
@ -575,6 +584,7 @@ var
|
|||||||
OldLink: TPackageLink;
|
OldLink: TPackageLink;
|
||||||
NewLink: TPackageLink;
|
NewLink: TPackageLink;
|
||||||
begin
|
begin
|
||||||
|
BeginUpdate;
|
||||||
// check if link already exists
|
// check if link already exists
|
||||||
OldLink:=FindLinkWithPackageID(APackage);
|
OldLink:=FindLinkWithPackageID(APackage);
|
||||||
if (OldLink<>nil) then begin
|
if (OldLink<>nil) then begin
|
||||||
@ -587,8 +597,12 @@ begin
|
|||||||
NewLink:=TPackageLink.Create;
|
NewLink:=TPackageLink.Create;
|
||||||
NewLink.AssignID(APackage);
|
NewLink.AssignID(APackage);
|
||||||
NewLink.Filename:=APackage.Filename;
|
NewLink.Filename:=APackage.Filename;
|
||||||
FUserLinks.Add(NewLink);
|
if NewLink.MakeSense then begin
|
||||||
Modified:=true;
|
FUserLinks.Add(NewLink);
|
||||||
|
Modified:=true;
|
||||||
|
end else
|
||||||
|
FUserLinks.Free;
|
||||||
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPackageLinks.RemoveLink(APackageID: TLazPackageID);
|
procedure TPackageLinks.RemoveLink(APackageID: TLazPackageID);
|
||||||
@ -596,12 +610,14 @@ var
|
|||||||
ANode: TAVLTreeNode;
|
ANode: TAVLTreeNode;
|
||||||
OldLink: TPackageLink;
|
OldLink: TPackageLink;
|
||||||
begin
|
begin
|
||||||
|
BeginUpdate;
|
||||||
// remove from user links
|
// remove from user links
|
||||||
ANode:=FUserLinks.Find(APackageID);
|
ANode:=FUserLinks.Find(APackageID);
|
||||||
if ANode<>nil then begin
|
if ANode<>nil then begin
|
||||||
OldLink:=TPackageLink(ANode.Data);
|
OldLink:=TPackageLink(ANode.Data);
|
||||||
FUserLinks.Remove(ANode);
|
FUserLinks.Remove(ANode);
|
||||||
OldLink.Free;
|
OldLink.Free;
|
||||||
|
Modified:=true;
|
||||||
end;
|
end;
|
||||||
// remove from global links
|
// remove from global links
|
||||||
ANode:=FGlobalLinks.Find(APackageID);
|
ANode:=FGlobalLinks.Find(APackageID);
|
||||||
@ -609,8 +625,9 @@ begin
|
|||||||
OldLink:=TPackageLink(ANode.Data);
|
OldLink:=TPackageLink(ANode.Data);
|
||||||
FGlobalLinks.Remove(ANode);
|
FGlobalLinks.Remove(ANode);
|
||||||
OldLink.Free;
|
OldLink.Free;
|
||||||
|
Modified:=true;
|
||||||
end;
|
end;
|
||||||
Modified:=true;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@ type
|
|||||||
ComponentClasses: array of TComponentClass);
|
ComponentClasses: array of TComponentClass);
|
||||||
procedure RegistrationError(const Msg: string);
|
procedure RegistrationError(const Msg: string);
|
||||||
procedure AddPackage(APackage: TLazPackage);
|
procedure AddPackage(APackage: TLazPackage);
|
||||||
|
procedure ReplacePackage(OldPackage, NewPackage: TLazPackage);
|
||||||
procedure AddStaticBasePackages;
|
procedure AddStaticBasePackages;
|
||||||
procedure ClosePackage(APackage: TLazPackage);
|
procedure ClosePackage(APackage: TLazPackage);
|
||||||
procedure MarkNeededPackages;
|
procedure MarkNeededPackages;
|
||||||
@ -149,6 +150,7 @@ type
|
|||||||
const NewName: string; NewVersion: TPkgVersion): TList;
|
const NewName: string; NewVersion: TPkgVersion): TList;
|
||||||
function CheckIfPackageCanBeClosed(APackage: TLazPackage): boolean;
|
function CheckIfPackageCanBeClosed(APackage: TLazPackage): boolean;
|
||||||
function PackageIsNeeded(APackage: TLazPackage): boolean;
|
function PackageIsNeeded(APackage: TLazPackage): boolean;
|
||||||
|
function PackageCanBeReplaced(OldPackage, NewPackage: TLazPackage): boolean;
|
||||||
procedure RegisterStaticPackages;
|
procedure RegisterStaticPackages;
|
||||||
procedure AddDependencyToPackage(APackage: TLazPackage;
|
procedure AddDependencyToPackage(APackage: TLazPackage;
|
||||||
Dependency: TPkgDependency);
|
Dependency: TPkgDependency);
|
||||||
@ -335,7 +337,8 @@ begin
|
|||||||
if FUpdateLock=1 then begin
|
if FUpdateLock=1 then begin
|
||||||
fChanged:=Change;
|
fChanged:=Change;
|
||||||
if Assigned(OnBeginUpdate) then OnBeginUpdate(Self);
|
if Assigned(OnBeginUpdate) then OnBeginUpdate(Self);
|
||||||
end;
|
end else
|
||||||
|
fChanged:=fChanged or Change;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLazPackageGraph.EndUpdate;
|
procedure TLazPackageGraph.EndUpdate;
|
||||||
@ -816,6 +819,14 @@ begin
|
|||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TLazPackageGraph.ReplacePackage(OldPackage, NewPackage: TLazPackage);
|
||||||
|
begin
|
||||||
|
BeginUpdate(true);
|
||||||
|
Delete(fItems.IndexOf(OldPackage));
|
||||||
|
AddPackage(NewPackage);
|
||||||
|
EndUpdate;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TLazPackageGraph.AddStaticBasePackages;
|
procedure TLazPackageGraph.AddStaticBasePackages;
|
||||||
begin
|
begin
|
||||||
// FCL
|
// FCL
|
||||||
@ -865,8 +876,6 @@ begin
|
|||||||
// get needed package from stack
|
// get needed package from stack
|
||||||
dec(StackPtr);
|
dec(StackPtr);
|
||||||
Pkg:=PkgStack[StackPtr];
|
Pkg:=PkgStack[StackPtr];
|
||||||
// mark package as needed
|
|
||||||
Pkg.Flags:=Pkg.Flags+[lpfNeeded,lpfVisited];
|
|
||||||
// put all required packages on stack
|
// put all required packages on stack
|
||||||
Dependency:=Pkg.FirstRequiredDependency;
|
Dependency:=Pkg.FirstRequiredDependency;
|
||||||
while Dependency<>nil do begin
|
while Dependency<>nil do begin
|
||||||
@ -891,8 +900,9 @@ var
|
|||||||
begin
|
begin
|
||||||
BeginUpdate(false);
|
BeginUpdate(false);
|
||||||
MarkNeededPackages;
|
MarkNeededPackages;
|
||||||
for i:=FItems.Count-1 downto 0 do
|
for i:=FItems.Count-1 downto 0 do begin
|
||||||
if not (lpfNeeded in Packages[i].Flags) then Delete(i);
|
if not (lpfNeeded in Packages[i].Flags) then Delete(i);
|
||||||
|
end;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -970,23 +980,55 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TLazPackageGraph.PackageIsNeeded(APackage: TLazPackage): boolean;
|
function TLazPackageGraph.PackageIsNeeded(APackage: TLazPackage): boolean;
|
||||||
|
// check if package is currently in use (installed, autoinstall, editor open)
|
||||||
|
// !!! it does not check if any needed package needs this package
|
||||||
begin
|
begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
// check if package is open, installed or will be installed
|
// check if package is open, installed or will be installed
|
||||||
if (APackage.Installed<>pitNope) or (APackage.AutoInstall<>pitNope)
|
if (APackage.Installed<>pitNope) or (APackage.AutoInstall<>pitNope)
|
||||||
or ((APackage.Editor<>nil) and (APackage.Editor.Visible)) then
|
or ((APackage.Editor<>nil) and (APackage.Editor.Visible)) then
|
||||||
begin
|
begin
|
||||||
Result:=true;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
// check if package is used
|
|
||||||
if (APackage.FirstUsedByDependency=nil) then begin
|
|
||||||
Result:=false;
|
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
Result:=false;
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TLazPackageGraph.PackageCanBeReplaced(
|
||||||
|
OldPackage, NewPackage: TLazPackage): boolean;
|
||||||
|
var
|
||||||
|
Dependency: TPkgDependency;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
if PackageIsNeeded(OldPackage) then exit;
|
||||||
|
|
||||||
|
// check all used-by dependencies
|
||||||
|
Dependency:=OldPackage.FirstUsedByDependency;
|
||||||
|
if Dependency<>nil then begin
|
||||||
|
MarkNeededPackages;
|
||||||
|
while Dependency<>nil do begin
|
||||||
|
if (not Dependency.IsCompatible(NewPackage)) then begin
|
||||||
|
// replacing will break this dependency
|
||||||
|
// -> check if Owner is needed
|
||||||
|
if (Dependency.Owner=nil) then begin
|
||||||
|
// dependency has no owner -> can be broken
|
||||||
|
end else if (Dependency.Owner is TLazPackage) then begin
|
||||||
|
if lpfNeeded in TLazPackage(Dependency.Owner).Flags then begin
|
||||||
|
// a needed package needs old package -> can no be broken
|
||||||
|
exit;
|
||||||
|
end else begin
|
||||||
|
// an unneeded package needs old package -> can be broken
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
// an other thing (e.g. a project) needs old package -> can not be broken
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Dependency:=Dependency.NextUsedByDependency;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TLazPackageGraph.RegisterStaticPackages;
|
procedure TLazPackageGraph.RegisterStaticPackages;
|
||||||
begin
|
begin
|
||||||
// FCL
|
// FCL
|
||||||
|
@ -277,7 +277,7 @@ end;
|
|||||||
|
|
||||||
procedure TPkgManager.PkgManagerAddPackage(Pkg: TLazPackage);
|
procedure TPkgManager.PkgManagerAddPackage(Pkg: TLazPackage);
|
||||||
begin
|
begin
|
||||||
PkgLinks.AddUserLink(Pkg);
|
if FileExists(Pkg.FileName) then PkgLinks.AddUserLink(Pkg);
|
||||||
if PackageGraphExplorer<>nil then
|
if PackageGraphExplorer<>nil then
|
||||||
PackageGraphExplorer.UpdatePackageAdded(Pkg);
|
PackageGraphExplorer.UpdatePackageAdded(Pkg);
|
||||||
end;
|
end;
|
||||||
@ -608,15 +608,21 @@ begin
|
|||||||
// check if Package with same name is already loaded
|
// check if Package with same name is already loaded
|
||||||
ConflictPkg:=PackageGraph.FindAPackageWithName(APackage.Name,nil);
|
ConflictPkg:=PackageGraph.FindAPackageWithName(APackage.Name,nil);
|
||||||
if ConflictPkg<>nil then begin
|
if ConflictPkg<>nil then begin
|
||||||
Result:=MessageDlg('Package Name already loaded',
|
if not PackageGraph.PackageCanBeReplaced(ConflictPkg,APackage) then begin
|
||||||
'There is already a package with the name "'+APackage.Name+'" loaded'#13
|
Result:=MessageDlg('Package Name already loaded',
|
||||||
+'from file "'+ConflictPkg.Filename+'".',
|
'There is already a package with the name "'+APackage.Name+'" loaded'#13
|
||||||
mtError,[mbCancel,mbAbort],0);
|
+'from file "'+ConflictPkg.Filename+'".'#13
|
||||||
exit;
|
+'See Components -> Package Graph.',
|
||||||
|
mtError,[mbCancel,mbAbort],0);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// replace package
|
||||||
|
PackageGraph.ReplacePackage(ConflictPkg,APackage);
|
||||||
|
end else begin
|
||||||
|
// add to graph
|
||||||
|
PackageGraph.AddPackage(APackage);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// add to graph
|
|
||||||
PackageGraph.AddPackage(APackage);
|
|
||||||
|
|
||||||
// save package file links
|
// save package file links
|
||||||
PkgLinks.SaveUserLinks;
|
PkgLinks.SaveUserLinks;
|
||||||
@ -670,8 +676,28 @@ function TPkgManager.DoOpenPackageFile(AFilename: string; Flags: TPkgOpenFlags
|
|||||||
var
|
var
|
||||||
APackage: TLazPackage;
|
APackage: TLazPackage;
|
||||||
XMLConfig: TXMLConfig;
|
XMLConfig: TXMLConfig;
|
||||||
|
AlternativePkgName: String;
|
||||||
begin
|
begin
|
||||||
AFilename:=CleanAndExpandFilename(AFilename);
|
AFilename:=CleanAndExpandFilename(AFilename);
|
||||||
|
|
||||||
|
// check file extension
|
||||||
|
if CompareFileExt(AFilename,'.lpk',false)<>0 then begin
|
||||||
|
Result:=MessageDlg('Invalid file extension',
|
||||||
|
'The file "'+AFilename+'" is not a lazarus package.',
|
||||||
|
mtError,[mbCancel,mbAbort],0);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// check filename
|
||||||
|
AlternativePkgName:=ExtractFileNameOnly(AFilename);
|
||||||
|
if (AlternativePkgName='') or (not IsValidIdent(AlternativePkgName)) then
|
||||||
|
begin
|
||||||
|
Result:=MessageDlg('Invalid package filename',
|
||||||
|
'The package file name "'+AlternativePkgName+'" in'#13
|
||||||
|
+'"'+AFilename+'" is not a valid lazarus package name.',
|
||||||
|
mtError,[mbCancel,mbAbort],0);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
// check if package is already loaded
|
// check if package is already loaded
|
||||||
APackage:=PackageGraph.FindPackageWithFilename(AFilename,true);
|
APackage:=PackageGraph.FindPackageWithFilename(AFilename,true);
|
||||||
@ -692,6 +718,7 @@ begin
|
|||||||
Result:=mrCancel;
|
Result:=mrCancel;
|
||||||
APackage:=TLazPackage.Create;
|
APackage:=TLazPackage.Create;
|
||||||
try
|
try
|
||||||
|
|
||||||
// load the package file
|
// load the package file
|
||||||
try
|
try
|
||||||
XMLConfig:=TXMLConfig.Create(AFilename);
|
XMLConfig:=TXMLConfig.Create(AFilename);
|
||||||
@ -709,8 +736,22 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// newly loaded is not modified
|
||||||
APackage.Modified:=false;
|
APackage.Modified:=false;
|
||||||
|
|
||||||
|
// check if package name and file name correspond
|
||||||
|
if (AnsiCompareText(AlternativePkgName,APackage.Name)<>0) then begin
|
||||||
|
Result:=MessageDlg('Filename differs from Packagename',
|
||||||
|
'The filename "'+ExtractFileName(AFilename)+'" does not correspond '
|
||||||
|
+'to the package name "'+APackage.Name+'" in the file.'#13
|
||||||
|
+'Change package name to "'+AlternativePkgName+'"?',
|
||||||
|
mtConfirmation,[mbYes,mbCancel,mbAbort],0);
|
||||||
|
if Result<>mrYes then exit;
|
||||||
|
APackage.Name:=AlternativePkgName;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// integrate it into the graph
|
||||||
Result:=AddPackageToGraph(APackage);
|
Result:=AddPackageToGraph(APackage);
|
||||||
finally
|
finally
|
||||||
if Result<>mrOk then APackage.Free;
|
if Result<>mrOk then APackage.Free;
|
||||||
|
Loading…
Reference in New Issue
Block a user