IDE: check i lpi file changes on disk

git-svn-id: trunk@22980 -
This commit is contained in:
mattias 2009-12-05 20:30:35 +00:00
parent d80a143fad
commit c3417c257b
6 changed files with 122 additions and 23 deletions

View File

@ -54,13 +54,15 @@ type
protected protected
doc: TXMLDocument; doc: TXMLDocument;
FModified: Boolean; FModified: Boolean;
fDoNotLoad: boolean; fDoNotLoadFromFile: boolean;
fAutoLoadFromSource: string;
procedure Loaded; override; procedure Loaded; override;
function ExtendedToStr(const e: extended): string; function ExtendedToStr(const e: extended): string;
function StrToExtended(const s: string; const ADefault: extended): extended; function StrToExtended(const s: string; const ADefault: extended): extended;
public public
constructor Create(const AFilename: String); overload; constructor Create(const AFilename: String); overload;
constructor CreateClean(const AFilename: String); constructor CreateClean(const AFilename: String);
constructor CreateWithSource(const AFilename, Source: String);
destructor Destroy; override; destructor Destroy; override;
procedure Clear; procedure Clear;
procedure Flush; // Writes the XML file procedure Flush; // Writes the XML file
@ -109,11 +111,21 @@ constructor TXMLConfig.CreateClean(const AFilename: String);
begin begin
//DebugLn(['TXMLConfig.CreateClean ',AFilename]); //DebugLn(['TXMLConfig.CreateClean ',AFilename]);
inherited Create(nil); inherited Create(nil);
fDoNotLoad:=true; fDoNotLoadFromFile:=true;
SetFilename(AFilename); SetFilename(AFilename);
FModified:=FileExistsCached(AFilename); FModified:=FileExistsCached(AFilename);
end; end;
constructor TXMLConfig.CreateWithSource(const AFilename, Source: String);
begin
fAutoLoadFromSource:=Source;
try
CreateClean(AFilename);
finally
fAutoLoadFromSource:='';
end;
end;
destructor TXMLConfig.Destroy; destructor TXMLConfig.Destroy;
begin begin
if Assigned(doc) then if Assigned(doc) then
@ -143,6 +155,7 @@ procedure TXMLConfig.Flush;
begin begin
if Modified and (Filename<>'') then if Modified and (Filename<>'') then
begin begin
DebugLn(['TXMLConfig.Flush ',Filename]);
WriteXMLFile(doc, Filename); WriteXMLFile(doc, Filename);
FModified := False; FModified := False;
end; end;
@ -429,6 +442,7 @@ end;
procedure TXMLConfig.SetFilename(const AFilename: String); procedure TXMLConfig.SetFilename(const AFilename: String);
var var
cfg: TDOMElement; cfg: TDOMElement;
ms: TMemoryStream;
begin begin
{$IFDEF MEM_CHECK}CheckHeapWrtMemCnt('TXMLConfig.SetFilename A '+AFilename);{$ENDIF} {$IFDEF MEM_CHECK}CheckHeapWrtMemCnt('TXMLConfig.SetFilename A '+AFilename);{$ENDIF}
if FFilename = AFilename then exit; if FFilename = AFilename then exit;
@ -444,8 +458,18 @@ begin
end; end;
doc:=nil; doc:=nil;
if FileExistsUTF8(AFilename) and (not fDoNotLoad) then if (not fDoNotLoadFromFile) and FileExistsUTF8(AFilename) then
ReadXMLFile(doc,AFilename); ReadXMLFile(doc,AFilename)
else if fAutoLoadFromSource<>'' then begin
ms:=TMemoryStream.Create;
try
ms.Write(fAutoLoadFromSource[1],length(fAutoLoadFromSource));
ms.Position:=0;
ReadXMLFile(doc,ms);
finally
ms.Free;
end;
end;
if not Assigned(doc) then if not Assigned(doc) then
doc := TXMLDocument.Create; doc := TXMLDocument.Create;

View File

