nix/scripts/common/bin/gitforge-url.ts

73 lines
2.1 KiB
TypeScript
Executable file

#!/usr/bin/env -S deno run --allow-read --allow-run --allow-net
import * as path from "https://deno.land/std@0.181.0/path/mod.ts";
// output the best guess URL for viewing the file at the current git revision in
// the git forge's web interface
// TODO: --help, -h menu
const file = Deno.args[0];
if (!file) {
console.error("No file argument provided");
Deno.exit(1);
}
async function cmdOutput(cmd: string[]) {
return new TextDecoder().decode(
await Deno.run({
cmd: cmd,
stdout: "piped",
})
.output(),
).trim();
}
type ForgeType = "gitlab" | "github" | "gitea";
function getForgeType(hostname: string): ForgeType {
if (hostname == "git.lyte.dev") {
return "gitea";
} else if (hostname.endsWith("github.com")) {
return "github";
} else {
return "gitlab";
}
}
function getUrl(repoRoot: string, remote: string, commit: string) {
try {
// try http remote
console.log(new URL(remote));
throw new Error("HTTP(S) remotes not implemented");
} catch {
const hostname = remote.split("@").slice(-1)[0].split(":")[0];
const forgeType = getForgeType(hostname);
let repoPath = remote.split(":")[1];
if (repoPath.endsWith(".git")) {
repoPath = repoPath.slice(0, -4);
}
let fileRepoPath = path.resolve(file);
if (fileRepoPath.startsWith(repoRoot)) {
fileRepoPath = fileRepoPath.slice(repoRoot.length + 1); // for the trailing slash
} else {
throw new Error(`File ${fileRepoPath} is not in repo at ${repoRoot}`);
}
switch (forgeType) {
case "gitlab":
return `https://${hostname}/${repoPath}/-/blob/${commit}/${fileRepoPath}`;
case "gitea":
return `https://${hostname}/${repoPath}/src/commit/${commit}/${fileRepoPath}`;
case "github":
return `https://${hostname}/${repoPath}/blob/${commit}/${fileRepoPath}`;
}
}
}
// TODO: cd to dir
const repoRoot = await cmdOutput(["git", "rev-parse", "--show-toplevel"]);
const remote = await cmdOutput(["git", "remote", "get-url", "origin"]);
const commit = await cmdOutput(["git", "rev-parse", "HEAD"]);
const url = getUrl(repoRoot, remote, commit);
console.log(url);