diff --git a/src/shared/git-worktree/parse-status-porcelain-line.test.ts b/src/shared/git-worktree/parse-status-porcelain-line.test.ts new file mode 100644 index 00000000..e07b124d --- /dev/null +++ b/src/shared/git-worktree/parse-status-porcelain-line.test.ts @@ -0,0 +1,72 @@ +/// + +import { describe, expect, test } from "bun:test" +import { parseGitStatusPorcelainLine } from "./parse-status-porcelain-line" + +describe("parseGitStatusPorcelainLine", () => { + test("#given modified porcelain line #when parsing #then returns modified status", () => { + //#given + const line = " M src/a.ts" + + //#when + const result = parseGitStatusPorcelainLine(line) + + //#then + expect(result).toEqual({ filePath: "src/a.ts", status: "modified" }) + }) + + test("#given added porcelain line #when parsing #then returns added status", () => { + //#given + const line = "A src/b.ts" + + //#when + const result = parseGitStatusPorcelainLine(line) + + //#then + expect(result).toEqual({ filePath: "src/b.ts", status: "added" }) + }) + + test("#given untracked porcelain line #when parsing #then returns added status", () => { + //#given + const line = "?? src/c.ts" + + //#when + const result = parseGitStatusPorcelainLine(line) + + //#then + expect(result).toEqual({ filePath: "src/c.ts", status: "added" }) + }) + + test("#given deleted porcelain line #when parsing #then returns deleted status", () => { + //#given + const line = "D src/d.ts" + + //#when + const result = parseGitStatusPorcelainLine(line) + + //#then + expect(result).toEqual({ filePath: "src/d.ts", status: "deleted" }) + }) + + test("#given empty line #when parsing #then returns null", () => { + //#given + const line = "" + + //#when + const result = parseGitStatusPorcelainLine(line) + + //#then + expect(result).toBeNull() + }) + + test("#given malformed line without path #when parsing #then returns null", () => { + //#given + const line = " M " + + //#when + const result = parseGitStatusPorcelainLine(line) + + //#then + expect(result).toBeNull() + }) +}) diff --git a/src/shared/git-worktree/parse-status-porcelain-line.ts b/src/shared/git-worktree/parse-status-porcelain-line.ts new file mode 100644 index 00000000..321fd42b --- /dev/null +++ b/src/shared/git-worktree/parse-status-porcelain-line.ts @@ -0,0 +1,27 @@ +import type { GitFileStatus } from "./types" + +export interface ParsedGitStatusPorcelainLine { + filePath: string + status: GitFileStatus +} + +function toGitFileStatus(statusToken: string): GitFileStatus { + if (statusToken === "A" || statusToken === "??") return "added" + if (statusToken === "D") return "deleted" + return "modified" +} + +export function parseGitStatusPorcelainLine( + line: string, +): ParsedGitStatusPorcelainLine | null { + if (!line) return null + + const statusToken = line.substring(0, 2).trim() + const filePath = line.substring(3) + if (!filePath) return null + + return { + filePath, + status: toGitFileStatus(statusToken), + } +}