Skip to content

Commit 1daa78c

Browse files
committed
fix(server): read quoted and header-line core.bare values
1 parent 0acbbf1 commit 1daa78c

3 files changed

Lines changed: 45 additions & 9 deletions

File tree

‎apps/server/src/project/AgentSessionScanner.test.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,40 @@ it.layer(NodeServices.layer)("AgentSessionScanner", (it) => {
10051005
}),
10061006
);
10071007

1008+
it.effect("reads core.bare from hand-edited config forms", () =>
1009+
Effect.gen(function* () {
1010+
const path = yield* Path.Path;
1011+
const fileSystem = yield* FileSystem.FileSystem;
1012+
const claudeHomePath = yield* makeTempDir("t3code-claude-home-");
1013+
const codexHomePath = yield* makeTempDir("t3code-codex-home-");
1014+
const worktrees: Array<string> = [];
1015+
for (const [index, config] of [
1016+
'[core]\n\tbare = "true" ; quoted\n',
1017+
"[core] bare = true\n",
1018+
"[core]\n\tbare\n",
1019+
].entries()) {
1020+
const bare = yield* makeTempDir(`t3code-workspace-bare-form-${index}-`);
1021+
const gitDir = path.join(bare, ".git", "worktrees", "wt");
1022+
yield* fileSystem.makeDirectory(gitDir, { recursive: true });
1023+
yield* fileSystem.writeFileString(path.join(bare, ".git", "config"), config);
1024+
yield* fileSystem.writeFileString(path.join(gitDir, "commondir"), "../..\n");
1025+
const worktree = path.join(bare, "wt");
1026+
yield* fileSystem.makeDirectory(worktree);
1027+
yield* fileSystem.writeFileString(path.join(worktree, ".git"), `gitdir: ${gitDir}\n`);
1028+
yield* writeTranscript({
1029+
filePath: path.join(claudeHomePath, "projects", `-slug-${index}`, "a.jsonl"),
1030+
contents: claudeSessionLine(worktree),
1031+
mtimeMs: Date.parse(`2026-01-0${index + 1}T00:00:00.000Z`),
1032+
});
1033+
worktrees.unshift(worktree);
1034+
}
1035+
1036+
const result = yield* runScan({ claudeHomePath, codexHomePath });
1037+
1038+
expect(result.candidates.map((candidate) => candidate.path)).toEqual(worktrees);
1039+
}),
1040+
);
1041+
10081042
it.effect("excludes sandboxes under the configured worktrees dir without .t3 in the path", () =>
10091043
Effect.gen(function* () {
10101044
const path = yield* Path.Path;

‎apps/server/src/project/AgentSessionScanner.ts‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import * as Stream from "effect/Stream";
4141

4242
import {
4343
normalizeGitRemoteUrl,
44+
parseGitConfigValue,
4445
parseGitHubRepositoryNameWithOwnerFromRemoteUrl,
4546
parseOriginUrlFromGitConfig,
4647
} from "@t3tools/shared/git";
@@ -567,17 +568,18 @@ function isBareGitConfig(configText: string): boolean {
567568
let inCore = false;
568569
let bare = false;
569570
for (const rawLine of configText.split(/\r?\n/)) {
570-
const line = rawLine.trim();
571-
if (line.startsWith("[")) {
572-
inCore = /^\[\s*core\s*\]/i.test(line);
573-
continue;
571+
let line = rawLine.trim();
572+
// Git accepts the first setting on the section header's own line.
573+
const header = /^\[\s*([^\]]*?)\s*\](.*)$/.exec(line);
574+
if (header !== null) {
575+
inCore = header[1]!.toLowerCase() === "core";
576+
line = header[2]!.trim();
574577
}
575578
if (!inCore) continue;
576-
const match = /^bare\s*(?:=\s*([^#;]*))?(?:[#;].*)?$/i.exec(line);
579+
const match = /^bare\s*(?:=(.*)|[#;].*)?$/i.exec(line);
577580
if (match === null) continue;
578-
const value = match[1]?.trim().toLowerCase();
579-
bare =
580-
value === undefined || value === "true" || value === "yes" || value === "on" || value === "1";
581+
const value = match[1] === undefined ? "true" : parseGitConfigValue(match[1]).toLowerCase();
582+
bare = value === "true" || value === "yes" || value === "on" || value === "1";
581583
}
582584
return bare;
583585
}

‎packages/shared/src/git.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export function normalizeGitRemoteUrl(value: string): string {
204204
* Unquote a git config value: strip an inline `#` or `;` comment outside
205205
* quotes, then drop surrounding quotes and backslash escapes.
206206
*/
207-
function parseGitConfigValue(raw: string): string {
207+
export function parseGitConfigValue(raw: string): string {
208208
let out = "";
209209
let quoted = false;
210210
for (let index = 0; index < raw.length; index += 1) {

0 commit comments

Comments
 (0)