1# -*- coding: utf-8 -*- 2# Copyright (c) 2013 The Chromium OS 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"""Tools for searching/manipulating the manifests repository.""" 7 8from __future__ import print_function 9 10__author__ = 'llozano@google.com (Luis Lozano)' 11 12import copy 13import os 14import re 15import shutil 16import tempfile 17import time 18 19from cros_utils import command_executer 20from cros_utils import logger 21 22MANIFEST_VERSION_MAIN_BRANCH = 'master' 23 24 25def IsCrosVersion(version): 26 match = re.search(r'(\d+\.\d+\.\d+\.\d+)', version) 27 return match is not None 28 29 30def IsRFormatCrosVersion(version): 31 match = re.search(r'(R\d+-\d+\.\d+\.\d+)', version) 32 return match is not None 33 34 35def RFormatCrosVersion(version): 36 assert IsCrosVersion(version) 37 tmp_major, tmp_minor = version.split('.', 1) 38 rformat = 'R' + tmp_major + '-' + tmp_minor 39 assert IsRFormatCrosVersion(rformat) 40 return rformat 41 42 43class ManifestVersions(object): 44 """This class handles interactions with the manifests repo.""" 45 46 def __init__(self, internal=True): 47 self.internal = internal 48 self.clone_location = tempfile.mkdtemp() 49 self.ce = command_executer.GetCommandExecuter() 50 if internal: 51 versions_git = ('https://chrome-internal.googlesource.com/' 52 'chromeos/manifest-versions.git') 53 else: 54 versions_git = ( 55 'https://chromium.googlesource.com/chromiumos/manifest-versions.git') 56 commands = [ 57 'cd {0}'.format(self.clone_location), 58 'git clone {0}'.format(versions_git) 59 ] 60 ret = self.ce.RunCommands(commands) 61 if ret: 62 logger.GetLogger().LogFatal('Failed to clone manifest-versions.') 63 64 def __del__(self): 65 if self.clone_location: 66 shutil.rmtree(self.clone_location) 67 68 def TimeToVersionChromeOS(self, my_time): 69 """Convert timestamp to version number, in ChromeOS/Paladin.""" 70 cur_time = time.mktime(time.gmtime()) 71 des_time = float(my_time) 72 if cur_time - des_time > 7000000: 73 logger.GetLogger().LogFatal('The time you specify is too early.') 74 commands = [ 75 'cd {0}'.format(self.clone_location), 'cd manifest-versions', 76 'git checkout -f $(git rev-list' + 77 ' --max-count=1 --before={0} origin/{1})'.format( 78 my_time, MANIFEST_VERSION_MAIN_BRANCH) 79 ] 80 ret = self.ce.RunCommands(commands) 81 if ret: 82 logger.GetLogger().LogFatal('Failed to checkout manifest at ' 83 'specified time') 84 path = os.path.realpath('{0}/manifest-versions/LKGM/lkgm.xml'.format( 85 self.clone_location)) 86 pp = path.split('/') 87 new_list = copy.deepcopy(pp) 88 for i, e in enumerate(pp): 89 if e == 'android-LKGM-candidates': 90 new_list[i] = 'paladin' 91 chrome_path = '/'.join(new_list) 92 if not os.path.exists(chrome_path): 93 logger.GetLogger().LogOutput('LKGM path is %s' % path) 94 logger.GetLogger().LogOutput('Cannot find path %s' % chrome_path) 95 pieces = os.path.basename(chrome_path).split('.') 96 pieces = pieces[:-2] 97 new_base = '.'.join(pieces) + '*' 98 wild_path = os.path.join('/', '/'.join(new_list[:-1]), new_base) 99 command = 'ls %s' % wild_path 100 ret, out, _ = self.ce.RunCommandWOutput(command) 101 if ret == 0: 102 out = out.strip() 103 files = out.split('\n') 104 latest = files[-1] 105 small = os.path.basename(latest).split('.xml')[0] 106 version = pp[-2] + '.' + small 107 else: 108 small = os.path.basename(path).split('.xml')[0] 109 version = pp[-2] + '.' + small 110 commands = [ 111 'cd {0}'.format(self.clone_location), 'cd manifest-versions', 112 'git checkout {0}'.format(MANIFEST_VERSION_MAIN_BRANCH) 113 ] 114 self.ce.RunCommands(commands) 115 return version 116 117 def TimeToVersion(self, my_time): 118 """Convert timestamp to version number.""" 119 cur_time = time.mktime(time.gmtime()) 120 des_time = float(my_time) 121 if cur_time - des_time > 7000000: 122 logger.GetLogger().LogFatal('The time you specify is too early.') 123 commands = [ 124 'cd {0}'.format(self.clone_location), 'cd manifest-versions', 125 'git checkout -f $(git rev-list' + 126 ' --max-count=1 --before={0} origin/{1})'.format( 127 my_time, MANIFEST_VERSION_MAIN_BRANCH) 128 ] 129 ret = self.ce.RunCommands(commands) 130 if ret: 131 logger.GetLogger().LogFatal('Failed to checkout manifest at ' 132 'specified time') 133 path = os.path.realpath('{0}/manifest-versions/LKGM/lkgm.xml'.format( 134 self.clone_location)) 135 pp = path.split('/') 136 small = os.path.basename(path).split('.xml')[0] 137 version = pp[-2] + '.' + small 138 commands = [ 139 'cd {0}'.format(self.clone_location), 'cd manifest-versions', 140 'git checkout {0}'.format(MANIFEST_VERSION_MAIN_BRANCH) 141 ] 142 self.ce.RunCommands(commands) 143 return version 144 145 def GetManifest(self, version, to_file): 146 """Get the manifest file from a given chromeos-internal version.""" 147 assert not IsRFormatCrosVersion(version) 148 version = version.split('.', 1)[1] 149 os.chdir(self.clone_location) 150 files = [ 151 os.path.join(r, f) 152 for r, _, fs in os.walk('.') 153 for f in fs 154 if version in f 155 ] 156 if files: 157 command = 'cp {0} {1}'.format(files[0], to_file) 158 ret = self.ce.RunCommand(command) 159 if ret: 160 raise RuntimeError('Cannot copy manifest to {0}'.format(to_file)) 161 else: 162 raise RuntimeError('Version {0} is not available.'.format(version)) 163