Skip to content

Commit

Permalink
🐛 Properly detect MERGE_HEAD in GinChaperon
Browse files Browse the repository at this point in the history
Close #146
  • Loading branch information
lambdalisue committed Sep 23, 2024
1 parent e3ea9b7 commit 9b5c346
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
4 changes: 3 additions & 1 deletion denops/gin/command/chaperon/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from "jsr:@std/fs@^1.0.0";
import * as path from "jsr:@std/path@^1.0.0";
import { findGitdir } from "../../git/finder.ts";

const beginMarker = `${"<".repeat(7)} `;
const endMarker = `${">".repeat(7)} `;
Expand Down Expand Up @@ -29,8 +30,9 @@ export type AliasHead = typeof validAliasHeads[number];
export async function getInProgressAliasHead(
worktree: string,
): Promise<AliasHead | undefined> {
const gitdir = await findGitdir(worktree);
for (const head of validAliasHeads) {
if (await fs.exists(path.join(worktree, ".git", head))) {
if (await fs.exists(path.join(gitdir, head))) {
return head;
}
}
Expand Down
25 changes: 25 additions & 0 deletions denops/gin/git/finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { decodeUtf8 } from "../util/text.ts";

const ttl = 30000; // seconds
const cacheWorktree = new Cache<string, string | Error>(ttl);
const cacheGitdir = new Cache<string, string | Error>(ttl);

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

/**
* Find a .git directory of a git working directory.
*
* @param cwd - A current working directory.
* @returns A root path of a git working directory.
*/
export async function findGitdir(cwd: string): Promise<string> {
const path = await Deno.realPath(cwd);
const result = cacheGitdir.get(path) ?? await (async () => {
let result: string | Error;
try {
result = await revParse(path, ["--git-dir"]);
} catch (e) {
result = e;
}
cacheGitdir.set(path, result);
return result;
})();
if (result instanceof Error) {
throw result;
}
return result;
}

async function revParse(cwd: string, args: string[]): Promise<string> {
const terms = cwd.split(SEPARATOR);
if (terms.includes(".git")) {
Expand Down
57 changes: 54 additions & 3 deletions denops/gin/git/finder_test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0";
import { sandbox } from "jsr:@lambdalisue/sandbox@^2.0.0";
import $ from "jsr:@david/dax@^0.42.0";
import { findWorktree } from "./finder.ts";
import { join } from "jsr:@std/path@^1.0.0";
import { findGitdir, findWorktree } from "./finder.ts";
import { ExecuteError } from "./process.ts";

Deno.test({
name: "find() returns a root path of a git working directory",
name: "findWorktree() returns a root path of a git working directory",
fn: async () => {
await using sbox = await prepare();
Deno.chdir("a/b/c");
Expand All @@ -18,7 +19,8 @@ Deno.test({
});

Deno.test({
name: "find() throws an error if the path is not in a git working directory",
name:
"findWorktree() throws an error if the path is not in a git working directory",
fn: async () => {
await assertRejects(async () => {
await findWorktree("/");
Expand All @@ -32,6 +34,55 @@ Deno.test({
sanitizeOps: false,
});

Deno.test({
name: "findGitdir() returns a root path of a git working directory",
fn: async () => {
await using sbox = await prepare();
Deno.chdir("a/b/c");
assertEquals(await findGitdir("."), join(sbox.path, ".git"));
// An internal cache will be used for the following call
assertEquals(await findGitdir("."), join(sbox.path, ".git"));
},
sanitizeResources: false,
sanitizeOps: false,
});

Deno.test({
name: "findGitdir() returns a worktree path of a git working directory",
fn: async () => {
await using sbox = await prepare();
await $`git worktree add -b test test main`;
Deno.chdir("test");
assertEquals(
await findGitdir("."),
join(sbox.path, ".git", "worktrees", "test"),
);
// An internal cache will be used for the following call
assertEquals(
await findGitdir("."),
join(sbox.path, ".git", "worktrees", "test"),
);
},
sanitizeResources: false,
sanitizeOps: false,
});

Deno.test({
name:
"findGitdir() throws an error if the path is not in a git working directory",
fn: async () => {
await assertRejects(async () => {
await findGitdir("/");
}, ExecuteError);
// An internal cache will be used for the following call
await assertRejects(async () => {
await findGitdir("/");
}, ExecuteError);
},
sanitizeResources: false,
sanitizeOps: false,
});

async function prepare(): ReturnType<typeof sandbox> {
const sbox = await sandbox();
await $`git init`;
Expand Down

0 comments on commit 9b5c346

Please sign in to comment.