diff --git a/ghjk.ts b/ghjk.ts index e525ee67..890c4cb2 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -26,11 +26,12 @@ import jco from "./plugs/jco.ts"; import mold from "./plugs/mold.ts"; import act from "./plugs/act.ts"; import asdf from "./plugs/asdf.ts"; +import protoc from "./plugs/protoc.ts"; // node({}); // wasmedge({}); // pnpm({}); -cargo_binstall({}); +// cargo_binstall({}); // wasm_tools({}); // wasm_opt({}); // cargo_insta({}); @@ -41,3 +42,4 @@ cargo_binstall({}); // plugRepo: "https://github.com/asdf-community/asdf-zig", // installType: "version", // }); +protoc({}); diff --git a/plugs/protoc.ts b/plugs/protoc.ts new file mode 100644 index 00000000..238c9950 --- /dev/null +++ b/plugs/protoc.ts @@ -0,0 +1,122 @@ +import { + addInstallGlobal, + depBinShimPath, + DownloadArgs, + downloadFile, + InstallArgs, + type InstallConfigBase, + type PlatformInfo, + PlugBase, + registerDenoPlugGlobal, + removeFile, + spawn, + std_fs, + std_path, + std_url, +} from "../plug.ts"; +import * as std_plugs from "../std.ts"; + +const manifest = { + name: "protoc@ghrel", + version: "0.1.0", + moduleSpecifier: import.meta.url, + deps: [ + std_plugs.unzip_aa, + ], +}; + +registerDenoPlugGlobal(manifest, () => new Plug()); + +export default function install(config: InstallConfigBase = {}) { + addInstallGlobal({ + plugName: manifest.name, + ...config, + }); +} + +const repoOwner = "protocolbuffers"; +const repoName = "protobuf"; +const repoAddress = `https://github.com/${repoOwner}/${repoName}`; + +export class Plug extends PlugBase { + manifest = manifest; + + async latestStable(): Promise { + const metadataRequest = await fetch( + `https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`, + ); + + const metadata = await metadataRequest.json() as { + tag_name: string; + }; + + return metadata.tag_name; + } + + async listAll() { + const metadataRequest = await fetch( + `https://api.github.com/repos/${repoOwner}/${repoName}/releases`, + ); + + const metadata = await metadataRequest.json() as [{ + tag_name: string; + }]; + + return metadata.map((rel) => rel.tag_name).reverse(); + } + + async download(args: DownloadArgs) { + await downloadFile(args, downloadUrl(args.installVersion, args.platform)); + } + + async install(args: InstallArgs) { + const fileName = std_url.basename( + downloadUrl(args.installVersion, args.platform), + ); + const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + + await spawn([ + depBinShimPath(std_plugs.unzip_aa, "unzip", args.depShims), + fileDwnPath, + "-d", + args.tmpDirPath, + ]); + + if (await std_fs.exists(args.installPath)) { + await removeFile(args.installPath, { recursive: true }); + } + + await std_fs.copy( + args.tmpDirPath, + args.installPath, + ); + } +} + +function downloadUrl(installVersion: string, platform: PlatformInfo) { + let os; + switch (platform.os) { + case "linux": + os = "linux"; + break; + case "darwin": + os = "osx"; + break; + default: + throw new Error(`unsupported os: ${platform.os}`); + } + let arch; + switch (platform.arch) { + case "x86_64": + arch = "x86_64"; + break; + case "aarch64": + arch = "aarch_64"; + break; + default: + throw new Error(`unsupported arch: ${platform.arch}`); + } + return `${repoAddress}/releases/download/${installVersion}/protoc-${ + installVersion.replace(/^v/, "") + }-${os}-${arch}.zip`; +} diff --git a/plugs/unzip.ts b/plugs/unzip.ts new file mode 100644 index 00000000..63f704ad --- /dev/null +++ b/plugs/unzip.ts @@ -0,0 +1,21 @@ +import { + addInstallGlobal, + type AmbientAccessPlugManifest, + registerAmbientPlugGlobal, +} from "../plug.ts"; + +export const manifest: AmbientAccessPlugManifest = { + name: "unzip@aa", + version: "0.1.0", + execName: "unzip", + versionExtractFlag: "-v", + versionExtractRegex: "(\\d+\\.\\d+)", + versionExtractRegexFlags: "", +}; + +registerAmbientPlugGlobal(manifest); +export default function install() { + addInstallGlobal({ + plugName: manifest.name, + }); +} diff --git a/std.ts b/std.ts index db26bdd1..636593dd 100644 --- a/std.ts +++ b/std.ts @@ -5,6 +5,7 @@ import validators from "./core/validators.ts"; import { manifest as man_tar_aa } from "./plugs/tar.ts"; import { manifest as man_git_aa } from "./plugs/git.ts"; import { manifest as man_curl_aa } from "./plugs/curl.ts"; +import { manifest as man_unzip_aa } from "./plugs/unzip.ts"; import { manifest as man_cbin_ghrel } from "./plugs/cargo-binstall.ts"; import { manifest as man_node_org } from "./plugs/node.ts"; import { manifest as man_pnpm_ghrel } from "./plugs/pnpm.ts"; @@ -13,6 +14,7 @@ const aaPlugs: RegisteredPlug[] = [ man_tar_aa, man_git_aa, man_curl_aa, + man_unzip_aa, ] .map((man) => ({ ty: "ambientAccess", @@ -48,6 +50,10 @@ export const curl_aa = Object.freeze({ id: man_curl_aa.name, } as PlugDep); +export const unzip_aa = Object.freeze({ + id: man_unzip_aa.name, +} as PlugDep); + export const cbin_ghrel = Object.freeze({ id: man_cbin_ghrel.name, } as PlugDep); diff --git a/tests/ambient.ts b/tests/ambient.ts index 5b0ee113..d9a56c07 100644 --- a/tests/ambient.ts +++ b/tests/ambient.ts @@ -6,6 +6,7 @@ import { type AmbientAccessPlugManifest } from "../core/types.ts"; import * as tar from "../plugs/tar.ts"; import * as git from "../plugs/git.ts"; import * as curl from "../plugs/curl.ts"; +import * as unzip from "../plugs/unzip.ts"; const manifests = [ { @@ -19,6 +20,7 @@ const manifests = [ tar.manifest, git.manifest, curl.manifest, + unzip.manifest, ]; for (const manifest of manifests) { Deno.test(`ambient access ${manifest.name}`, async () => {