import { describe, expect, it } from "vitest"; import { buildCloneArgs, validateSparsePath } from "../clone"; describe("git-safe sparse clone planning", () => { it("keeps current shallow no-checkout clone without sparse", () => { expect(buildCloneArgs("https://x/repo.git", "/tmp/repo", {})).toEqual([ "clone", "--no-checkout", "--depth", "1", "--single-branch", "-c", "core.symlinks=false", "https://x/repo.git", "/tmp/repo", ]); }); it("adds partial clone and sparse checkout flags when sparse paths exist", () => { expect( buildCloneArgs("https://x/repo.git", "/tmp/repo", { branch: "main", sparse: ["docs", "src/web"], }), ).toEqual([ "clone", "--no-checkout", "--depth", "1", "--single-branch", "--filter=blob:none", "--sparse", "-c", "core.symlinks=false", "--branch", "main", "https://x/repo.git", "/tmp/repo", ]); }); it("rejects sparse traversal and absolute paths", () => { expect(() => validateSparsePath("docs")).not.toThrow(); expect(() => validateSparsePath("../secrets")).toThrow( /unsafe sparse path/, ); expect(() => validateSparsePath("/etc")).toThrow(/unsafe sparse path/); }); });