1#!/usr/bin/env nix-shell
2#!nix-shell -i python3 -p python3
3
4import os
5import re
6import json
7import urllib.request
8
9from distutils.version import LooseVersion
10
11UPSTREAM_INFO_FILE = os.path.join(
12 os.path.dirname(os.path.abspath(__file__)),
13 "upstream-info.json"
14)
15
16
17def fetch_latest_version():
18 url = "http://download.virtualbox.org/virtualbox/LATEST.TXT"
19 return urllib.request.urlopen(url).read().strip().decode()
20
21
22def load_upstream_info():
23 try:
24 with open(UPSTREAM_INFO_FILE, 'r') as fp:
25 return json.load(fp)
26 except FileNotFoundError:
27 return {'version': "0"}
28
29
30def save_upstream_info(contents):
31 remark = "Generated using update.py from the same directory."
32 contents['__NOTE'] = remark
33 data = json.dumps(contents, indent=2, sort_keys=True)
34 with open(UPSTREAM_INFO_FILE, 'w') as fp:
35 fp.write(data + "\n")
36
37
38def fetch_file_table(version):
39 url = "http://download.virtualbox.org/virtualbox/{}/SHA256SUMS"
40 url = url.format(version)
41 result = {}
42 for line in urllib.request.urlopen(url):
43 sha, name = line.rstrip().split()
44 result[name.lstrip(b'*').decode()] = sha.decode()
45 return result
46
47
48def update_to_version(version):
49 extpack_start = 'Oracle_VM_VirtualBox_Extension_Pack-'
50 version_re = version.replace('.', '\\.')
51 attribute_map = {
52 'extpack': r'^' + extpack_start + r'[^-]+-[^.]+.vbox-extpack$',
53 'extpackRev': r'^' + extpack_start + r'[^-]+-([^.]+).vbox-extpack$',
54 'main': r'^VirtualBox-' + version_re + r'.tar.bz2$',
55 'guest': r'^VBoxGuestAdditions_' + version_re + r'.iso$',
56 }
57 table = fetch_file_table(version)
58 new_attrs = {'version': version}
59 for attr, searchexpr in attribute_map.items():
60 result = [re.search(searchexpr, key) for key in table.keys()]
61 filtered = filter(lambda m: m is not None, result)
62 found = [m.groups()[0] if len(m.groups()) > 0 else table[m.group(0)]
63 for m in filtered if m is not None]
64
65 if len(found) == 0:
66 msg = "No package found for attribute {}".format(attr)
67 raise AssertionError(msg)
68 elif len(found) != 1:
69 msg = "More than one package found for attribute {}: ".format(attr)
70 msg += ', '.join(found)
71 raise AssertionError(msg)
72 else:
73 new_attrs[attr] = found[0]
74 return new_attrs
75
76
77info = load_upstream_info()
78latest = fetch_latest_version()
79if LooseVersion(info['version']) < LooseVersion(latest):
80 print("Updating to version {}...".format(latest), end="", flush=True)
81 new_attrs = update_to_version(latest)
82 save_upstream_info(new_attrs)
83 print(" done.")
84else:
85 print("Version {} is already the latest one.".format(info['version']))