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
--- 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("}")