Skip to content

Commit 513f9ca

Browse files
committed
🐛 Properly detect MERGE_HEAD in GinChaperon
Close #146
1 parent 6dc8899 commit 513f9ca

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

denops/gin/command/chaperon/util.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as fs from "jsr:@std/fs@^1.0.0";
22
import * as path from "jsr:@std/path@^1.0.0";
3+
import { findGitdir } from "../../git/finder.ts";
34

45
const beginMarker = `${"<".repeat(7)} `;
56
const endMarker = `${">".repeat(7)} `;
@@ -29,8 +30,9 @@ export type AliasHead = typeof validAliasHeads[number];
2930
export async function getInProgressAliasHead(
3031
worktree: string,
3132
): Promise<AliasHead | undefined> {
33+
const gitdir = await findGitdir(worktree);
3234
for (const head of validAliasHeads) {
33-
if (await fs.exists(path.join(worktree, ".git", head))) {
35+
if (await fs.exists(path.join(gitdir, head))) {
3436
return head;
3537
}
3638
}

denops/gin/git/finder.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { decodeUtf8 } from "../util/text.ts";
55

66
const ttl = 30000; // seconds
77
const cacheWorktree = new Cache<string, string | Error>(ttl);
8+
const cacheGitdir = new Cache<string, string | Error>(ttl);
89

910
/**
1011
* Find a root path of a git working directory.
@@ -33,6 +34,30 @@ export async function findWorktree(cwd: string): Promise<string> {
3334
return result;
3435
}
3536

37+
/**
38+
* Find a .git directory of a git working directory.
39+
*
40+
* @param cwd - A current working directory.
41+
* @returns A root path of a git working directory.
42+
*/
43+
export async function findGitdir(cwd: string): Promise<string> {
44+
const path = await Deno.realPath(cwd);
45+
const result = cacheGitdir.get(path) ?? await (async () => {
46+
let result: string | Error;
47+
try {
48+
result = await revParse(path, ["--git-dir"]);
49+
} catch (e) {
50+
result = e;
51+
}
52+
cacheGitdir.set(path, result);
53+
return result;
54+
})();
55+
if (result instanceof Error) {
56+
throw result;
57+
}
58+
return result;
59+
}
60+
3661
async function revParse(cwd: string, args: string[]): Promise<string> {
3762
const terms = cwd.split(SEPARATOR);
3863
if (terms.includes(".git")) {

denops/gin/git/finder_test.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0";
22
import { sandbox } from "jsr:@lambdalisue/sandbox@^2.0.0";
33
import $ from "jsr:@david/dax@^0.42.0";
44
import { join } from "jsr:@std/path@^1.0.0";
5-
import { findWorktree } from "./finder.ts";
5+
import { findGitdir, findWorktree } from "./finder.ts";
66
import { ExecuteError } from "./process.ts";
77

88
Deno.test({
@@ -34,6 +34,55 @@ Deno.test({
3434
sanitizeOps: false,
3535
});
3636

37+
Deno.test({
38+
name: "findGitdir() returns a root path of a git working directory",
39+
fn: async () => {
40+
await using sbox = await prepare();
41+
Deno.chdir(join("a", "b", "c"));
42+
assertEquals(await findGitdir("."), join(sbox.path, ".git"));
43+
// An internal cache will be used for the following call
44+
assertEquals(await findGitdir("."), join(sbox.path, ".git"));
45+
},
46+
sanitizeResources: false,
47+
sanitizeOps: false,
48+
});
49+
50+
Deno.test({
51+
name: "findGitdir() returns a worktree path of a git working directory",
52+
fn: async () => {
53+
await using sbox = await prepare();
54+
await $`git worktree add -b test test main`;
55+
Deno.chdir("test");
56+
assertEquals(
57+
await findGitdir("."),
58+
join(sbox.path, ".git", "worktrees", "test"),
59+
);
60+
// An internal cache will be used for the following call
61+
assertEquals(
62+
await findGitdir("."),
63+
join(sbox.path, ".git", "worktrees", "test"),
64+
);
65+
},
66+
sanitizeResources: false,
67+
sanitizeOps: false,
68+
});
69+
70+
Deno.test({
71+
name:
72+
"findGitdir() throws an error if the path is not in a git working directory",
73+
fn: async () => {
74+
await assertRejects(async () => {
75+
await findGitdir("/");
76+
}, ExecuteError);
77+
// An internal cache will be used for the following call
78+
await assertRejects(async () => {
79+
await findGitdir("/");
80+
}, ExecuteError);
81+
},
82+
sanitizeResources: false,
83+
sanitizeOps: false,
84+
});
85+
3786
async function prepare(): ReturnType<typeof sandbox> {
3887
const sbox = await sandbox();
3988
await $`git init`;

0 commit comments

Comments
 (0)