From b4e1a5e8ff97b524a856616f18fd3e0d3a5a150d Mon Sep 17 00:00:00 2001
From: Tom Prince <tom.prince@private.storage>
Date: Fri, 8 Oct 2021 15:16:00 -0600
Subject: [PATCH] Update PaymentServer.

---
 nixos/pkgs/zkapissuer/default.nix |  5 +-
 nixos/pkgs/zkapissuer/repo.json   |  8 +++
 nixos/pkgs/zkapissuer/repo.nix    |  7 ---
 tools/default.nix                 |  1 +
 tools/update-github-repo          | 89 +++++++++++++++++++++++++++++++
 5 files changed, 101 insertions(+), 9 deletions(-)
 create mode 100644 nixos/pkgs/zkapissuer/repo.json
 delete mode 100644 nixos/pkgs/zkapissuer/repo.nix
 create mode 100644 tools/update-github-repo

diff --git a/nixos/pkgs/zkapissuer/default.nix b/nixos/pkgs/zkapissuer/default.nix
index b4f90d35..efa55ff1 100644
--- a/nixos/pkgs/zkapissuer/default.nix
+++ b/nixos/pkgs/zkapissuer/default.nix
@@ -1,6 +1,7 @@
-{ callPackage }:
+{ callPackage, fetchFromGitHub, lib }:
 let
-  repo = callPackage ./repo.nix { };
+  repo-data = lib.importJSON ./repo.json;
+  repo = fetchFromGitHub (builtins.removeAttrs repo-data [ "branch" ]);
   PaymentServer = (import "${repo}/nix").PaymentServer;
 in
   PaymentServer.components.exes."PaymentServer-exe"
diff --git a/nixos/pkgs/zkapissuer/repo.json b/nixos/pkgs/zkapissuer/repo.json
new file mode 100644
index 00000000..0a003dc6
--- /dev/null
+++ b/nixos/pkgs/zkapissuer/repo.json
@@ -0,0 +1,8 @@
+{
+  "owner": "PrivateStorageio",
+  "repo": "PaymentServer",
+  "rev": "e080beb14ec58ffe8e55c35e6dddd46c5082887f",
+  "branch": "main",
+  "outputHashAlgo": "sha256",
+  "outputHash": "1zck9kawbs2lkr3qjipira9gawa4gxlqijqqjrmlvvyp9mr0fgxm"
+}
diff --git a/nixos/pkgs/zkapissuer/repo.nix b/nixos/pkgs/zkapissuer/repo.nix
deleted file mode 100644
index 6646a2e3..00000000
--- a/nixos/pkgs/zkapissuer/repo.nix
+++ /dev/null
@@ -1,7 +0,0 @@
-{ fetchFromGitHub }:
-fetchFromGitHub {
-  owner = "PrivateStorageio";
-  repo = "PaymentServer";
-  rev = "ff30e85c231a3b5ad76426bbf8801f8f76884367";
-  sha256 = "1spz19f5z96shmfpazj0rv6877xvchf3gl49a4xahjbbsz39x34x";
-}
diff --git a/tools/default.nix b/tools/default.nix
index fb44c660..b10bb5f2 100644
--- a/tools/default.nix
+++ b/tools/default.nix
@@ -16,6 +16,7 @@ let
   python-commands = [
     ./update-nixpkgs
     ./update-gitlab-repo
+    ./update-github-repo
   ];
 in
   # This derivation creates a package that wraps our tools to setup an environment
diff --git a/tools/update-github-repo b/tools/update-github-repo
new file mode 100644
index 00000000..0e7e1511
--- /dev/null
+++ b/tools/update-github-repo
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+
+"""
+Update a pinned github repository.
+
+Pass this path to a JSON file and it will update it to the latest
+version of the branch it specifies. You can also pass a different
+branch or repository owner, which will update the file to point at
+the new branch/repository, and update to the latest version.
+"""
+
+import argparse
+import json
+from pathlib import Path
+
+import httpx
+from ps_tools import get_url_hash
+
+HASH_TYPE = "sha512"
+
+ARCHIVE_TEMPLATE = "https://api.github.com/repos/{owner}/{repo}/tarball/{rev}"
+BRANCH_TEMPLATE = (
+    "https://api.github.com/repos/{owner}/{repo}/commits/{branch}"
+)
+
+
+def get_github_commit(config):
+    response = httpx.get(BRANCH_TEMPLATE.format(**config))
+    response.raise_for_status()
+    return response.json()["sha"]
+
+
+def get_github_archive_url(config):
+    return ARCHIVE_TEMPLATE.format(**config)
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument(
+        "repo_file",
+        metavar="repo-file",
+        type=Path,
+        help="JSON file with pinned configuration.",
+    )
+    parser.add_argument(
+        "--branch",
+        type=str,
+        help="Branch to update to.",
+    )
+    parser.add_argument(
+        "--owner",
+        type=str,
+        help="Repository owner to update to.",
+    )
+    parser.add_argument(
+        "--rev",
+        type=str,
+        help="Revision to pin.",
+    )
+    parser.add_argument(
+        "--dry-run",
+        action="store_true",
+    )
+    args = parser.parse_args()
+
+    repo_file = args.repo_file
+    config = json.loads(repo_file.read_text())
+
+    for key in ["owner", "branch"]:
+        if getattr(args, key) is not None:
+            config[key] = getattr(args, key)
+
+    if args.rev is not None:
+        config["rev"] = args.rev
+    else:
+        config["rev"] = get_github_commit(config)
+
+    archive_url = get_github_archive_url(config)
+    config.update(get_url_hash(HASH_TYPE, "source", archive_url))
+
+    output = json.dumps(config, indent=2)
+    if args.dry_run:
+        print(output)
+    else:
+        repo_file.write_text(output)
+
+
+if __name__ == "__main__":
+    main()
-- 
GitLab