text: #!/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.
  
  """Script that reads omahaproxy and gsutil to determine a version of the
  sdk_tools bundle to use.
  
  Please note the differences between this script and update_nacl_manifest.py:
  
  update_sdktools.py is run by a SDK-team developer to assist in updating to a
  new sdk_tools bundle. A file on the developer's hard drive is modified, and
  must be checked in for the new sdk_tools bundle to be used.
  
  update_nacl_manifest.py is customarily run by a cron job, and does not check in
  any changes. Instead it modifies the manifest file in cloud storage."""
  
  
  import collections
  import difflib
  import json
  import optparse
  import re
  import sys
  import urllib2
  
  from manifest_util import DownloadAndComputeHash, DictToJSON
  from update_nacl_manifest import RealDelegate
  
  
  SDK_TOOLS_DESCRIPTION_FORMAT = 'Native Client SDK Tools, revision %d'
  BUCKET_PATH = 'nativeclient-mirror/nacl/nacl_sdk/'
  GS_BUCKET_PATH = 'gs://' + BUCKET_PATH
  HTTPS_BUCKET_PATH = 'https://storage.googleapis.com/' + BUCKET_PATH
  
  
  def GetSdkToolsUrl(revision):
    return HTTPS_BUCKET_PATH + 'trunk.%d/sdk_tools.tgz' % revision
  
  
  def GetTrunkRevisions(delegate):
    urls = delegate.GsUtil_ls(GS_BUCKET_PATH)
    revisions = []
    for url in urls:
      m = re.match(GS_BUCKET_PATH + 'trunk\.(\d+)', url)
      if m:
        revisions.append((int(m.group(1)), url))
    return sorted(revisions)
  
  
  def FindMostRecentSdkTools(delegate):
    for revision, url in reversed(GetTrunkRevisions(delegate)):
      sdktools_url = url + 'sdk_tools.tgz'
      if delegate.GsUtil_ls(sdktools_url):
        return revision, sdktools_url
    return None
  
  
  def JsonLoadFromString(json_string):
    if sys.version_info > (2, 7):
      return json.loads(json_string, object_pairs_hook=collections.OrderedDict)
    else:
      return json.loads(json_string)
  
  
  def GetBundleByName(bundles, name):
    for bundle in bundles:
      if bundle['name'] == name:
        return bundle
    return None
  
  
  def UpdateSdkToolsBundle(sdk_tools_bundle, revision, url, sha1, size):
    sdk_tools_bundle['description'] = SDK_TOOLS_DESCRIPTION_FORMAT % revision
    sdk_tools_bundle['revision'] = revision
    # Update archive for each OS
    for archive in sdk_tools_bundle['archives']:
      archive['url'] = url
      archive['checksum']['sha1'] = sha1
      archive['size'] = size
  
  
  def UpdateManifest(manifest, revision):
    sdk_tools_bundle = GetBundleByName(manifest['bundles'], 'sdk_tools')
    url = GetSdkToolsUrl(revision)
    sha1, size = DownloadAndComputeHash(urllib2.urlopen(url))
    UpdateSdkToolsBundle(sdk_tools_bundle, revision, url, sha1, size)
  
  
  def UpdateManifestFileToRevision(filename, revision):
    with open(filename) as stream:
      manifest_string = stream.read()
  
    manifest = JsonLoadFromString(manifest_string)
    UpdateManifest(manifest, revision)
    new_manifest_string = DictToJSON(manifest)
  
    diff_string = ''.join(difflib.unified_diff(manifest_string.splitlines(1),
                                               new_manifest_string.splitlines(1)))
  
    print 'diff %s' % filename
    print diff_string
    print
  
    with open(filename, 'w') as stream:
      stream.write(new_manifest_string)
  
  
  def main(args):
    parser = optparse.OptionParser(description=__doc__)
    parser.add_option('-r', '--revision',
        help='set revision manually, rather than using the latest version')
    options, args = parser.parse_args(args)
    if len(args) != 0:
      parser.error('Unexpected args: %s' % ', '.join(args))
  
    # TODO(binji): http://crbug.com/169047. Rename RealDelegate to something else.
    delegate = RealDelegate()
    if not options.revision:
      revision, _ = FindMostRecentSdkTools(delegate)
    else:
      revision = int(options.revision)
  
    UpdateManifestFileToRevision('json/naclsdk_manifest0.json', revision)
    UpdateManifestFileToRevision('json/naclsdk_manifest2.json', revision)
    return 0
  
  
  if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
  