blob: b710ba7bbdefca4a91448c0e042f4579274fe5c8 [file] [log] [blame]
#!/usr/bin/python3
#
# 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 os,sys,json
from constants_and_utils import *
def usage():
print("""
Merges certain results of the gradle build.
This script recognizes the following arguments in any order:
mergeBuildInfo (merge the buildInfo files (used by jetpad) produced by the most recent (compose and androidx) builds)
mergeExecutionData (merge the coverage execution data (recorded by jacoco) produced by the most recent builds)
mergeSourceJars (merge the source jars (used by jacoco/coverage ui) produced by the most recent builds)
(these args are case sensitive)
DIST_DIR=<a path to a directory> if this is not passed, the default value is out/dist.
Should be absolute or relative to e.g. androidx-master-dev/
Sample usage: time busytown/merge.py mergeSourceJars DIST_DIR=out/dist
""")
exit(1)
def main():
things_to_merge, dist_dir = parse_arguments()
move_to_dist_dir(dist_dir)
if SOURCE_JARS in things_to_merge: mergeSourceJars()
if EXECUTION_DATA in things_to_merge: mergeCoverageExecution()
if BUILD_INFO in things_to_merge:
mergeAggregateBuildInfoFiles()
mergeBuildInfoFolders()
if LIBRARY_METRICS in things_to_merge: mergeLibraryMetrics()
def parse_arguments():
things_to_merge = []
for arg in sys.argv:
if any(arg.endswith(SKIPPED_SUFFIX) for SKIPPED_SUFFIX in SKIPPED_ARG_SUFFIXES): continue
elif arg in MERGE_COMMANDS:
things_to_merge.append(arg)
elif any(help_keyword in arg for help_keyword in HELP_SYNTAX_LIST):
usage()
else:
print("ERROR:", arg, "is an invalid keyword")
usage()
dist_dir = os.environ['DIST_DIR'] if 'DIST_DIR' in os.environ else "out/dist"
return things_to_merge, dist_dir
def move_to_dist_dir(dist_dir):
move_to_base_dir(print_pwd=False)
os.chdir(dist_dir)
print("Currently in", os.getcwd())
def thisRunIsValidForCoverage():
# Assert that AMD did not exclude any projects from being tested
# in either androidx or ui build (thereby invalidating this run for coverage).
# If the AMD ran, that file will exist; if it skipped browser, that log will have:
# "checking whether I should include :browser:browser and my answer is false"
if (os.path.exists("affected_module_detector_log.txt") and\
'false' in open('affected_module_detector_log.txt').read()) or\
(os.path.exists("ui/affected_module_detector_log.txt") and\
'false' in open('ui/affected_module_detector_log.txt').read()):
print("WARNING: not doing coverage merging because the AMD was not a no-op")
return False
return True
def mergeSourceJars():
if not thisRunIsValidForCoverage(): return
# assert that the report jars exist
if not (os.path.exists("jacoco-report-classes.jar") and os.path.exists("ui/jacoco-report-classes.jar")):
print("WARNING: not merging jacoco source jars as the source jars are not present")
return
ziptmp = "ziptmp"
run_command("rm -rf " + ziptmp)
run_command("mkdir " + ziptmp)
# exclude these test/sample app files which are duplicated in the source jars so that `unzip` doesn't fail
# See b/145211240 for more context. A full solution may be blocked on b/143934485.
run_command("unzip -quo jacoco-report-classes.jar -d ziptmp -x \"testapp-debug-androidTest-allclasses*\"")
run_command("unzip -quo ui/jacoco-report-classes.jar -d ziptmp -x \"samples-debug-androidTest-allclasses*\"")
run_command("rm -f jacoco-report-classes-all.jar") # -f to not fail if file doesn't exist
run_command("jar -cf jacoco-report-classes-all.jar -C ziptmp .")
run_command("rm -rf " + ziptmp)
def mergeCoverageExecution():
if not thisRunIsValidForCoverage(): return
# assert that the coverage zips exist
if not (os.path.exists("coverage_ec_files.zip") and os.path.exists("ui/coverage_ec_files.zip")):
print("WARNING: not merging coverage execution data as the coverage zips are not present")
return
ziptmp = "ziptmp"
run_command("rm -rf " + ziptmp)
run_command("mkdir " + ziptmp)
run_command("unzip -quo coverage_ec_files.zip -d ziptmp") # -quo = quiet; keep newer only
run_command("unzip -quo ui/coverage_ec_files.zip -d ziptmp")
run_command("rm -f coverage_ec_files_all.zip") # -f to not fail if file doesn't exist
run_command("zip -rq coverage_ec_files_all.zip ziptmp")
run_command("rm -rf " + ziptmp)
def mergeAggregateBuildInfoFiles() :
print("merging aggregate build info files")
androidx_buildInfo = json.load(open("androidx_aggregate_build_info.txt"))["artifacts"]
compose_buildInfo = json.load(open("ui/androidx_aggregate_build_info.txt"))["artifacts"]
duplicate_checking_dict = {}
for buildinfo in androidx_buildInfo + compose_buildInfo:
artifactId, groupId, sha = buildinfo["artifactId"], buildinfo["groupId"], buildinfo["sha"]
# artifactid and groupid is the unique identifier for libraries
if (artifactId, groupId) not in duplicate_checking_dict:
duplicate_checking_dict[(artifactId, groupId)] = (sha, buildinfo)
else:
expected_hash = duplicate_checking_dict[(artifactId, groupId)][0]
if expected_hash != sha:
raise Exception("Build info specifies having been built from multiple commits: " + expected_hash + " and " + sha + ". Were AndroidX and Compose built from the same commit?")
# don't allow androidx and compose to release two different versions of the same lib
resultJson = {"artifacts":[buildinfo for sha,buildinfo in duplicate_checking_dict.values()]}
with open("androidx_aggregate_build_info.txt", 'w') as outfile:
json.dump(resultJson, outfile, sort_keys=True, indent=4, separators=(',', ': '))
def mergeBuildInfoFolders(): # -a = all in directory. -u = overwrite older (in case androidx build hasn't been run in a while)
run_command("cp -au ui/build-info/. build-info/")
def mergeLibraryMetrics():
run_command("cp -au ui/librarymetrics/. librarymetrics/")
if __name__ == "__main__": main()