From edac588a96c9113f38ce48abcfb0465b0c08b19a Mon Sep 17 00:00:00 2001 From: mattias Date: Thu, 3 Aug 2023 13:44:39 +0200 Subject: [PATCH] ide: added FileIsInSPDirectory --- ide/packages/ideconfig/searchpathprocs.pas | 100 +++++++++++++++++++++ packager/pkgmanager.pas | 13 +-- test/ideintf/testsearchpathprocs.pas | 88 +++++++++++++++++- 3 files changed, 190 insertions(+), 11 deletions(-) diff --git a/ide/packages/ideconfig/searchpathprocs.pas b/ide/packages/ideconfig/searchpathprocs.pas index 93cf7eb4c6..7131e96c22 100644 --- a/ide/packages/ideconfig/searchpathprocs.pas +++ b/ide/packages/ideconfig/searchpathprocs.pas @@ -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 diff --git a/packager/pkgmanager.pas b/packager/pkgmanager.pas index ade6e552ec..1adfadbd44 100644 --- a/packager/pkgmanager.pas +++ b/packager/pkgmanager.pas @@ -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; diff --git a/test/ideintf/testsearchpathprocs.pas b/test/ideintf/testsearchpathprocs.pas index b5da70c13e..3145bc1a8a 100644 --- a/test/ideintf/testsearchpathprocs.pas +++ b/test/ideintf/testsearchpathprocs.pas @@ -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.