@@ -21,9 +21,41 @@ const ignoreFilesGlobOptions = {
2121
2222export const GITIGNORE_FILES_PATTERN = '**/.gitignore' ;
2323
24- const applyBaseToPattern = ( pattern , base ) => isNegativePattern ( pattern )
25- ? '!' + path . posix . join ( base , pattern . slice ( 1 ) )
26- : path . posix . join ( base , pattern ) ;
24+ // Apply base path to gitignore patterns based on .gitignore spec 2.22.1
25+ // https://git-scm.com/docs/gitignore#_pattern_format
26+ // See also https://github.com/sindresorhus/globby/issues/146
27+ const applyBaseToPattern = ( pattern , base ) => {
28+ if ( ! base ) {
29+ return pattern ;
30+ }
31+
32+ const isNegative = isNegativePattern ( pattern ) ;
33+ const cleanPattern = isNegative ? pattern . slice ( 1 ) : pattern ;
34+
35+ // Check if pattern has non-trailing slashes
36+ const slashIndex = cleanPattern . indexOf ( '/' ) ;
37+ const hasNonTrailingSlash = slashIndex !== - 1 && slashIndex !== cleanPattern . length - 1 ;
38+
39+ let result ;
40+ if ( ! hasNonTrailingSlash ) {
41+ // "If there is no separator at the beginning or middle of the pattern,
42+ // then the pattern may also match at any level below the .gitignore level."
43+ // So patterns like '*.log' or 'temp' or 'build/' (trailing slash) match recursively.
44+ result = path . posix . join ( base , '**' , cleanPattern ) ;
45+ } else if ( cleanPattern . startsWith ( '/' ) ) {
46+ // "If there is a separator at the beginning [...] of the pattern,
47+ // then the pattern is relative to the directory level of the particular .gitignore file itself."
48+ // Leading slash anchors the pattern to the .gitignore's directory.
49+ result = path . posix . join ( base , cleanPattern . slice ( 1 ) ) ;
50+ } else {
51+ // "If there is a separator [...] middle [...] of the pattern,
52+ // then the pattern is relative to the directory level of the particular .gitignore file itself."
53+ // Patterns like 'src/foo' are relative to the .gitignore's directory.
54+ result = path . posix . join ( base , cleanPattern ) ;
55+ }
56+
57+ return isNegative ? '!' + result : result ;
58+ } ;
2759
2860const parseIgnoreFile = ( file , cwd ) => {
2961 const base = slash ( path . relative ( cwd , path . dirname ( file . filePath ) ) ) ;
0 commit comments