ide: added FileIsInSPDirectory

This commit is contained in:
mattias 2023-08-03 13:44:39 +02:00
parent 478c8209a6
commit edac588a96
3 changed files with 190 additions and 11 deletions

View File

@ -104,6 +104,10 @@ function SearchUnitInSearchPath(const AnUnitname, BasePath: string;
procedure CollectFilesInSearchPath(const SearchPath: string;
Files: TFilenameToStringTree; const Value: string = ''); overload;
function FileIsInSPDirectory(const Filename: string; Directory{without **}: string;
MaskType: TSPMaskType): boolean; overload; // both must be ResolveDots
function FileIsInSPDirectory(const Filename: string; Directory{with **}: string): boolean; overload; // both must be ResolveDots
function FilenamePIsAbsolute(TheFilename: PChar): boolean;
function FilenamePIsUnixAbsolute(TheFilename: PChar): boolean;
function FilenamePIsWinAbsolute(TheFilename: PChar): boolean;
@ -113,6 +117,7 @@ function RelateDirectoryMasks(const Left, Right: TSPMaskRecord): TSPFileMaskRela
function GetSPMaskRecord(const aDirectory: string; aStartPos: integer; out MaskRecord: TSPMaskRecord): boolean;
function GetSPMaskType(const aFilename: string): TSPMaskType;
function dbgs(t: TSPMaskType): string; overload;
function dbgs(r: TSPFileMaskRelation): string; overload;
implementation
@ -762,6 +767,92 @@ begin
until false;
end;
function FileIsInSPDirectory(const Filename: string; Directory: string;
MaskType: TSPMaskType): boolean;
var
l: SizeInt;
p, PathDelimCount: Integer;
begin
Result:=false;
if Filename='' then exit;
l:=length(Filename);
if (l>1) and (Filename[1]='.') and (Filename[2]='.') then
begin
if (l=2) or (Filename[3]=PathDelim) then
exit; // e.g. '../foo'
end;
Directory:=AppendPathDelim(Directory);
case MaskType of
TSPMaskType.None:
if Filename='.' then
exit(false)
else
Result:=CompareFilenames(ExtractFilePath(Filename),Directory)=0;
TSPMaskType.Star:
if Directory='' then
begin
// test if file is 'something/something'
p:=1;
while (p<=l) and (Filename[p]<>PathDelim) do inc(p);
if (p=1) or (p>l) then exit;
inc(p);
while (p<=l) and (Filename[p]<>PathDelim) do inc(p);
Result:=p>l;
end else begin
// test if file is 'directory/something/something'
p:=l;
while (p>0) and (Filename[p]<>PathDelim) do dec(p);
if p<=2 then exit;
dec(p);
while (p>0) and (Filename[p]<>PathDelim) do dec(p);
if p=0 then exit;
Result:=CompareFilenames(LeftStr(Filename,p),Directory)=0;
end;
TSPMaskType.StarStar:
if Directory='' then
begin
Result:=not FilenameIsAbsolute(Filename);
end else begin
p:=1;
PathDelimCount:=0;
while (p<=length(Directory)) do
begin
if Directory[p]=PathDelim then inc(PathDelimCount);
inc(p);
end;
p:=1;
while (p<=l) do
begin
if Filename[p]=PathDelim then
begin
dec(PathDelimCount);
if PathDelimCount=0 then
begin
Result:=CompareFilenames(LeftStr(Filename,p),Directory)=0;
exit;
end;
end;
inc(p);
end;
end;
end;
end;
function FileIsInSPDirectory(const Filename: string; Directory: string
): boolean;
var
MaskType: TSPMaskType;
begin
Directory:=ChompPathDelim(Directory);
MaskType:=GetSPMaskType(Directory);
if MaskType=TSPMaskType.None then
Result:=FileIsInSPDirectory(Filename,Directory,MaskType)
else
Result:=FileIsInSPDirectory(Filename,ExtractFilePath(Directory),MaskType);
end;
function FilenamePIsAbsolute(TheFilename: PChar): boolean;
begin
{$IFDEF Unix}
@ -971,6 +1062,15 @@ begin
exit(TSPMaskType.StarStar);
end;
function dbgs(t: TSPMaskType): string;
begin
case t of
TSPMaskType.None: Result:='None';
TSPMaskType.Star: Result:='Star';
TSPMaskType.StarStar: Result:='StarStar';
end;
end;
function dbgs(r: TSPFileMaskRelation): string;
begin
case r of

View File

@ -3835,19 +3835,12 @@ var
Result:=TLazPackage(SrcDirToPkg[Dir]);
exit;
end;
Dir:=ChompPathDelim(ExtractFilePath(Dir));
Dir:=ExtractFilePath(Dir);
for Item in SrcDirToPkg do
begin
CurDir:=Item^.Name;
case MaskType of
TSPMaskType.Star:
if CompareFilenames(ChompPathDelim(ExtractFilePath(CurDir)),Dir)=0 then
exit(TLazPackage(Item^.Value));
TSPMaskType.StarStar:
if (CompareFilenames(CurDir,Dir)=0)
or FileIsInPath(CurDir,Dir) then
exit(TLazPackage(Item^.Value));
end;
if FileIsInSPDirectory(AppendPathDelim(CurDir),Dir,MaskType) then
exit(TLazPackage(Item^.Value));
end;
Result:=nil;
end;

View File

@ -22,6 +22,7 @@ type
TTestSearchPathProcs = class(TTestCase)
published
procedure TestRelateDirectoryMasks;
procedure TestFileIsInSPDirectory;
end;
implementation
@ -46,7 +47,7 @@ procedure TTestSearchPathProcs.TestRelateDirectoryMasks;
LeftStart:=length(SearchPath)+1;
if i=Right then
RightStart:=length(SearchPath)+1;
SearchPath+=Paths[i];
SearchPath+=SetDirSeparators(Paths[i]);
end;
Actual:=RelateDirectoryMasks(SearchPath,LeftStart,SearchPath,RightStart);
@ -108,6 +109,91 @@ begin
t(['**','..'],0,1,TSPFileMaskRelation.None);
end;
procedure TTestSearchPathProcs.TestFileIsInSPDirectory;
procedure t(Filename, Directory: string; MaskType: TSPMaskType; Expected: boolean);
var
Actual: Boolean;
begin
Filename:=SetDirSeparators(Filename);
Directory:=SetDirSeparators(Directory);
Actual:=FileIsInSPDirectory(Filename,Directory,MaskType);
if Actual=Expected then exit;
Fail('Filename="'+Filename+'" Directory="'+Directory+'" MaskType='+dbgs(MaskType)+' Expected='+dbgs(Expected)+', but was '+dbgs(Actual));
end;
begin
t('','',TSPMaskType.None,false);
t('.','',TSPMaskType.None,false);
t('..','',TSPMaskType.None,false);
t('../','',TSPMaskType.None,false);
t('a','',TSPMaskType.None,true);
t('a/b','',TSPMaskType.None,false);
t('','foo',TSPMaskType.None,false);
t('a','foo',TSPMaskType.None,false);
t('foo/','foo',TSPMaskType.None,true);
t('foo/a','foo',TSPMaskType.None,true);
t('foo/bar/a','foo',TSPMaskType.None,false);
t('/a','',TSPMaskType.None,false);
t('/a/b','',TSPMaskType.None,false);
t('/','foo',TSPMaskType.None,false);
t('/','/foo',TSPMaskType.None,false);
t('/a','/foo',TSPMaskType.None,false);
t('/foo/','/foo',TSPMaskType.None,true);
t('/foo/a','/foo',TSPMaskType.None,true);
t('/foo/bar/a','/foo',TSPMaskType.None,false);
t('','',TSPMaskType.Star,false);
t('.','',TSPMaskType.Star,false);
t('..','',TSPMaskType.Star,false);
t('../','',TSPMaskType.Star,false);
t('a','',TSPMaskType.Star,false);
t('a/b','',TSPMaskType.Star,true);
t('a/b/c','',TSPMaskType.Star,false);
t('','foo',TSPMaskType.Star,false);
t('a','foo',TSPMaskType.Star,false);
t('foo/','foo',TSPMaskType.Star,false);
t('foo/bar','foo',TSPMaskType.Star,false);
t('foo/bar/a','foo',TSPMaskType.Star,true);
t('foo/bar/a/b','foo',TSPMaskType.Star,false);
t('/a','',TSPMaskType.Star,false);
t('/a','/',TSPMaskType.Star,false);
t('/a/b','/',TSPMaskType.Star,true);
t('/a/b/c','/',TSPMaskType.Star,false);
t('/','/foo',TSPMaskType.Star,false);
t('/a','/foo',TSPMaskType.Star,false);
t('/foo/','/foo',TSPMaskType.Star,false);
t('/foo/bar','/foo',TSPMaskType.Star,false);
t('/foo/bar/a','/foo',TSPMaskType.Star,true);
t('/foo/bar/a/b','/foo',TSPMaskType.Star,false);
t('','',TSPMaskType.StarStar,false);
t('.','',TSPMaskType.StarStar,true);
t('..','',TSPMaskType.StarStar,false);
t('../','',TSPMaskType.StarStar,false);
t('a','',TSPMaskType.StarStar,true);
t('a/b','',TSPMaskType.StarStar,true);
t('a/b/c','',TSPMaskType.StarStar,true);
t('','foo',TSPMaskType.StarStar,false);
t('a','foo',TSPMaskType.StarStar,false);
t('foo/','foo',TSPMaskType.StarStar,true);
t('foo/bar','foo',TSPMaskType.StarStar,true);
t('foo/bar','foo/bar',TSPMaskType.StarStar,false);
t('foo/bar/a','foo',TSPMaskType.StarStar,true);
t('foo/bar/a','foo/bar',TSPMaskType.StarStar,true);
t('foo/','/foo',TSPMaskType.StarStar,false);
t('/a','/',TSPMaskType.StarStar,true);
t('/a/b','/',TSPMaskType.StarStar,true);
t('/a/b/c','/',TSPMaskType.StarStar,true);
t('/','/foo',TSPMaskType.StarStar,false);
t('/a','/foo',TSPMaskType.StarStar,false);
t('/foo/','/foo',TSPMaskType.StarStar,true);
t('/foo/bar','/foo',TSPMaskType.StarStar,true);
t('/foo/bar','/foo/bar',TSPMaskType.StarStar,false);
t('/foo/bar/a','/foo',TSPMaskType.StarStar,true);
t('/foo/bar/a','/foo/bar',TSPMaskType.StarStar,true);
end;
initialization
AddToIDEIntfTestSuite(TTestSearchPathProcs);
end.