* Gets stat-only logs for worktree paths (no file reads).
( worktreePaths: string[], limit?: number, )
| 4111 | * Gets stat-only logs for worktree paths (no file reads). |
| 4112 | */ |
| 4113 | async function getStatOnlyLogsForWorktrees( |
| 4114 | worktreePaths: string[], |
| 4115 | limit?: number, |
| 4116 | ): Promise<LogOption[]> { |
| 4117 | const projectsDir = getProjectsDir() |
| 4118 | |
| 4119 | if (worktreePaths.length <= 1) { |
| 4120 | const cwd = getOriginalCwd() |
| 4121 | const projectDir = getProjectDir(cwd) |
| 4122 | return getSessionFilesLite(projectDir, undefined, cwd) |
| 4123 | } |
| 4124 | |
| 4125 | // On Windows, drive letter case can differ between git worktree list |
| 4126 | // output (e.g. C:/Users/...) and how paths were stored in project |
| 4127 | // directories (e.g. c:/Users/...). Use case-insensitive comparison. |
| 4128 | const caseInsensitive = process.platform === 'win32' |
| 4129 | |
| 4130 | // Sort worktree paths by sanitized prefix length (longest first) so |
| 4131 | // more specific matches take priority over shorter ones. Without this, |
| 4132 | // a short prefix like -code-myrepo could match -code-myrepo-worktree1 |
| 4133 | // before the longer, more specific prefix gets a chance. |
| 4134 | const indexed = worktreePaths.map(wt => { |
| 4135 | const sanitized = sanitizePath(wt) |
| 4136 | return { |
| 4137 | path: wt, |
| 4138 | prefix: caseInsensitive ? sanitized.toLowerCase() : sanitized, |
| 4139 | } |
| 4140 | }) |
| 4141 | indexed.sort((a, b) => b.prefix.length - a.prefix.length) |
| 4142 | |
| 4143 | const allLogs: LogOption[] = [] |
| 4144 | const seenDirs = new Set<string>() |
| 4145 | |
| 4146 | let allDirents: Dirent[] |
| 4147 | try { |
| 4148 | allDirents = await readdir(projectsDir, { withFileTypes: true }) |
| 4149 | } catch (e) { |
| 4150 | // Fall back to current project |
| 4151 | logForDebugging( |
| 4152 | `Failed to read projects dir ${projectsDir}, falling back to current project: ${e}`, |
| 4153 | ) |
| 4154 | const projectDir = getProjectDir(getOriginalCwd()) |
| 4155 | return getSessionFilesLite(projectDir, limit, getOriginalCwd()) |
| 4156 | } |
| 4157 | |
| 4158 | for (const dirent of allDirents) { |
| 4159 | if (!dirent.isDirectory()) continue |
| 4160 | const dirName = caseInsensitive ? dirent.name.toLowerCase() : dirent.name |
| 4161 | if (seenDirs.has(dirName)) continue |
| 4162 | |
| 4163 | for (const { path: wtPath, prefix } of indexed) { |
| 4164 | if (dirName === prefix || dirName.startsWith(prefix + '-')) { |
| 4165 | seenDirs.add(dirName) |
| 4166 | allLogs.push( |
| 4167 | ...(await getSessionFilesLite( |
| 4168 | join(projectsDir, dirent.name), |
| 4169 | undefined, |
| 4170 | wtPath, |
no test coverage detected