Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export function getUntrackedFiles(): string[] {
return out ? out.split("\n") : [];
}

function hasStringStdout(err: unknown): err is { stdout: string } {
export function hasStringStdout(err: unknown): err is { stdout: string } {
return (
typeof err === "object" && err !== null && "stdout" in err && typeof err.stdout === "string"
);
Expand Down
44 changes: 41 additions & 3 deletions packages/cli/src/routes/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,40 @@ import { eq } from "drizzle-orm";
import type { StageDb } from "../db/client.js";
import type { ChapterRunRow } from "../db/schema/chapter-run.js";
import { chapterRun } from "../db/schema/index.js";
import { buildDiffArgs } from "../git.js";
import { buildDiffArgs, hasStringStdout } from "../git.js";
import { SCOPE_KIND, WORKING_TREE_REF } from "../schema.js";
import type { Route } from "../server.js";
import { writeJson } from "./json.js";

const execFileAsync = promisify(execFile);

const MAX_FILE_BYTES = 5 * 1024 * 1024;
const MAX_DIFF_BYTES = 50 * 1024 * 1024;

async function buildUntrackedPatch(cwd: string): Promise<string> {
const { stdout } = await execFileAsync("git", ["ls-files", "--others", "--exclude-standard"], {
cwd,
encoding: "utf8",
});
const files = stdout.trim() ? stdout.trim().split("\n") : [];
if (files.length === 0) return "";

const patches: string[] = [];
for (const file of files) {
try {
await execFileAsync("git", ["diff", "--no-index", "--no-color", "--", "/dev/null", file], {
Comment thread
dastratakos marked this conversation as resolved.
Outdated
cwd,
encoding: "utf8",
maxBuffer: MAX_DIFF_BYTES,
});
} catch (err: unknown) {
if (hasStringStdout(err)) {
patches.push(err.stdout);
}
}
}
return patches.join("\n");
Comment thread
dastratakos marked this conversation as resolved.
Outdated
}
Comment thread
dastratakos marked this conversation as resolved.
Comment thread
dastratakos marked this conversation as resolved.

export function diffRoutes(db: StageDb): Route[] {
return [
Expand Down Expand Up @@ -47,11 +73,23 @@ export function diffRoutes(db: StageDb): Route[] {
run.scopeKind === SCOPE_KIND.COMMITTED ? "private, max-age=300" : "no-store";

try {
const { stdout: patch } = await execFileAsync("git", args, {
const { stdout: trackedPatch } = await execFileAsync("git", args, {
cwd: repoRoot,
encoding: "utf8",
maxBuffer: 50 * 1024 * 1024,
maxBuffer: MAX_DIFF_BYTES,
});

let patch = trackedPatch;
if (
run.scopeKind === SCOPE_KIND.WORKING_TREE &&
run.workingTreeRef === WORKING_TREE_REF.WORK
) {
const untrackedPatch = await buildUntrackedPatch(repoRoot);
if (untrackedPatch) {
patch = patch ? `${patch}\n${untrackedPatch}` : untrackedPatch;
}
}

const fileContents = await buildFileContents(run, repoRoot, patch);
const body: DiffResponse = { patch, fileContents };
res.writeHead(200, {
Expand Down
Loading