at 18.09-beta 131 lines 3.9 kB view raw
1#!/usr/bin/env nix-shell 2#!nix-shell -p nix -p python3 -p git -i python 3# USAGE - just run the script: ./update.py 4# When editing this file, make also sure it passes the mypy typecheck 5# and is formatted with black. 6import fileinput 7import json 8import re 9import subprocess 10import tempfile 11import urllib.request 12from datetime import datetime 13from pathlib import Path 14from typing import Dict 15 16 17def sh(*args: str) -> str: 18 out = subprocess.check_output(list(args)) 19 return out.strip().decode("utf-8") 20 21 22def prefetch_github(owner: str, repo: str, ref: str) -> str: 23 return sh( 24 "nix-prefetch-url", 25 "--unpack", 26 f"https://github.com/{owner}/{repo}/archive/{ref}.tar.gz", 27 ) 28 29 30def get_radare2_rev() -> str: 31 url = "https://api.github.com/repos/radare/radare2/releases/latest" 32 with urllib.request.urlopen(url) as response: 33 release = json.load(response) # type: ignore 34 return release["tag_name"] 35 36 37def get_r2_cutter_rev() -> str: 38 url = "https://api.github.com/repos/radareorg/cutter/contents/" 39 with urllib.request.urlopen(url) as response: 40 data = json.load(response) # type: ignore 41 for entry in data: 42 if entry["name"] == "radare2": 43 return entry["sha"] 44 raise Exception("no radare2 submodule found in github.com/radareorg/cutter") 45 46 47def git(dirname: str, *args: str) -> str: 48 return sh("git", "-C", dirname, *args) 49 50 51def get_repo_info(dirname: str, rev: str) -> Dict[str, str]: 52 sha256 = prefetch_github("radare", "radare2", rev) 53 54 cs_tip = None 55 with open(Path(dirname).joinpath("shlr", "Makefile")) as makefile: 56 for l in makefile: 57 match = re.match("CS_TIP=(\S+)", l) 58 if match: 59 cs_tip = match.group(1) 60 assert cs_tip is not None 61 62 cs_sha256 = prefetch_github("aquynh", "capstone", cs_tip) 63 64 return dict( 65 rev=rev, 66 sha256=sha256, 67 version_commit=git(dirname, "rev-list", "--all", "--count"), 68 gittap=git(dirname, "describe", "--tags", "--match", "[0-9]*"), 69 gittip=git(dirname, "rev-parse", "HEAD"), 70 cs_tip=cs_tip, 71 cs_sha256=cs_sha256, 72 ) 73 74 75def write_package_expr(version: str, info: Dict[str, str]) -> str: 76 return f"""generic {{ 77 version_commit = "{info["version_commit"]}"; 78 gittap = "{info["gittap"]}"; 79 gittip = "{info["gittip"]}"; 80 rev = "{info["rev"]}"; 81 version = "{version}"; 82 sha256 = "{info["sha256"]}"; 83 cs_tip = "{info["cs_tip"]}"; 84 cs_sha256 = "{info["cs_sha256"]}"; 85 }}""" 86 87 88def main() -> None: 89 radare2_rev = get_radare2_rev() 90 r2_cutter_rev = get_r2_cutter_rev() 91 92 with tempfile.TemporaryDirectory() as dirname: 93 git( 94 dirname, 95 "clone", 96 "--branch", 97 radare2_rev, 98 "https://github.com/radare/radare2", 99 ".", 100 ) 101 nix_file = str(Path(__file__).parent.joinpath("default.nix")) 102 103 radare2_info = get_repo_info(dirname, radare2_rev) 104 105 git(dirname, "checkout", r2_cutter_rev) 106 107 timestamp = git(dirname, "log", "-n1", "--format=%at") 108 r2_cutter_version = datetime.fromtimestamp(int(timestamp)).strftime("%Y-%m-%d") 109 110 r2_cutter_info = get_repo_info(dirname, r2_cutter_rev) 111 112 in_block = False 113 with fileinput.FileInput(nix_file, inplace=True) as f: 114 for l in f: 115 if "#<generated>" in l: 116 in_block = True 117 print( 118 f""" #<generated> 119 # DO NOT EDIT! Automatically generated by ./update.py 120 radare2 = {write_package_expr(radare2_rev, radare2_info)}; 121 r2-for-cutter = {write_package_expr(r2_cutter_version, r2_cutter_info)}; 122 #</generated>""" 123 ) 124 elif "#</generated>" in l: 125 in_block = False 126 elif not in_block: 127 print(l, end="") 128 129 130if __name__ == "__main__": 131 main()