about summary refs log tree commit diff
path: root/pkgs/applications/version-management/sapling/gen-deps
blob: 3ff7e24916c1ba6dee370c3b2d0d90c848a657e2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ requests ])" nixpkgs-fmt

# vim: set syntax=python:

import hashlib
import json
import re
import struct
import subprocess

import requests

gen_file = "deps.nix"
repo = "facebook/sapling"
source_file = "eden/scm/setup.py"

# Fetch the latest stable release metadata from GitHub
latest = requests.get(f"https://api.github.com/repos/{repo}/releases/latest").text
latest = json.loads(latest)

# Find latest's git tag which corresponds to the Sapling version. Also needed
# is a hash of the version, so calculate that here. Taken from Sapling source
# `$root/eden/scm/setup_with_version.py`.
version = str(latest["tag_name"])
version_hash = str(
    struct.unpack(">Q", hashlib.sha1(version.encode("ascii")).digest()[:8])[0]
)

# Fetch the `setup.py` source and look for instances of assets being downloaded
# from files.pythonhosted.org.
source = requests.get(
    f"https://raw.githubusercontent.com/{repo}/{version}/{source_file}"
).text
matches = re.findall(
    r'(https://files\.pythonhosted\.org/packages/.*?/.*?/.*?/)(.*?)(-.*?)"', source
)

# For each matched asset URL, prefetch said asset and build the corresponding
# Nix code needed to call `fetchurl` and perform symlinks in the actual build.
assets = ""
links = ""
for m in matches:
    sha256 = (
        subprocess.Popen(
            ["nix-prefetch-url", "--type", "sha256", f"{m[0]}{m[1]}{m[2]}"],
            text=True,
            stdout=subprocess.PIPE,
        )
        .stdout.read()
        .strip()
    )
    assets += """  {} = fetchurl {{
    url = "{}{}{}";
    sha256 = "{}";
  }};\n""".format(
        m[1], m[0], m[1], m[2], sha256
    )
    links += "    ln -s ${{{}}} {}{}\n".format(m[1], m[1], m[2])
assets = assets.strip()
links = links.strip()

# Render an autogenerated Nix file with the fetched dependency and version
# information for import in the main derivation.
out = f"""
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# Generated by `gen-deps`

{{ lib, fetchurl }}:
let
  {assets}
in
{{
  links = ''
    {links}
  '';

  version = "{version}";

  versionHash = "{version_hash}";
}}
"""
with open(gen_file, "w+") as f:
    f.write(out.strip())

# Formamt the generated Nix file, which also serves as a syntax sanity check.
subprocess.run(["nixpkgs-fmt", gen_file], check=True)