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 { Const } from "../../const";
import { Env } from "../../env";
import type { RepositoryServiceDeps } from "./types";
const makeIsFileInRepositoryPath: ServiceMethodFactory<
RepositoryServiceDeps,
[Repository, string, string[], string | undefined],
Promise<string[]>
> = ({ request }) => {
return async (repo, path, filesToMatch, ref = Const.DEFAULT_HEAD_REF) => {
if (path !== "" && path.endsWith("/") === false) {
throw new Error("Could not search for files in a non-tree blob.");
}
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 gitLsTreeProcess = spawn(
"git",
["ls-tree", "--name-only", `${ref}:${path}`],
{
cwd: repoPath,
env: {
LANG: "C",
},
}
);
const gitLsTreeResult = await new Promise<string>((resolve, reject) => {
let buffer = [] as string[];
gitLsTreeProcess.stdout.on("data", (data) => buffer.push(data));
gitLsTreeProcess.stderr.on("data", (data) => {
reject(new Error(Buffer.from(data).toString("utf-8")));
});
gitLsTreeProcess.stdout.on("close", () => {
resolve(buffer.join(""));
});
});
const files = gitLsTreeResult.split("\n");
return files.reduce((acc, currFile) => {
if (currFile.trim() !== "" && filesToMatch.includes(currFile)) {
acc = [...acc, currFile];
}
return acc;
}, [] as string[]);
} catch (_) {
return [];
}
};
};
export default makeIsFileInRepositoryPath;