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