implemented automatic redirecting of package output directory and filestate cache

git-svn-id: trunk@6680 -
This commit is contained in:
mattias 2005-01-25 01:14:19 +00:00
parent a7606840be
commit 81f9980ad0
30 changed files with 636 additions and 71 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -205,6 +205,7 @@ var
Path: String;
begin
try
InvalidateFileStateCache;
Filename:=GetConfigFilename;
XMLConfig:=TXMLConfig.CreateClean(Filename);
except

View File

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

View File

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

View File

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

View File

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

View File

@ -236,6 +236,7 @@ var
fs: TFileStream;
begin
try
InvalidateFileStateCache;
fs:=TFileStream.Create(Filename,fmCreate);
try
if Content<>'' then

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -471,6 +471,7 @@ var
XMLConfig: TXMLConfig;
begin
try
InvalidateFileStateCache;
XMLConfig:=TXMLConfig.CreateClean(FFileName);
XMLConfig.SetDeleteValue('InputHistory/Version/Value',
InputHistoryVersion,0);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2062,6 +2062,7 @@ begin
end;
XMLConfig.SetDeleteValue(Path+'Count/Value',LayoutCount,0);
InvalidateFileStateCache;
XMLConfig.Flush;
finally
XMLConfig.Free;

View File

@ -606,6 +606,7 @@ begin
end;
XMLConfig.SetDeleteValue(Path+'Count',FUserLinksSortID.Count,0);
InvalidateFileStateCache;
XMLConfig.Flush;
XMLConfig.Free;

View File

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