Add script to merge upstream package
Test: ojluni_merge_package java.util.concurrent.atomic
Test: ojluni_cleanup_merge_branches
Change-Id: I2dfdd53b389113b71c8f8a240bbeb8e791e3ccfa
diff --git a/tools/expected_upstream/install_tools.sh b/tools/expected_upstream/install_tools.sh
index 3763066..604aedd 100755
--- a/tools/expected_upstream/install_tools.sh
+++ b/tools/expected_upstream/install_tools.sh
@@ -5,12 +5,14 @@
# See go/pip-install-remediation how to regenerate the requirements.txt file.
pip3 install --require-hashes -r ${THIS_DIR}/requirements.txt
+pushd ${THIS_DIR}
git fetch aosp expected_upstream
git fetch aosp upstream-openjdk7u
git fetch aosp upstream-openjdk8u
git fetch aosp upstream-openjdk9
git fetch aosp upstream-openjdk11u
git fetch aosp upstream-openjdk17u
+popd
alias ojluni_refresh_files=${THIS_DIR}/ojluni_refresh_files.py
alias ojluni_merge_to_master=${THIS_DIR}/ojluni_merge_to_master.py
@@ -18,7 +20,8 @@
alias ojluni_run_tool_tests='PYTHONPATH=${PYTHONPATH}:${THIS_DIR} python3 -B -m unittest discover -v -s tests -p "*_test.py"'
alias ojluni_upgrade_identicals=${THIS_DIR}/ojluni_upgrade_identicals.py
alias ojluni_versions_report=${THIS_DIR}/ojluni_versions_report.py
-
+alias ojluni_merge_package=${THIS_DIR}/ojluni_merge_package.sh
+alias ojluni_cleanup_merged_branches=${THIS_DIR}/ojluni_cleanup_merged_branches.sh
_ojluni_modify_expectation ()
{
diff --git a/tools/expected_upstream/ojluni_cleanup_merged_branches.sh b/tools/expected_upstream/ojluni_cleanup_merged_branches.sh
new file mode 100755
index 0000000..2037ee7
--- /dev/null
+++ b/tools/expected_upstream/ojluni_cleanup_merged_branches.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# Script that cleans up branches created by ojluni_merge_to_master. They are
+# usually name something like 'expected_upstream_e0bywxovb5'.
+
+if [[ -z "${ANDROID_BUILD_TOP}" ]]
+then
+ echo -e "ANDROID_BUILD_TOP not found. You need to run lunch first."
+ exit 1
+fi
+
+pushd "${ANDROID_BUILD_TOP}/libcore"
+
+for br in $(git branch | grep -E "^\s*expected_upstream_[a-z0-9]+$")
+do
+ echo git branch -D ${br}
+ git branch -D ${br}
+done
+
+popd
diff --git a/tools/expected_upstream/ojluni_merge_package.sh b/tools/expected_upstream/ojluni_merge_package.sh
new file mode 100755
index 0000000..8b612fa
--- /dev/null
+++ b/tools/expected_upstream/ojluni_merge_package.sh
@@ -0,0 +1,189 @@
+#!/bin/bash
+
+SELF=$(basename "${0}")
+DEFAULT_TAG="jdk17u/jdk-17.0.5-ga"
+SUPPORTED_TAGS="jdk7u/jdk7u40-b60"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk8u/jdk8u121-b13"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk8u/jdk8u60-b31"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk9/jdk-9+181"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk11u/jdk-11+28"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk11u/jdk-11.0.13-ga"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk17u/jdk-17.0.2-ga"
+SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk17u/jdk-17.0.5-ga"
+
+USAGE=$(cat << EndOfUsage
+Usage:
+ ${SELF} [-b <bug_number>] [-t <upstream_tag>] <package_name> <package_name> ...
+ For example:
+ ${SELF} -b 123456 -t jdk17u/jdk-17.0.5.-ga java.util.concurrent java.util.concurrent.atomic
+
+Possible arguments:
+ -h|--help - print help and exit
+ -t|--tag - the upstream tag to merge to; default: ${DEFAULT_TAG} or
+ OJLUNI_MERGE_TARGET (if defined)
+ -b|--bug - the bug number to use in the commit message; if not defined it will
+ be picked up from the libcore branch name (for example
+ "b-12345-oj-merge" -> "-b 12345")
+
+The supported upstream tags are:
+ $(echo ${SUPPORTED_TAGS} | sed 's/ /\n /g')
+EndOfUsage
+)
+
+HELP=$(cat << EndOfHelp
+Merges one or more packages from an upstream branch.
+
+This will use the correct form of add/modify based on what is already stored in
+libcore/EXPECTED_UPSTREAM. Also it will find new files in the new version of
+the upstream package and add those as well.
+
+${USAGE}
+EndOfHelp
+)
+
+BUG=""
+PACKAGES=""
+TAG="${OJLUNI_MERGE_TARGET:-"$DEFAULT_TAG"}"
+
+function die()
+{
+ echo -e ${1}
+ if [[ -n "${2}" ]]
+ then
+ echo -e ""
+ echo -e "${USAGE}"
+ fi
+ exit 1
+}
+
+function validate_tag
+{
+ for expected in ${SUPPORTED_TAGS}
+ do
+ if [[ "${TAG}" == "${expected}" ]]
+ then
+ return
+ fi
+ done
+ die "Unknown tag: ${TAG}" "y"
+}
+
+function setup_env
+{
+ if [[ -z "${ANDROID_BUILD_TOP}" ]]
+ then
+ die "ANDROID_BUILD_TOP not found. You need to run lunch first."
+ fi
+
+ shopt -s expand_aliases
+ source "${ANDROID_BUILD_TOP}/libcore/tools/expected_upstream/install_tools.sh"
+}
+
+while [[ $# -gt 0 ]]; do
+ case ${1} in
+ -h|--help)
+ echo "${HELP}"
+ exit 0
+ ;;
+ -b|--bug)
+ BUG="${2}"
+ shift
+ ;;
+ -t|--tag)
+ TAG="${2}"
+ shift
+ ;;
+ *)
+ PACKAGES="${PACKAGES} ${1}"
+ ;;
+ esac
+ shift
+done
+
+if [[ -z "${PACKAGES}" ]]
+then
+ die "You need to specify at least one package to merge." "y"
+fi
+
+setup_env
+validate_tag
+
+if [[ -z "${BUG}" ]]
+then
+ pushd "${ANDROID_BUILD_TOP}/libcore"
+ BUG=$(git branch --show-current | grep -E -o "\<b\>[-/][0-9]+-" | grep -E -o "[0-9]+")
+ popd
+fi
+
+function ojluni-merge-class
+{
+ local method="${1}"
+ local name="${2}"
+ local version="${3}"
+
+ local first_arg="${name}"
+ local second_arg="${version}"
+
+ if [[ "${method}" == "add" ]]
+ then
+ first_arg="${version}"
+ second_arg="${name}"
+ fi
+ echo ojluni_modify_expectation "${method}" "${first_arg}" "${second_arg}"
+ ojluni_modify_expectation "${method}" "${first_arg}" "${second_arg}" || \
+ die "Failed to modify expectation file for ${name}"
+}
+
+function ojluni-merge-package
+{
+ local package="${1}"
+ local version="${2}"
+ local bug="${3}"
+ local package_path=$(echo "${package}" | sed --sandbox 's/\./\//'g)
+ local package_full_path="${ANDROID_BUILD_TOP}/libcore/ojluni/src/main/java/${package_path}"
+
+ pushd "${ANDROID_BUILD_TOP}/libcore"
+
+ for f in $(ls "${package_full_path}"/*.java)
+ do
+ local class_name=$(basename -s .java ${f})
+ local class_path="ojluni/src/main/java/${package_path}/${class_name}\.java"
+ local in_expected_upstream=$(grep "${class_path}" "${ANDROID_BUILD_TOP}/libcore/EXPECTED_UPSTREAM")
+ if [[ -n "${in_expected_upstream}" ]]
+ then
+ ojluni-merge-class modify "${package}.${class_name}" "${version}"
+ else
+ ojluni-merge-class add "${package}.${class_name}" "${version}"
+ fi
+ done
+
+ local version_id=$(echo "${version}" | grep -oE "^[^/]+")
+ local branch="aosp/upstream-open${version_id}"
+ local new_classes=$(git diff --name-only --diff-filter=D "${branch}" -- \
+ "src/java.base/share/classes/${package_path}" \
+ "ojluni/src/main/java/${package_path}")
+
+ for f in ${new_classes}
+ do
+ local class_name=$(basename -s .java ${f})
+ local class_path="ojluni/src/main/java/${package_path}/${class_name}\.java"
+ ojluni-merge-class add "${package}.${class_name}" "${version}"
+ done
+
+ if [[ -n "${bug}" ]]
+ then
+ echo ojluni_merge_to_master -b "${bug}"
+ ojluni_merge_to_master -b "${bug}" || die "Failed to merge ${package} to master"
+ else
+ echo ojluni_merge_to_master
+ ojluni_merge_to_master || die "Failed to merge ${package} to master"
+ fi
+
+ popd
+}
+
+for package in ${PACKAGES}
+do
+ echo "Merging '${package}' from ${TAG}"
+ ojluni-merge-package "${package}" "${TAG}" "${BUG}"
+done
diff --git a/tools/expected_upstream/ojluni_modify_expectation.py b/tools/expected_upstream/ojluni_modify_expectation.py
index 558b754..4c3934d 100755
--- a/tools/expected_upstream/ojluni_modify_expectation.py
+++ b/tools/expected_upstream/ojluni_modify_expectation.py
@@ -48,6 +48,7 @@
'jdk11u/jdk-11+28',
'jdk11u/jdk-11.0.13-ga',
'jdk17u/jdk-17.0.2-ga',
+ 'jdk17u/jdk-17.0.5-ga',
]