(opts: StatusWithDeps)
| 63 | } |
| 64 | |
| 65 | export async function statusWith(opts: StatusWithDeps): Promise<StatusEntry[]> { |
| 66 | const dir = opts.dir ?? "/"; |
| 67 | let rows: StatusMatrixRow[]; |
| 68 | try { |
| 69 | rows = await opts.git.statusMatrix({ fs: opts.fs, dir, cache: opts.cache }); |
| 70 | } catch (cause) { |
| 71 | if (isNotARepositoryCause(cause)) throw new NotARepositoryError(dir, { cause }); |
| 72 | throw new GitError("ESTATUSFAIL", `git status failed: ${errorMessage(cause)}`, { cause }); |
| 73 | } |
| 74 | |
| 75 | const out: StatusEntry[] = []; |
| 76 | for (const [path, head, workdir, stage] of rows) { |
| 77 | // Skip fully clean rows. |
| 78 | if (head === 1 && workdir === 1 && stage === 1) continue; |
| 79 | const index = indexCode(head, stage); |
| 80 | const worktree = worktreeCode(head, workdir, stage); |
| 81 | if (index === " " && worktree === " ") continue; |
| 82 | out.push({ path, index, worktree }); |
| 83 | } |
| 84 | // Stable ordering by path. Real git is lexicographic; match it |
| 85 | // so a snapshot doesn't churn on cache iteration order. |
| 86 | out.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)); |
| 87 | return out; |
| 88 | } |
| 89 | |
| 90 | // Derive the X (index-vs-HEAD) column. |
| 91 | // HEAD absent, stage present -> A |
no test coverage detected