at 22.05-pre 91 lines 3.9 kB view raw
1#! /usr/bin/env nix-shell 2#! nix-shell -p nix-prefetch-git "python3.withPackages (ps: with ps; [ lxml ])" 3#! nix-shell -i python 4 5import base64 6import json 7import re 8import subprocess 9from codecs import iterdecode 10from os.path import dirname, splitext 11from lxml import etree 12from lxml.etree import HTMLParser 13from urllib.request import urlopen 14 15# ChromiumOS components required to build crosvm. 16components = ['chromiumos/platform/crosvm', 'chromiumos/third_party/adhd'] 17 18git_root = 'https://chromium.googlesource.com/' 19manifest_versions = f'{git_root}chromiumos/manifest-versions' 20buildspecs_url = f'{manifest_versions}/+/refs/heads/master/full/buildspecs/' 21 22# CrOS version numbers look like this: 23# [<chrome-major-version>.]<tip-build>.<branch-build>.<branch-branch-build> 24# 25# As far as I can tell, branches are where internal Google 26# modifications are added to turn Chromium OS into Chrome OS, and 27# branch branches are used for fixes for specific devices. So for 28# Chromium OS they will always be 0. This is a best guess, and is not 29# documented. 30with urlopen('https://cros-updates-serving.appspot.com/') as resp: 31 document = etree.parse(resp, HTMLParser()) 32 # bgcolor="lightgreen" is set on the most up-to-date version for 33 # each channel, so find a lightgreen cell in the "Stable" column. 34 (platform_version, chrome_version) = document.xpath(""" 35 (//table[@id="cros-updates"]/tr/td[1 + count( 36 //table[@id="cros-updates"]/thead/tr[1]/th[text() = "Stable"] 37 /preceding-sibling::*) 38 ][@bgcolor="lightgreen"])[1]/text() 39 """) 40 41chrome_major_version = re.match(r'\d+', chrome_version)[0] 42chromeos_tip_build = re.match(r'\d+', platform_version)[0] 43 44# Find the most recent buildspec for the stable Chrome version and 45# Chromium OS build number. Its branch build and branch branch build 46# numbers will (almost?) certainly be 0. It will then end with an rc 47# number -- presumably these are release candidates, one of which 48# becomes the final release. Presumably the one with the highest rc 49# number. 50with urlopen(f'{buildspecs_url}{chrome_major_version}/?format=TEXT') as resp: 51 listing = base64.decodebytes(resp.read()).decode('utf-8') 52 buildspecs = [(line.split('\t', 1)[1]) for line in listing.splitlines()] 53 buildspecs = [s for s in buildspecs if s.startswith(chromeos_tip_build)] 54 buildspecs.sort(reverse=True) 55 buildspec = splitext(buildspecs[0])[0] 56 57revisions = {} 58 59# Read the buildspec, and extract the git revisions for each component. 60with urlopen(f'{buildspecs_url}{chrome_major_version}/{buildspec}.xml?format=TEXT') as resp: 61 xml = base64.decodebytes(resp.read()) 62 root = etree.fromstring(xml) 63 for project in root.findall('project'): 64 revisions[project.get('name')] = project.get('revision') 65 66# Initialize the data that will be output from this script. Leave the 67# rc number in buildspec so nobody else is subject to the same level 68# of confusion I have been. 69data = {'version': f'{chrome_major_version}.{buildspec}', 'components': {}} 70 71# Fill in the 'components' dictionary with the output from 72# nix-prefetch-git, which can be passed straight to fetchGit when 73# imported by Nix. 74for component in components: 75 argv = ['nix-prefetch-git', 76 '--url', git_root + component, 77 '--rev', revisions[component]] 78 79 output = subprocess.check_output(argv) 80 data['components'][component] = json.loads(output.decode('utf-8')) 81 82# Find the path to crosvm's default.nix, so the srcs data can be 83# written into the same directory. 84argv = ['nix-instantiate', '--eval', '--json', '-A', 'crosvm.meta.position'] 85position = json.loads(subprocess.check_output(argv).decode('utf-8')) 86filename = re.match(r'[^:]*', position)[0] 87 88# Finally, write the output. 89with open(dirname(filename) + '/upstream-info.json', 'w') as out: 90 json.dump(data, out, indent=2) 91 out.write('\n')