@@ -98,6 +98,54 @@ export function getProjectFileTree(
9898 return root . children
9999}
100100
101+ function rebaseGitignorePattern (
102+ rawPattern : string ,
103+ relativeDirPath : string ,
104+ ) : string {
105+ // Preserve negation and directory-only flags
106+ const isNegated = rawPattern . startsWith ( '!' )
107+ let pattern = isNegated ? rawPattern . slice ( 1 ) : rawPattern
108+
109+ const dirOnly = pattern . endsWith ( '/' )
110+ // Strip the trailing slash for slash-detection only
111+ const core = dirOnly ? pattern . slice ( 0 , - 1 ) : pattern
112+
113+ const anchored = core . startsWith ( '/' ) // anchored to .gitignore dir
114+ // Detect if the "meaningful" part (minus optional leading '/' and trailing '/')
115+ // contains a slash. If not, git treats it as recursive.
116+ const coreNoLead = anchored ? core . slice ( 1 ) : core
117+ const hasSlash = coreNoLead . includes ( '/' )
118+
119+ // Build the base (where this .gitignore lives relative to projectRoot)
120+ const base = relativeDirPath . replace ( / \\ / g, '/' ) // normalize
121+
122+ let rebased : string
123+ if ( anchored ) {
124+ // "/foo" from evals/.gitignore -> "evals/foo"
125+ rebased = base ? `${ base } /${ coreNoLead } ` : coreNoLead
126+ } else if ( ! hasSlash ) {
127+ // "logs" or "logs/" should recurse from evals/: "evals/**/logs[/]"
128+ if ( base ) {
129+ rebased = `${ base } /**/${ coreNoLead } `
130+ } else {
131+ // At project root already; "logs" stays "logs" to keep recursive semantics
132+ rebased = coreNoLead
133+ }
134+ } else {
135+ // "foo/bar" relative to evals/: "evals/foo/bar"
136+ rebased = base ? `${ base } /${ coreNoLead } ` : coreNoLead
137+ }
138+
139+ if ( dirOnly && ! rebased . endsWith ( '/' ) ) {
140+ rebased += '/'
141+ }
142+
143+ // Normalize to forward slashes
144+ rebased = rebased . replace ( / \\ / g, '/' )
145+
146+ return isNegated ? `!${ rebased } ` : rebased
147+ }
148+
101149export function parseGitignore (
102150 fullDirPath : string ,
103151 projectRoot : string ,
@@ -111,48 +159,17 @@ export function parseGitignore(
111159 ]
112160
113161 for ( const ignoreFilePath of ignoreFiles ) {
114- if ( fs . existsSync ( ignoreFilePath ) ) {
115- const ignoreContent = fs . readFileSync ( ignoreFilePath , 'utf8' )
116- const lines = ignoreContent . split ( '\n' )
117- for ( let line of lines ) {
118- line = line . trim ( )
119- if ( line === '' || line . startsWith ( '#' ) ) {
120- continue
121- }
162+ if ( ! fs . existsSync ( ignoreFilePath ) ) continue
122163
123- let isNegated = false
124- let pattern = line
125- if ( pattern . startsWith ( '!' ) ) {
126- isNegated = true
127- pattern = pattern . slice ( 1 )
128- }
164+ const ignoreContent = fs . readFileSync ( ignoreFilePath , 'utf8' )
165+ const lines = ignoreContent . split ( '\n' )
166+ for ( let line of lines ) {
167+ line = line . trim ( )
168+ if ( line === '' || line . startsWith ( '#' ) ) continue
129169
130- let finalPattern = pattern
131- // All patterns added to the ignore instance should be relative to the projectRoot.
132- if ( pattern . startsWith ( '/' ) ) {
133- // A pattern starting with '/' is relative to the .gitignore file's directory.
134- // Remove the leading '/' and prepend the relativeDirPath to make it relative to projectRoot.
135- finalPattern = pattern . slice ( 1 )
136- if ( relativeDirPath !== '' ) {
137- finalPattern = path . join ( relativeDirPath , finalPattern )
138- }
139- } else {
140- // A pattern not starting with '/' is also relative to the .gitignore file's directory.
141- // Prepend relativeDirPath (if it exists) to make it relative to projectRoot.
142- // If relativeDirPath is empty, the pattern is already relative to projectRoot.
143- if ( relativeDirPath !== '' ) {
144- finalPattern = path . join ( relativeDirPath , pattern )
145- }
146- // else: pattern is already relative to projectRoot, so finalPattern remains pattern
147- }
148- finalPattern = finalPattern . replace ( / \\ / g, '/' )
170+ const finalPattern = rebaseGitignorePattern ( line , relativeDirPath )
149171
150- if ( isNegated ) {
151- ig . add ( `!${ finalPattern } ` )
152- } else {
153- ig . add ( finalPattern )
154- }
155- }
172+ ig . add ( finalPattern )
156173 }
157174 }
158175
0 commit comments