#!/usr/bin/env python
|
#
|
# Copyright (C) 2016 The Android Open Source Project
|
#
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
# you may not use this file except in compliance with the License.
|
# You may obtain a copy of the License at
|
#
|
# http://www.apache.org/licenses/LICENSE-2.0
|
#
|
# Unless required by applicable law or agreed to in writing, software
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# See the License for the specific language governing permissions and
|
# limitations under the License.
|
#
|
import argparse
|
import glob
|
import logging
|
import os
|
import shutil
|
import subprocess
|
import textwrap
|
|
|
THIS_DIR = os.path.realpath(os.path.dirname(__file__))
|
|
|
def logger():
|
return logging.getLogger(__name__)
|
|
|
def check_call(cmd):
|
logger().debug('Running `%s`', ' '.join(cmd))
|
subprocess.check_call(cmd)
|
|
|
def remove(path):
|
logger().debug('remove `%s`', path)
|
os.remove(path)
|
|
|
def fetch_artifact(branch, build, pattern):
|
fetch_artifact_path = '/google/data/ro/projects/android/fetch_artifact'
|
cmd = [fetch_artifact_path, '--branch', branch, '--target=linux',
|
'--bid', build, pattern]
|
check_call(cmd)
|
|
|
def api_str(api_level):
|
return 'android-{}'.format(api_level)
|
|
|
def start_branch(build):
|
branch_name = 'update-' + (build or 'latest')
|
logger().info('Creating branch %s', branch_name)
|
check_call(['repo', 'start', branch_name, '.'])
|
|
|
def remove_old_release(install_dir):
|
if os.path.exists(os.path.join(install_dir, '.git')):
|
logger().info('Removing old install directory "%s"', install_dir)
|
check_call(['git', 'rm', '-rf', install_dir])
|
|
# Need to check again because git won't remove directories if they have
|
# non-git files in them.
|
if os.path.exists(install_dir):
|
shutil.rmtree(install_dir)
|
|
|
def install_new_release(branch, build, install_dir):
|
os.makedirs(install_dir)
|
|
artifact_pattern = 'android-ndk-*.tar.bz2'
|
logger().info('Fetching %s from %s (artifacts matching %s)', build, branch,
|
artifact_pattern)
|
fetch_artifact(branch, build, artifact_pattern)
|
artifacts = glob.glob('android-ndk-*.tar.bz2')
|
try:
|
assert len(artifacts) == 1
|
artifact = artifacts[0]
|
|
logger().info('Extracting release')
|
cmd = ['tar', 'xf', artifact, '-C', install_dir, '--wildcards',
|
'--strip-components=1', '*/platforms', '*/sources',
|
'*/source.properties']
|
check_call(cmd)
|
finally:
|
for artifact in artifacts:
|
os.unlink(artifact)
|
|
|
def remove_unneeded_files(install_dir):
|
for path, _dirs, files in os.walk(os.path.join(install_dir, 'platforms')):
|
for file_name in files:
|
if file_name.endswith('.so'):
|
file_path = os.path.join(path, file_name)
|
remove(file_path)
|
|
for path, _dirs, files in os.walk(os.path.join(install_dir, 'sources')):
|
for file_name in files:
|
if file_name == 'Android.bp':
|
file_path = os.path.join(path, file_name)
|
remove(file_path)
|
|
|
def make_symlinks(install_dir):
|
old_dir = os.getcwd()
|
os.chdir(os.path.join(THIS_DIR, install_dir, 'platforms'))
|
|
first_api = 9
|
first_lp64_api = 21
|
|
for api in xrange(first_api, first_lp64_api):
|
if not os.path.exists(api_str(api)):
|
continue
|
|
for arch in ('arch-arm64', 'arch-mips64', 'arch-x86_64'):
|
src = os.path.join('..', api_str(first_lp64_api), arch)
|
dst = os.path.join(api_str(api), arch)
|
if os.path.islink(dst):
|
os.unlink(dst)
|
os.symlink(src, dst)
|
|
os.chdir(old_dir)
|
|
|
def commit(branch, build, install_dir):
|
logger().info('Making commit')
|
check_call(['git', 'add', install_dir])
|
message = textwrap.dedent("""\
|
Update NDK prebuilts to build {build}.
|
|
Taken from branch {branch}.""").format(branch=branch, build=build)
|
check_call(['git', 'commit', '-m', message])
|
|
|
def get_args():
|
parser = argparse.ArgumentParser()
|
parser.add_argument(
|
'-b', '--branch', default='master-ndk',
|
help='Branch to pull build from.')
|
parser.add_argument(
|
'major_release', help='Major release being installed, e.g. "r11".')
|
parser.add_argument('--build', required=True, help='Build number to pull.')
|
parser.add_argument(
|
'--use-current-branch', action='store_true',
|
help='Perform the update in the current branch. Do not repo start.')
|
parser.add_argument(
|
'-v', '--verbose', action='count', default=0,
|
help='Increase output verbosity.')
|
return parser.parse_args()
|
|
|
def main():
|
os.chdir(THIS_DIR)
|
|
args = get_args()
|
verbose_map = (logging.WARNING, logging.INFO, logging.DEBUG)
|
verbosity = args.verbose
|
if verbosity > 2:
|
verbosity = 2
|
logging.basicConfig(level=verbose_map[verbosity])
|
|
install_dir = os.path.realpath(args.major_release)
|
|
if not args.use_current_branch:
|
start_branch(args.build)
|
remove_old_release(install_dir)
|
install_new_release(args.branch, args.build, install_dir)
|
remove_unneeded_files(install_dir)
|
make_symlinks(install_dir)
|
commit(args.branch, args.build, install_dir)
|
|
|
if __name__ == '__main__':
|
main()
|