import { existsSync } from "node:fs";
import { spawn } from "node:child_process";
import { ServiceMethodFactory } from "@ethicdevs/react-monolith";
import parseDiff from "diffparser";
import type { Repository } from "@prisma/client";
import type { RepositoryFileDiff } from "../../types";
import { Env } from "../../env";
import { RepositoryServiceDeps } from "./types";
const makeGetRepositoryRefDiff: ServiceMethodFactory<
RepositoryServiceDeps,
[Repository, string, string | undefined],
Promise<RepositoryFileDiff[]>
> = ({ request }) => {
return async (repo, refA, refB = undefined) => {
const parentOrg = await request.prisma.organization.findUnique({
where: {
id: repo.organizationId,
},
});
if (parentOrg == null) {
throw new Error(
`Could not find the parent organization for project "${repo.slug}".`
);
}
try {
const repoPath = `${Env.GIT_REPOSITORIES_ROOT}/${parentOrg.slug}/${repo.slug}.git`;
if (existsSync(repoPath) === false) {
throw new Error(
`Could not find a valid git repository at: ${repoPath}`
);
}
const gitDiffRefsProcess = spawn(
"git",
["diff", `${refB}${refA != null ? `..${refA}` : ""}`],
{
cwd: repoPath,
}
);
const gitDiffRefsResult = await new Promise<string>((resolve, reject) => {
let buffer = [] as string[];
gitDiffRefsProcess.stdout.on("data", (data) => buffer.push(data));
gitDiffRefsProcess.stderr.on("data", (data) => {
reject(new Error(Buffer.from(data).toString("utf-8")));
});
gitDiffRefsProcess.stdout.on("close", () => {
resolve(buffer.join(""));
});
});
return parseDiff(gitDiffRefsResult, { findRenames: true });
} catch (_) {
return [];
}
};
};
export default makeGetRepositoryRefDiff;