Bug 1286799 - mozboot: Add a script to fetch rust installer hashes. r=gps draft
authorRalph Giles <giles@mozilla.com>
Thu, 17 Nov 2016 14:23:41 -0800
changeset 442189 1b7793724c6f8044abcb4cee74e3a4964eb61ef1
parent 442188 75cf121d2dff55c21de7a4ee5e08efecbb6c2c1a
child 442190 3d58caa72b32cdeaf4c830c260b301ebb2b566de
push id36622
push userbmo:giles@thaumas.net
push dateTue, 22 Nov 2016 01:00:21 +0000
reviewersgps
bugs1286799
milestone53.0a1
Bug 1286799 - mozboot: Add a script to fetch rust installer hashes. r=gps Make the mozboot.rust module invokable as a utility. E.g. python rust.py --update When called with the --update option it downloads and generates checksums for the latest version of the installer on supported platforms, suitable for updating the values coded in the script. When invoked without the --update option, it verifies the current version and checksums against the server. MozReview-Commit-ID: 2NVFf0ptvbM
python/mozboot/mozboot/rust.py
--- a/python/mozboot/mozboot/rust.py
+++ b/python/mozboot/mozboot/rust.py
@@ -62,8 +62,113 @@ def platform():
         # Bravely assume we'll be building 64-bit Firefox.
         return 'x86_64-pc-windows-msvc'
     elif sys.platform.startswith('linux'):
         return 'x86_64-unknown-linux-gnu'
     elif sys.platform.startswith('freebsd'):
         return 'x86_64-unknown-freebsd'
 
     return None
+
+USAGE = '''
+python rust.py [--update]
+
+Pass the --update option print info for the latest release of rustup-init.
+
+When invoked without the --update option, it queries the latest version
+and verifies the current stored checksums against the distribution server,
+but doesn't update the version installed by `mach bootstrap`.
+'''
+
+def unquote(s):
+    '''Strip outer quotation marks from a string.'''
+    return s.strip("'").strip('"')
+
+def rustup_latest_version():
+    '''Query the latest version of the rustup installer.'''
+    import urllib2
+    f = urllib2.urlopen(RUSTUP_MANIFEST)
+    # The manifest is toml, but we might not have the toml4 python module
+    # available, so use ad-hoc parsing to obtain the current release version.
+    #
+    # The manifest looks like:
+    #
+    # schema-version = '1'
+    # version = '0.6.5'
+    #
+    for line in f:
+        key, value = map(str.strip, line.split('=', 2))
+        if key == 'schema-version':
+            schema = int(unquote(value))
+            if schema != 1:
+                print('ERROR: Unknown manifest schema %s' % value)
+                sys.exit(1)
+        elif key == 'version':
+            return unquote(value)
+    return None
+
+def http_download_and_hash(url):
+    import hashlib
+    import urllib2
+    f = urllib2.urlopen(url)
+    h = hashlib.sha256()
+    while True:
+        data = f.read(4096)
+        if data:
+            h.update(data)
+        else:
+            break
+    return h.hexdigest()
+
+def make_checksums(version, validate=False):
+    hashes = []
+    for platform in RUSTUP_HASHES.keys():
+        if validate:
+            print('Checking %s... ' % platform, end='')
+            sys.stdout.flush()
+        else:
+            print('Fetching %s... ' % platform, end='')
+            sys.stdout.flush()
+        checksum = http_download_and_hash(rustup_url(platform, version))
+        if validate and checksum != rustup_hash(platform):
+            print('mismatch:\n  script: %s\n  server: %s' % (
+                RUSTUP_HASHES[platform], checksum))
+        else:
+            print('OK')
+        hashes.append((platform, checksum))
+    return hashes
+
+if __name__ == '__main__':
+    '''Allow invoking the module as a utility to update checksums.'''
+    update = False
+    if len(sys.argv) > 1:
+        if sys.argv[1] == '--update':
+            update = True
+        else:
+            print(USAGE)
+            sys.exit(1)
+
+    print('Checking latest installer version... ', end='')
+    sys.stdout.flush()
+    version = rustup_latest_version()
+    if not version:
+        print('ERROR: Could not query current rustup installer version.')
+        sys.exit(1)
+    print(version)
+
+    if version == RUSTUP_VERSION:
+        print("We're up to date. Validating checksums.")
+        make_checksums(version, validate=True)
+        exit()
+
+    if not update:
+        print('Out of date. We use %s. Validating checksums.' % RUSTUP_VERSION)
+        make_checksums(RUSTUP_VERSION, validate=True)
+        exit()
+
+    print('Out of date. We use %s. Calculating checksums.' % RUSTUP_VERSION)
+    hashes = make_checksums(version)
+    print('')
+    print("RUSTUP_VERSION = '%s'" % version)
+    print("RUSTUP_HASHES = {")
+    for item in hashes:
+        print("    '%s':\n        '%s'," % item)
+    print("}")