import { which } from "./path.ts";
import { execProcess } from "./process.ts";
import { join } from "../deno_ral/path.ts";
import { existsSync } from "../deno_ral/fs.ts";
import { isHttpUrl } from "./url.ts";
import { GitHubContext } from "./github-types.ts";
import { gitBranchExists } from "./git.ts";
export async function gitHubContext(dir: string) {
const context: GitHubContext = {
git: false,
repo: false,
};
context.git = !!(await which("git"));
if (context.git) {
context.repo = (await execProcess({
cmd: "git",
args: ["rev-parse"],
cwd: dir,
stdout: "piped",
stderr: "piped",
})).success;
if (context.repo) {
const result = await execProcess({
cmd: "git",
args: ["config", "--get", "remote.origin.url"],
cwd: dir,
stdout: "piped",
stderr: "piped",
});
if (result.success) {
context.originUrl = result.stdout?.trim();
const ghPagesRemote = await execProcess({
cmd: "git",
args: [
"ls-remote",
"--quiet",
"--exit-code",
"origin",
"gh-pages",
],
stdout: "piped",
stderr: "piped",
});
context.ghPagesRemote = ghPagesRemote.success;
if (!ghPagesRemote.success) {
if (ghPagesRemote.code === 2) {
context.ghPagesLocal = await gitBranchExists("gh-pages");
} else {
throw new Error(
`There is an error while retrieving information from remote 'origin'.\n Git error: ${ghPagesRemote.stderr}. \n Git status code: ${ghPagesRemote.code}.`,
);
}
}
context.siteUrl = siteUrl(
dir,
context.originUrl!,
);
const repo = repoInfo(context.originUrl!);
if (repo) {
context.repoUrl = repo.repoUrl;
context.organization = repo.organization;
context.repository = repo.repository;
}
}
}
}
return context;
}
const kGithubCom = "github.com";
const kGithubIo = "github.io";
const kGithubGitPattern = /^git@([^:]+):([^\/]+)\/(.+?)(?:\.git)?$/;
const kGithubHttpsPattern = /^https:\/\/([^\/]+)\/([^\/]+)\/(.+?)(?:\.git)?$/;
function repoInfo(originUrl: string) {
const match = originUrl?.match(kGithubGitPattern) ||
originUrl?.match(kGithubHttpsPattern);
if (match && match.includes(kGithubCom)) {
return {
repoUrl: `https://${match[1]}/${match[2]}/${match[3]}/`,
organization: match[2],
repository: match[3],
};
}
}
function siteUrl(
dir: string,
originUrl: string,
) {
const cname = join(dir, "CNAME");
if (existsSync(cname)) {
const url = Deno.readTextFileSync(cname).trim();
if (isHttpUrl(url)) {
return url;
} else {
return `https://${url}`;
}
} else {
const match = originUrl?.match(kGithubGitPattern) ||
originUrl?.match(kGithubHttpsPattern);
if (match && match.includes(kGithubCom)) {
const server = match[1].replace(kGithubCom, kGithubIo);
const domain = `${match[2]}.${server}`;
if (domain === match[3]) {
return `https://${domain}/`;
} else {
return `https://${domain}/${match[3]}/`;
}
}
}
}