1#!/usr/bin/env python 2# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Script that reads omahaproxy and gsutil to determine a version of the 7sdk_tools bundle to use. 8 9Please note the differences between this script and update_nacl_manifest.py: 10 11update_sdktools.py is run by a SDK-team developer to assist in updating to a 12new sdk_tools bundle. A file on the developer's hard drive is modified, and 13must be checked in for the new sdk_tools bundle to be used. 14 15update_nacl_manifest.py is customarily run by a cron job, and does not check in 16any changes. Instead it modifies the manifest file in cloud storage.""" 17 18 19import collections 20import difflib 21import json 22import optparse 23import re 24import sys 25import urllib2 26 27from manifest_util import DownloadAndComputeHash, DictToJSON 28from update_nacl_manifest import RealDelegate 29 30 31SDK_TOOLS_DESCRIPTION_FORMAT = 'Native Client SDK Tools, revision %d' 32BUCKET_PATH = 'nativeclient-mirror/nacl/nacl_sdk/' 33GS_BUCKET_PATH = 'gs://' + BUCKET_PATH 34HTTPS_BUCKET_PATH = 'https://storage.googleapis.com/' + BUCKET_PATH 35 36 37def GetSdkToolsUrl(revision): 38 return HTTPS_BUCKET_PATH + 'trunk.%d/sdk_tools.tgz' % revision 39 40 41def GetTrunkRevisions(delegate): 42 urls = delegate.GsUtil_ls(GS_BUCKET_PATH) 43 revisions = [] 44 for url in urls: 45 m = re.match(GS_BUCKET_PATH + 'trunk\.(\d+)', url) 46 if m: 47 revisions.append((int(m.group(1)), url)) 48 return sorted(revisions) 49 50 51def FindMostRecentSdkTools(delegate): 52 for revision, url in reversed(GetTrunkRevisions(delegate)): 53 sdktools_url = url + 'sdk_tools.tgz' 54 if delegate.GsUtil_ls(sdktools_url): 55 return revision, sdktools_url 56 return None 57 58 59def JsonLoadFromString(json_string): 60 if sys.version_info > (2, 7): 61 return json.loads(json_string, object_pairs_hook=collections.OrderedDict) 62 else: 63 return json.loads(json_string) 64 65 66def GetBundleByName(bundles, name): 67 for bundle in bundles: 68 if bundle['name'] == name: 69 return bundle 70 return None 71 72 73def UpdateSdkToolsBundle(sdk_tools_bundle, revision, url, sha1, size): 74 sdk_tools_bundle['description'] = SDK_TOOLS_DESCRIPTION_FORMAT % revision 75 sdk_tools_bundle['revision'] = revision 76 # Update archive for each OS 77 for archive in sdk_tools_bundle['archives']: 78 archive['url'] = url 79 archive['checksum']['sha1'] = sha1 80 archive['size'] = size 81 82 83def UpdateManifest(manifest, revision): 84 sdk_tools_bundle = GetBundleByName(manifest['bundles'], 'sdk_tools') 85 url = GetSdkToolsUrl(revision) 86 sha1, size = DownloadAndComputeHash(urllib2.urlopen(url)) 87 UpdateSdkToolsBundle(sdk_tools_bundle, revision, url, sha1, size) 88 89 90def UpdateManifestFileToRevision(filename, revision): 91 with open(filename) as stream: 92 manifest_string = stream.read() 93 94 manifest = JsonLoadFromString(manifest_string) 95 UpdateManifest(manifest, revision) 96 new_manifest_string = DictToJSON(manifest) 97 98 diff_string = ''.join(difflib.unified_diff(manifest_string.splitlines(1), 99 new_manifest_string.splitlines(1))) 100 101 print 'diff %s' % filename 102 print diff_string 103 print 104 105 with open(filename, 'w') as stream: 106 stream.write(new_manifest_string) 107 108 109def main(args): 110 parser = optparse.OptionParser(description=__doc__) 111 parser.add_option('-r', '--revision', 112 help='set revision manually, rather than using the latest version') 113 options, args = parser.parse_args(args[1:]) 114 if len(args) != 0: 115 parser.error('Unexpected args: %s' % ', '.join(args)) 116 117 # TODO(binji): http://crbug.com/169047. Rename RealDelegate to something else. 118 delegate = RealDelegate() 119 if not options.revision: 120 revision, _ = FindMostRecentSdkTools(delegate) 121 else: 122 revision = int(options.revision) 123 124 UpdateManifestFileToRevision('json/naclsdk_manifest0.json', revision) 125 UpdateManifestFileToRevision('json/naclsdk_manifest2.json', revision) 126 127 128if __name__ == '__main__': 129 sys.exit(main(sys.argv)) 130