about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/web/deno/update
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/development/web/deno/update')
-rw-r--r--nixpkgs/pkgs/development/web/deno/update/common.ts52
-rw-r--r--nixpkgs/pkgs/development/web/deno/update/deps.ts79
-rw-r--r--nixpkgs/pkgs/development/web/deno/update/src.ts67
-rwxr-xr-xnixpkgs/pkgs/development/web/deno/update/update.ts50
4 files changed, 248 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/web/deno/update/common.ts b/nixpkgs/pkgs/development/web/deno/update/common.ts
new file mode 100644
index 000000000000..71e4d638f8d7
--- /dev/null
+++ b/nixpkgs/pkgs/development/web/deno/update/common.ts
@@ -0,0 +1,52 @@
+interface GHRelease {
+  tag_name: string;
+}
+
+const decode = (buffer: Uint8Array) => new TextDecoder("utf-8").decode(buffer);
+const run = async (command: string, args: string[]) => {
+  const cmd = Deno.run(
+    { cmd: [command, ...args], stdout: "piped", stderr: "piped" },
+  );
+  if (!(await cmd.status()).success) {
+    throw await cmd.stderrOutput().then((b) => decode(b));
+  }
+  return cmd.output().then((b) => decode(b).trimEnd());
+};
+
+// Exports
+export const versionRegExp = /\d+\.\d+\.\d+/;
+export const sha256RegExp = /[a-z0-9]{52}/;
+
+export async function commit(
+  name: string,
+  oldVer: string,
+  newVer: string,
+  files: string[],
+) {
+  await run("git", ["add", ...files]);
+  await run("git", ["commit", "-m", `${name}: ${oldVer} -> ${newVer}`]);
+}
+
+export const getExistingVersion = async (filePath: string) =>
+  read(filePath).then((s) =>
+    s.match(genValueRegExp("version", versionRegExp))?.shift() || ""
+  );
+
+export const getLatestVersion = (owner: string, repo: string) =>
+  fetch(`https://api.github.com/repos/${owner}/${repo}/releases`)
+    .then((res) => res.json())
+    .then((res: GHRelease[]) => res[0].tag_name);
+
+// The (?<=) and (?=) allow replace to only change inside
+// Match the regex passed in or empty
+export const genValueRegExp = (key: string, regex: RegExp) =>
+  new RegExp(`(?<=${key} = ")(${regex.source}|)(?=")`);
+
+export const logger = (name: string) =>
+  (...a: any) => console.log(`[${name}]`, ...a);
+
+export const nixPrefetch = (args: string[]) => run("nix-prefetch", args);
+export const nixPrefetchURL = (args: string[]) => run("nix-prefetch-url", args);
+
+export const read = Deno.readTextFile;
+export const write = Deno.writeTextFile;
diff --git a/nixpkgs/pkgs/development/web/deno/update/deps.ts b/nixpkgs/pkgs/development/web/deno/update/deps.ts
new file mode 100644
index 000000000000..beedeade3a86
--- /dev/null
+++ b/nixpkgs/pkgs/development/web/deno/update/deps.ts
@@ -0,0 +1,79 @@
+import {
+  getExistingVersion,
+  genValueRegExp,
+  logger,
+  nixPrefetchURL,
+  versionRegExp,
+  write,
+} from "./common.ts";
+
+const log = logger("deps");
+
+export interface Architecture {
+  nix: string;
+  rust: string;
+}
+interface PrefetchResult {
+  arch: Architecture;
+  sha256: string;
+}
+
+const getRustyV8Version = async (
+  owner: string,
+  repo: string,
+  version: string,
+) =>
+  fetch(
+    `https://github.com/${owner}/${repo}/raw/${version}/core/Cargo.toml`,
+  )
+    .then((res) => res.text())
+    .then((txt) =>
+      txt.match(genValueRegExp("rusty_v8", versionRegExp))?.shift()
+    );
+
+const archShaTasks = (version: string, arches: Architecture[]) =>
+  arches.map(async (arch: Architecture): Promise<PrefetchResult> => {
+    log("Fetching:", arch.nix);
+    const sha256 = await nixPrefetchURL(
+      [`https://github.com/denoland/rusty_v8/releases/download/v${version}/librusty_v8_release_${arch.rust}.a`],
+    );
+    log("Done:    ", arch.nix);
+    return { arch, sha256 };
+  });
+
+const templateDeps = (version: string, deps: PrefetchResult[]) =>
+  `# auto-generated file -- DO NOT EDIT!
+{}:
+rec {
+  rustyV8Lib = {
+    version = "${version}";
+    sha256s = {
+${deps.map((d) => `      ${d.arch.nix} = "${d.sha256}";`).join("\n")}
+    };
+  };
+}
+`;
+
+export async function updateDeps(
+  filePath: string,
+  owner: string,
+  repo: string,
+  denoVersion: string,
+  arches: Architecture[],
+) {
+  log("Starting deps update");
+  // 0.0.0
+  const version = await getRustyV8Version(owner, repo, denoVersion);
+  if (typeof version !== "string") {
+    throw "no rusty_v8 version";
+  }
+  log("rusty_v8 version:", version);
+  const existingVersion = await getExistingVersion(filePath);
+  if (version === existingVersion) {
+    log("Version already matches latest, skipping...");
+    return;
+  }
+  const archShaResults = await Promise.all(archShaTasks(version, arches));
+  await write(filePath, templateDeps(version, archShaResults));
+  log("Finished deps update");
+}
diff --git a/nixpkgs/pkgs/development/web/deno/update/src.ts b/nixpkgs/pkgs/development/web/deno/update/src.ts
new file mode 100644
index 000000000000..fae15acd0d2c
--- /dev/null
+++ b/nixpkgs/pkgs/development/web/deno/update/src.ts
@@ -0,0 +1,67 @@
+import {
+  genValueRegExp,
+  logger,
+  nixPrefetch,
+  read,
+  sha256RegExp,
+  versionRegExp,
+  write,
+} from "./common.ts";
+
+interface Replacer {
+  regex: RegExp;
+  value: string;
+}
+
+const log = logger("src");
+
+const prefetchSha256 = (nixpkgs: string, version: string) =>
+  nixPrefetch(["-f", nixpkgs, "deno.src", "--rev", version]);
+const prefetchCargoSha256 = (nixpkgs: string) =>
+  nixPrefetch(
+    [`{ sha256 }: (import ${nixpkgs} {}).deno.cargoDeps.overrideAttrs (_: { outputHash = sha256; })`],
+  );
+
+const replace = (str: string, replacers: Replacer[]) =>
+  replacers.reduce(
+    (str, r) => str.replace(r.regex, r.value),
+    str,
+  );
+
+const updateNix = (filePath: string, replacers: Replacer[]) =>
+  read(filePath).then((str) => write(filePath, replace(str, replacers)));
+
+const genVerReplacer = (k: string, value: string): Replacer => (
+  { regex: genValueRegExp(k, versionRegExp), value }
+);
+const genShaReplacer = (k: string, value: string): Replacer => (
+  { regex: genValueRegExp(k, sha256RegExp), value }
+);
+
+export async function updateSrc(
+  filePath: string,
+  nixpkgs: string,
+  denoVersion: string,
+) {
+  log("Starting src update");
+  const trimVersion = denoVersion.substr(1);
+  log("Fetching sha256 for:", trimVersion);
+  const sha256 = await prefetchSha256(nixpkgs, denoVersion);
+  log("sha256 to update:", sha256);
+  await updateNix(
+    filePath,
+    [
+      genVerReplacer("version", trimVersion),
+      genShaReplacer("sha256", sha256),
+      genShaReplacer("cargoSha256", ""), // Empty ready for prefetchCargoSha256
+    ],
+  );
+  log("Fetching cargoSha256 for:", sha256);
+  const cargoSha256 = await prefetchCargoSha256(nixpkgs);
+  log("cargoSha256 to update:", cargoSha256);
+  await updateNix(
+    filePath,
+    [genShaReplacer("cargoSha256", cargoSha256)],
+  );
+  log("Finished src update");
+}
diff --git a/nixpkgs/pkgs/development/web/deno/update/update.ts b/nixpkgs/pkgs/development/web/deno/update/update.ts
new file mode 100755
index 000000000000..18d451480137
--- /dev/null
+++ b/nixpkgs/pkgs/development/web/deno/update/update.ts
@@ -0,0 +1,50 @@
+#!/usr/bin/env nix-shell
+/*
+#!nix-shell -i "deno run --allow-net --allow-run --allow-read --allow-write" -p deno git nix-prefetch
+*/
+import {
+  commit,
+  getExistingVersion,
+  getLatestVersion,
+  logger,
+} from "./common.ts";
+import { Architecture, updateDeps } from "./deps.ts";
+import { updateSrc } from "./src.ts";
+
+const log = logger("update");
+// TODO: Getting current file position to more-safely point to nixpkgs root
+const nixpkgs = Deno.cwd();
+// TODO: Read values from default.nix
+const owner = "denoland";
+const repo = "deno";
+const denoDir = `${nixpkgs}/pkgs/development/web/${repo}`;
+const src = `${denoDir}/default.nix`;
+const deps = `${denoDir}/deps.nix`;
+const architectures: Architecture[] = [
+  { nix: "x86_64-linux", rust: "x86_64-unknown-linux-gnu" },
+  { nix: "aarch64-linux", rust: "aarch64-unknown-linux-gnu" },
+  { nix: "x86_64-darwin", rust: "x86_64-apple-darwin" },
+];
+
+log("Updating deno");
+
+log("Getting latest deno version");
+const version = await getLatestVersion(owner, repo);
+const existingVersion = await getExistingVersion(src);
+const trimVersion = version.substr(1); // Strip v from v0.0.0
+log("Latest version:   ", trimVersion);
+log("Extracted version:", existingVersion);
+if (trimVersion === existingVersion) {
+  log("Version already matches latest, skipping...");
+  Deno.exit(0);
+}
+
+const tasks = [
+  updateSrc(src, nixpkgs, version),
+  updateDeps(deps, owner, repo, version, architectures),
+];
+await Promise.all(tasks);
+log("Updating deno complete");
+log("Commiting");
+await commit(repo, existingVersion, trimVersion, [src, deps]);
+log("Done");