Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@
"@graphql-codegen/cli": "^7.1.2",
"@tsconfig/node22": "^22.0.5",
"@types/node": "^25.9.1",
"fs-fixture": "^2.14.0",
"oxfmt": "^0.53.0",
"oxlint": "^1.68.0",
"oxlint-tsgolint": "^0.23.0",
"pino": "^9.3.2",
"pino-pretty": "^11.2.2",
"publint": "^0.3.21",
"tinyexec": "^1.2.4",
"tsdown": "^0.22.1",
"typescript": "^6.0.3",
"vitest": "^4.1.8"
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 25 additions & 20 deletions src/fs.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
import { promises as fs } from "fs";
import * as path from "path";
import { commitFilesFromBase64 } from "./core.ts";
import type {
CommitFilesFromBuffersArgs,
CommitFilesFromBase64Args,
CommitFilesFromDirectoryArgs,
CommitFilesResult,
} from "./interface.ts";
import { commitFilesFromBuffers } from "./node.ts";

export const commitFilesFromDirectory = async ({
export async function commitFilesFromDirectory({
cwd,
fileChanges,
...otherArgs
}: CommitFilesFromDirectoryArgs): Promise<CommitFilesResult> => {
const additions: CommitFilesFromBuffersArgs["fileChanges"]["additions"] =
await Promise.all(
(fileChanges.additions || []).map(async (p) => {
return {
path: p,
contents: await fs.readFile(path.join(cwd, p)),
};
}),
);

return commitFilesFromBuffers({
}: CommitFilesFromDirectoryArgs): Promise<CommitFilesResult> {
return await commitFilesFromBase64({
...otherArgs,
fileChanges: {
additions,
deletions: fileChanges.deletions,
},
fileChanges: await normalizeFileChanges(fileChanges, cwd),
});
};
}

// Exported for testing only
export async function normalizeFileChanges(
fileChanges: CommitFilesFromDirectoryArgs["fileChanges"],
cwd: string,
): Promise<CommitFilesFromBase64Args["fileChanges"]> {
return {
additions: fileChanges.additions
? await Promise.all(
fileChanges.additions.map(async (a) => ({
path: a,
contents: await fs.readFile(path.join(cwd, a), "base64"),
})),
)
: undefined,
deletions: fileChanges.deletions?.map((d) => ({ path: d })),
};
}
52 changes: 31 additions & 21 deletions src/git.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { promises as fs } from "fs";
import { relative, resolve } from "path";
import git from "isomorphic-git";
import { commitFilesFromBase64 } from "./core.ts";
import type {
CommitChangesFromRepoArgs,
CommitFilesFromBuffersArgs,
CommitFilesFromBase64Args,
CommitFilesResult,
} from "./interface.ts";
import { commitFilesFromBuffers } from "./node.ts";

/**
* @see https://isomorphic-git.org/docs/en/walk#walkerentry-mode
Expand All @@ -23,7 +23,6 @@ export const commitChangesFromRepo = async ({
cwd: workingDirectory,
recursivelyFindRoot = true,
filterFiles,
log,
...otherArgs
}: CommitChangesFromRepoArgs): Promise<CommitFilesResult> => {
const ref = base?.commit ?? "HEAD";
Expand All @@ -44,6 +43,27 @@ export const commitChangesFromRepo = async ({
throw new Error(`Could not determine oid for ${ref}`);
}

return await commitFilesFromBase64({
...otherArgs,
fileChanges: await getFileChanges(
workingDirectory,
repoRoot,
oid,
filterFiles,
),
base: {
commit: oid,
},
});
};

// Exported for testing only
export async function getFileChanges(
cwd: string,
repoRoot: string,
ref: string,
filterFiles?: CommitChangesFromRepoArgs["filterFiles"],
): Promise<CommitFilesFromBase64Args["fileChanges"]> {
/**
* The directory to add files from. This is relative to the repository
* root, and is used to filter files.
Expand All @@ -52,13 +72,10 @@ export const commitChangesFromRepo = async ({
cwd === repoRoot ? null : relative(repoRoot, cwd) + "/";

// Determine changed files
const trees = [git.TREE({ ref: oid }), git.WORKDIR()];
const additions: CommitFilesFromBuffersArgs["fileChanges"]["additions"] = [];
const deletions: CommitFilesFromBuffersArgs["fileChanges"]["deletions"] = [];
const fileChanges = {
additions,
deletions,
};
const trees = [git.TREE({ ref }), git.WORKDIR()];
const additions: CommitFilesFromBase64Args["fileChanges"]["additions"] = [];
const deletions: CommitFilesFromBase64Args["fileChanges"]["deletions"] = [];

await git.walk({
fs,
dir: repoRoot,
Expand Down Expand Up @@ -115,7 +132,7 @@ export const commitChangesFromRepo = async ({
}
if (!workdir) {
// File was deleted
deletions.push(filepath);
deletions.push({ path: filepath });
return null;
} else {
// File was added / updated
Expand All @@ -125,19 +142,12 @@ export const commitChangesFromRepo = async ({
}
additions.push({
path: filepath,
contents: Buffer.from(arr),
contents: Buffer.from(arr).toString("base64"),
});
}
return true;
},
});

return commitFilesFromBuffers({
...otherArgs,
fileChanges,
log,
base: {
commit: oid,
},
});
};
return { additions, deletions };
}
30 changes: 19 additions & 11 deletions src/node.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { commitFilesFromBase64 } from "./core.js";
import type {
CommitFilesFromBase64Args,
CommitFilesFromBuffersArgs,
CommitFilesResult,
} from "./interface.ts";

export const commitFilesFromBuffers = async ({
export async function commitFilesFromBuffers({
fileChanges,
...otherArgs
}: CommitFilesFromBuffersArgs): Promise<CommitFilesResult> => {
return commitFilesFromBase64({
}: CommitFilesFromBuffersArgs): Promise<CommitFilesResult> {
return await commitFilesFromBase64({
...otherArgs,
fileChanges: {
additions: fileChanges.additions?.map(({ path, contents }) => ({
path,
contents: contents.toString("base64"),
})),
deletions: fileChanges.deletions?.map((path) => ({ path })),
},
fileChanges: normalizeFileChanges(fileChanges),
});
};
}

// Exported for testing only
export function normalizeFileChanges(
fileChanges: CommitFilesFromBuffersArgs["fileChanges"],
): CommitFilesFromBase64Args["fileChanges"] {
return {
additions: fileChanges.additions?.map((a) => ({
path: a.path,
contents: a.contents.toString("base64"),
})),
deletions: fileChanges.deletions?.map((d) => ({ path: d })),
};
}
38 changes: 38 additions & 0 deletions tests/fs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createFixture } from "fs-fixture";
import { describe, expect, it } from "vitest";
import { normalizeFileChanges } from "../src/fs.ts";

describe("normalizeFileChanges", () => {
it("should convert file contents to base64", async () => {
await using fixture = await createFixture({
"foo.txt": "Hello, world!",
});

const result = await normalizeFileChanges(
{
additions: ["foo.txt"],
deletions: ["bar.txt"],
},
fixture.path,
);

expect(result).toEqual({
additions: [
{
path: "foo.txt",
contents: await fixture.readFile("foo.txt", "base64"),
},
],
deletions: [{ path: "bar.txt" }],
});
});

it("should pass through empty file changes", async () => {
const result = await normalizeFileChanges(
{ additions: [], deletions: [] },
"/",
);

expect(result).toEqual({ additions: [], deletions: [] });
});
});
Loading