| 115 | * @returns Array of removed lock file paths |
| 116 | */ |
| 117 | export async function cleanStaleLockFiles( |
| 118 | worktreePath: string, |
| 119 | maxAgeMs: number = 5 * 60 * 1000 |
| 120 | ): Promise<string[]> { |
| 121 | const removedLocks: string[] = []; |
| 122 | const basicLocks = [ |
| 123 | ".git/index.lock", |
| 124 | ".git/config.lock", |
| 125 | ".git/HEAD.lock", |
| 126 | ".git/shallow.lock", |
| 127 | ]; |
| 128 | |
| 129 | for (const lockRelPath of basicLocks) { |
| 130 | const lockPath = join(worktreePath, lockRelPath); |
| 131 | try { |
| 132 | const stats = await stat(lockPath); |
| 133 | const age = Date.now() - stats.mtimeMs; |
| 134 | |
| 135 | if (age > maxAgeMs) { |
| 136 | await unlink(lockPath); |
| 137 | removedLocks.push(lockPath); |
| 138 | console.log(`[git-factory] Removed stale lock file: ${lockPath} (age: ${Math.round(age / 1000)}s)`); |
| 139 | } |
| 140 | } catch { |
| 141 | // Lock file doesn't exist, which is fine |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | return removedLocks; |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * Detects if an error is caused by a git lock file conflict. |