Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/env python
      2 #
      3 # Copyright (C) 2016 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 """Downloads simpleperf prebuilts from the build server."""
     18 import argparse
     19 import logging
     20 import os
     21 import shutil
     22 import stat
     23 import textwrap
     24 
     25 
     26 THIS_DIR = os.path.realpath(os.path.dirname(__file__))
     27 
     28 
     29 class InstallEntry(object):
     30     def __init__(self, target, name, install_path, need_strip=False):
     31         self.target = target
     32         self.name = name
     33         self.install_path = install_path
     34         self.need_strip = need_strip
     35 
     36 
     37 install_list = [
     38     # simpleperf on device
     39     InstallEntry('sdk_arm64-sdk', 'simpleperf', 'android/arm64/simpleperf'),
     40     InstallEntry('sdk_arm64-sdk', 'simpleperf32', 'android/arm/simpleperf'),
     41     InstallEntry('sdk_x86_64-sdk', 'simpleperf', 'android/x86_64/simpleperf'),
     42     InstallEntry('sdk_x86_64-sdk', 'simpleperf32', 'android/x86/simpleperf'),
     43 
     44     # simpleperf on host
     45     InstallEntry('sdk_arm64-sdk', 'simpleperf_host', 'linux/x86_64/simpleperf', True),
     46     InstallEntry('sdk_arm64-sdk', 'simpleperf_host32', 'linux/x86/simpleperf', True),
     47     InstallEntry('sdk_mac', 'simpleperf_host', 'darwin/x86_64/simpleperf'),
     48     InstallEntry('sdk_mac', 'simpleperf_host32', 'darwin/x86/simpleperf'),
     49     InstallEntry('sdk', 'simpleperf.exe', 'windows/x86_64/simpleperf.exe', True),
     50     InstallEntry('sdk', 'simpleperf32.exe', 'windows/x86/simpleperf.exe', True),
     51 
     52     # libsimpleperf_report.so on host
     53     InstallEntry('sdk_arm64-sdk', 'libsimpleperf_report.so', 'linux/x86_64/libsimpleperf_report.so', True),
     54     InstallEntry('sdk_arm64-sdk', 'libsimpleperf_report32.so', 'linux/x86/libsimpleperf_report.so', True),
     55     InstallEntry('sdk_mac', 'libsimpleperf_report.dylib', 'darwin/x86_64/libsimpleperf_report.dylib'),
     56     InstallEntry('sdk_mac', 'libsimpleperf_report32.so', 'darwin/x86/libsimpleperf_report.dylib'),
     57     InstallEntry('sdk', 'libsimpleperf_report.dll', 'windows/x86_64/libsimpleperf_report.dll', True),
     58     InstallEntry('sdk', 'libsimpleperf_report32.dll', 'windows/x86/libsimpleperf_report.dll', True),
     59 ]
     60 
     61 
     62 def logger():
     63     """Returns the main logger for this module."""
     64     return logging.getLogger(__name__)
     65 
     66 
     67 def check_call(cmd):
     68     """Proxy for subprocess.check_call with logging."""
     69     import subprocess
     70     logger().debug('check_call `%s`', ' '.join(cmd))
     71     subprocess.check_call(cmd)
     72 
     73 
     74 def fetch_artifact(branch, build, target, pattern):
     75     """Fetches and artifact from the build server."""
     76     logger().info('Fetching %s from %s %s (artifacts matching %s)', build,
     77                   target, branch, pattern)
     78     fetch_artifact_path = '/google/data/ro/projects/android/fetch_artifact'
     79     cmd = [fetch_artifact_path, '--branch', branch, '--target', target,
     80            '--bid', build, pattern]
     81     check_call(cmd)
     82 
     83 
     84 def start_branch(build):
     85     """Creates a new branch in the project."""
     86     branch_name = 'update-' + (build or 'latest')
     87     logger().info('Creating branch %s', branch_name)
     88     check_call(['repo', 'start', branch_name, '.'])
     89 
     90 
     91 def commit(branch, build, add_paths):
     92     """Commits the new prebuilts."""
     93     logger().info('Making commit')
     94     check_call(['git', 'add'] + add_paths)
     95     message = textwrap.dedent("""\
     96         simpleperf: update simpleperf prebuilts to build {build}.
     97 
     98         Taken from branch {branch}.""").format(branch=branch, build=build)
     99     check_call(['git', 'commit', '-m', message])
    100 
    101 
    102 def remove_old_release(install_dir):
    103     """Removes the old prebuilts."""
    104     if os.path.exists(install_dir):
    105         logger().info('Removing old install directory "%s"', install_dir)
    106         check_call(['git', 'rm', '-rf', '--ignore-unmatch', install_dir])
    107 
    108     # Need to check again because git won't remove directories if they have
    109     # non-git files in them.
    110     if os.path.exists(install_dir):
    111         shutil.rmtree(install_dir)
    112 
    113 
    114 def install_new_release(branch, build, install_dir):
    115     """Installs the new release."""
    116     for entry in install_list:
    117         install_entry(branch, build, install_dir, entry)
    118 
    119 
    120 def install_entry(branch, build, install_dir, entry):
    121     """Installs the device specific components of the release."""
    122     target = entry.target
    123     name = entry.name
    124     install_path = os.path.join(install_dir, entry.install_path)
    125     need_strip = entry.need_strip
    126 
    127     fetch_artifact(branch, build, target, name)
    128     exe_stat = os.stat(name)
    129     os.chmod(name, exe_stat.st_mode | stat.S_IEXEC)
    130     if need_strip:
    131         check_call(['strip', name])
    132     dir = os.path.dirname(install_path)
    133     if not os.path.isdir(dir):
    134         os.makedirs(dir)
    135     shutil.move(name, install_path)
    136 
    137 
    138 def get_args():
    139     """Parses and returns command line arguments."""
    140     parser = argparse.ArgumentParser()
    141 
    142     parser.add_argument(
    143         '-b', '--branch', default='aosp-master',
    144         help='Branch to pull build from.')
    145     parser.add_argument('--build', required=True, help='Build number to pull.')
    146     parser.add_argument(
    147         '--use-current-branch', action='store_true',
    148         help='Perform the update in the current branch. Do not repo start.')
    149     parser.add_argument(
    150         '-v', '--verbose', action='count', default=0,
    151         help='Increase output verbosity.')
    152 
    153     return parser.parse_args()
    154 
    155 
    156 def main():
    157     """Program entry point."""
    158     os.chdir(THIS_DIR)
    159 
    160     args = get_args()
    161     verbose_map = (logging.WARNING, logging.INFO, logging.DEBUG)
    162     verbosity = args.verbose
    163     if verbosity > 2:
    164         verbosity = 2
    165     logging.basicConfig(level=verbose_map[verbosity])
    166 
    167     install_dir = 'bin'
    168 
    169     if not args.use_current_branch:
    170         start_branch(args.build)
    171     remove_old_release(install_dir)
    172     install_new_release(args.branch, args.build, install_dir)
    173     artifacts = [install_dir]
    174     commit(args.branch, args.build, artifacts)
    175 
    176 
    177 if __name__ == '__main__':
    178     main()