| Index: native_client_sdk/src/build_tools/sdk_tools/update_manifest.py
|
| diff --git a/native_client_sdk/src/build_tools/sdk_tools/update_manifest.py b/native_client_sdk/src/build_tools/sdk_tools/update_manifest.py
|
| deleted file mode 100755
|
| index f0af47d63792eec62971f3fa445851627530d581..0000000000000000000000000000000000000000
|
| --- a/native_client_sdk/src/build_tools/sdk_tools/update_manifest.py
|
| +++ /dev/null
|
| @@ -1,463 +0,0 @@
|
| -#!/usr/bin/env python
|
| -# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -'''Utility to update the SDK manifest file in the build_tools directory'''
|
| -
|
| -
|
| -import optparse
|
| -import os
|
| -import re
|
| -import string
|
| -import subprocess
|
| -import sys
|
| -import urllib2
|
| -
|
| -# Create the various paths of interest
|
| -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
| -SDK_SRC_DIR = os.path.dirname(os.path.dirname(SCRIPT_DIR))
|
| -SRC_DIR = os.path.dirname(os.path.dirname(SDK_SRC_DIR))
|
| -NACL_DIR = os.path.join(SRC_DIR, 'native_client')
|
| -
|
| -sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
|
| -sys.path.append(os.path.join(NACL_DIR, 'build'))
|
| -
|
| -import sdk_update
|
| -
|
| -HELP = '''"Usage: %prog [-b bundle] [options]"
|
| -
|
| -Actions for particular bundles:
|
| - sdk_tools: Upload the most recently built nacl_sdk.zip and sdk_tools.tgz
|
| - files to the server and update the manifest file
|
| - pepper_??: Download the latest pepper builds off the appropriate branch,
|
| - upload these files to the appropriate location on the server, and
|
| - update the manifest file.
|
| - <others>: Only update manifest file -- you'll need to upload the file yourself
|
| -'''
|
| -
|
| -# Map option keys to manifest attribute key. Option keys are used to retrieve
|
| -# option values from cmd-line options. Manifest attribute keys label the
|
| -# corresponding value in the manifest object.
|
| -OPTION_KEY_MAP = {
|
| - # option key manifest attribute key
|
| - 'bundle_desc_url': 'desc_url',
|
| - 'bundle_revision': sdk_update.REVISION_KEY,
|
| - 'bundle_version': sdk_update.VERSION_KEY,
|
| - 'desc': 'description',
|
| - 'recommended': 'recommended',
|
| - 'stability': 'stability',
|
| - }
|
| -# Map options keys to platform key, as stored in the bundle.
|
| -OPTION_KEY_TO_PLATFORM_MAP = {
|
| - 'mac_arch_url': 'mac',
|
| - 'win_arch_url': 'win',
|
| - 'linux_arch_url': 'linux',
|
| - 'all_arch_url': 'all',
|
| - }
|
| -
|
| -NACL_SDK_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(
|
| - os.path.abspath(__file__))))
|
| -
|
| -BUILD_TOOLS_OUT = os.path.join(NACL_SDK_ROOT, 'scons-out', 'build', 'obj',
|
| - 'build_tools')
|
| -
|
| -BUNDLE_SDK_TOOLS = 'sdk_tools'
|
| -BUNDLE_PEPPER_MATCHER = re.compile('^pepper_([0-9]+)$')
|
| -IGNORE_OPTIONS = set([
|
| - 'archive_id', 'gsutil', 'manifest_file', 'upload', 'root_url'])
|
| -
|
| -
|
| -class Error(Exception):
|
| - '''Generic error/exception for update_manifest module'''
|
| - pass
|
| -
|
| -
|
| -def UpdateBundle(bundle, options):
|
| - ''' Update the bundle per content of the options.
|
| -
|
| - Args:
|
| - options: options data. Attributes that are used are also deleted from
|
| - options.'''
|
| - # Check, set and consume individual bundle options.
|
| - for option_key, attribute_key in OPTION_KEY_MAP.iteritems():
|
| - option_val = getattr(options, option_key, None)
|
| - if option_val is not None:
|
| - bundle[attribute_key] = option_val
|
| - delattr(options, option_key)
|
| - # Validate what we have so far; we may just avoid going through a lengthy
|
| - # download, just to realize that some other trivial stuff is missing.
|
| - bundle.Validate()
|
| - # Check and consume archive-url options.
|
| - for option_key, host_os in OPTION_KEY_TO_PLATFORM_MAP.iteritems():
|
| - platform_url = getattr(options, option_key, None)
|
| - if platform_url is not None:
|
| - bundle.UpdateArchive(host_os, platform_url)
|
| - delattr(options, option_key)
|
| -
|
| -
|
| -class UpdateSDKManifest(sdk_update.SDKManifest):
|
| - '''Adds functions to SDKManifest that are only used in update_manifest'''
|
| -
|
| - def _ValidateBundleName(self, name):
|
| - ''' Verify that name is a valid bundle.
|
| -
|
| - Args:
|
| - name: the proposed name for the bundle.
|
| -
|
| - Return:
|
| - True if the name is valid for a bundle, False otherwise.'''
|
| - valid_char_set = '()-_.%s%s' % (string.ascii_letters, string.digits)
|
| - name_len = len(name)
|
| - return (name_len > 0 and all(c in valid_char_set for c in name))
|
| -
|
| - def _UpdateManifestVersion(self, options):
|
| - ''' Update the manifest version number from the options
|
| -
|
| - Args:
|
| - options: options data containing an attribute self.manifest_version '''
|
| - version_num = int(options.manifest_version)
|
| - self._manifest_data['manifest_version'] = version_num
|
| - del options.manifest_version
|
| -
|
| - def _UpdateBundle(self, options):
|
| - ''' Update or setup a bundle from the options.
|
| -
|
| - Args:
|
| - options: options data containing at least a valid bundle_name
|
| - attribute. Other relevant bundle attributes will also be
|
| - used (and consumed) by this function. '''
|
| - # Get and validate the bundle name
|
| - if not self._ValidateBundleName(options.bundle_name):
|
| - raise Error('Invalid bundle name: "%s"' % options.bundle_name)
|
| - bundle_name = options.bundle_name
|
| - del options.bundle_name
|
| - # Get the corresponding bundle, or create it.
|
| - bundle = self.GetBundle(bundle_name)
|
| - if not bundle:
|
| - bundle = sdk_update.Bundle(bundle_name)
|
| - self.SetBundle(bundle)
|
| - UpdateBundle(bundle, options)
|
| -
|
| - def _VerifyAllOptionsConsumed(self, options, bundle_name):
|
| - ''' Verify that all the options have been used. Raise an exception if
|
| - any valid option has not been used. Returns True if all options have
|
| - been consumed.
|
| -
|
| - Args:
|
| - options: the object containing the remaining unused options attributes.
|
| - bundle_name: The name of the bundle, or None if it's missing.'''
|
| - # Any option left in the list should have value = None
|
| - for key, val in options.__dict__.items():
|
| - if val != None and key not in IGNORE_OPTIONS:
|
| - if bundle_name:
|
| - raise Error('Unused option "%s" for bundle "%s"' % (key, bundle_name))
|
| - else:
|
| - raise Error('No bundle name specified')
|
| - return True
|
| -
|
| - def UpdateManifest(self, options):
|
| - ''' Update the manifest object with values from the command-line options
|
| -
|
| - Args:
|
| - options: options object containing attribute for the command-line options.
|
| - Note that all the non-trivial options are consumed.
|
| - '''
|
| - # Go over all the options and update the manifest data accordingly.
|
| - # Valid options are consumed as they are used. This gives us a way to
|
| - # verify that all the options are used.
|
| - if options.manifest_version is not None:
|
| - self._UpdateManifestVersion(options)
|
| - # Keep a copy of bundle_name, which will be consumed by UpdateBundle, for
|
| - # use in _VerifyAllOptionsConsumed below.
|
| - bundle_name = options.bundle_name
|
| - if bundle_name is not None:
|
| - self._UpdateBundle(options)
|
| - self._VerifyAllOptionsConsumed(options, bundle_name)
|
| - self._ValidateManifest()
|
| -
|
| - def ValidateManifestLinks(self):
|
| - '''Validates all the links in the manifest file and throws if one is bad'''
|
| - valid = True
|
| - for bundle in self._manifest_data[sdk_update.BUNDLES_KEY]:
|
| - for archive in bundle.GetArchives():
|
| - stream = None
|
| - try:
|
| - print "Checking size of data at link: %s" % archive.GetUrl()
|
| - stream = urllib2.urlopen(archive.GetUrl())
|
| - server_size = int(stream.info()[sdk_update.HTTP_CONTENT_LENGTH])
|
| - if server_size != archive.GetSize():
|
| - sys.stderr.write('Size mismatch for %s. Expected %s but got %s\n' %
|
| - (archive.GetUrl(), archive.GetSize(), server_size))
|
| - sys.stderr.flush()
|
| - valid = False
|
| - finally:
|
| - if stream:
|
| - stream.close()
|
| - if not valid:
|
| - raise Error('Files on server do not match the manifest file')
|
| -
|
| -
|
| -class GsUtil(object):
|
| - def __init__(self, gsutil):
|
| - '''gsutil is the path to the gsutil executable'''
|
| - self.gsutil = gsutil
|
| - self.root = 'gs://nativeclient-mirror/nacl/nacl_sdk'
|
| -
|
| - def GetURI(self, path):
|
| - '''Return the full gs:// URI for a given relative path'''
|
| - return '/'.join([self.root, path])
|
| -
|
| - def Run(self, command):
|
| - '''Runs gsutil with a given argument list and returns exit status'''
|
| - args = [self.gsutil] + command
|
| - print 'GSUtil.Run(%s)' % args
|
| - sys.stdout.flush()
|
| - return subprocess.call(args)
|
| -
|
| - def CheckIfExists(self, path):
|
| - '''Check whether a given path exists on commondatastorage
|
| -
|
| - Args:
|
| - path: path relative to SDK root directory on the server
|
| -
|
| - Returns: True if it exists, False if it does not'''
|
| - # todo(mball): Be a little more intelligent about this check and compare
|
| - # the output strings against expected values
|
| - return self.Run(['ls', self.GetURI(path)]) == 0
|
| -
|
| - def Copy(self, source, destination):
|
| - '''Copies a given source file to a destination path and makes it readable
|
| -
|
| - Args:
|
| - source: path to source file on local filesystem
|
| - destination: path to destination, relative to root directory'''
|
| - args = ['cp', '-a', 'public-read', source, self.GetURI(destination)]
|
| - if self.Run(args) != 0:
|
| - raise Error('Unable to copy %s to %s' % (source, destination))
|
| -
|
| -
|
| -class UpdateSDKManifestFile(sdk_update.SDKManifestFile):
|
| - '''Adds functions to SDKManifestFile that are only used in update_manifest'''
|
| -
|
| - def __init__(self, options):
|
| - '''Create a new SDKManifest object with default contents.
|
| -
|
| - If |json_filepath| is specified, and it exists, its contents are loaded and
|
| - used to initialize the internal manifest.
|
| -
|
| - Args:
|
| - json_filepath: path to json file to read/write, or None to write a new
|
| - manifest file to stdout.
|
| - '''
|
| - # Strip-off all the I/O-based options that do not relate to bundles
|
| - self._json_filepath = options.manifest_file
|
| - self.gsutil = GsUtil(options.gsutil)
|
| - self.options = options
|
| - self._manifest = UpdateSDKManifest()
|
| - if self._json_filepath:
|
| - self._LoadFile()
|
| -
|
| - def _HandleSDKTools(self):
|
| - '''Handles the sdk_tools bundle'''
|
| - # General sanity checking of parameters
|
| - SDK_TOOLS_FILES = ['sdk_tools.tgz', 'nacl_sdk.zip']
|
| - options = self.options
|
| - if options.bundle_version is None:
|
| - options.bundle_version = sdk_update.MAJOR_REV
|
| - if options.bundle_version != sdk_update.MAJOR_REV:
|
| - raise Error('Specified version (%s) does not match MAJOR_REV (%s)' %
|
| - (options.bundle_version, sdk_update.MAJOR_REV))
|
| - if options.bundle_revision is None:
|
| - options.bundle_revision = sdk_update.MINOR_REV
|
| - if options.bundle_revision != sdk_update.MINOR_REV:
|
| - raise Error('Specified revision (%s) does not match MINOR_REV (%s)' %
|
| - (options.bundle_revision, sdk_update.MINOR_REV))
|
| - version = '%s.%s' % (options.bundle_version, options.bundle_revision)
|
| - # Update the remaining options
|
| - if options.desc is None:
|
| - options.desc = ('Native Client SDK Tools, revision %s.%s' %
|
| - (options.bundle_version, options.bundle_revision))
|
| - options.recommended = options.recommended or 'yes'
|
| - options.stability = options.stability or 'stable'
|
| - if options.upload:
|
| - # Check whether the tools already exist
|
| - for name in SDK_TOOLS_FILES:
|
| - path = '/'.join([version, name])
|
| - if self.gsutil.CheckIfExists(path):
|
| - raise Error('File already exists at %s' % path)
|
| - # Upload the tools files to the server
|
| - for name in SDK_TOOLS_FILES:
|
| - source = os.path.join(BUILD_TOOLS_OUT, name)
|
| - destination = '/'.join([version, name])
|
| - self.gsutil.Copy(source, destination)
|
| - url = '/'.join([options.root_url, version, 'sdk_tools.tgz'])
|
| - options.mac_arch_url = options.mac_arch_url or url
|
| - options.linux_arch_url = options.linux_arch_url or url
|
| - options.win_arch_url = options.win_arch_url or url
|
| -
|
| - def _HandlePepper(self):
|
| - '''Handles the pepper bundles'''
|
| - options = self.options
|
| - match = BUNDLE_PEPPER_MATCHER.match(options.bundle_name)
|
| - if match is not None:
|
| - options.bundle_version = int(match.group(1))
|
| - if options.bundle_version is None:
|
| - raise Error('Need to specify a bundle version')
|
| - if options.bundle_revision is None:
|
| - raise Error('Need to specify a bundle revision')
|
| - if options.bundle_name == 'pepper':
|
| - self.options.bundle_name = 'pepper_%s' % options.bundle_version
|
| - if options.desc is None:
|
| - options.desc = ('Chrome %s bundle, revision %s' %
|
| - (options.bundle_version, options.bundle_revision))
|
| - root_url = options.root_url
|
| - if options.archive_id:
|
| - # Support archive names like trunk.113440 or 17.0.963.3, which is how
|
| - # the Chrome builders archive things.
|
| - root_url = '/'.join([root_url, options.archive_id])
|
| - else:
|
| - # This is the old archive naming scheme
|
| - root_url = '%s/pepper_%s_%s' % (root_url, options.bundle_version,
|
| - options.bundle_revision)
|
| - options.mac_arch_url = '/'.join([root_url, 'naclsdk_mac.bz2'])
|
| - options.linux_arch_url = '/'.join([root_url, 'naclsdk_linux.bz2'])
|
| - options.win_arch_url = '/'.join([root_url, 'naclsdk_win.bz2'])
|
| -
|
| - def HandleBundles(self):
|
| - '''Handles known bundles by automatically uploading files'''
|
| - bundle_name = self.options.bundle_name
|
| - print 'bundle_name=' + bundle_name
|
| - if bundle_name == BUNDLE_SDK_TOOLS:
|
| - self._HandleSDKTools()
|
| - elif bundle_name.startswith('pepper'):
|
| - self._HandlePepper()
|
| -
|
| - def UpdateWithOptions(self):
|
| - ''' Update the manifest file with the given options. Create the manifest
|
| - if it doesn't already exists. Raises an Error if the manifest doesn't
|
| - validate after updating.
|
| -
|
| - Args:
|
| - options: option data'''
|
| - # UpdateManifest does not know how to deal with file-related options
|
| - self._manifest.UpdateManifest(self.options)
|
| - self.WriteFile()
|
| -
|
| -
|
| -def CommandPush(options, args, manifest_file):
|
| - '''Check the manifest file and push it to the server if it's okay'''
|
| - print 'Running Push with options=%s and args=%s' % (options, args)
|
| - manifest = manifest_file._manifest
|
| - manifest.UpdateManifest(options)
|
| - print 'Validating links within manifest file'
|
| - manifest.ValidateManifestLinks()
|
| - print 'Copying manifest file to server'
|
| - manifest_file.gsutil.Copy(options.manifest_file, 'naclsdk_manifest.json')
|
| -
|
| -
|
| -def main(argv):
|
| - '''Main entry for update_manifest.py'''
|
| -
|
| - buildtools_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| - parser = optparse.OptionParser(usage=HELP)
|
| -
|
| - # Setup options
|
| - parser.add_option(
|
| - '-a', '--archive-id', dest='archive_id',
|
| - default=None,
|
| - help='Archive identifier, produced by the Chromium builders; string '
|
| - 'like "trunk.113440" or "17.0.963.3". Used with --root-url to '
|
| - 'build the full archive URL. If not set the archive id defaults to '
|
| - '"pepper_<version>_<revision>"')
|
| - parser.add_option(
|
| - '-b', '--bundle-version', dest='bundle_version',
|
| - type='int',
|
| - default=None,
|
| - help='Required: Version number for the bundle.')
|
| - parser.add_option(
|
| - '-B', '--bundle-revision', dest='bundle_revision',
|
| - type='int',
|
| - default=None,
|
| - help='Required: Revision number for the bundle.')
|
| - parser.add_option(
|
| - '-d', '--description', dest='desc',
|
| - default=None,
|
| - help='Required: Description for this bundle.')
|
| - parser.add_option(
|
| - '-f', '--manifest-file', dest='manifest_file',
|
| - default=os.path.join(buildtools_dir, 'json',
|
| - sdk_update.MANIFEST_FILENAME),
|
| - help='location of manifest file to read and update')
|
| - parser.add_option(
|
| - '-g', '--gsutil', dest='gsutil',
|
| - default='gsutil', help='location of gsutil tool for uploading bundles')
|
| - parser.add_option(
|
| - '-L', '--linux-archive', dest='linux_arch_url',
|
| - default=None,
|
| - help='URL for the Linux archive.')
|
| - parser.add_option(
|
| - '-M', '--mac-archive', dest='mac_arch_url',
|
| - default=None,
|
| - help='URL for the Mac archive.')
|
| - parser.add_option(
|
| - '-n', '--bundle-name', dest='bundle_name',
|
| - default=None,
|
| - help='Required: Name of the bundle.')
|
| - parser.add_option(
|
| - '-r', '--recommended', dest='recommended',
|
| - choices=sdk_update.YES_NO_LITERALS,
|
| - default=None,
|
| - help='Required: whether this bundle is recommended. One of "yes" or "no"')
|
| - parser.add_option(
|
| - '-R', '--root-url', dest='root_url',
|
| - default='http://commondatastorage.googleapis.com/nativeclient-mirror/'
|
| - 'nacl/nacl_sdk',
|
| - help='Root url for uploading')
|
| - parser.add_option(
|
| - '-s', '--stability', dest='stability',
|
| - choices=sdk_update.STABILITY_LITERALS,
|
| - default=None,
|
| - help='Required: Stability for this bundle; one of. '
|
| - '"obsolete", "post_stable", "stable", "beta", "dev", "canary".')
|
| - parser.add_option(
|
| - '-u', '--desc-url', dest='bundle_desc_url',
|
| - default=None,
|
| - help='Optional: URL to follow to read additional bundle info.')
|
| - parser.add_option(
|
| - '-U', '--upload', dest='upload', default=False, action='store_true',
|
| - help='Indicates whether to upload bundle to server')
|
| - parser.add_option(
|
| - '-v', '--manifest-version', dest='manifest_version',
|
| - type='int',
|
| - default=None,
|
| - help='Required for new manifest files: '
|
| - 'Version number for the manifest.')
|
| - parser.add_option(
|
| - '-W', '--win-archive', dest='win_arch_url',
|
| - default=None,
|
| - help='URL for the Windows archive.')
|
| -
|
| - # Parse options and arguments and check.
|
| - (options, args) = parser.parse_args(argv)
|
| - manifest_file = UpdateSDKManifestFile(options)
|
| - if len(args) == 0:
|
| - manifest_file.HandleBundles()
|
| - manifest_file.UpdateWithOptions()
|
| - return 0
|
| -
|
| - COMMANDS = {
|
| - 'push': CommandPush
|
| - }
|
| - def CommandUnknown(options, args, manifest_file):
|
| - raise Error("Unknown command %s" % args[0])
|
| - try:
|
| - COMMANDS.get(args[0], CommandUnknown)(options, args, manifest_file)
|
| - except Error as error:
|
| - print "Error: %s" % error
|
| - return 1
|
| - return 0
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - sys.exit(main(sys.argv[1:]))
|
|
|