import { existsSync } from "node:fs";
import { spawn } from "node:child_process";
import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
import type { Repository } from "@prisma/client";
import { Env } from "../../env";
import type { RepositoryLog } from "../../types";
import type { RepositoryServiceDeps } from "./types";
const makeGetRepositoryCommitLog: ServiceMethodFactory<
RepositoryServiceDeps,
[Repository, string | undefined, string | undefined, boolean | undefined],
Promise<RepositoryLog[]>
> = ({ request }) => {
return async (repo, path = "", ref = "HEAD", onlyLast = false) => {
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}".`
);
}
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}`);
}
var format =
"{%n ^@^commit^@^: ^@^%H^@^,%n ^@^abbreviated_commit^@^: ^@^%h^@^,%n ^@^tree^@^: ^@^%T^@^,%n ^@^abbreviated_tree^@^: ^@^%t^@^,%n ^@^parent^@^: ^@^%P^@^,%n ^@^abbreviated_parent^@^: ^@^%p^@^,%n ^@^refs^@^: ^@^%D^@^,%n ^@^encoding^@^: ^@^%e^@^,%n ^@^subject^@^: ^@^%s^@^,%n ^@^sanitized_subject_line^@^: ^@^%f^@^,%n ^@^body^@^: ^@^%b^@^,%n ^@^commit_notes^@^: ^@^%N^@^,%n ^@^verification_flag^@^: ^@^%G?^@^,%n ^@^signer^@^: ^@^%GS^@^,%n ^@^signer_key^@^: ^@^%GK^@^,%n ^@^author^@^: {%n ^@^name^@^: ^@^%aN^@^,%n ^@^email^@^: ^@^%aE^@^,%n ^@^date^@^: ^@^%aD^@^%n },%n ^@^commiter^@^: {%n ^@^name^@^: ^@^%cN^@^,%n ^@^email^@^: ^@^%cE^@^,%n ^@^date^@^: ^@^%cD^@^%n }%n},";
const args = [
"log",
"--quiet",
`--pretty=format:${format}`,
onlyLast ? "-1" : null,
ref,
path != null && path.trim() !== "" ? "--" : null,
path != null && path.trim() !== "" ? "-p" : null,
path != null && path.trim() !== "" ? `${path}` : null,
].filter((x): x is string => x != null);
const gitLogProcess = spawn("git", args, {
cwd: repoPath,
});
const gitLogResult = await new Promise<RepositoryLog[]>(
(resolve, reject) => {
let buffer = [] as string[];
gitLogProcess.stdout.on("data", (data) => buffer.push(data));
gitLogProcess.stderr.on("data", (data) => {
reject(new Error(Buffer.from(data).toString("utf-8")));
});
gitLogProcess.stdout.on("close", () => {
const escapedJson = buffer
.join("")
.replace(/\n\^@\^/g, "\\n^@^")
.replace(/"/gm, '\\"')
.replace(/\^@\^/gm, '"');
resolve(
JSON.parse(`[${escapedJson.substring(0, escapedJson.length - 1)}]`)
);
});
}
);
return gitLogResult as RepositoryLog[];
};
};
export default makeGetRepositoryCommitLog;