blob: 7b6be0c679fd4cd1876f68ff43d3934eb24c19fa [file] [log] [blame]
Alan Viverette95f6d362017-04-06 09:40:50 -04001#!/usr/bin/python
2
3import os, sys, getopt, zipfile, re
Alan Viveretted4527e62017-05-11 15:03:25 -04004import argparse
5import subprocess
Alan Viverette95f6d362017-04-06 09:40:50 -04006from shutil import copyfile, rmtree
Alan Viveretted4527e62017-05-11 15:03:25 -04007from distutils.version import LooseVersion
Alan Viverette95f6d362017-04-06 09:40:50 -04008
9output_path = 'current/support'
10
Alan Viveretted4527e62017-05-11 15:03:25 -040011# See go/fetch_artifact
12FETCH_ARTIFACT = '/google/data/ro/projects/android/fetch_artifact'
13
Alan Viverette95f6d362017-04-06 09:40:50 -040014# Does not import support-v4, which is handled as a separate Android.mk (../support-v4) to
15# statically include dependencies. Similarly, the support-v13 module is imported as
16# support-v13-nodeps and then handled as a separate Android.mk (../support-v13) to statically
17# include dependencies.
18maven_to_make = {
19 'animated-vector-drawable': ['android-support-animatedvectordrawable', 'graphics/drawable'],
20 'appcompat-v7': ['android-support-v7-appcompat', 'v7/appcompat'],
21 'cardview-v7': ['android-support-v7-cardview', 'v7/cardview'],
22 'customtabs': ['android-support-customtabs', 'customtabs'],
23 'design': ['android-support-design', 'design'],
24 'exifinterface': ['android-support-exifinterface', 'exifinterface'],
25 'gridlayout-v7': ['android-support-v7-gridlayout', 'v7/gridlayout'],
26 'leanback-v17': ['android-support-v17-leanback', 'v17/leanback'],
27 'mediarouter-v7': ['android-support-v7-mediarouter', 'v7/mediarouter'],
28 'multidex': ['android-support-multidex', 'multidex/library'],
29 'multidex-instrumentation': ['android-support-multidex-instrumentation', 'multidex/instrumentation'],
30 'palette-v7': ['android-support-v7-palette', 'v7/palette'],
31 'percent': ['android-support-percent', 'percent'],
32 'preference-leanback-v17': ['android-support-v17-preference-leanback', 'v17/preference-leanback'],
33 'preference-v14': ['android-support-v14-preference', 'v14/preference'],
34 'preference-v7': ['android-support-v7-preference', 'v7/preference'],
35 'recommendation': ['android-support-recommendation', 'recommendation'],
36 'recyclerview-v7': ['android-support-v7-recyclerview', 'v7/recyclerview'],
37 'support-annotations': ['android-support-annotations', 'annotations'],
38 'support-compat': ['android-support-compat', 'compat'],
39 'support-core-ui': ['android-support-core-ui', 'core-ui'],
40 'support-core-utils': ['android-support-core-utils', 'core-utils'],
41 'support-dynamic-animation': ['android-support-dynamic-animation', 'dynamic-animation'],
42 'support-emoji': ['android-support-emoji', 'emoji'],
43 'support-emoji-appcompat': ['android-support-emoji-appcompat', 'emoji-appcompat'],
44 'support-emoji-bundled': ['android-support-emoji-bundled', 'emoji-bundled'],
45 'support-fragment': ['android-support-fragment', 'fragment'],
46 'support-media-compat': ['android-support-media-compat', 'media-compat'],
47 'support-tv-provider': ['android-support-tv-provider', 'tv-provider'],
48 'support-v13': ['android-support-v13-nodeps', 'v13-nodeps'],
49 'support-vector-drawable': ['android-support-vectordrawable', 'graphics/drawable'],
50 'transition': ['android-support-transition', 'transition'],
51 'wear': ['android-support-wear', 'wear']
52}
53
54# Always remove these files.
55blacklist_files = [
56 'annotations.zip',
57 'public.txt',
58 'R.txt',
59 'AndroidManifest.xml'
60]
61
Alan Viveretted4527e62017-05-11 15:03:25 -040062artifact_pattern = re.compile(r"^(.+?)-(\d+\.\d+\.\d+(?:-\w+\d*)?)\.(jar|aar)$")
Alan Viverette95f6d362017-04-06 09:40:50 -040063
64
65def touch(fname, times=None):
66 with open(fname, 'a'):
67 os.utime(fname, times)
68
69
Alan Viveretted4527e62017-05-11 15:03:25 -040070def transform_support(repoDir):
Alan Viverette95f6d362017-04-06 09:40:50 -040071 cwd = os.getcwd()
72
Alan Viverette95f6d362017-04-06 09:40:50 -040073 # Use a temporary working directory.
74 working_dir = os.path.join(cwd, 'support_tmp')
75 if os.path.exists(working_dir):
76 rmtree(working_dir)
77 os.mkdir(working_dir)
78
Alan Viveretted4527e62017-05-11 15:03:25 -040079 maven_lib_info = {}
80
81 for root, dirs, files in os.walk(repoDir):
Alan Viverette95f6d362017-04-06 09:40:50 -040082 for file in files:
83 matcher = artifact_pattern.match(file)
84 if matcher:
85 maven_lib_name = matcher.group(1)
Alan Viveretted4527e62017-05-11 15:03:25 -040086 maven_lib_vers = LooseVersion(matcher.group(2))
Alan Viverette95f6d362017-04-06 09:40:50 -040087
88 if maven_lib_name in maven_to_make:
Alan Viveretted4527e62017-05-11 15:03:25 -040089 if maven_lib_name not in maven_lib_info \
90 or maven_lib_vers > maven_lib_info[maven_lib_name][0]:
91 maven_lib_info[maven_lib_name] = [maven_lib_vers, root, file]
Alan Viverette95f6d362017-04-06 09:40:50 -040092
Alan Viveretted4527e62017-05-11 15:03:25 -040093 for info in maven_lib_info.values():
94 transform_maven_lib(working_dir, info[1], info[2])
Alan Viverette95f6d362017-04-06 09:40:50 -040095
96 # Replace the old directory.
97 output_dir = os.path.join(cwd, output_path)
98 if os.path.exists(output_dir):
99 rmtree(output_dir)
100 os.rename(working_dir, output_dir)
101
Alan Viveretted4527e62017-05-11 15:03:25 -0400102
103def transform_maven_lib(working_dir, root, file):
104 matcher = artifact_pattern.match(file)
105 maven_lib_name = matcher.group(1)
106 maven_lib_vers = matcher.group(2)
107 maven_lib_type = matcher.group(3)
108
109 make_lib_name = maven_to_make[maven_lib_name][0]
110 make_dir_name = maven_to_make[maven_lib_name][1]
111 artifact_file = os.path.join(root, file)
112 target_dir = os.path.join(working_dir, make_dir_name)
113 if not os.path.exists(target_dir):
114 os.makedirs(target_dir)
115
116 if maven_lib_type == "aar":
117 process_aar(artifact_file, target_dir, make_lib_name)
118 else:
119 target_file = os.path.join(target_dir, make_lib_name + ".jar")
120 os.rename(artifact_file, target_file)
121
122 print maven_lib_vers, ":", maven_lib_name, "->", make_lib_name
123
Alan Viverette95f6d362017-04-06 09:40:50 -0400124
125def process_aar(artifact_file, target_dir, make_lib_name):
126 # Extract AAR file to target_dir.
127 with zipfile.ZipFile(artifact_file) as zip:
128 zip.extractall(target_dir)
129
130 # Rename classes.jar to match the make artifact
131 classes_jar = os.path.join(target_dir, "classes.jar")
132 if os.path.exists(classes_jar):
133 # If it has resources, it needs a libs dir.
134 res_dir = os.path.join(target_dir, "res")
135 if os.path.exists(res_dir) and os.listdir(res_dir):
136 libs_dir = os.path.join(target_dir, "libs")
137 if not os.path.exists(libs_dir):
138 os.mkdir(libs_dir)
139 else:
140 libs_dir = target_dir
141 target_jar = os.path.join(libs_dir, make_lib_name + ".jar")
142 os.rename(classes_jar, target_jar)
143
144 # Remove or preserve empty dirs.
145 for root, dirs, files in os.walk(target_dir):
146 for dir in dirs:
147 dir_path = os.path.join(root, dir)
148 if not os.listdir(dir_path):
149 os.rmdir(dir_path)
150
151 # Remove top-level cruft.
152 for file in blacklist_files:
153 file_path = os.path.join(target_dir, file)
154 if os.path.exists(file_path):
155 os.remove(file_path)
156
157
Alan Viveretted4527e62017-05-11 15:03:25 -0400158parser = argparse.ArgumentParser(
159 description=('Update prebuilt android extras'))
160parser.add_argument(
161 'buildId',
162 type=int,
163 nargs='?',
164 help='Build server build ID')
165parser.add_argument(
166 '--target',
167 default='support_library',
168 help='Download m2repository from the specified build server target')
169args = parser.parse_args()
170if not args.buildId:
171 parser.error("You must specify a build ID")
172 sys.exit(1)
173
174try:
175 # Make sure we don't overwrite any pending changes.
176 subprocess.check_call(['git', 'diff', '--quiet', '--', '**'])
177 subprocess.check_call(['git', 'diff', '--quiet', '--cached', '--', '**'])
178except subprocess.CalledProcessError:
179 print >> sys.stderr, "FAIL: There are uncommitted changes here; please revert or stash"
180 sys.exit(1)
181
182try:
183 repoArtifact = 'sdk-repo-linux-m2repository-' + str(args.buildId) + '.zip'
184
185 # Download the repo zip archive.
186 fetchCmd = [FETCH_ARTIFACT, '--bid', str(args.buildId), '--target', args.target, repoArtifact]
187 try:
188 subprocess.check_output(fetchCmd, stderr=subprocess.STDOUT)
189 except subprocess.CalledProcessError:
190 print >> sys.stderr, "FAIL: Unable to retrieve artifact for build ID %d" % args.buildId
191 sys.exit(1)
192
193 # Unzip the repo archive into a separate directory.
194 repoDir = os.path.basename(repoArtifact)[:-4]
195 with zipfile.ZipFile(repoArtifact) as zipFile:
196 zipFile.extractall(repoDir)
197
198 # Transform the repo archive into a Makefile-compatible format.
199 transform_support(repoDir)
200
201 # Commit all changes.
202 subprocess.check_call(['git', 'add', output_path])
203 msg = ("Import support libs from build %s\n\n%s\n" % (args.buildId, " ".join(fetchCmd)))
204 subprocess.check_call(['git', 'commit', '-m', msg])
205 print 'Be sure to upload this manually to gerrit.'
206
207finally:
208 # Revert all stray files, including the downloaded zip.
209 try:
210 with open(os.devnull, 'w') as bitbucket:
211 subprocess.check_call(['git', 'add', '-Af', '.'], stdout=bitbucket)
212 subprocess.check_call(
213 ['git', 'commit', '-m', 'COMMIT TO REVERT - RESET ME!!!'], stdout=bitbucket)
214 subprocess.check_call(['git', 'reset', '--hard', 'HEAD~1'], stdout=bitbucket)
215 except subprocess.CalledProcessError:
216 print >> sys.stderr, "ERROR: Failed cleaning up, manual cleanup required!!!"