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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
{ writePython3
, getBins
, requests
, nix
, gnutar
, git
}:
let
bins = (getBins nix [ "nix-hash" ])
// (getBins gnutar [ "tar" ])
// (getBins git [ "git" ])
;
in
writePython3 "vuizvui-update-programs-sqlite" {
flakeIgnore = [
# whitespaces around { }
"E201" "E202"
# fuck 4-space indentation
"E121" "E111"
# who cares about blank lines
"W391" "E302" "E305"
# URLs are long
"E501"
];
libraries = [ requests ];
} ''
from pathlib import Path
import re
import requests
import subprocess
import sys
from tempfile import TemporaryDirectory
def latest_nixexprs_url():
r = requests.head('https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz')
assert r.status_code == 301
return r.headers['location']
def nixos_version_for_url(url):
match = re.match(r"https://releases\.nixos\.org/nixos/unstable/nixos-([0-9a-fpre.]+)/nixexprs\.tar\.xz", url)
return match.group(1)
def download(url: str, filename: Path) -> Path:
with requests.get(url, stream=True) as r:
r.raise_for_status()
with open(filename, 'wb') as f:
for c in r.iter_content(chunk_size=16384):
f.write(c)
return filename
def main():
if len(sys.argv) > 2:
print(f'Usage: {sys.argv[0]} /path/to/release.nix', file=sys.stderr)
raise SystemExit(64)
url = latest_nixexprs_url()
version = nixos_version_for_url(url)
print(f'Updating programs.sqlite to {version}', file=sys.stderr)
with TemporaryDirectory(prefix="vuizvui-update-programs-sqlite") as dir:
nixexprs = download(url, dir / Path('nixexprs.tar.xz'))
programs_sqlite = dir / Path('programs.sqlite')
with open(programs_sqlite, 'wb') as f:
subprocess.run([
'${bins.tar}',
'-xJOf',
nixexprs,
f'nixos-{version}/programs.sqlite'
], stdout=f, check=True)
hash = subprocess.run([
'${bins.nix-hash}',
'--base32',
'--type', 'sha256',
'--flat',
programs_sqlite
],
check=True,
capture_output=True).stdout.decode('utf-8').strip()
print(f'New hash: {hash}', file=sys.stderr)
if len(sys.argv) == 1:
print('Doing nothing (dry run)', file=sys.stderr)
elif len(sys.argv) == 2:
release_nix = Path(sys.argv[1])
with open(release_nix, 'r+') as f:
text = f.read()
# base32 alphabet as per nix-rust/src/util/base32.rs
new_text = re.sub(r'programsSqliteSha256\s*=\s*"[0-9a-fg-np-sv-z]+"',
f'programsSqliteSha256 = "{hash}"',
text)
new_text = re.sub(r'programsSqliteVersion\s*=\s*"[0-9a-fpre.]+"',
f'programsSqliteVersion = "{version}"',
new_text)
if text == new_text:
print('Already up to date')
else:
f.seek(0)
f.write(new_text)
print(f'Wrote to {release_nix}', file=sys.stderr)
subprocess.run([
'${bins.git}',
'commit', '-m',
f'release.nix: update programs.sqlite to {version}',
'--',
release_nix
],
check=True)
if __name__ == '__main__':
main()
''
|