oh-my-opencode/src/shared/git-worktree/collect-git-diff-stats.ts
YeonGyu-Kim 3553ab79e1 fix(git-worktree): use trimEnd instead of trim to preserve leading whitespace
Git status porcelain output uses leading spaces for status indicators;
trim() was stripping them which could break parsing.
2026-02-11 00:45:51 +09:00

57 lines
1.8 KiB
TypeScript

import { execFileSync } from "node:child_process"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { parseGitStatusPorcelain } from "./parse-status-porcelain"
import { parseGitDiffNumstat } from "./parse-diff-numstat"
import type { GitFileStat } from "./types"
export function collectGitDiffStats(directory: string): GitFileStat[] {
try {
const diffOutput = execFileSync("git", ["diff", "--numstat", "HEAD"], {
cwd: directory,
encoding: "utf-8",
timeout: 5000,
stdio: ["pipe", "pipe", "pipe"],
}).trimEnd()
const statusOutput = execFileSync("git", ["status", "--porcelain"], {
cwd: directory,
encoding: "utf-8",
timeout: 5000,
stdio: ["pipe", "pipe", "pipe"],
}).trimEnd()
const untrackedOutput = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
cwd: directory,
encoding: "utf-8",
timeout: 5000,
stdio: ["pipe", "pipe", "pipe"],
}).trimEnd()
const untrackedNumstat = untrackedOutput
? untrackedOutput
.split("\n")
.filter(Boolean)
.map((filePath) => {
try {
const content = readFileSync(join(directory, filePath), "utf-8")
const lineCount = content.split("\n").length - (content.endsWith("\n") ? 1 : 0)
return `${lineCount}\t0\t${filePath}`
} catch {
return `0\t0\t${filePath}`
}
})
.join("\n")
: ""
const combinedNumstat = [diffOutput, untrackedNumstat].filter(Boolean).join("\n").trim()
if (!combinedNumstat) return []
const statusMap = parseGitStatusPorcelain(statusOutput)
return parseGitDiffNumstat(combinedNumstat, statusMap)
} catch {
return []
}
}