@ -391,7 +391,7 @@ begin
break; break;
end else begin end else begin
Result:=IDEMessageDialog(lisUnableToWriteFile, Result:=IDEMessageDialog(lisUnableToWriteFile,
Format(lisUnableToWriteFile2, ['"', Buffer.Filename, '"']), Format(lisUnableToWriteToFile, ['"', Buffer.Filename, '"']),
mtError,ErrorButtons+[mbCancel]); mtError,ErrorButtons+[mbCancel]);
if Result<>mrRetry then exit; if Result<>mrRetry then exit;
end; end;
@ -450,7 +450,7 @@ begin
end; end;
except except
Result:=IDEMessageDialog(lisUnableToWriteFile, Result:=IDEMessageDialog(lisUnableToWriteFile,
Format(lisUnableToWriteFilename, ['"', AFilename, '"']), mtError, [ Format(lisUnableToWriteToFile, ['"', AFilename, '"']), mtError, [
mbCancel, mbAbort]); mbCancel, mbAbort]);
exit; exit;
end; end;
@ -479,7 +479,7 @@ begin
Result:=mrOk; Result:=mrOk;
while not FileIsWritable(Filename) do begin while not FileIsWritable(Filename) do begin
Result:=IDEMessageDialog(lisFileIsNotWritable, Result:=IDEMessageDialog(lisFileIsNotWritable,
Format(lisUnableToWriteToFile2, ['"', Filename, '"']), Format(lisUnableToWriteToFile, ['"', Filename, '"']),
mtError,ErrorButtons+[mbCancel]); mtError,ErrorButtons+[mbCancel]);
if Result<>mrRetry then exit; if Result<>mrRetry then exit;
end; end;

View File

@ -531,6 +531,11 @@ resourcestring
lisFileNotText = 'File not text'; lisFileNotText = 'File not text';
lisUnableToRenameFile = 'Unable to rename file'; lisUnableToRenameFile = 'Unable to rename file';
lisUnableToCopyFile = 'Unable to copy file'; lisUnableToCopyFile = 'Unable to copy file';
lisWriteError = 'Write Error';
lisFileDoesNotLookLikeATextFileOpenItAnyway2 = 'File %s%s%s%sdoes not look '
+'like a text file.%sOpen it anyway?';
lisUnableToCreateBackupDirectory =
'Unable to create backup directory %s%s%s.';
lisSourceAndDestinationAreTheSame = lisSourceAndDestinationAreTheSame =
'Source and Destination are the same:%s%s'; 'Source and Destination are the same:%s%s';
lisUnableToRenameFileTo2 = 'Unable to rename file %s%s%s%sto %s%s%s.'; lisUnableToRenameFileTo2 = 'Unable to rename file %s%s%s%sto %s%s%s.';
@ -588,12 +593,6 @@ resourcestring
+'file.'; +'file.';
lisUnableToReadTheProjectInfoFile2 = 'Unable to read the project info file%' lisUnableToReadTheProjectInfoFile2 = 'Unable to read the project info file%'
+'s%s%s%s.'; +'s%s%s%s.';
lisWriteError = 'Write Error';
lisUnableToWriteToFile = 'Unable to write to file %s%s%s!';
lisFileDoesNotLookLikeATextFileOpenItAnyway2 = 'File %s%s%s%sdoes not look '
+'like a text file.%sOpen it anyway?';
lisUnableToCreateBackupDirectory =
'Unable to create backup directory %s%s%s.';
lisAmbiguousUnitFound2 = 'Ambiguous unit found'; lisAmbiguousUnitFound2 = 'Ambiguous unit found';
lisTheUnitExistsTwiceInTheUnitPathOfThe = 'The unit %s exists twice in the ' lisTheUnitExistsTwiceInTheUnitPathOfThe = 'The unit %s exists twice in the '
+'unit path of the %s:'; +'unit path of the %s:';
@ -2956,10 +2955,8 @@ resourcestring
+'yet in the unit path.%sAdd it?'; +'yet in the unit path.%sAdd it?';
lisUnableToCreateFilename = 'Unable to create file %s%s%s.'; lisUnableToCreateFilename = 'Unable to create file %s%s%s.';
lisUnableToWriteFile = 'Unable to write file'; lisUnableToWriteFile = 'Unable to write file';
lisUnableToWriteFile2 = 'Unable to write file %s%s%s'; lisUnableToWriteToFile = 'Unable to write to file %s%s%s.';
lisFileIsNotWritable = 'File is not writable'; lisFileIsNotWritable = 'File is not writable';
lisUnableToWriteToFile2 = 'Unable to write to file %s%s%s';
lisUnableToWriteFilename = 'Unable to write file %s%s%s.';
lisUnableToReadFile = 'Unable to read file'; lisUnableToReadFile = 'Unable to read file';
lisUnableToReadFilename = 'Unable to read file %s%s%s.'; lisUnableToReadFilename = 'Unable to read file %s%s%s.';
lisErrorDeletingFile = 'Error deleting file'; lisErrorDeletingFile = 'Error deleting file';
@ -4345,6 +4342,10 @@ resourcestring
+'default compiler. e.g. ppc386 ppcx64 ppcppc etc. default is stored in ' +'default compiler. e.g. ppc386 ppcx64 ppcppc etc. default is stored in '
+'environmentoptions.xml'; +'environmentoptions.xml';
lisNo = 'No'; lisNo = 'No';
lisProjectChangedOnDisk = 'Project changed on disk';
lisTheProjectInformationFileHasChangedOnDisk = 'The project information '
+'file %s%s%s%shas changed on disk.';
lisReopenProject = 'Reopen project';
rsOk = 'ok'; rsOk = 'ok';
rsScanners = 'Scanners'; rsScanners = 'Scanners';
rsAvailableScanners = 'Available scanners'; rsAvailableScanners = 'Available scanners';

