Diffing
The diff method computes file-level and hunk-level differences, similar to git diff.
Working Tree vs Index
By default, diff compares the working tree against the index (staged snapshot):
// Modify a file
await layer.writeFile("/README.md", "# Updated Project\n\nNew content.");
// See what changed
const diffs = await repo.diff();
for (const entry of diffs) {
console.log(entry.path); // "README.md"
console.log(entry.type); // "modified"
}
Index vs HEAD (Staged Changes)
Pass { staged: true } to compare the index against the last commit:
// Stage a change
await repo.add("README.md");
// Diff staged changes
const stagedDiffs = await repo.diff({ staged: true });
for (const entry of stagedDiffs) {
console.log(entry.path, entry.type);
}
Diff Entry Structure
Each diff entry contains:
interface DiffEntry {
path: string;
type: "added" | "modified" | "deleted";
hunks: DiffHunk[];
}
Hunks
Each hunk represents a contiguous region of changes:
interface DiffHunk {
oldStart: number; // Line number in the old file
oldLines: number; // Number of lines in the old file
newStart: number; // Line number in the new file
newLines: number; // Number of lines in the new file
lines: DiffLine[];
}
interface DiffLine {
type: "context" | "add" | "delete";
content: string;
}
Reading Hunks
const diffs = await repo.diff();
for (const entry of diffs) {
console.log(`--- ${entry.path} ---`);
for (const hunk of entry.hunks) {
console.log(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`);
for (const line of hunk.lines) {
const prefix = line.type === "add" ? "+" : line.type === "delete" ? "-" : " ";
console.log(`${prefix} ${line.content}`);
}
}
}
Diff for Specific Files
const diffs = await repo.diff();
// Filter to a specific file
const readmeDiff = diffs.find((d) => d.path === "README.md");
if (readmeDiff) {
console.log(`${readmeDiff.hunks.length} hunks changed`);
}
Detecting New and Deleted Files
const diffs = await repo.diff();
const added = diffs.filter((d) => d.type === "added");
const deleted = diffs.filter((d) => d.type === "deleted");
const modified = diffs.filter((d) => d.type === "modified");
console.log(`${added.length} added, ${deleted.length} deleted, ${modified.length} modified`);
Full Example
import { createMemoryLayer } from "@catmint-fs/core";
import { initRepository } from "@catmint-fs/git";
const layer = createMemoryLayer();
const repo = await initRepository(layer);
const author = { name: "Alice", email: "alice@example.com" };
// Create initial content
await layer.writeFile("/hello.txt", "Hello\nWorld\n");
await repo.add("hello.txt");
await repo.commit({ message: "Add hello.txt", author });
// Modify the file
await layer.writeFile("/hello.txt", "Hello\nTypeScript\nWorld\n");
// Diff working tree
const diffs = await repo.diff();
const entry = diffs[0];
console.log(entry.path); // "hello.txt"
console.log(entry.hunks[0].lines);
// [
// { type: "context", content: "Hello" },
// { type: "add", content: "TypeScript" },
// { type: "context", content: "World" },
// ]
