import { existsSync } from "node:fs";
import { mkdir } from "node:fs/promises";
import { spawn } from "node:child_process";
import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
import type { Repository } from "@prisma/client";
import { Const } from "../../const";
import type { CreateRepositoryDTO, RepositoryServiceDeps } from "./types";
const makeCreateRepository: ServiceMethodFactory<
RepositoryServiceDeps,
[CreateRepositoryDTO],
Promise<Repository>
> = ({ request }) => {
return async ({ parentOrgSlug, repoSlug, repoData, repoInitFlags }) => {
const {
orgRepositoriesDir,
withBaseReadmeFile: _,
withLicense: __,
withLicenseKind: ___,
} = repoInitFlags;
const parentOrg = await request.prisma.organization.findUnique({
where: {
slug: parentOrgSlug,
},
});
if (parentOrg == null) {
throw new Error(
`Could not find the parent organization to create new repository in.`
);
}
console.log(
`[..] creating repository "${parentOrg.slug}/${repoSlug}" in database`
);
const newRepo = await request.prisma.repository.create({
data: {
...repoData,
organizationId: parentOrg.id,
slug: repoSlug,
},
});
console.log(
`[ok] created repository in database with id "${newRepo.id}" and slug "${parentOrg.slug}/${newRepo.slug}"!`
);
if (existsSync(orgRepositoriesDir.toString()) === false) {
console.log(`[..] creating organization directory...`);
await mkdir(orgRepositoriesDir.toString(), { recursive: true });
console.log(
`[ok] created organization directory in:`,
orgRepositoriesDir
);
}
console.log(
`[..] creating repository folder with "git init --bare --shared=group" in org directory:`,
orgRepositoriesDir
);
const gitInitBareRepoProcess = spawn(
"git",
[
"init",
"--bare",
`--initial-branch=${Const.PRIMARY_BRANCH_REF}`,
"--shared=group",
`${newRepo.slug}.git`,
],
{
cwd: orgRepositoriesDir.toString(),
env: {
LANG: "C",
},
}
);
const gitInitBareRepoResult = await new Promise<string>(
(resolve, reject) => {
let buffer = [] as string[];
gitInitBareRepoProcess.stdout.on("data", (data) => buffer.push(data));
gitInitBareRepoProcess.stderr.on("data", (data) => {
reject(new Error(Buffer.from(data).toString("utf-8")));
});
gitInitBareRepoProcess.stdout.on("close", () => {
resolve(buffer.join(""));
});
}
);
console.log(
`[ok] finished execution of "git init --bare --shared=group" with result:\n\t`,
gitInitBareRepoResult
);
return newRepo;
};
};
export default makeCreateRepository;