Home | History | Annotate | Download | only in toolchain-utils
      1 #!/usr/bin/env python2
      2 #
      3 # Copyright 2010 The Chromium OS Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 """Script to checkout the ChromeOS source.
      7 
      8 This script sets up the ChromeOS source in the given directory, matching a
      9 particular release of ChromeOS.
     10 """
     11 
     12 from __future__ import print_function
     13 
     14 __author__ = 'raymes (at] google.com (Raymes Khoury)'
     15 
     16 from datetime import datetime
     17 
     18 import argparse
     19 import os
     20 import pickle
     21 import sys
     22 import tempfile
     23 import time
     24 from cros_utils import command_executer
     25 from cros_utils import logger
     26 from cros_utils import manifest_versions
     27 
     28 GCLIENT_FILE = """solutions = [
     29   { "name"        : "CHROME_DEPS",
     30     "url"         :
     31     "svn://svn.chromium.org/chrome-internal/trunk/tools/buildspec/releases/%s",
     32     "custom_deps" : {
     33       "src/third_party/WebKit/LayoutTests": None,
     34       "src-pdf": None,
     35       "src/pdf": None,
     36     },
     37     "safesync_url": "",
     38    },
     39 ]
     40 """
     41 
     42 # List of stable versions used for common team image
     43 # Sheriff must update this list when a new common version becomes available
     44 COMMON_VERSIONS = '/home/mobiletc-prebuild/common_images/common_list.txt'
     45 
     46 
     47 def Usage(parser):
     48   parser.print_help()
     49   sys.exit(0)
     50 
     51 
     52 # Get version spec file, either from "paladin" or "buildspec" directory.
     53 def GetVersionSpecFile(version, versions_git):
     54   temp = tempfile.mkdtemp()
     55   commands = ['cd {0}'.format(temp), \
     56               'git clone {0} versions'.format(versions_git)]
     57   cmd_executer = command_executer.GetCommandExecuter()
     58   ret = cmd_executer.RunCommands(commands)
     59   err_msg = None
     60   if ret:
     61     err_msg = 'Failed to checkout versions_git - {0}'.format(versions_git)
     62     ret = None
     63   else:
     64     v, m = version.split('.', 1)
     65     paladin_spec = 'paladin/buildspecs/{0}/{1}.xml'.format(v, m)
     66     generic_spec = 'buildspecs/{0}/{1}.xml'.format(v, m)
     67     paladin_path = '{0}/versions/{1}'.format(temp, paladin_spec)
     68     generic_path = '{0}/versions/{1}'.format(temp, generic_spec)
     69     if os.path.exists(paladin_path):
     70       ret = paladin_spec
     71     elif os.path.exists(generic_path):
     72       ret = generic_spec
     73     else:
     74       err_msg = 'No spec found for version {0}'.format(version)
     75       ret = None
     76     # Fall through to clean up.
     77 
     78   commands = ['rm -rf {0}'.format(temp)]
     79   cmd_executer.RunCommands(commands)
     80   if err_msg:
     81     logger.GetLogger().LogFatal(err_msg)
     82   return ret
     83 
     84 
     85 def TimeToCommonVersion(timestamp):
     86   """Convert timestamp to common image version."""
     87   tdt = datetime.fromtimestamp(float(timestamp))
     88   with open(COMMON_VERSIONS, 'r') as f:
     89     common_list = pickle.load(f)
     90     for sv in common_list:
     91       sdt = datetime.strptime(sv['date'], '%Y-%m-%d %H:%M:%S.%f')
     92       if tdt >= sdt:
     93         return '%s.%s' % (sv['chrome_major_version'], sv['chromeos_version'])
     94     # should never reach here
     95     logger.GetLogger().LogFatal('No common version for timestamp')
     96   return None
     97 
     98 
     99 def Main(argv):
    100   """Checkout the ChromeOS source."""
    101   parser = argparse.ArgumentParser()
    102   parser.add_argument(
    103       '--dir',
    104       dest='directory',
    105       help='Target directory for ChromeOS installation.')
    106   parser.add_argument(
    107       '--version',
    108       dest='version',
    109       default='latest_lkgm',
    110       help="""ChromeOS version. Can be:
    111 (1) A release version in the format: 'X.X.X.X'
    112 (2) 'top' for top of trunk
    113 (3) 'latest_lkgm' for the latest lkgm version
    114 (4) 'lkgm' for the lkgm release before timestamp
    115 (5) 'latest_common' for the latest team common stable version
    116 (6) 'common' for the team common stable version before timestamp
    117 Default is 'latest_lkgm'.""")
    118   parser.add_argument(
    119       '--timestamp',
    120       dest='timestamp',
    121       default=None,
    122       help='Timestamps in epoch format. It will check out the'
    123       'latest LKGM or the latest COMMON version of ChromeOS'
    124       ' before the timestamp. Use in combination with'
    125       ' --version=latest or --version=common. Use '
    126       '"date -d <date string> +%s" to find epoch time')
    127   parser.add_argument(
    128       '--minilayout',
    129       dest='minilayout',
    130       default=False,
    131       action='store_true',
    132       help='Whether to checkout the minilayout (smaller '
    133       'checkout).')
    134   parser.add_argument(
    135       '--jobs', '-j', dest='jobs', help='Number of repo sync threads to use.')
    136   parser.add_argument(
    137       '--public',
    138       '-p',
    139       dest='public',
    140       default=False,
    141       action='store_true',
    142       help='Use the public checkout instead of the private '
    143       'one.')
    144 
    145   options = parser.parse_args(argv)
    146 
    147   if not options.version:
    148     parser.print_help()
    149     logger.GetLogger().LogFatal('No version specified.')
    150   else:
    151     version = options.version.strip()
    152 
    153   if not options.timestamp:
    154     timestamp = ''
    155   else:
    156     timestamp = options.timestamp.strip()
    157     if version not in ('lkgm', 'common'):
    158       parser.print_help()
    159       logger.GetLogger().LogFatal('timestamp option only applies for '
    160                                   "versions \"lkgm\" or \"common\"")
    161 
    162   if not options.directory:
    163     parser.print_help()
    164     logger.GetLogger().LogFatal('No directory specified.')
    165 
    166   directory = options.directory.strip()
    167 
    168   if options.public:
    169     manifest_repo = 'https://chromium.googlesource.com/chromiumos/manifest.git'
    170     versions_repo = ('https://chromium.googlesource.com/'
    171                      'chromiumos/manifest-versions.git')
    172   else:
    173     manifest_repo = ('https://chrome-internal.googlesource.com/chromeos/'
    174                      'manifest-internal.git')
    175     versions_repo = ('https://chrome-internal.googlesource.com/chromeos/'
    176                      'manifest-versions.git')
    177 
    178   if version == 'top':
    179     init = 'repo init -u %s' % manifest_repo
    180   elif version == 'latest_lkgm':
    181     manifests = manifest_versions.ManifestVersions()
    182     version = manifests.TimeToVersionChromeOS(time.mktime(time.gmtime()))
    183     version, manifest = version.split('.', 1)
    184     logger.GetLogger().LogOutput('found version %s.%s for latest LKGM' %
    185                                  (version, manifest))
    186     init = ('repo init -u %s -m paladin/buildspecs/%s/%s.xml' %
    187             (versions_repo, version, manifest))
    188     del manifests
    189   elif version == 'lkgm':
    190     if not timestamp:
    191       parser.print_help()
    192       logger.GetLogger().LogFatal('No timestamp specified for version=lkgm')
    193     manifests = manifest_versions.ManifestVersions()
    194     version = manifests.TimeToVersion(timestamp)
    195     version, manifest = version.split('.', 1)
    196     logger.GetLogger().LogOutput(
    197         'found version %s.%s for LKGM at timestamp %s' % (version, manifest,
    198                                                           timestamp))
    199     init = ('repo init -u %s -m paladin/buildspecs/%s/%s.xml' %
    200             (versions_repo, version, manifest))
    201     del manifests
    202   elif version == 'latest_common':
    203     version = TimeToCommonVersion(time.mktime(time.gmtime()))
    204     version, manifest = version.split('.', 1)
    205     logger.GetLogger().LogOutput('found version %s.%s for latest Common image' %
    206                                  (version, manifest))
    207     init = ('repo init -u %s -m buildspecs/%s/%s.xml' % (versions_repo, version,
    208                                                          manifest))
    209   elif version == 'common':
    210     if not timestamp:
    211       parser.print_help()
    212       logger.GetLogger().LogFatal('No timestamp specified for version=lkgm')
    213     version = TimeToCommonVersion(timestamp)
    214     version, manifest = version.split('.', 1)
    215     logger.GetLogger().LogOutput('found version %s.%s for latest common image '
    216                                  'at timestamp %s' % (version, manifest,
    217                                                       timestamp))
    218     init = ('repo init -u %s -m buildspecs/%s/%s.xml' % (versions_repo, version,
    219                                                          manifest))
    220   else:
    221     # user specified a specific version number
    222     version_spec_file = GetVersionSpecFile(version, versions_repo)
    223     if not version_spec_file:
    224       return 1
    225     init = 'repo init -u %s -m %s' % (versions_repo, version_spec_file)
    226 
    227   if options.minilayout:
    228     init += ' -g minilayout'
    229 
    230   init += ' --repo-url=https://chromium.googlesource.com/external/repo.git'
    231 
    232   # crosbug#31837 - "Sources need to be world-readable to properly
    233   # function inside the chroot"
    234   sync = 'umask 022 && repo sync'
    235   if options.jobs:
    236     sync += ' -j %s' % options.jobs
    237 
    238   commands = ['mkdir -p %s' % directory, 'cd %s' % directory, init, sync]
    239   cmd_executer = command_executer.GetCommandExecuter()
    240   ret = cmd_executer.RunCommands(commands)
    241   if ret:
    242     return ret
    243 
    244   return cmd_executer.RunCommand(
    245       'git ls-remote '
    246       'https://chrome-internal.googlesource.com/chrome/src-internal.git '
    247       '> /dev/null')
    248 
    249 
    250 if __name__ == '__main__':
    251   retval = Main(sys.argv[1:])
    252   sys.exit(retval)
    253