@@ -4,6 +4,7 @@ import ignore from 'ignore';
44import isBinaryPath from 'is-binary-path' ;
55import micromatch from 'micromatch' ;
66import readdir , { type Dirent , type DirentLike } from 'tiny-readdir' ;
7+ import { createRelativePathResolver , type RelativePathResolver } from './relativePath.ts' ;
78
89const defaultIgnoredDirNames = new Set ( [ '.git' , '.sl' , '.svn' , '.hg' , '.jj' , 'node_modules' ] ) ;
910
@@ -38,19 +39,6 @@ const isRelativePathInside = (relativePath: string): boolean =>
3839const isPathInside = ( rootPath : string , filePath : string ) : boolean =>
3940 isRelativePathInside ( path . relative ( rootPath , filePath ) ) ;
4041
41- type RelativePathResolver = ( filePath : string ) => string ;
42-
43- const createRelativePathResolver = ( rootPath : string ) : RelativePathResolver => {
44- const rootPrefix = rootPath . endsWith ( path . sep ) ? rootPath : `${ rootPath } ${ path . sep } ` ;
45-
46- return ( filePath ) =>
47- filePath === rootPath
48- ? ''
49- : filePath . startsWith ( rootPrefix )
50- ? filePath . slice ( rootPrefix . length )
51- : path . relative ( rootPath , filePath ) ;
52- } ;
53-
5442const toPosixPath = ( filePath : string ) : string =>
5543 path . sep === '\\' ? filePath . replaceAll ( '\\' , '/' ) : filePath ;
5644
@@ -86,14 +74,14 @@ const findGitRoot = async (cwd: string): Promise<string> => {
8674
8775class GitIgnoreMatcher {
8876 readonly #rootPath: string ;
89- readonly #rootPrefix: string ;
77+ readonly #resolveRelativePath: RelativePathResolver ;
9078 readonly #matchers = new Map < string , ReturnType < typeof ignore > > ( ) ;
9179 readonly #loads = new Map < string , Promise < void > > ( ) ;
9280 readonly #ignoredDirectories = new Map < string , boolean > ( ) ;
9381
9482 private constructor ( rootPath : string ) {
9583 this . #rootPath = rootPath ;
96- this . #rootPrefix = rootPath . endsWith ( path . sep ) ? rootPath : ` ${ rootPath } ${ path . sep } ` ;
84+ this . #resolveRelativePath = createRelativePathResolver ( rootPath ) ;
9785 }
9886
9987 static async create ( cwd : string ) : Promise < GitIgnoreMatcher > {
@@ -103,11 +91,11 @@ class GitIgnoreMatcher {
10391 }
10492
10593 async loadThrough ( directoryPath : string ) : Promise < void > {
106- if ( ! isPathInside ( this . #rootPath, directoryPath ) ) {
94+ const relativePath = this . #resolveRelativePath( directoryPath ) ;
95+ if ( ! isRelativePathInside ( relativePath ) ) {
10796 return ;
10897 }
10998
110- const relativePath = path . relative ( this . #rootPath, directoryPath ) ;
11199 const segments = relativePath ? relativePath . split ( path . sep ) : [ ] ;
112100 const loads = [ this . #load( this . #rootPath) ] ;
113101 let currentPath = this . #rootPath;
@@ -121,7 +109,7 @@ class GitIgnoreMatcher {
121109 }
122110
123111 async load ( directoryPath : string ) : Promise < void > {
124- if ( isPathInside ( this . #rootPath , directoryPath ) ) {
112+ if ( isRelativePathInside ( this . #resolveRelativePath ( directoryPath ) ) ) {
125113 await this . #load( directoryPath ) ;
126114 }
127115 }
@@ -131,12 +119,7 @@ class GitIgnoreMatcher {
131119 return false ;
132120 }
133121
134- const relativePath =
135- filePath === this . #rootPath
136- ? ''
137- : filePath . startsWith ( this . #rootPrefix)
138- ? filePath . slice ( this . #rootPrefix. length )
139- : path . relative ( this . #rootPath, filePath ) ;
122+ const relativePath = this . #resolveRelativePath( filePath ) ;
140123 if ( relativePath === '' || ! isRelativePathInside ( relativePath ) ) {
141124 return false ;
142125 }
@@ -175,7 +158,7 @@ class GitIgnoreMatcher {
175158 return cached ;
176159 }
177160
178- relativePath ??= path . relative ( this . #rootPath , directoryPath ) ;
161+ relativePath ??= this . #resolveRelativePath ( directoryPath ) ;
179162
180163 // Git cannot re-include a path below an ignored directory.
181164 const parentPath = path . dirname ( directoryPath ) ;
0 commit comments