diff --git a/packages/coding-agent/src/utils/git.ts b/packages/coding-agent/src/utils/git.ts index d68e13868..ecd7c60de 100644 --- a/packages/coding-agent/src/utils/git.ts +++ b/packages/coding-agent/src/utils/git.ts @@ -561,10 +561,27 @@ function parsePackedRefs(content: string | null, targetRef: string): string | nu return null; } +function stripGitConfigComments(line: string): string { + let clean = ""; + let inQuotes = false; + for (let i = 0; i < line.length; i++) { + const char = line[i]; + if (char === '"') { + inQuotes = !inQuotes; + clean += char; + } else if (!inQuotes && (char === ";" || char === "#")) { + break; + } else { + clean += char; + } + } + return clean.trim(); +} + function parseGitConfigHasReftable(content: string): boolean { let inExtensions = false; for (const line of content.split("\n")) { - const trimmed = line.trim(); + const trimmed = stripGitConfigComments(line); if (trimmed.startsWith("[") && trimmed.endsWith("]")) { const section = trimmed.slice(1, -1).trim().toLowerCase(); inExtensions = section === "extensions"; @@ -572,27 +589,12 @@ function parseGitConfigHasReftable(content: string): boolean { const eqIndex = trimmed.indexOf("="); if (eqIndex !== -1) { const key = trimmed.slice(0, eqIndex).trim().toLowerCase(); - const value = trimmed.slice(eqIndex + 1).trim(); + let value = trimmed.slice(eqIndex + 1).trim(); if (key === "refstorage") { - // Strip trailing comments per git-config(5) - let cleanValue = ""; - let inQuotes = false; - for (let i = 0; i < value.length; i++) { - const char = value[i]; - if (char === '"') { - inQuotes = !inQuotes; - cleanValue += char; - } else if (!inQuotes && (char === ";" || char === "#")) { - break; - } else { - cleanValue += char; - } + if (value.startsWith('"') && value.endsWith('"')) { + value = value.slice(1, -1).trim(); } - cleanValue = cleanValue.trim().toLowerCase(); - if (cleanValue.startsWith('"') && cleanValue.endsWith('"')) { - cleanValue = cleanValue.slice(1, -1).trim(); - } - if (cleanValue === "reftable") { + if (value.toLowerCase() === "reftable") { return true; } } diff --git a/packages/coding-agent/test/git-reftable.test.ts b/packages/coding-agent/test/git-reftable.test.ts index df494edd1..1aa46f25c 100644 --- a/packages/coding-agent/test/git-reftable.test.ts +++ b/packages/coding-agent/test/git-reftable.test.ts @@ -158,6 +158,20 @@ describe.skipIf(!supportsReftable)("git reftable support", () => { expect(await git.repo.isReftable(repository6)).toBe(true); expect(git.repo.isReftableSync(repository6)).toBe(true); } + + // Test section header with trailing comment + const newConfigWithSectionComment = baseConfig.replace( + "[extensions]", + "[extensions] # extensions section comment", + ); + await fs.writeFile(configPath, newConfigWithSectionComment); + + const repository7 = await git.repo.resolve(testRepoDir); + expect(repository7).not.toBeNull(); + if (repository7) { + expect(await git.repo.isReftable(repository7)).toBe(true); + expect(git.repo.isReftableSync(repository7)).toBe(true); + } }); test("resolves references in a reftable worktree", async () => {