View File

@ -11245,6 +11245,21 @@ begin
APackageList:=nil; APackageList:=nil;
try try
InvalidateFileStateCache; InvalidateFileStateCache;
if Project1.HasProjectInfoFileChangedOnDisk then begin
if QuestionDlg(lisProjectChangedOnDisk,
Format(lisTheProjectInformationFileHasChangedOnDisk, ['"',
Project1.ProjectInfoFile, '"', #13]), mtConfirmation, [mrYes,
lisReopenProject, mrIgnore], '')
=mrYes
then begin
DoOpenProjectFile(Project1.ProjectInfoFile,[]);
end else begin
Project1.IgnoreProjectInfoFileOnDisk;
end;
exit(mrOk);
end;
Project1.GetUnitsChangedOnDisk(AnUnitList); Project1.GetUnitsChangedOnDisk(AnUnitList);
PkgBoss.GetPackagesChangedOnDisk(APackageList); PkgBoss.GetPackagesChangedOnDisk(APackageList);
if (AnUnitList=nil) and (APackageList=nil) then exit; if (AnUnitList=nil) and (APackageList=nil) then exit;

View File

@ -609,6 +609,8 @@ type
fProjectDirectory: string; fProjectDirectory: string;
fProjectDirectoryReferenced: string; fProjectDirectoryReferenced: string;
fProjectInfoFile: String; // the lpi filename fProjectInfoFile: String; // the lpi filename
fProjectInfoFileBuffer: TCodeBuffer;
fProjectInfoFileDate: LongInt;
FPublishOptions: TPublishProjectOptions; FPublishOptions: TPublishProjectOptions;
FResources: TProjectResources; FResources: TProjectResources;
FRevertLockCount: integer; FRevertLockCount: integer;
@ -693,6 +695,8 @@ type
function SomethingModified(CheckData, CheckSession: boolean): boolean; function SomethingModified(CheckData, CheckSession: boolean): boolean;
procedure MainSourceFilenameChanged; procedure MainSourceFilenameChanged;
procedure GetUnitsChangedOnDisk(var AnUnitList: TFPList); procedure GetUnitsChangedOnDisk(var AnUnitList: TFPList);
function HasProjectInfoFileChangedOnDisk: boolean;
procedure IgnoreProjectInfoFileOnDisk;
function ReadProject(const NewProjectInfoFile: string): TModalResult; function ReadProject(const NewProjectInfoFile: string): TModalResult;
function WriteProject(ProjectWriteFlags: TProjectWriteFlags; function WriteProject(ProjectWriteFlags: TProjectWriteFlags;
const OverrideProjectInfoFile: string): TModalResult; const OverrideProjectInfoFile: string): TModalResult;
@ -2171,10 +2175,18 @@ begin
Result:=mrOk; Result:=mrOk;
except except
on E: Exception do begin on E: Exception do begin
Result:=MessageDlg('Write error','Unable to write to file "'+CfgFilename+'".', Result:=MessageDlg(lisCodeToolsDefsWriteError, Format(
lisUnableToWriteToFile, ['"', CfgFilename, '"']),
mtError,[mbRetry,mbAbort],0); mtError,[mbRetry,mbAbort],0);
end; end;
end; end;
if CompareFilenames(ProjectInfoFile,xmlconfig.Filename)=0 then begin
fProjectInfoFileBuffer:=CodeToolBoss.LoadFile(ProjectInfoFile,true,true);
try
fProjectInfoFileDate:=FileAgeUTF8(ProjectInfoFile);
except
end;
end;
try try
xmlconfig.Free; xmlconfig.Free;
except except
@ -2489,9 +2501,15 @@ begin
Clear; Clear;
ProjectInfoFile:=NewProjectInfoFile; ProjectInfoFile:=NewProjectInfoFile;
fProjectInfoFileBuffer:=CodeToolBoss.LoadFile(ProjectInfoFile,true,true);
try try
fProjectInfoFileDate:=FileAgeUTF8(ProjectInfoFile);
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject A reading lpi');{$ENDIF} {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject A reading lpi');{$ENDIF}
xmlconfig := TXMLConfig.Create(ProjectInfoFile); if fProjectInfoFileBuffer=nil then
xmlconfig := TXMLConfig.CreateClean(ProjectInfoFile)
else
xmlconfig := TXMLConfig.CreateWithSource(ProjectInfoFile,
fProjectInfoFileBuffer.Source);
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject B done lpi');{$ENDIF} {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject B done lpi');{$ENDIF}
except except
MessageDlg(Format(lisUnableToReadTheProjectInfoFile, [#13, '"', MessageDlg(Format(lisUnableToReadTheProjectInfoFile, [#13, '"',
@ -2591,6 +2609,7 @@ begin
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject freeing xml');{$ENDIF} {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject freeing xml');{$ENDIF}
fPathDelimChanged:=false; fPathDelimChanged:=false;
try try
xmlconfig.Modified:=false;
xmlconfig.Free; xmlconfig.Free;
except except
end; end;
@ -2633,6 +2652,7 @@ begin
fPathDelimChanged:=false; fPathDelimChanged:=false;
try try
xmlconfig.Modified:=false;
xmlconfig.Free; xmlconfig.Free;
except except
end; end;
@ -3628,6 +3648,37 @@ begin
end; end;
end; end;
function TProject.HasProjectInfoFileChangedOnDisk: boolean;
var
AnUnitInfo: TUnitInfo;
begin
Result:=false;
if IsVirtual or Modified then exit;
AnUnitInfo:=UnitInfoWithFilename(ProjectInfoFile,[pfsfOnlyEditorFiles]);
if (AnUnitInfo<>nil) then begin
// users is editing the lpi file in source editor
exit;
end;
AnUnitInfo:=fFirst[uilAutoRevertLocked];
while (AnUnitInfo<>nil) do begin
if CompareFilenames(AnUnitInfo.Filename,ProjectInfoFile)=0 then begin
// revert locked
exit;
end;
AnUnitInfo:=AnUnitInfo.fNext[uilAutoRevertLocked];
end;
if not FileExistsCached(ProjectInfoFile) then exit;
if fProjectInfoFileDate=FileAgeUTF8(ProjectInfoFile) then exit;
//DebugLn(['TProject.HasProjectInfoFileChangedOnDisk ',ProjectInfoFile,' fProjectInfoFileDate=',fProjectInfoFileDate,' ',FileAgeUTF8(ProjectInfoFile)]);
Result:=true;
end;
procedure TProject.IgnoreProjectInfoFileOnDisk;
begin
fProjectInfoFileDate:=FileAgeUTF8(ProjectInfoFile);
end;
procedure TProject.SetBookmark(AnUnitInfo: TUnitInfo; X, Y, ID: integer); procedure TProject.SetBookmark(AnUnitInfo: TUnitInfo; X, Y, ID: integer);
begin begin
if AnUnitInfo.EditorIndex>=0 then if AnUnitInfo.EditorIndex>=0 then

View File

@ -151,6 +151,7 @@ type
procedure BeginUpdate; procedure BeginUpdate;
procedure EndUpdate; procedure EndUpdate;
procedure SaveUserLinks; procedure SaveUserLinks;
function NeedSaveUserLinks(const ConfigFilename: string): boolean;
procedure WriteLinkTree(LinkTree: TAVLTree); procedure WriteLinkTree(LinkTree: TAVLTree);
function FindLinkWithPkgName(const PkgName: string): TPackageLink; function FindLinkWithPkgName(const PkgName: string): TPackageLink;
function FindLinkWithDependency(Dependency: TPkgDependency): TPackageLink; function FindLinkWithDependency(Dependency: TPkgDependency): TPackageLink;
@ -531,6 +532,7 @@ begin
end else end else
NewPkgLink.Free; NewPkgLink.Free;
end; end;
XMLConfig.Modified:=false;
XMLConfig.Free; XMLConfig.Free;
UserLinkLoadTime:=FileAgeUTF8(ConfigFilename); UserLinkLoadTime:=FileAgeUTF8(ConfigFilename);
@ -608,11 +610,8 @@ begin
ConfigFilename:=GetUserLinkFile; ConfigFilename:=GetUserLinkFile;
// check if file needs saving // check if file needs saving
if (not Modified) if not NeedSaveUserLinks(ConfigFilename) then exit;
and UserLinkLoadTimeValid and FileExistsUTF8(ConfigFilename) //DebugLn(['TPackageLinks.SaveUserLinks saving ... ',ConfigFilename,' Modified=',Modified,' UserLinkLoadTimeValid=',UserLinkLoadTimeValid,' ',FileAgeUTF8(ConfigFilename)=UserLinkLoadTime]);
and (FileAgeUTF8(ConfigFilename)=UserLinkLoadTime) then
exit;
//DebugLn(['TPackageLinks.SaveUserLinks saving ... ',ConfigFilename]);
LazSrcDir:=EnvironmentOptions.LazarusDirectory; LazSrcDir:=EnvironmentOptions.LazarusDirectory;
@ -621,6 +620,7 @@ begin
XMLConfig:=TXMLConfig.CreateClean(ConfigFilename); XMLConfig:=TXMLConfig.CreateClean(ConfigFilename);
Path:='UserPkgLinks/'; Path:='UserPkgLinks/';
XMLConfig.SetValue(Path+'Version',PkgLinksFileVersion);
ANode:=FUserLinksSortID.FindLowest; ANode:=FUserLinksSortID.FindLowest;
i:=0; i:=0;
while ANode<>nil do begin while ANode<>nil do begin
@ -665,6 +665,14 @@ begin
Modified:=false; Modified:=false;
end; end;
function TPackageLinks.NeedSaveUserLinks(const ConfigFilename: string): boolean;
begin
Result:=Modified
or (not UserLinkLoadTimeValid)
or (not FileExistsUTF8(ConfigFilename))
or (FileAgeUTF8(ConfigFilename)<>UserLinkLoadTime);
end;
procedure TPackageLinks.WriteLinkTree(LinkTree: TAVLTree); procedure TPackageLinks.WriteLinkTree(LinkTree: TAVLTree);
var var
ANode: TAVLTreeNode; ANode: TAVLTreeNode;