@@ -3,6 +3,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
33import { formatPatch , structuredPatch } from "diff"
44import path from "path"
55import z from "zod"
6+ import ignore from "ignore"
67import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
78import { InstanceState } from "@/effect/instance-state"
89import { AppFileSystem } from "@/filesystem"
@@ -148,6 +149,17 @@ export namespace Snapshot {
148149 yield * fs . writeFileString ( target , text ? `${ text } \n` : "" ) . pipe ( Effect . orDie )
149150 } )
150151
152+ const parseIgnore = Effect . fnUntraced ( function * ( ) {
153+ const ig = ignore ( )
154+ const gitignorePath = path . join ( state . worktree , ".gitignore" )
155+ const gitignoreText = yield * read ( gitignorePath )
156+ if ( gitignoreText ) ig . add ( gitignoreText )
157+ const ignorePath = path . join ( state . worktree , ".ignore" )
158+ const ignoreText = yield * read ( ignorePath )
159+ if ( ignoreText ) ig . add ( ignoreText )
160+ return ig . ignores . bind ( ig )
161+ } )
162+
151163 const add = Effect . fnUntraced ( function * ( ) {
152164 yield * sync ( )
153165 const [ diff , other ] = yield * Effect . all (
@@ -179,21 +191,12 @@ export namespace Snapshot {
179191 // Filter out files that are now gitignored even if previously tracked
180192 // Files may have been tracked before being gitignored, so we need to check
181193 // against the source project's current gitignore rules
182- // Use --no-index to check purely against patterns (ignoring whether file is tracked)
183- const checkArgs = [
184- ...quote ,
185- "--git-dir" ,
186- path . join ( state . worktree , ".git" ) ,
187- "--work-tree" ,
188- state . worktree ,
189- "check-ignore" ,
190- "--no-index" ,
191- "--" ,
192- ...all ,
193- ]
194- const check = yield * git ( checkArgs , { cwd : state . directory } )
195- const ignored =
196- check . code === 0 ? new Set ( check . text . trim ( ) . split ( "\n" ) . filter ( Boolean ) ) : new Set < string > ( )
194+ // Use local ignore library to avoid command line length limits
195+ const ignored = new Set < string > ( )
196+ const isIgnored = yield * parseIgnore ( )
197+ for ( const item of all ) {
198+ if ( isIgnored ( item ) || isIgnored ( item + "/" ) ) ignored . add ( item )
199+ }
197200 const filtered = all . filter ( ( item ) => ! ignored . has ( item ) )
198201
199202 // Remove newly-ignored files from snapshot index to prevent re-adding
@@ -297,25 +300,11 @@ export namespace Snapshot {
297300
298301 // Filter out files that are now gitignored
299302 if ( files . length > 0 ) {
300- const checkArgs = [
301- ...quote ,
302- "--git-dir" ,
303- path . join ( state . worktree , ".git" ) ,
304- "--work-tree" ,
305- state . worktree ,
306- "check-ignore" ,
307- "--no-index" ,
308- "--" ,
309- ...files ,
310- ]
311- const check = yield * git ( checkArgs , { cwd : state . directory } )
312- if ( check . code === 0 ) {
313- const ignored = new Set ( check . text . trim ( ) . split ( "\n" ) . filter ( Boolean ) )
314- const filtered = files . filter ( ( item ) => ! ignored . has ( item ) )
315- return {
316- hash,
317- files : filtered . map ( ( x ) => path . join ( state . worktree , x ) . replaceAll ( "\\" , "/" ) ) ,
318- }
303+ const isIgnored = yield * parseIgnore ( )
304+ const filtered = files . filter ( ( item ) => ! isIgnored ( item ) && ! isIgnored ( item + "/" ) )
305+ return {
306+ hash,
307+ files : filtered . map ( ( x ) => path . join ( state . worktree , x ) . replaceAll ( "\\" , "/" ) ) ,
319308 }
320309 }
321310
@@ -674,25 +663,10 @@ export namespace Snapshot {
674663
675664 // Filter out files that are now gitignored
676665 if ( rows . length > 0 ) {
677- const files = rows . map ( ( r ) => r . file )
678- const checkArgs = [
679- ...quote ,
680- "--git-dir" ,
681- path . join ( state . worktree , ".git" ) ,
682- "--work-tree" ,
683- state . worktree ,
684- "check-ignore" ,
685- "--no-index" ,
686- "--" ,
687- ...files ,
688- ]
689- const check = yield * git ( checkArgs , { cwd : state . directory } )
690- if ( check . code === 0 ) {
691- const ignored = new Set ( check . text . trim ( ) . split ( "\n" ) . filter ( Boolean ) )
692- const filtered = rows . filter ( ( r ) => ! ignored . has ( r . file ) )
693- rows . length = 0
694- rows . push ( ...filtered )
695- }
666+ const isIgnored = yield * parseIgnore ( )
667+ const filtered = rows . filter ( ( r ) => ! isIgnored ( r . file ) && ! isIgnored ( r . file + "/" ) )
668+ rows . length = 0
669+ rows . push ( ...filtered )
696670 }
697671
698672 const step = 100
0 commit comments