fix: only generate exclude file once on initial creation

- Modified ShadowCheckpointService to check if exclude file exists before regenerating
- Avoids expensive file scanning (1-3 seconds) on every checkpoint initialization
- Only runs the scan on initial shadow repo creation or when exclude file is missing
- Added refreshExcludePatterns() method for manual refresh if needed
- Maintains backwards compatibility while fixing performance regression
This commit is contained in:
Merge Resolver 2025-08-19 17:47:00 -06:00
parent 72809666ca
commit 18f76b8715

View file

@ -95,7 +95,12 @@ export abstract class ShadowCheckpointService extends EventEmitter {
)
}
await this.writeExcludeFile()
// Only regenerate exclude file if it doesn't exist
const excludePath = path.join(this.dotGitDir, "info", "exclude")
if (!(await fileExistsAtPath(excludePath))) {
this.log(`[${this.constructor.name}#initShadowGit] exclude file missing, regenerating`)
await this.writeExcludeFile()
}
this.baseHash = await git.revparse(["HEAD"])
} else {
this.log(`[${this.constructor.name}#initShadowGit] creating shadow git repo at ${this.checkpointsDir}`)
@ -137,7 +142,18 @@ export abstract class ShadowCheckpointService extends EventEmitter {
// .git/info/exclude is local to the shadow git repo, so it's not
// shared with the main repo - and won't conflict with user's
// .gitignore.
protected async writeExcludeFile() {
// Note: This is only called on initial creation or when the exclude file is missing
// to avoid expensive scans on every initialization.
protected async writeExcludeFile(forceRefresh: boolean = false) {
// Skip if exclude file exists and not forcing refresh
if (!forceRefresh) {
const excludePath = path.join(this.dotGitDir, "info", "exclude")
if (await fileExistsAtPath(excludePath)) {
this.log(`[${this.constructor.name}#writeExcludeFile] exclude file exists, skipping regeneration`)
return
}
}
await fs.mkdir(path.join(this.dotGitDir, "info"), { recursive: true })
const { patterns, stats } = await getExcludePatternsWithStats(this.workspaceDir)
await fs.writeFile(path.join(this.dotGitDir, "info", "exclude"), patterns.join("\n"))
@ -157,6 +173,15 @@ export abstract class ShadowCheckpointService extends EventEmitter {
}
}
// Public method to allow manual refresh of exclude patterns if needed
public async refreshExcludePatterns() {
if (!this.git) {
throw new Error("Shadow git repo not initialized")
}
this.log(`[${this.constructor.name}#refreshExcludePatterns] manually refreshing exclude patterns`)
await this.writeExcludeFile(true)
}
private async stageAll(git: SimpleGit) {
try {
await git.add(".")