mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-17 04:29:25 +02:00
implemented automatic redirecting of package output directory and filestate cache
git-svn-id: trunk@6680 -
This commit is contained in:
parent
a7606840be
commit
81f9980ad0
@ -261,7 +261,7 @@ begin
|
||||
if Result=nil then begin
|
||||
// load new buffer
|
||||
Result:=TCodeBuffer.Create;
|
||||
if (not FileExists(AFilename)) then begin
|
||||
if (not FileExistsCached(AFilename)) then begin
|
||||
Result.Free;
|
||||
Result:=nil;
|
||||
exit;
|
||||
@ -281,7 +281,7 @@ begin
|
||||
end;
|
||||
end else if Result.IsDeleted then begin
|
||||
// file in cache, but marked as deleted -> load from disk
|
||||
if (not FileExists(AFilename))
|
||||
if (not FileExistsCached(AFilename))
|
||||
or (not Result.LoadFromFile(AFilename)) then
|
||||
begin
|
||||
Result:=nil;
|
||||
@ -419,7 +419,7 @@ begin
|
||||
if OnlyIfExists then begin
|
||||
Result:=FindFile(AFilename);
|
||||
if (Result=nil)
|
||||
and (FilenameIsAbsolute(AFilename) and FileExists(AFilename)) then
|
||||
and (FilenameIsAbsolute(AFilename) and FileExistsCached(AFilename)) then
|
||||
Result:=LoadFile(AFilename);
|
||||
end else
|
||||
Result:=LoadFile(AFilename);
|
||||
@ -541,7 +541,8 @@ begin
|
||||
if OnlyIfChanged and fLastIncludeLinkFileValid
|
||||
and (fLastIncludeLinkFileChangeStep=fChangeStep)
|
||||
and (fLastIncludeLinkFile=AFilename)
|
||||
and FileExists(AFilename) and (FileAge(AFilename)=fLastIncludeLinkFileAge)
|
||||
and FileExistsCached(AFilename)
|
||||
and (FileAge(AFilename)=fLastIncludeLinkFileAge)
|
||||
then begin
|
||||
exit;
|
||||
end;
|
||||
|
@ -543,7 +543,7 @@ begin
|
||||
inc(UnitLinkEnd);
|
||||
if UnitLinkEnd>UnitLinkStart then begin
|
||||
Filename:=copy(UnitLinks,UnitLinkStart,UnitLinkEnd-UnitLinkStart);
|
||||
if FileExists(Filename) then begin
|
||||
if FileExistsCached(Filename) then begin
|
||||
Result:=true;
|
||||
exit;
|
||||
end;
|
||||
@ -552,7 +552,7 @@ begin
|
||||
Filename:=ChangeFileExt(Filename,'.pas')
|
||||
else
|
||||
Filename:=ChangeFileExt(Filename,'.pp');
|
||||
if FileExists(Filename) then begin
|
||||
if FileExistsCached(Filename) then begin
|
||||
Result:=true;
|
||||
exit;
|
||||
end;
|
||||
@ -2738,7 +2738,7 @@ begin
|
||||
SetLength(Buf,1024);
|
||||
try
|
||||
CmdLine:=PPC386Path+' -va ';
|
||||
if FileExists(EnglishErrorMsgFilename) then
|
||||
if FileExistsCached(EnglishErrorMsgFilename) then
|
||||
CmdLine:=CmdLine+'-Fr'+EnglishErrorMsgFilename+' ';
|
||||
if PPCOptions<>'' then
|
||||
CmdLine:=CmdLine+PPCOptions+' ';
|
||||
|
@ -35,7 +35,8 @@ uses
|
||||
{$IFDEF MEM_CHECK}
|
||||
MemCheck,
|
||||
{$ENDIF}
|
||||
Classes, SysUtils, CodeToolsStrConsts;
|
||||
Classes, SysUtils, {$IFNDEF VER1_0}AVL_Tree{$ELSE}OldAvLTree{$ENDIF},
|
||||
CodeToolsStrConsts;
|
||||
|
||||
type
|
||||
TFPCStreamSeekType = int64;
|
||||
@ -58,6 +59,7 @@ function CompareFileExt(const Filename, Ext: string;
|
||||
CaseSensitive: boolean): integer;
|
||||
function GetFilenameOnDisk(const AFilename: string): string;
|
||||
function DirPathExists(DirectoryName: string): boolean;
|
||||
function DirectoryIsWritable(const DirectoryName: string): boolean;
|
||||
function ExtractFileNameOnly(const AFilename: string): string;
|
||||
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
||||
function FilenameIsWinAbsolute(const TheFilename: string):boolean;
|
||||
@ -79,6 +81,7 @@ function SearchFileInPath(const Filename, BasePath, SearchPath,
|
||||
function FilenameIsMatching(const Mask, Filename: string;
|
||||
MatchExactly: boolean): boolean;
|
||||
function ClearFile(const Filename: string; RaiseOnError: boolean): boolean;
|
||||
function GetTempFilename(const Path, Prefix: string): string;
|
||||
|
||||
|
||||
// debugging
|
||||
@ -116,6 +119,95 @@ function DbgSName(const p: TObject): string;
|
||||
function DbgStr(const StringWithSpecialChars: string): string;
|
||||
|
||||
|
||||
type
|
||||
TFileStateCacheItemFlag = (
|
||||
fsciExists, // file or directory exists
|
||||
fsciDirectory, // file exists and is directory
|
||||
fsciReadable, // file is readable
|
||||
fsciWritable, // file is writable
|
||||
fsciDirectoryReadable, // file is directory and can be searched
|
||||
fsciDirectoryWritable, // file is directory and new files can be created
|
||||
fsciText, // file is text file (not binary)
|
||||
fsciExecutable // file is executable
|
||||
);
|
||||
TFileStateCacheItemFlags = set of TFileStateCacheItemFlag;
|
||||
|
||||
{ TFileStateCacheItem }
|
||||
|
||||
TFileStateCacheItem = class
|
||||
private
|
||||
FFilename: string;
|
||||
FFlags: TFileStateCacheItemFlags;
|
||||
FTestedFlags: TFileStateCacheItemFlags;
|
||||
FTimeStamp: integer;
|
||||
public
|
||||
constructor Create(const TheFilename: string; NewTimeStamp: integer);
|
||||
public
|
||||
property Filename: string read FFilename;
|
||||
property Flags: TFileStateCacheItemFlags read FFlags;
|
||||
property TestedFlags: TFileStateCacheItemFlags read FTestedFlags;
|
||||
property TimeStamp: integer read FTimeStamp;
|
||||
end;
|
||||
|
||||
{ TFileStateCache }
|
||||
|
||||
TFileStateCache = class
|
||||
private
|
||||
FFiles: TAVLTree;
|
||||
FTimeStamp: integer;
|
||||
FLockCount: integer;
|
||||
procedure SetFlag(AFile: TFileStateCacheItem;
|
||||
AFlag: TFileStateCacheItemFlag; NewValue: boolean);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Lock;
|
||||
procedure Unlock;
|
||||
function Locked: boolean;
|
||||
procedure IncreaseTimeStamp;
|
||||
function FileExistsCached(const Filename: string): boolean;
|
||||
function DirPathExistsCached(const Filename: string): boolean;
|
||||
function DirectoryIsWritableCached(const DirectoryName: string): boolean;
|
||||
function FileIsExecutableCached(const AFilename: string): boolean;
|
||||
function FileIsReadableCached(const AFilename: string): boolean;
|
||||
function FileIsWritableCached(const AFilename: string): boolean;
|
||||
function FileIsTextCached(const AFilename: string): boolean;
|
||||
function FindFile(const Filename: string;
|
||||
CreateIfNotExists: boolean): TFileStateCacheItem;
|
||||
function Check(const Filename: string; AFlag: TFileStateCacheItemFlag;
|
||||
var AFile: TFileStateCacheItem; var FlagIsSet: boolean): boolean;
|
||||
procedure WriteDebugReport;
|
||||
public
|
||||
property TimeStamp: integer read FTimeStamp;
|
||||
end;
|
||||
|
||||
var
|
||||
FileStateCache: TFileStateCache;
|
||||
|
||||
function FileExistsCached(const Filename: string): boolean;
|
||||
function DirPathExistsCached(const Filename: string): boolean;
|
||||
function DirectoryIsWritableCached(const DirectoryName: string): boolean;
|
||||
function FileIsExecutableCached(const AFilename: string): boolean;
|
||||
function FileIsReadableCached(const AFilename: string): boolean;
|
||||
function FileIsWritableCached(const AFilename: string): boolean;
|
||||
function FileIsTextCached(const AFilename: string): boolean;
|
||||
|
||||
procedure InvalidateFileStateCache;
|
||||
function CompareFileStateItems(Data1, Data2: Pointer): integer;
|
||||
function CompareFilenameWithFileStateCacheItem(Key, Data: Pointer): integer;
|
||||
|
||||
const
|
||||
FileStateCacheItemFlagNames: array[TFileStateCacheItemFlag] of string = (
|
||||
'fsciExists',
|
||||
'fsciDirectory',
|
||||
'fsciReadable',
|
||||
'fsciWritable',
|
||||
'fsciDirectoryReadable',
|
||||
'fsciDirectoryWritable',
|
||||
'fsciText',
|
||||
'fsciExecutable'
|
||||
);
|
||||
|
||||
implementation
|
||||
|
||||
// to get more detailed error messages consider the os
|
||||
@ -136,6 +228,7 @@ var
|
||||
begin
|
||||
if FileExists(Filename) then begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmOpenWrite);
|
||||
fs.Size:=0;
|
||||
fs.Free;
|
||||
@ -150,12 +243,49 @@ begin
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function DirectoryIsWritable(const DirectoryName: string): boolean;
|
||||
var
|
||||
TempFilename: String;
|
||||
fs: TFileStream;
|
||||
s: String;
|
||||
begin
|
||||
TempFilename:=GetTempFilename(DirectoryName,'tstperm');
|
||||
Result:=false;
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(TempFilename,fmCreate);
|
||||
s:='WriteTest';
|
||||
fs.Write(s[1],length(s));
|
||||
fs.Free;
|
||||
DeleteFile(TempFilename);
|
||||
Result:=true;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetTempFilename(const Path, Prefix: string): string;
|
||||
var
|
||||
i: Integer;
|
||||
CurPath: String;
|
||||
CurName: String;
|
||||
begin
|
||||
Result:=ExpandFilename(Path);
|
||||
CurPath:=AppendPathDelim(ExtractFilePath(Result));
|
||||
CurName:=Prefix+ExtractFileNameOnly(Result);
|
||||
i:=1;
|
||||
repeat
|
||||
Result:=CurPath+CurName+IntToStr(i)+'.tmp';
|
||||
if not FileExists(Result) then exit;
|
||||
inc(i);
|
||||
until false;
|
||||
end;
|
||||
|
||||
function CompareFilenames(const Filename1, Filename2: string): integer;
|
||||
begin
|
||||
{$IFDEF WIN32}
|
||||
Result:=AnsiCompareText(Filename1, Filename2);
|
||||
Result:=CompareText(Filename1, Filename2);
|
||||
{$ELSE}
|
||||
Result:=AnsiCompareStr(Filename1, Filename2);
|
||||
Result:=CompareStr(Filename1, Filename2);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
@ -1014,19 +1144,274 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function FileExistsCached(const Filename: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.FileExistsCached(Filename);
|
||||
end;
|
||||
|
||||
function DirPathExistsCached(const Filename: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.DirPathExistsCached(Filename);
|
||||
end;
|
||||
|
||||
function DirectoryIsWritableCached(const DirectoryName: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.DirectoryIsWritableCached(DirectoryName);
|
||||
end;
|
||||
|
||||
function FileIsExecutableCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.FileIsExecutableCached(AFilename);
|
||||
end;
|
||||
|
||||
function FileIsReadableCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.FileIsReadableCached(AFilename);
|
||||
end;
|
||||
|
||||
function FileIsWritableCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.FileIsWritableCached(AFilename);
|
||||
end;
|
||||
|
||||
function FileIsTextCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileStateCache.FileIsTextCached(AFilename);
|
||||
end;
|
||||
|
||||
procedure InvalidateFileStateCache;
|
||||
begin
|
||||
FileStateCache.IncreaseTimeStamp;
|
||||
end;
|
||||
|
||||
function CompareFileStateItems(Data1, Data2: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareFilenames(TFileStateCacheItem(Data1).FFilename,
|
||||
TFileStateCacheItem(Data2).FFilename);
|
||||
end;
|
||||
|
||||
function CompareFilenameWithFileStateCacheItem(Key, Data: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareFilenames(AnsiString(Key),TFileStateCacheItem(Data).FFilename);
|
||||
//debugln('CompareFilenameWithFileStateCacheItem Key=',AnsiString(Key),' Data=',TFileStateCacheItem(Data).FFilename,' Result=',dbgs(Result));
|
||||
end;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
procedure InternalInit;
|
||||
var
|
||||
c: char;
|
||||
begin
|
||||
FileStateCache:=TFileStateCache.Create;
|
||||
for c:=Low(char) to High(char) do begin
|
||||
UpChars[c]:=upcase(c);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TFileStateCacheItem }
|
||||
|
||||
constructor TFileStateCacheItem.Create(const TheFilename: string;
|
||||
NewTimeStamp: integer);
|
||||
begin
|
||||
FFilename:=TheFilename;
|
||||
FTimeStamp:=NewTimeStamp;
|
||||
end;
|
||||
|
||||
{ TFileStateCache }
|
||||
|
||||
procedure TFileStateCache.SetFlag(AFile: TFileStateCacheItem;
|
||||
AFlag: TFileStateCacheItemFlag; NewValue: boolean);
|
||||
begin
|
||||
if AFile.FTimeStamp<>FTimeStamp then begin
|
||||
AFile.FTestedFlags:=[];
|
||||
AFile.FTimeStamp:=FTimeStamp;
|
||||
end;
|
||||
Include(AFile.FTestedFlags,AFlag);
|
||||
if NewValue then
|
||||
Include(AFile.FFlags,AFlag)
|
||||
else
|
||||
Exclude(AFile.FFlags,AFlag);
|
||||
//debugln('TFileStateCache.SetFlag AFile.Filename=',AFile.Filename,' ',FileStateCacheItemFlagNames[AFlag],'=',dbgs(AFlag in AFile.FFlags),' Valid=',dbgs(AFlag in AFile.FTestedFlags));
|
||||
end;
|
||||
|
||||
constructor TFileStateCache.Create;
|
||||
begin
|
||||
FFiles:=TAVLTree.Create(@CompareFileStateItems);
|
||||
FTimeStamp:=1; // one higher than default for new files
|
||||
end;
|
||||
|
||||
destructor TFileStateCache.Destroy;
|
||||
begin
|
||||
FFiles.FreeAndClear;
|
||||
FFiles.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TFileStateCache.Lock;
|
||||
begin
|
||||
inc(FLockCount);
|
||||
end;
|
||||
|
||||
procedure TFileStateCache.Unlock;
|
||||
|
||||
procedure RaiseTooManyUnlocks;
|
||||
begin
|
||||
raise Exception.Create('TFileStateCache.Unlock');
|
||||
end;
|
||||
|
||||
begin
|
||||
if FLockCount<=0 then RaiseTooManyUnlocks;
|
||||
dec(FLockCount);
|
||||
end;
|
||||
|
||||
function TFileStateCache.Locked: boolean;
|
||||
begin
|
||||
Result:=FLockCount>0;
|
||||
end;
|
||||
|
||||
procedure TFileStateCache.IncreaseTimeStamp;
|
||||
begin
|
||||
if Self<>nil then begin
|
||||
if FTimeStamp<maxLongint then
|
||||
inc(FTimeStamp)
|
||||
else
|
||||
FTimeStamp:=-maxLongint;
|
||||
end;
|
||||
//debugln('TFileStateCache.IncreaseTimeStamp FTimeStamp=',dbgs(FTimeStamp));
|
||||
end;
|
||||
|
||||
function TFileStateCache.FileExistsCached(const Filename: string): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(Filename,fsciExists,AFile,Result) then exit;
|
||||
Result:=FileExists(AFile.Filename);
|
||||
SetFlag(AFile,fsciExists,Result);
|
||||
{if not Check(Filename,fsciExists,AFile,Result) then begin
|
||||
WriteDebugReport;
|
||||
raise Exception.Create('');
|
||||
end;}
|
||||
end;
|
||||
|
||||
function TFileStateCache.DirPathExistsCached(const Filename: string): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(Filename,fsciDirectory,AFile,Result) then exit;
|
||||
Result:=DirPathExists(AFile.Filename);
|
||||
SetFlag(AFile,fsciDirectory,Result);
|
||||
end;
|
||||
|
||||
function TFileStateCache.DirectoryIsWritableCached(const DirectoryName: string
|
||||
): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(DirectoryName,fsciDirectoryWritable,AFile,Result) then exit;
|
||||
Result:=DirectoryIsWritable(AFile.Filename);
|
||||
SetFlag(AFile,fsciDirectoryWritable,Result);
|
||||
end;
|
||||
|
||||
function TFileStateCache.FileIsExecutableCached(
|
||||
const AFilename: string): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(AFilename,fsciExecutable,AFile,Result) then exit;
|
||||
Result:=FileIsExecutable(AFile.Filename);
|
||||
SetFlag(AFile,fsciExecutable,Result);
|
||||
end;
|
||||
|
||||
function TFileStateCache.FileIsReadableCached(const AFilename: string): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(AFilename,fsciReadable,AFile,Result) then exit;
|
||||
Result:=FileIsReadable(AFile.Filename);
|
||||
SetFlag(AFile,fsciReadable,Result);
|
||||
end;
|
||||
|
||||
function TFileStateCache.FileIsWritableCached(const AFilename: string): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(AFilename,fsciWritable,AFile,Result) then exit;
|
||||
Result:=FileIsWritable(AFile.Filename);
|
||||
SetFlag(AFile,fsciWritable,Result);
|
||||
end;
|
||||
|
||||
function TFileStateCache.FileIsTextCached(const AFilename: string): boolean;
|
||||
var
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
if Check(AFilename,fsciText,AFile,Result) then exit;
|
||||
Result:=FileIsText(AFile.Filename);
|
||||
SetFlag(AFile,fsciText,Result);
|
||||
end;
|
||||
|
||||
function TFileStateCache.FindFile(const Filename: string;
|
||||
CreateIfNotExists: boolean): TFileStateCacheItem;
|
||||
var
|
||||
TrimmedFilename: String;
|
||||
ANode: TAVLTreeNode;
|
||||
begin
|
||||
// make filename unique
|
||||
TrimmedFilename:=ChompPathDelim(TrimFilename(Filename));
|
||||
ANode:=FFiles.FindKey(PChar(TrimmedFilename),
|
||||
@CompareFilenameWithFileStateCacheItem);
|
||||
if ANode<>nil then
|
||||
Result:=TFileStateCacheItem(ANode.Data)
|
||||
else if CreateIfNotExists then begin
|
||||
Result:=TFileStateCacheItem.Create(TrimmedFilename,FTimeStamp);
|
||||
FFiles.Add(Result);
|
||||
if FFiles.FindKey(PChar(TrimmedFilename),
|
||||
@CompareFilenameWithFileStateCacheItem)=nil
|
||||
then begin
|
||||
WriteDebugReport;
|
||||
raise Exception.Create('');
|
||||
end;
|
||||
end else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TFileStateCache.Check(const Filename: string;
|
||||
AFlag: TFileStateCacheItemFlag; var AFile: TFileStateCacheItem;
|
||||
var FlagIsSet: boolean): boolean;
|
||||
begin
|
||||
AFile:=FindFile(Filename,true);
|
||||
if FTimeStamp=AFile.FTimeStamp then begin
|
||||
Result:=AFlag in AFile.FTestedFlags;
|
||||
FlagIsSet:=AFlag in AFile.FFlags;
|
||||
end else begin
|
||||
AFile.FTestedFlags:=[];
|
||||
AFile.FTimeStamp:=FTimeStamp;
|
||||
Result:=false;
|
||||
FlagIsSet:=false;
|
||||
end;
|
||||
//debugln('TFileStateCache.Check Filename=',Filename,' AFile.Filename=',AFile.Filename,' ',FileStateCacheItemFlagNames[AFlag],'=',dbgs(FlagIsSet),' Valid=',dbgs(Result));
|
||||
end;
|
||||
|
||||
procedure TFileStateCache.WriteDebugReport;
|
||||
var
|
||||
ANode: TAVLTreeNode;
|
||||
AFile: TFileStateCacheItem;
|
||||
begin
|
||||
debugln('TFileStateCache.WriteDebugReport FTimeStamp=',dbgs(FTimeStamp));
|
||||
ANode:=FFiles.FindLowest;
|
||||
while ANode<>nil do begin
|
||||
AFile:=TFileStateCacheItem(ANode.Data);
|
||||
debugln(' "',AFile.Filename,'" TimeStamp=',dbgs(AFile.TimeStamp));
|
||||
ANode:=FFiles.FindSuccessor(ANode);
|
||||
end;
|
||||
debugln(' FFiles=',dbgs(FFiles.ConsistencyCheck));
|
||||
debugln(FFiles.ReportAsString);
|
||||
end;
|
||||
|
||||
initialization
|
||||
InternalInit;
|
||||
|
||||
finalization
|
||||
FileStateCache.Free;
|
||||
FileStateCache:=nil;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -2643,13 +2643,24 @@ begin
|
||||
RaiseClassOfWithoutIdentifier;
|
||||
end;
|
||||
Params.Save(OldInput);
|
||||
// first search backwards
|
||||
Params.SetIdentifier(Self,@Src[ClassIdentNode.StartPos],
|
||||
@CheckSrcIdentifier);
|
||||
Params.Flags:=[fdfSearchInParentNodes,fdfExceptionOnNotFound,
|
||||
Params.Flags:=[fdfSearchInParentNodes,
|
||||
fdfIgnoreCurContextNode]
|
||||
+(fdfGlobals*Params.Flags);
|
||||
+(fdfGlobals*Params.Flags)-[fdfExceptionOnNotFound];
|
||||
Params.ContextNode:=Result.Node.Parent;
|
||||
FindIdentifierInContext(Params);
|
||||
if not FindIdentifierInContext(Params) then begin
|
||||
// then search forwards
|
||||
Params.Load(OldInput);
|
||||
Params.SetIdentifier(Self,@Src[ClassIdentNode.StartPos],
|
||||
@CheckSrcIdentifier);
|
||||
Params.Flags:=[fdfSearchInParentNodes,fdfExceptionOnNotFound,
|
||||
fdfIgnoreCurContextNode,fdfSearchForward]
|
||||
+(fdfGlobals*Params.Flags);
|
||||
Params.ContextNode:=Result.Node.Parent;
|
||||
FindIdentifierInContext(Params);
|
||||
end;
|
||||
if (Params.NewNode.Desc<>ctnTypeDefinition) then begin
|
||||
MoveCursorToCleanPos(Result.Node.StartPos);
|
||||
RaiseClassOfNotResolved;
|
||||
|
@ -36,7 +36,7 @@ uses
|
||||
{$IFDEF MEM_CHECK}
|
||||
MemCheck,
|
||||
{$ENDIF}
|
||||
Classes, SysUtils;
|
||||
Classes, SysUtils, FileProcs;
|
||||
|
||||
type
|
||||
TSourceLog = class;
|
||||
@ -669,6 +669,7 @@ begin
|
||||
//DebugLn('TSourceLog.SaveToFile Self=',HexStr(Cardinal(Self),8));
|
||||
Result:=true;
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename, fmCreate);
|
||||
try
|
||||
if fSrcLen>0 then
|
||||
|
@ -38,7 +38,8 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, LCLProc, Forms, Controls, Menus, Graphics, GraphType,
|
||||
Buttons, StdCtrls, ExtCtrls, ComponentEditors, LazConf, ComCtrls, Arrow,
|
||||
{$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},LazarusIDEStrConsts, PropEdits;
|
||||
{$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},LazarusIDEStrConsts,
|
||||
PropEdits, IDEProcs;
|
||||
|
||||
type
|
||||
|
||||
@ -1136,6 +1137,7 @@ begin
|
||||
end;
|
||||
XMLConfig.SetValue(templatemenuitem + '/Description/Value', TemplateMenuForm.GetDescription);
|
||||
SaveAsTemplate(templatemenuitem, SelectedDesignerMenuItem);
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
end;
|
||||
end;
|
||||
@ -1234,6 +1236,7 @@ begin
|
||||
old_templatemenuitem:='menu_' + old_templatemenuitem;
|
||||
XMLConfig.DeletePath(old_templatemenuitem);
|
||||
end;
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
end;
|
||||
end;
|
||||
|
@ -486,7 +486,7 @@ begin
|
||||
|
||||
if (NewTargetDirectory<>'') and DirPathExists(NewTargetDirectory) then
|
||||
begin
|
||||
if not DirectoryIsWritable(NewTargetDirectory) then begin
|
||||
if not DirectoryIsWritableCached(NewTargetDirectory) then begin
|
||||
// Case 3. the lazarus directory is not writable
|
||||
// create directory <primary config dir>/bin/
|
||||
NewTargetDirectory:=AppendPathDelim(GetPrimaryConfigPath)+'bin';
|
||||
@ -598,6 +598,7 @@ begin
|
||||
if Result<>mrOk then exit;
|
||||
Filename:=GetMakeIDEConfigFilename;
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmCreate);
|
||||
try
|
||||
if ExtraOptions<>'' then begin
|
||||
|
@ -205,6 +205,7 @@ var
|
||||
Path: String;
|
||||
begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
Filename:=GetConfigFilename;
|
||||
XMLConfig:=TXMLConfig.CreateClean(Filename);
|
||||
except
|
||||
|
@ -36,7 +36,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
{$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF}, Buttons, ExtCtrls, FileUtil,
|
||||
LazConf;
|
||||
LazConf, IDEProcs;
|
||||
|
||||
type
|
||||
{ TCodeExplorerOptions }
|
||||
@ -185,6 +185,7 @@ var
|
||||
XMLConfig: TXMLConfig;
|
||||
begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig:=TXMLConfig.CreateClean(FOptionsFilename);
|
||||
XMLConfig.SetDeleteValue('CodeExplorer/Version/Value',
|
||||
CodeExplorerVersion,0);
|
||||
|
@ -38,7 +38,7 @@ uses
|
||||
Classes, SysUtils, LazConf, {$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},
|
||||
LResources, Forms, Controls, Buttons, LclProc, ExtCtrls, StdCtrls, ComCtrls,
|
||||
Dialogs, CodeToolManager, DefineTemplates, SourceChanger, SynEdit,
|
||||
IDEOptionDefs, EditDefineTree, LazarusIDEStrConsts;
|
||||
IDEOptionDefs, EditDefineTree, LazarusIDEStrConsts, IDEProcs;
|
||||
|
||||
type
|
||||
TCodeToolsOptions = class
|
||||
@ -459,6 +459,7 @@ var
|
||||
XMLConfig: TXMLConfig;
|
||||
begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig:=TXMLConfig.CreateClean(FFileName);
|
||||
XMLConfig.SetValue('CodeToolsOptions/Version/Value',
|
||||
CodeToolsOptionsVersion);
|
||||
|
@ -103,14 +103,19 @@ const
|
||||
pcosLibraryPath,pcosSrcPath,pcosDebugPath];
|
||||
ParsedCompilerFilenames = [pcosCompilerPath];
|
||||
ParsedCompilerDirectories = [pcosOutputDir];
|
||||
ParsedCompilerOutDirectories = [pcosOutputDir];
|
||||
ParsedCompilerFiles =
|
||||
ParsedCompilerSearchPaths+ParsedCompilerFilenames+ParsedCompilerDirectories;
|
||||
|
||||
type
|
||||
TLocalSubstitutionEvent = function(const s: string): string of object;
|
||||
TGetWritableOutputDirectory = procedure(var s: string) of object;
|
||||
|
||||
{ TParsedCompilerOptions }
|
||||
|
||||
TParsedCompilerOptions = class
|
||||
private
|
||||
FGetWritableOutputDirectory: TGetWritableOutputDirectory;
|
||||
FInvalidateGraphOnChange: boolean;
|
||||
FOnLocalSubstitute: TLocalSubstitutionEvent;
|
||||
public
|
||||
@ -129,6 +134,8 @@ type
|
||||
write FOnLocalSubstitute;
|
||||
property InvalidateGraphOnChange: boolean read FInvalidateGraphOnChange
|
||||
write FInvalidateGraphOnChange;
|
||||
property GetWritableOutputDirectory: TGetWritableOutputDirectory
|
||||
read FGetWritableOutputDirectory write FGetWritableOutputDirectory;
|
||||
end;
|
||||
|
||||
TParseStringEvent =
|
||||
@ -1074,6 +1081,7 @@ begin
|
||||
ExecuteAfter.SaveToXMLConfig(XMLConfigFile,p+'ExecuteAfter/');
|
||||
|
||||
// write
|
||||
InvalidateFileStateCache;
|
||||
XMLConfigFile.Flush;
|
||||
end;
|
||||
|
||||
@ -2302,7 +2310,7 @@ begin
|
||||
s:=TrimFilename(s);
|
||||
if (s<>'') and (not FilenameIsAbsolute(s)) then begin
|
||||
BaseDirectory:=GetParsedValue(pcosBaseDir);
|
||||
if (BaseDirectory<>'') then s:=BaseDirectory+s;
|
||||
if (BaseDirectory<>'') then s:=TrimFilename(BaseDirectory+s);
|
||||
end;
|
||||
end
|
||||
else if Option in ParsedCompilerDirectories then begin
|
||||
@ -2310,7 +2318,11 @@ begin
|
||||
s:=TrimFilename(s);
|
||||
if (s='') or (not FilenameIsAbsolute(s)) then begin
|
||||
BaseDirectory:=GetParsedValue(pcosBaseDir);
|
||||
if (BaseDirectory<>'') then s:=BaseDirectory+s;
|
||||
if (BaseDirectory<>'') then s:=TrimFilename(BaseDirectory+s);
|
||||
if (Option in ParsedCompilerOutDirectories)
|
||||
and Assigned(GetWritableOutputDirectory) then begin
|
||||
GetWritableOutputDirectory(s);
|
||||
end;
|
||||
end;
|
||||
s:=AppendPathDelim(s);
|
||||
end
|
||||
|
@ -52,10 +52,13 @@ interface
|
||||
*)
|
||||
|
||||
uses
|
||||
Messages, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons,
|
||||
{$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF}, SysUtils, Classes;
|
||||
Messages, Graphics, Controls, Forms, LCLProc, Dialogs, StdCtrls, Buttons,
|
||||
IDEProcs, {$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF}, SysUtils, Classes;
|
||||
|
||||
type
|
||||
|
||||
{ TCondForm }
|
||||
|
||||
TCondForm = class(TForm)
|
||||
AddInverse: TButton;
|
||||
FirstTest: TComboBox;
|
||||
@ -76,12 +79,11 @@ type
|
||||
Shift: TShiftState);
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure FormShow(Sender: TObject);
|
||||
private
|
||||
XMLConfig: TXMLCOnfig;
|
||||
public
|
||||
Choice, First, Second, FS: string;
|
||||
procedure DeleteSelected;
|
||||
procedure SaveChoices;
|
||||
function CreateXMLConfig: TXMLConfig;
|
||||
end;
|
||||
|
||||
|
||||
@ -152,29 +154,31 @@ end;
|
||||
|
||||
procedure TCondForm.CondFormCREATE(Sender: TObject);
|
||||
var
|
||||
ConfFileName: string;
|
||||
i: Integer;
|
||||
XMLConfig: TXMLConfig;
|
||||
begin
|
||||
ConfFileName:=SetDirSeparators(GetPrimaryConfigPath+'/condef.xml');
|
||||
try
|
||||
if (not FileExists(ConfFileName)) then
|
||||
XMLConfig:=TXMLConfig.CreateClean(ConfFileName)
|
||||
else
|
||||
XMLConfig:=TXMLConfig.Create(ConfFileName);
|
||||
Choice := XMLConfig.GetValue('condef/Choice', '"MSWINDOWS,UNIX","MSWINDOWS,ELSE","FPC,NONE","FPC,ELSE","DEBUG,NONE"');
|
||||
First := XMLConfig.GetValue('condef/First', 'MSWINDOWS');
|
||||
Second := XMLConfig.GetValue('condef/Second', 'UNIX');
|
||||
with ListBox do begin
|
||||
Items.CommaText := Choice;
|
||||
i := Items.IndexOf(First+','+Second);
|
||||
if i < 0 then begin
|
||||
Items.Add(First+','+Second);
|
||||
ItemIndex := 0;
|
||||
end else
|
||||
ItemIndex := i;
|
||||
XMLConfig:=CreateXMLConfig;
|
||||
try
|
||||
Choice := XMLConfig.GetValue('condef/Choice', '"MSWINDOWS,UNIX","MSWINDOWS,ELSE","FPC,NONE","FPC,ELSE","DEBUG,NONE"');
|
||||
First := XMLConfig.GetValue('condef/First', 'MSWINDOWS');
|
||||
Second := XMLConfig.GetValue('condef/Second', 'UNIX');
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
end;
|
||||
except
|
||||
XMLConfig:=nil;
|
||||
on E: Exception do begin
|
||||
debugln('TCondForm.CondFormCREATE ',E.Message);
|
||||
end;
|
||||
end;
|
||||
with ListBox do begin
|
||||
Items.CommaText := Choice;
|
||||
i := Items.IndexOf(First+','+Second);
|
||||
if i < 0 then begin
|
||||
Items.Add(First+','+Second);
|
||||
ItemIndex := 0;
|
||||
end else
|
||||
ItemIndex := i;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -194,7 +198,6 @@ end;
|
||||
|
||||
procedure TCondForm.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
FreeAndNil(XMLConfig);
|
||||
end;
|
||||
|
||||
procedure TCondForm.FormShow(Sender: TObject);
|
||||
@ -214,12 +217,42 @@ begin
|
||||
end;
|
||||
|
||||
procedure TCondForm.SaveChoices;
|
||||
var
|
||||
XMLConfig: TXMLConfig;
|
||||
begin
|
||||
if Assigned(XMLConfig) then begin
|
||||
XMLConfig.SetValue('condef/Choice', Choice);
|
||||
XMLConfig.SetValue('condef/First', First);
|
||||
XMLConfig.SetValue('condef/Second', Second);
|
||||
XMLConfig.Flush;
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig:=CreateXMLConfig;
|
||||
try
|
||||
XMLConfig.SetValue('condef/Choice', Choice);
|
||||
XMLConfig.SetValue('condef/First', First);
|
||||
XMLConfig.SetValue('condef/Second', Second);
|
||||
XMLConfig.Flush;
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
end;
|
||||
except
|
||||
on E: Exception do begin
|
||||
debugln('TCondForm.SaveChoices ',E.Message);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCondForm.CreateXMLConfig: TXMLConfig;
|
||||
var
|
||||
ConfFileName: String;
|
||||
begin
|
||||
Result:=nil;
|
||||
ConfFileName:=SetDirSeparators(GetPrimaryConfigPath+'/condef.xml');
|
||||
try
|
||||
if (not FileExists(ConfFileName)) then
|
||||
Result:=TXMLConfig.CreateClean(ConfFileName)
|
||||
else
|
||||
Result:=TXMLConfig.Create(ConfFileName);
|
||||
except
|
||||
on E: Exception do begin
|
||||
debugln('TCondForm.CreateXMLConfig ',E.Message);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -236,6 +236,7 @@ var
|
||||
fs: TFileStream;
|
||||
begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmCreate);
|
||||
try
|
||||
if Content<>'' then
|
||||
|
@ -1153,6 +1153,7 @@ begin
|
||||
res:=LazarusResources.Find('lazarus_dci_file');
|
||||
if (res<>nil) and (res.Value<>'') and (res.ValueType='DCI') then begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(fCodeTemplateFileName,fmCreate);
|
||||
try
|
||||
fs.Write(res.Value[1],length(res.Value));
|
||||
@ -1411,6 +1412,7 @@ begin
|
||||
,fCTemplIndentToTokenStart,false);
|
||||
|
||||
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
except
|
||||
on E: Exception do
|
||||
|
@ -1409,6 +1409,7 @@ begin
|
||||
if FileHasChangedOnDisk or (FXMLCfg=nil) then begin
|
||||
FConfigStore.Free;
|
||||
FXMLCfg.Free;
|
||||
InvalidateFileStateCache;
|
||||
if CleanConfig then
|
||||
FXMLCfg:=TXMLConfig.CreateClean(Filename)
|
||||
else
|
||||
|
@ -88,7 +88,7 @@ type
|
||||
property TimeStamp: integer read FTimeStamp;
|
||||
property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
function CompareFileReferences(Data1, Data2: Pointer): integer;
|
||||
|
@ -36,8 +36,9 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
Buttons, ExtCtrls, HelpIntf, {$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},
|
||||
ObjectInspector, LazConf, LazarusIDEStrConsts, IDEOptionDefs, StdCtrls;
|
||||
StdCtrls, Buttons, ExtCtrls,
|
||||
HelpIntf, {$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},
|
||||
ObjectInspector, LazConf, LazarusIDEStrConsts, IDEProcs, IDEOptionDefs;
|
||||
|
||||
type
|
||||
{ THelpOptions }
|
||||
@ -323,6 +324,7 @@ var
|
||||
Storage: TXMLOptionsStorage;
|
||||
begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig:=TXMLConfig.CreateClean(FFileName);
|
||||
try
|
||||
XMLConfig.SetValue('HelpOptions/Version/Value',HelpOptionsVersion);
|
||||
|
@ -91,6 +91,16 @@ function CreateRelativePath(const Filename, BaseDirectory: string): string;
|
||||
function CreateAbsolutePath(const SearchPath, BaseDirectory: string): string;
|
||||
function SwitchPathDelims(const Filename: string; Switch: boolean): string;
|
||||
|
||||
// file stats
|
||||
procedure InvalidateFileStateCache;
|
||||
function FileExistsCached(const Filename: string): boolean;
|
||||
function DirPathExistsCached(const Filename: string): boolean;
|
||||
function DirectoryIsWritableCached(const DirectoryName: string): boolean;
|
||||
function FileIsExecutableCached(const AFilename: string): boolean;
|
||||
function FileIsReadableCached(const AFilename: string): boolean;
|
||||
function FileIsWritableCached(const AFilename: string): boolean;
|
||||
function FileIsTextCached(const AFilename: string): boolean;
|
||||
|
||||
// cmd line
|
||||
procedure SplitCmdLine(const CmdLine: string;
|
||||
var ProgramFilename, Params: string);
|
||||
@ -851,6 +861,46 @@ begin
|
||||
Result:=FileProcs.FilenameIsMatching(Mask,Filename,MatchExactly);
|
||||
end;
|
||||
|
||||
procedure InvalidateFileStateCache;
|
||||
begin
|
||||
FileStateCache.IncreaseTimeStamp;
|
||||
end;
|
||||
|
||||
function FileExistsCached(const Filename: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.FileExistsCached(Filename);
|
||||
end;
|
||||
|
||||
function DirPathExistsCached(const Filename: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.DirPathExistsCached(Filename);
|
||||
end;
|
||||
|
||||
function DirectoryIsWritableCached(const DirectoryName: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.DirectoryIsWritableCached(DirectoryName);
|
||||
end;
|
||||
|
||||
function FileIsExecutableCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.FileIsExecutableCached(AFilename);
|
||||
end;
|
||||
|
||||
function FileIsReadableCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.FileIsReadableCached(AFilename);
|
||||
end;
|
||||
|
||||
function FileIsWritableCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.FileIsWritableCached(AFilename);
|
||||
end;
|
||||
|
||||
function FileIsTextCached(const AFilename: string): boolean;
|
||||
begin
|
||||
Result:=FileProcs.FileIsTextCached(AFilename);
|
||||
end;
|
||||
|
||||
procedure SplitCmdLine(const CmdLine: string;
|
||||
var ProgramFilename, Params: string);
|
||||
var p, s, l: integer;
|
||||
@ -1250,6 +1300,7 @@ var
|
||||
begin
|
||||
if FileExists(Filename) then begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmOpenWrite);
|
||||
fs.Size:=0;
|
||||
fs.Free;
|
||||
@ -1941,6 +1992,7 @@ var
|
||||
begin
|
||||
Result:=false;
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmCreate);
|
||||
fs.Free;
|
||||
Result:=true;
|
||||
@ -1973,6 +2025,7 @@ begin
|
||||
try
|
||||
SrcFileStream:=TFileStream.Create(SrcFilename,fmOpenRead);
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
DestFileStream:=TFileSTream.Create(DestFilename,fmCreate);
|
||||
try
|
||||
DestFileStream.CopyFrom(SrcFileStream,SrcFileStream.Size);
|
||||
|
@ -33,7 +33,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
|
||||
Buttons, FileUtil, {$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},
|
||||
Buttons, IDEProcs, FileUtil, {$IFNDEF VER1_0}XMLCfg{$ELSE}Laz_XMLCfg{$ENDIF},
|
||||
LazarusIDEStrConsts, InputHistory, CompilerOptions, CompilerOptionsDlg;
|
||||
|
||||
type
|
||||
@ -154,6 +154,7 @@ begin
|
||||
try
|
||||
Result:=mrCancel;
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig:=TXMLConfig.Create(Filename);
|
||||
try
|
||||
Path:=GetXMLPathForCompilerOptions(XMLConfig);
|
||||
|
@ -32,7 +32,7 @@ uses
|
||||
Classes, SysUtils, Math, Forms, Controls, Dialogs, Buttons, StdCtrls,
|
||||
FileUtil, LResources,
|
||||
// IDE
|
||||
TransferMacros, InputHistory;
|
||||
TransferMacros, InputHistory, IDEProcs;
|
||||
|
||||
type
|
||||
TInputFileFlag = (iftDirectory, iftFilename, iftCmdLine,
|
||||
@ -277,11 +277,11 @@ begin
|
||||
if FTransferMacros<>nil then
|
||||
Macros.SubstituteStr(Filename);
|
||||
Filename:=ExpandFileName(Filename);
|
||||
if (not (iftDirectory in CurFileFlags)) and DirPathExists(Filename)
|
||||
if (not (iftDirectory in CurFileFlags)) and DirPathExistsCached(Filename)
|
||||
then
|
||||
exit;
|
||||
if (not (iftFilename in CurFileFlags)) and FileExists(Filename)
|
||||
and (not DirPathExists(Filename))
|
||||
and (not DirPathExistsCached(Filename))
|
||||
then
|
||||
exit;
|
||||
end;
|
||||
|
@ -471,6 +471,7 @@ var
|
||||
XMLConfig: TXMLConfig;
|
||||
begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig:=TXMLConfig.CreateClean(FFileName);
|
||||
XMLConfig.SetDeleteValue('InputHistory/Version/Value',
|
||||
InputHistoryVersion,0);
|
||||
|
@ -2046,6 +2046,12 @@ resourcestring
|
||||
lisPkgMangDeleteOldPackageFile = 'Delete Old Package File?';
|
||||
lisPkgMangDeleteOldPackageFile2 = 'Delete old package file %s%s%s?';
|
||||
lisPkgMangDeleteFailed = 'Delete failed';
|
||||
lisAmbigiousUnitFound = 'Ambigious Unit found';
|
||||
lisTheFileWasFoundInOneOfTheSourceDirectoriesOfThePac = 'The file %s%s%s%'
|
||||
+'swas found in one of the source directories of the package %s and looks '
|
||||
+'like a compiled unit.Compiled units must be in the output directory of '
|
||||
+'the package, otherwise other packages can get problems using this '
|
||||
+'package.%s%sDelete ambigious file?';
|
||||
lisPkgMangUnableToDeleteFile = 'Unable to delete file %s%s%s.';
|
||||
lisPkgMangUnsavedPackage = 'Unsaved package';
|
||||
lisPkgMangThereIsAnUnsavedPackageInTheRequiredPackages = 'There is an '
|
||||
|
@ -5346,6 +5346,7 @@ var
|
||||
begin
|
||||
try
|
||||
ClearFile(Filename,true);
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmCreate);
|
||||
try
|
||||
if Src<>'' then
|
||||
@ -7731,6 +7732,7 @@ var
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if Project1=nil then exit;
|
||||
InvalidateFileStateCache;
|
||||
Project1.GetUnitsChangedOnDisk(AnUnitList);
|
||||
if AnUnitList=nil then exit;
|
||||
Result:=ShowDiskDiffsDialog(AnUnitList);
|
||||
@ -7780,7 +7782,7 @@ begin
|
||||
SplitCmdLine(CommandAfter,CmdAfterExe,CmdAfterParams);
|
||||
if (CmdAfterExe<>'') then begin
|
||||
CmdAfterExe:=FindDefaultExecutablePath(CmdAfterExe);
|
||||
if not FileIsExecutable(CmdAfterExe) then begin
|
||||
if not FileIsExecutableCached(CmdAfterExe) then begin
|
||||
MessageDlg(lisCommandAfterInvalid,
|
||||
Format(lisTheCommandAfterPublishingIsInvalid, [#13, '"', CmdAfterExe,
|
||||
'"']), mtError, [mbCancel], 0);
|
||||
@ -7832,7 +7834,7 @@ begin
|
||||
|
||||
// execute 'CommandAfter'
|
||||
if (CmdAfterExe<>'') then begin
|
||||
if FileIsExecutable(CmdAfterExe) then begin
|
||||
if FileIsExecutableCached(CmdAfterExe) then begin
|
||||
Tool:=TExternalToolOptions.Create;
|
||||
Tool.Filename:=CmdAfterExe;
|
||||
Tool.Title:=lisCommandAfterPublishingModule;
|
||||
@ -11378,6 +11380,9 @@ end.
|
||||
|
||||
{ =============================================================================
|
||||
$Log$
|
||||
Revision 1.838 2005/01/25 01:14:19 mattias
|
||||
implemented automatic redirecting of package output directory and filestate cache
|
||||
|
||||
Revision 1.837 2005/01/24 02:42:34 mattias
|
||||
fixed search path to cmd line param
|
||||
|
||||
|
@ -896,6 +896,7 @@ begin
|
||||
// create if not yet done
|
||||
if not FileExists(AFilename) then begin
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(AFilename,fmCreate);
|
||||
fs.Free;
|
||||
except
|
||||
@ -907,9 +908,10 @@ begin
|
||||
end;
|
||||
// check writable
|
||||
try
|
||||
if CheckReadable then
|
||||
if CheckReadable then begin
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(AFilename,fmOpenWrite)
|
||||
else
|
||||
end else
|
||||
fs:=TFileStream.Create(AFilename,fmOpenReadWrite);
|
||||
try
|
||||
fs.Position:=fs.Size;
|
||||
@ -925,6 +927,7 @@ begin
|
||||
end;
|
||||
// check readable
|
||||
try
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(AFilename,fmOpenReadWrite);
|
||||
try
|
||||
fs.Position:=fs.Size-1;
|
||||
|
@ -939,7 +939,7 @@ begin
|
||||
and (FIgnoreFileDateOnDisk=Source.FileDateOnDisk) then
|
||||
Result:=false;
|
||||
if (not IsVirtual) and FileExists(Filename) then
|
||||
FileReadOnly:=not FileIsWritable(Filename)
|
||||
FileReadOnly:=not FileIsWritableCached(Filename)
|
||||
else
|
||||
FileReadOnly:=false;
|
||||
end;
|
||||
@ -1376,6 +1376,7 @@ begin
|
||||
if Assigned(OnSaveProjectInfo) then
|
||||
OnSaveProjectInfo(Self,XMLConfig,ProjectWriteFlags);
|
||||
|
||||
InvalidateFileStateCache;
|
||||
xmlconfig.Flush;
|
||||
Modified:=false;
|
||||
Result:=mrOk;
|
||||
@ -3170,6 +3171,9 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.180 2005/01/25 01:14:19 mattias
|
||||
implemented automatic redirecting of package output directory and filestate cache
|
||||
|
||||
Revision 1.179 2005/01/20 13:10:58 mattias
|
||||
fixed win compilation
|
||||
|
||||
|
@ -41,7 +41,7 @@ uses
|
||||
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
StdCtrls, Buttons, FileUtil,
|
||||
{$IFNDEF VER1_0}AVL_Tree, XMLCfg{$ELSE}OldAvLTree, Laz_XMLCfg{$ENDIF},
|
||||
LazarusIDEStrConsts, EnvironmentOpts, InputHistory, LazConf,
|
||||
LazarusIDEStrConsts, EnvironmentOpts, InputHistory, LazConf, IDEProcs,
|
||||
PackageDefs, PackageSystem;
|
||||
|
||||
type
|
||||
@ -513,6 +513,7 @@ begin
|
||||
XMLConfig.SetDeleteValue('Packages/Item'+IntToStr(i)+'/ID',
|
||||
LazPackageID.IDAsString,'');
|
||||
end;
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
|
@ -64,6 +64,8 @@ type
|
||||
procedure(FirstDependency: TPkgDependency; var List: TList) of object;
|
||||
TGetDependencyOwnerDescription =
|
||||
procedure(Dependency: TPkgDependency; var Description: string) of object;
|
||||
TGetWritablePkgOutputDirectory =
|
||||
procedure(APackage: TLazPackage; var AnOutDirectory: string) of object;
|
||||
|
||||
|
||||
{ TPkgComponent }
|
||||
@ -521,6 +523,8 @@ type
|
||||
TPkgChangeNameEvent = procedure(Pkg: TLazPackage;
|
||||
const OldName: string) of object;
|
||||
|
||||
{ TLazPackage }
|
||||
|
||||
TLazPackage = class(TLazPackageID)
|
||||
private
|
||||
FAuthor: string;
|
||||
@ -593,6 +597,7 @@ type
|
||||
var Handled, Abort: boolean);
|
||||
procedure SetUserReadOnly(const AValue: boolean);
|
||||
function SubstitutePkgMacro(const s: string): string;
|
||||
procedure GetWritableOutputDirectory(var AnOutDir: string);
|
||||
procedure Clear;
|
||||
procedure UpdateSourceDirectories;
|
||||
procedure VersionChanged(Sender: TObject); override;
|
||||
@ -784,6 +789,7 @@ var
|
||||
|
||||
OnGetAllRequiredPackages: TGetAllRequiredPackagesEvent;
|
||||
OnGetDependencyOwnerDescription: TGetDependencyOwnerDescription;
|
||||
OnGetWritablePkgOutputDirectory: TGetWritablePkgOutputDirectory;
|
||||
|
||||
function CompareLazPackageID(Data1, Data2: Pointer): integer;
|
||||
function CompareNameWithPackageID(Key, Data: Pointer): integer;
|
||||
@ -1796,11 +1802,11 @@ end;
|
||||
procedure TLazPackage.OnMacroListSubstitution(TheMacro: TTransferMacro;
|
||||
var s: string; var Handled, Abort: boolean);
|
||||
begin
|
||||
if AnsiCompareText(s,'PkgOutDir')=0 then begin
|
||||
if CompareText(s,'PkgOutDir')=0 then begin
|
||||
Handled:=true;
|
||||
s:=CompilerOptions.ParsedOpts.GetParsedValue(pcosOutputDir);
|
||||
end
|
||||
else if AnsiCompareText(s,'PkgDir')=0 then begin
|
||||
else if CompareText(s,'PkgDir')=0 then begin
|
||||
Handled:=true;
|
||||
s:=FDirectory;
|
||||
end;
|
||||
@ -1818,6 +1824,12 @@ begin
|
||||
FMacros.SubstituteStr(Result);
|
||||
end;
|
||||
|
||||
procedure TLazPackage.GetWritableOutputDirectory(var AnOutDir: string);
|
||||
begin
|
||||
if Assigned(OnGetWritablePkgOutputDirectory) then
|
||||
OnGetWritablePkgOutputDirectory(Self,AnOutDir);
|
||||
end;
|
||||
|
||||
function TLazPackage.GetAutoIncrementVersionOnBuild: boolean;
|
||||
begin
|
||||
Result:=lpfAutoIncrementVersionOnBuild in FFlags;
|
||||
@ -2019,6 +2031,8 @@ begin
|
||||
FMacros.OnSubstitution:=@OnMacroListSubstitution;
|
||||
FCompilerOptions:=TPkgCompilerOptions.Create(Self);
|
||||
FCompilerOptions.ParsedOpts.OnLocalSubstitute:=@SubstitutePkgMacro;
|
||||
FCompilerOptions.ParsedOpts.GetWritableOutputDirectory:=
|
||||
@GetWritableOutputDirectory;
|
||||
FCompilerOptions.DefaultMakeOptionsFlags:=[ccloNoLinkerOpts];
|
||||
FUsageOptions:=TPkgAdditionalCompilerOptions.Create(Self);
|
||||
FUsageOptions.ParsedOpts.OnLocalSubstitute:=@SubstitutePkgMacro;
|
||||
|
@ -2062,6 +2062,7 @@ begin
|
||||
end;
|
||||
XMLConfig.SetDeleteValue(Path+'Count/Value',LayoutCount,0);
|
||||
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
|
@ -606,6 +606,7 @@ begin
|
||||
end;
|
||||
XMLConfig.SetDeleteValue(Path+'Count',FUserLinksSortID.Count,0);
|
||||
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
XMLConfig.Free;
|
||||
|
||||
|
@ -65,6 +65,9 @@ uses
|
||||
MainBar, MainIntf, MainBase;
|
||||
|
||||
type
|
||||
|
||||
{ TPkgManager }
|
||||
|
||||
TPkgManager = class(TBasePkgManager)
|
||||
// events - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// package editor
|
||||
@ -136,6 +139,8 @@ type
|
||||
procedure OnApplicationIdle(Sender: TObject);
|
||||
procedure GetDependencyOwnerDescription(Dependency: TPkgDependency;
|
||||
var Description: string);
|
||||
procedure GetWritablePkgOutputDirectory(APackage: TLazPackage;
|
||||
var AnOutDirectory: string);
|
||||
private
|
||||
FirstAutoInstallDependency: TPkgDependency;
|
||||
// helper functions
|
||||
@ -413,6 +418,22 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPkgManager.GetWritablePkgOutputDirectory(APackage: TLazPackage;
|
||||
var AnOutDirectory: string);
|
||||
var
|
||||
NewOutDir: String;
|
||||
begin
|
||||
if DirectoryIsWritableCached(AnOutDirectory) then exit;
|
||||
// output directory is not writable
|
||||
// -> redirect to home directory
|
||||
NewOutDir:=SetDirSeparators('/$(TargetCPU)/$(TargetOS)');
|
||||
MainIDE.MacroList.SubstituteStr(NewOutDir);
|
||||
NewOutDir:=TrimFilename(GetPrimaryConfigPath+PathDelim+'lib'+PathDelim
|
||||
+APackage.Name+NewOutDir);
|
||||
AnOutDirectory:=NewOutDir;
|
||||
debugln('TPkgManager.GetWritablePkgOutputDirectory APackage=',APackage.IDAsString,' AnOutDirectory="',AnOutDirectory,'"');
|
||||
end;
|
||||
|
||||
procedure TPkgManager.MainIDEitmPkgAddCurUnitToPkgClick(Sender: TObject);
|
||||
begin
|
||||
DoAddActiveUnitToAPackage;
|
||||
@ -1040,6 +1061,7 @@ begin
|
||||
XMLConfig.SetValue('Compiler/Value',CompilerFilename);
|
||||
XMLConfig.SetValue('Compiler/Date',CompilerFileDate);
|
||||
XMLConfig.SetValue('Params/Value',CompilerParams);
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
@ -1302,14 +1324,9 @@ var
|
||||
SearchFlags);
|
||||
if (AmbigiousFilename='') then exit;
|
||||
if not YesToAll then
|
||||
Result:=MessageDlg('Ambigious Unit found',
|
||||
'The file "'+AmbigiousFilename+'"'#13
|
||||
+'was found in one of the source directories of the package '
|
||||
+APackage.IDAsString+' and looks like a compiled unit.'
|
||||
+'Compiled units must be in the output directory of the package, '
|
||||
+'otherwise other packages can get problems using this package.'#13
|
||||
+#13
|
||||
+'Delete ambigious file?',
|
||||
Result:=MessageDlg(lisAmbigiousUnitFound,
|
||||
Format(lisTheFileWasFoundInOneOfTheSourceDirectoriesOfThePac, ['"',
|
||||
AmbigiousFilename, '"', #13, APackage.IDAsString, #13, #13]),
|
||||
mtWarning,[mbYes,mbYesToAll,mbNo,mbAbort],0)
|
||||
else
|
||||
Result:=mrYesToAll;
|
||||
@ -1601,6 +1618,7 @@ var
|
||||
begin
|
||||
inherited Create(TheOwner);
|
||||
OnGetDependencyOwnerDescription:=@GetDependencyOwnerDescription;
|
||||
OnGetWritablePkgOutputDirectory:=@GetWritablePkgOutputDirectory;
|
||||
|
||||
// componentpalette
|
||||
IDEComponentPalette:=TComponentPalette.Create;
|
||||
@ -2140,6 +2158,7 @@ begin
|
||||
try
|
||||
XMLConfig.Clear;
|
||||
APackage.SaveToXMLConfig(XMLConfig,'Package/');
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
PkgLink:=PkgLinks.AddUserLink(APackage);
|
||||
if PkgLink<>nil then begin
|
||||
|
Loading…
Reference in New Issue
Block a user