Skip to content

Commit 0a99e14

Browse files
committed
Fix filesystem root detection for windows
1 parent 8165719 commit 0a99e14

File tree

2 files changed

+70
-7
lines changed

2 files changed

+70
-7
lines changed

denops/gin/git/finder.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { resolve, SEPARATOR } from "jsr:@std/path@^1.0.0";
1+
import { resolve } from "jsr:@std/path@^1.0.0";
22
import { Cache } from "jsr:@lambdalisue/ttl-cache@^1.0.0";
33
import { execute } from "./process.ts";
44
import { decodeUtf8 } from "../util/text.ts";
@@ -7,6 +7,17 @@ const ttl = 30000; // seconds
77
const cacheWorktree = new Cache<string, string | Error>(ttl);
88
const cacheGitdir = new Cache<string, string | Error>(ttl);
99

10+
/**
11+
* Check if we've reached the filesystem root by comparing a path with its parent.
12+
* This works cross-platform (Windows, Linux, Mac).
13+
*
14+
* @param currentPath - The path to check
15+
* @returns true if the path is the filesystem root, false otherwise
16+
*/
17+
function isFilesystemRoot(currentPath: string): boolean {
18+
return currentPath === resolve(currentPath, "..");
19+
}
20+
1021
/**
1122
* Find a root path of a git working directory.
1223
*
@@ -20,10 +31,7 @@ export async function findWorktree(cwd: string): Promise<string> {
2031
try {
2132
// Search upward from current directory to find worktree root
2233
let currentPath = path;
23-
while (
24-
currentPath && currentPath !== "/" &&
25-
currentPath !== resolve(currentPath, "..")
26-
) {
34+
while (!isFilesystemRoot(currentPath)) {
2735
if (await isWorktreeRoot(currentPath)) {
2836
result = currentPath;
2937
cacheWorktree.set(path, result);
@@ -38,7 +46,7 @@ export async function findWorktree(cwd: string): Promise<string> {
3846
"--show-superproject-working-tree",
3947
]);
4048
} catch (e) {
41-
result = e;
49+
result = e as Error;
4250
}
4351
cacheWorktree.set(path, result);
4452
return result;
@@ -62,7 +70,7 @@ export async function findGitdir(cwd: string): Promise<string> {
6270
try {
6371
result = await revParse(path, ["--git-dir"]);
6472
} catch (e) {
65-
result = e;
73+
result = e as Error;
6674
}
6775
cacheGitdir.set(path, result);
6876
return result;

denops/gin/git/finder_test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,61 @@ Deno.test({
6767
sanitizeOps: false,
6868
});
6969

70+
Deno.test({
71+
name: "findWorktree() returns a root path for worktree inside .git directory",
72+
fn: async () => {
73+
await using sbox = await prepare();
74+
// Create a worktree inside .git/workspaces/ directory
75+
await Deno.mkdir(join(".git", "workspaces"), { recursive: true });
76+
await $`git worktree add -b workspace-test .git/workspaces/test main`;
77+
78+
// Change to a subdirectory within the worktree
79+
await Deno.mkdir(join(".git", "workspaces", "test", "subdir"), {
80+
recursive: true,
81+
});
82+
Deno.chdir(join(".git", "workspaces", "test", "subdir"));
83+
84+
// findWorktree should return the worktree root, not the main repository root
85+
assertEquals(
86+
await findWorktree("."),
87+
join(sbox.path, ".git", "workspaces", "test"),
88+
);
89+
// An internal cache will be used for the following call
90+
assertEquals(
91+
await findWorktree("."),
92+
join(sbox.path, ".git", "workspaces", "test"),
93+
);
94+
},
95+
sanitizeResources: false,
96+
sanitizeOps: false,
97+
});
98+
99+
Deno.test({
100+
name: "findGitdir() returns a gitdir path for worktree inside .git directory",
101+
fn: async () => {
102+
await using sbox = await prepare();
103+
// Create a worktree inside .git/workspaces/ directory
104+
await Deno.mkdir(join(".git", "workspaces"), { recursive: true });
105+
await $`git worktree add -b workspace-test2 .git/workspaces/test2 main`;
106+
107+
// Change to the worktree
108+
Deno.chdir(join(".git", "workspaces", "test2"));
109+
110+
// findGitdir should return the correct gitdir for this worktree
111+
assertEquals(
112+
await findGitdir("."),
113+
join(sbox.path, ".git", "worktrees", "test2"),
114+
);
115+
// An internal cache will be used for the following call
116+
assertEquals(
117+
await findGitdir("."),
118+
join(sbox.path, ".git", "worktrees", "test2"),
119+
);
120+
},
121+
sanitizeResources: false,
122+
sanitizeOps: false,
123+
});
124+
70125
Deno.test({
71126
name:
72127
"findGitdir() throws an error if the path is not in a git working directory",

0 commit comments

Comments
 (0)