1 # Copyright (C) 2016 The Android Open-Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 """Various utility functions""" 16 17 import logging 18 import os 19 import shlex 20 import subprocess 21 22 23 # The default location in which symbols and minidumps will be saved. 24 _DEFAULT_ARTIFACT_CACHE_ROOT = os.environ.get('ARC_ARTIFACT_CACHE_ROOT', 25 '/tmp/arc-artifact-cache') 26 27 28 def get_command_str(command): 29 """Returns a quoted version of the command, friendly to copy/paste.""" 30 return ' '.join(shlex.quote(arg) for arg in command) 31 32 33 def check_call(*subprocess_args, sudo=False, dryrun=False, **kwargs): 34 """Runs a subprocess and returns its exit code.""" 35 if sudo: 36 subprocess_args = ('/usr/bin/sudo',) + subprocess_args 37 if logging.getLogger().isEnabledFor(logging.DEBUG): 38 if kwargs: 39 logging.debug('Calling: %s (kwargs %r)', get_command_str(subprocess_args), 40 kwargs) 41 else: 42 logging.debug('Calling: %s', get_command_str(subprocess_args)) 43 if dryrun: 44 return 45 try: 46 return subprocess.check_call(subprocess_args, **kwargs) 47 except subprocess.CalledProcessError as e: 48 logging.error('Error while executing %s', get_command_str(subprocess_args)) 49 logging.error(e.output) 50 raise 51 52 53 def check_output(*subprocess_args, sudo=False, dryrun=False, 54 universal_newlines=True, **kwargs): 55 """Runs a subprocess and returns its output.""" 56 if sudo: 57 subprocess_args = ('/usr/bin/sudo',) + subprocess_args 58 if logging.getLogger().isEnabledFor(logging.DEBUG): 59 if kwargs: 60 logging.debug('Calling: %s (kwargs %r)', get_command_str(subprocess_args), 61 kwargs) 62 else: 63 logging.debug('Calling: %s', get_command_str(subprocess_args)) 64 if dryrun: 65 logging.info('Cannot return any output without running the command. ' 66 'Returning an empty string instead.') 67 return '' 68 try: 69 return subprocess.check_output(subprocess_args, 70 universal_newlines=universal_newlines, 71 **kwargs) 72 except subprocess.CalledProcessError as e: 73 logging.error('Error while executing %s', get_command_str(subprocess_args)) 74 logging.error(e.output) 75 raise 76 77 78 def find_repo_root(path=None): 79 """Locate the top level of this repo checkout starting at |path|.""" 80 if path is None: 81 path = os.getcwd() 82 orig_path = path 83 path = os.path.abspath(path) 84 while not os.path.exists(os.path.join(path, '.repo')): 85 path = os.path.dirname(path) 86 if path == '/': 87 raise ValueError('Could not locate .repo in %s' % orig_path) 88 return path 89 90 91 def makedirs(path): 92 """Makes directories if necessary, like 'mkdir -p'""" 93 if not os.path.exists(path): 94 os.makedirs(path) 95 96 97 def get_prebuilt(tool): 98 """Locates a prebuilt file to run.""" 99 return os.path.abspath(os.path.join( 100 os.path.dirname(os.path.dirname(__file__)), 'prebuilt/x86-linux/', tool)) 101 102 103 def helper_temp_path(*path, artifact_cache_root=_DEFAULT_ARTIFACT_CACHE_ROOT): 104 """Returns the path to use for temporary/cached files.""" 105 return os.path.join(artifact_cache_root, *path) 106 107 108 def get_product_arch(product): 109 """Returns the architecture of a given target |product|.""" 110 # The prefix can itself have other prefixes, like 'generic_' or 'aosp_'. 111 for product_prefix in ('bertha_', 'cheets_'): 112 idx = product.find(product_prefix) 113 if idx < 0: 114 continue 115 return product[idx + len(product_prefix):] 116 raise Exception('Unrecognized product: %s' % product) 117 118 119 def get_product_name(product): 120 """Returns the name of a given target |product|.""" 121 # The prefix can itself have other prefixes, like 'generic_' or 'aosp_'. 122 for product_prefix in ('bertha_', 'cheets_'): 123 idx = product.find(product_prefix) 124 if idx < 0: 125 continue 126 return product_prefix.rstrip('_') 127 raise Exception('Unrecognized product: %s' % product) 128 129 130 def get_image_type(image_path): 131 """Returns the type of a given image |image_path|.""" 132 if 'Squashfs' in subprocess.check_output( 133 ['/usr/bin/file', '--brief', image_path], universal_newlines=True): 134 return 'squashfs' 135 else: 136 return 'ext4' 137