blob: d40691024c932b87ed4adf04fa6fe7ae4398ea71 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright 2014 Google Inc. All Rights Reserved.
import argparse
import os
import re
import shutil
import subprocess
import sys
import zipfile
parser = argparse.ArgumentParser(
description=('Update prebuilt android support libraries'))
parser.add_argument(
'buildId',
type=int,
nargs='?',
help='Build server build ID')
parser.add_argument(
'--target',
default='sdk',
help='Download from the specified build server target')
parser.add_argument(
'--from-local-dir',
dest='localDir',
help='Copy prebuilts from local directory instead of buildserver')
parser.add_argument(
'--no-git',
action='store_true',
help='Do not create a git commit for the import')
args = parser.parse_args()
if not args.buildId and not args.localDir:
parser.error("you must specify either a build ID or --from-local-dir")
sys.exit(1)
if not args.no_git:
# Make sure we don't overwrite any pending changes
try:
subprocess.check_call(['git', 'diff', '--quiet', '--', '**'])
subprocess.check_call(['git', 'diff', '--quiet', '--cached', '--', '**'])
except subprocess.CalledProcessError:
print >> sys.stderr, "FAIL: There are uncommitted changes here; please revert or stash"
sys.exit(1)
def GetSSOCmdline(url):
return ['sso_client', '--location', '--request_timeout', '90', '--url', url]
def SSOFetch(url):
return subprocess.check_output(GetSSOCmdline(url), stderr=subprocess.STDOUT)
def FetchFile(srcFile, dstFile):
if not args.localDir:
fileURL = buildURL + '/' + srcFile
subprocess.check_call(' '.join(GetSSOCmdline(fileURL) + ['>', dstFile]), shell=True)
else:
shutil.copyfile(os.path.join(args.localDir, srcFile), dstFile)
if not args.localDir:
# to start, find the build server branch we're downloading from
try:
branch = SSOFetch("http://android-build/buildbot-update?op=GET-BRANCH&bid=%d" % args.buildId)
except subprocess.CalledProcessError:
print >> sys.stderr, "FAIL: Unable to retrieve branch for build ID %d" % args.buildId
sys.exit(1)
buildURL = "http://android-build/builds/%s-linux-%s/%d" % (branch, args.target, args.buildId)
# fetch the list build artifacts
try:
listingText = SSOFetch(buildURL + "?output=text")
except subprocess.CalledProcessError:
print >> sys.stderr, "FAIL: Unable to retrieve listing for build ID %d" % args.buildId
sys.exit(1)
listing = listingText.strip().split('\n')
else:
listing = os.listdir(args.localDir)
supportZipRE = re.compile(r'^sdk-repo-linux-support-.*\.zip$')
supportZipFile = None
for fname in listing:
if supportZipRE.match(fname):
supportZipFile = fname
break
if not supportZipFile:
src = 'directory' if args.localDir else 'build'
print >> sys.stderr, "FAIL: The specified %s contains no support library ZIP" % src
sys.exit(1)
try:
FetchFile(supportZipFile, supportZipFile)
except:
print >> sys.stderr, "FAIL: Unable to fetch %s" % supportZipFile
sys.exit(1)
try: # make sure we delete the downloaded ZIP
SUPPORT_LIBS = [
('support/v4', 'v4'),
('support/v7/appcompat', 'appcompat'),
('support/v7/cardview', 'cardview'),
('support/v7/gridlayout', 'gridlayout'),
('support/v7/mediarouter', 'mediarouter'),
('support/v7/recyclerview', 'recyclerview'),
('support/v7/palette', 'palette'),
('support/v13', 'v13'),
('support/v17/leanback', 'leanback'),
('support/multidex/library', 'multidex'),
]
with zipfile.ZipFile(supportZipFile) as supportZip:
# update each support library
for libEntry in SUPPORT_LIBS:
# clean out the existing prebuilt
buildDotGradle = os.path.join(libEntry[1], 'build.gradle')
hadBuildDotGradle = False
if os.path.exists(libEntry[1]) and os.path.isdir(libEntry[1]):
hadBuildDotGradle = os.path.isfile(buildDotGradle)
subprocess.check_call(['git', 'rm', '-rf', libEntry[1]])
# extract the new version of the library
libZipDir = libEntry[0] + '/'
libSrcZipDir = libEntry[0] + '/src/'
for fname in supportZip.namelist():
if (fname[-1] != '/'
and fname.startswith(libZipDir)
and not fname.startswith(libSrcZipDir)):
relativePath = fname[len(libZipDir):]
subdirs = os.path.join(libEntry[1], os.path.dirname(relativePath))
if not os.path.exists(subdirs):
os.makedirs(subdirs)
with supportZip.open(fname, 'r') as infile:
with open(os.path.join(libEntry[1], relativePath), 'w+') as outfile:
shutil.copyfileobj(infile, outfile)
subprocess.check_call(['git', 'add', libEntry[1]])
# bring back any pre-existing build.gradle
if hadBuildDotGradle:
subprocess.check_call(['git', 'checkout', 'HEAD', buildDotGradle])
if not args.no_git:
# commit all changes
if not args.localDir:
# gather useful info
buildInfo = dict(
buildURL = buildURL,
buildId = args.buildId,
branch = branch,
supportZipFile = supportZipFile,
)
msg = """Import prebuilt android support libs build {buildId}
{buildURL}/{supportZipFile}
""".format(**buildInfo)
else:
msg = "DO NOT SUBMIT Import locally built android support libs from %s" % args.localDir
subprocess.check_call(['git', 'commit', '-m', msg])
print 'Update successful.'
if not args.localDir:
print 'Be sure to upload this manually to gerrit.'
finally:
# revert all stray files, including the downloaded zip
try:
with open(os.devnull, 'w') as bitbucket:
subprocess.check_call(['git', 'add', '-Af', '.'], stdout=bitbucket)
subprocess.check_call(
['git', 'commit', '-m', 'COMMIT TO REVERT - RESET ME!!!'], stdout=bitbucket)
subprocess.check_call(['git', 'reset', '--hard', 'HEAD~1'], stdout=bitbucket)
except subprocess.CalledProcessError:
print >> sys.stderr, "ERROR: Failed cleaning up, manual cleanup required!!!"