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 type { RepositoryFileContent } from "../../types";
import { Const } from "../../const";
import { Env } from "../../env";
import type { RepositoryServiceDeps } from "./types";
const makeGetRepositoryFileContentBase64: ServiceMethodFactory<
RepositoryServiceDeps,
[Repository, string, string | undefined],
Promise<null | RepositoryFileContent>
> = ({ request }) => {
return async (repo, path, ref = Const.DEFAULT_HEAD_REF) => {
if (path.endsWith("/")) {
throw new Error("Could not retrieve file content for a folder.");
}
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 gitCatFileProcess = spawn(
"git",
["cat-file", "-p", `${ref}:${path}`],
{
cwd: repoPath,
env: {
LANG: "C",
},
}
);
const base64FileProcess = spawn("base64", [], {
cwd: repoPath,
stdio: [gitCatFileProcess.stdout, "pipe"],
env: {
LANG: "C",
},
});
const gitCatFileResult = await new Promise<string>((resolve, reject) => {
let buffer = [] as string[];
base64FileProcess.stdout?.on("data", (data) => buffer.push(data));
base64FileProcess.stderr?.on("data", (data) => {
reject(new Error(Buffer.from(data).toString("utf-8")));
});
base64FileProcess.stdout?.on("close", () => {
resolve(buffer.join(""));
});
});
const { mimeType } =
await request.codeAnalysisService.getLinguistFileInfos(
path,
gitCatFileResult
);
return {
content: `data:${mimeType};base64,${gitCatFileResult}`,
mimeType,
};
} catch (_) {
console.error("err:", _);
return null;
}
};
};
export default makeGetRepositoryFileContentBase64;