Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1#!/usr/bin/env nix-shell 2#!nix-shell -i python -p nix 'python3.withPackages (pp: [ pp.requests ])' 3 4import json 5import os 6from pathlib import Path 7import sys 8import subprocess 9import requests 10 11USAGE = """Usage: {0} [ | plugin-name | plugin-file-path] 12 13eg. 14 {0} 15 {0} dprint-plugin-json 16 {0} /path/to/dprint-plugin-json.nix""" 17 18FILE_PATH = Path(os.path.realpath(__file__)) 19SCRIPT_DIR = FILE_PATH.parent 20 21pname = "" 22if len(sys.argv) > 1: 23 if "-help" in "".join(sys.argv): 24 print(USAGE.format(FILE_PATH.name)) 25 exit(0) 26 pname = sys.argv[1] 27else: 28 pname = os.environ.get("UPDATE_NIX_PNAME", "") 29 30 31# get sri hash for a url, no unpack 32def nix_prefetch_url(url, algo="sha256"): 33 hash = ( 34 subprocess.check_output(["nix-prefetch-url", "--type", algo, url]) 35 .decode("utf-8") 36 .rstrip() 37 ) 38 sri = ( 39 subprocess.check_output( 40 # split by space is enough for this command 41 "nix --extra-experimental-features nix-command " 42 f"hash convert --hash-algo {algo} --to sri {hash}".split(" ") 43 ) 44 .decode("utf-8") 45 .rstrip() 46 ) 47 return sri 48 49 50# json object to nix string 51def json_to_nix(jsondata): 52 # to quote strings, dumps twice does it 53 json_str = json.dumps(json.dumps(jsondata)) 54 return ( 55 subprocess.check_output( 56 "nix --extra-experimental-features nix-command eval " 57 f"--expr 'builtins.fromJSON ''{json_str}''' --impure | nixfmt", 58 shell=True, 59 ) 60 .decode("utf-8") 61 .rstrip() 62 ) 63 64 65# nix string to json object 66def nix_to_json(nixstr): 67 return json.loads( 68 subprocess.check_output( 69 f"nix --extra-experimental-features nix-command eval --json --expr '{nixstr}'", 70 shell=True, 71 ) 72 .decode("utf-8") 73 .rstrip() 74 ) 75 76 77# nixfmt a file 78def nixfmt(nixfile): 79 subprocess.run(["nixfmt", nixfile]) 80 81 82def get_update_url(plugin_url): 83 """Get a single plugin's update url given the plugin's url""" 84 85 # remove -version.wasm at the end 86 url = "-".join(plugin_url.split("-")[:-1]) 87 names = url.split("/")[3:] 88 # if single name then -> dprint/<name> 89 if len(names) == 1: 90 names.insert(0, "dprint") 91 return "https://plugins.dprint.dev/" + "/".join(names) + "/latest.json" 92 93 94def write_plugin_derivation(drv_attrs): 95 drv = f"{{ mkDprintPlugin }}: mkDprintPlugin {json_to_nix(drv_attrs)}" 96 filepath = SCRIPT_DIR / f"{drv_attrs["pname"]}.nix" 97 with open(filepath, "w+", encoding="utf8") as f: 98 f.write(drv) 99 nixfmt(filepath) 100 101 102def update_plugin_by_name(name): 103 """Update a single plugin by name""" 104 105 # allow passing in filename as well as pname 106 if name.endswith(".nix"): 107 name = Path(name[:-4]).name 108 try: 109 p = (SCRIPT_DIR / f"{name}.nix").read_text().replace("\n", "") 110 except OSError as e: 111 print(f"failed to update plugin {name}: error: {e}") 112 exit(1) 113 114 start_idx = p.find("mkDprintPlugin {") + len("mkDprintPlugin {") 115 p = nix_to_json("{" + p[start_idx:].strip()) 116 117 data = requests.get(p["updateUrl"]).json() 118 p["url"] = data["url"] 119 p["version"] = data["version"] 120 p["hash"] = nix_prefetch_url(data["url"]) 121 122 write_plugin_derivation(p) 123 124 125def update_plugins(): 126 """Update all the plugins""" 127 128 data = requests.get("https://plugins.dprint.dev/info.json").json()["latest"] 129 130 for e in data: 131 update_url = get_update_url(e["url"]) 132 pname = e["name"] 133 if "/" in e["name"]: 134 pname = pname.replace("/", "-") 135 drv_attrs = { 136 "url": e["url"], 137 "hash": nix_prefetch_url(e["url"]), 138 "updateUrl": update_url, 139 "pname": pname, 140 "version": e["version"], 141 "description": e["description"], 142 "initConfig": { 143 "configKey": e["configKey"], 144 "configExcludes": e["configExcludes"], 145 "fileExtensions": e["fileExtensions"], 146 }, 147 } 148 write_plugin_derivation(drv_attrs) 149 150 151if pname != "": 152 update_plugin_by_name(pname) 153else: 154 update_plugins()