Detect git workspaces with rev-parse instead of a .git stat
`isGitRepo` only accepted a `.git` directory, so linked worktrees and submodules — both of which store `.git` as a file containing `gitdir: …` — silently fell into the non-git branch. The baseline diff then replaced `git status` as the source of truth for workspaces that git itself recognises, and edge cases where the baseline is missing (a freshly-created worktree mid-run, a submodule without a captured snapshot) bled into `no_baseline` skips instead of running the authoritative diff. Call `git rev-parse --is-inside-work-tree` and take git's own yes/no answer. Exit 0 means git would happily run `status` there; any other outcome (no git binary, corrupted ref, genuinely non-git) lands us on the baseline path exactly as before.
This commit is contained in:
1 parent
1cb7e9fffa
commit
f9349f374c
1 file changed
+21
-2
@@ -1,6 +1,6 @@
|
||||
import { isAbsolute, relative, resolve } from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, readdirSync, statSync } from "node:fs";
|
||||
import { readdirSync, statSync } from "node:fs";
|
||||
import type { AppDatabase } from "@main/database";
|
||||
|
||||
/**
|
||||
@@ -392,9 +392,28 @@ function projectBashArtifacts(
|
||||
return projectChangedPaths(db, ctx, change.paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask git whether `workspacePath` sits inside a working tree. This
|
||||
* covers the three forms the `.git` entry takes in real setups:
|
||||
*
|
||||
* - a directory (a plain clone),
|
||||
* - a file with `gitdir: …` (a linked worktree), or
|
||||
* - a file with `gitdir: …/modules/…` (a submodule).
|
||||
*
|
||||
* The previous `existsSync + isDirectory` probe only recognised the
|
||||
* first form, so linked worktrees and submodules silently degraded
|
||||
* onto the baseline path — and lost `git status` as the authoritative
|
||||
* diff source. `rev-parse --is-inside-work-tree` exits 0 whenever git
|
||||
* itself would accept the directory, which is the semantics we want.
|
||||
*/
|
||||
function isGitRepo(workspacePath: string): boolean {
|
||||
try {
|
||||
return existsSync(resolve(workspacePath, ".git")) && statSync(resolve(workspacePath, ".git")).isDirectory();
|
||||
execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
||||
cwd: workspacePath,
|
||||
timeout: 2_000,
|
||||
stdio: ["ignore", "ignore", "ignore"],
|
||||
});
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user