1#!/bin/bash 2 3SELF=$(basename "${0}") 4DEFAULT_TAG="jdk21u/jdk-21.0.2-ga" 5SUPPORTED_TAGS="jdk7u/jdk7u40-b60" 6SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk8u/jdk8u121-b13" 7SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk8u/jdk8u60-b31" 8SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk9/jdk-9+181" 9SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk11u/jdk-11.0.22-ga" 10SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk17u/jdk-17.0.10-ga" 11SUPPORTED_TAGS="${SUPPORTED_TAGS} jdk21u/jdk-21.0.2-ga" 12 13 14USAGE=$(cat << EndOfUsage 15Usage: 16 ${SELF} [-b <bug_number>] [-t <upstream_tag>] <package_name> <package_name> ... 17 For example: 18 ${SELF} -b 123456 -t jdk21u/jdk-21.0.2-ga java.util.concurrent java.util.concurrent.atomic 19 ${SELF} java.util.concurrent.atomic -c AtomicInteger,AtomicBoolean,AtomicLong 20 ${SELF} java.util.concurrent.atomic -c AtomicInteger -c AtomicBoolean -c AtomicLong 21 22Possible arguments: 23 -h|--help - print help and exit 24 -t|--tag - the upstream tag to merge to; default: ${DEFAULT_TAG} or 25 OJLUNI_MERGE_TARGET (if defined) 26 -c|--classes - list of classes from the package to be processed; this is useful if only 27 some classes from a package are to be merged; only a single 28 package must be specified; can be provided as a comma-separated 29 list, or repeated -c arguments 30 -b|--bug - the bug number to use in the commit message; if not defined it will 31 be picked up from the libcore branch name (for example 32 "b-12345-oj-merge" -> "-b 12345") 33 34The supported upstream tags are: 35 $(echo ${SUPPORTED_TAGS} | sed 's/ /\n /g') 36EndOfUsage 37) 38 39HELP=$(cat << EndOfHelp 40Merges one or more packages from an upstream branch. 41 42This will use the correct form of add/modify based on what is already stored in 43libcore/EXPECTED_UPSTREAM. Also it will find new files in the new version of 44the upstream package and add those as well. 45 46${USAGE} 47EndOfHelp 48) 49 50BUG="" 51PACKAGES=() 52TAG="${OJLUNI_MERGE_TARGET:-"$DEFAULT_TAG"}" 53CLASSES=() 54 55function die() 56{ 57 echo -e ${1} 58 if [[ -n "${2}" ]] 59 then 60 echo -e "" 61 echo -e "${USAGE}" 62 fi 63 exit 1 64} 65 66function validate_tag 67{ 68 for expected in ${SUPPORTED_TAGS} 69 do 70 if [[ "${TAG}" == "${expected}" ]] 71 then 72 return 73 fi 74 done 75 die "Unknown tag: ${TAG}" "y" 76} 77 78function setup_env 79{ 80 if [[ -z "${ANDROID_BUILD_TOP}" ]] 81 then 82 die "ANDROID_BUILD_TOP not found. You need to run lunch first." 83 fi 84 85 shopt -s expand_aliases 86 source "${ANDROID_BUILD_TOP}/libcore/tools/expected_upstream/install_tools.sh" 87} 88 89while [[ $# -gt 0 ]]; do 90 case ${1} in 91 -h|--help) 92 echo "${HELP}" 93 exit 0 94 ;; 95 -b|--bug) 96 BUG="${2}" 97 shift 98 ;; 99 -t|--tag) 100 TAG="${2}" 101 shift 102 ;; 103 -c|--classes) 104 classes=$(echo "${2}" | sed 's/,/ /g') 105 for class in $(echo "${2}" | sed 's/,/ /g') 106 do 107 CLASSES+=(${class}) 108 done 109 shift 110 ;; 111 *) 112 PACKAGES+=(${1}) 113 ;; 114 esac 115 shift 116done 117 118if [[ ${#PACKAGES[@]} -eq 0 ]] 119then 120 die "You need to specify at least one package to merge." "y" 121elif [[ ${#CLASSES[@]} -gt 0 && ${#PACKAGES[@]} -gt 1 ]] 122then 123 die "The -c|--classes argument can only be provided with a single package" "y" 124fi 125 126setup_env 127validate_tag 128 129if [[ -z "${BUG}" ]] 130then 131 pushd "${ANDROID_BUILD_TOP}/libcore" 132 BUG=$(git branch --show-current | grep -E -o "\<b\>[-/][0-9]+-" | grep -E -o "[0-9]+") 133 popd 134fi 135 136function merge-class 137{ 138 local method="${1}" 139 local name="${2}" 140 local version="${3}" 141 142 local first_arg="${name}" 143 local second_arg="${version}" 144 145 if [[ "${method}" == "add" ]] 146 then 147 first_arg="${version}" 148 second_arg="${name}" 149 fi 150 echo ojluni_modify_expectation "${method}" "${first_arg}" "${second_arg}" 151 ojluni_modify_expectation "${method}" "${first_arg}" "${second_arg}" || \ 152 die "Failed to modify expectation file for ${name}" 153} 154 155function do-merge 156{ 157 local package="${1}" 158 local bug="${2}" 159 160 if [[ -n "${bug}" ]] 161 then 162 echo ojluni_merge_to_main -b "${bug}" 163 ojluni_merge_to_main -b "${bug}" || die "Failed to merge ${package} to master" 164 else 165 echo ojluni_merge_to_main 166 ojluni_merge_to_main || die "Failed to merge ${package} to master" 167 fi 168} 169 170function is-class-in-expected-upstream 171{ 172 local package_path="${1}" 173 local class_name="${2}" 174 local class_path="ojluni/src/main/java/${package_path}/${class_name}\.java" 175 grep "${class_path}" "${ANDROID_BUILD_TOP}/libcore/EXPECTED_UPSTREAM" 176} 177 178function get-package-path 179{ 180 local package="${1}" 181 echo "${package}" | sed --sandbox 's/\./\//'g 182} 183 184function ojluni-merge-package 185{ 186 local package="${1}" 187 local version="${2}" 188 local bug="${3}" 189 local package_path=$(get-package-path "${package}") 190 local package_full_path="${ANDROID_BUILD_TOP}/libcore/ojluni/src/main/java/${package_path}" 191 192 pushd "${ANDROID_BUILD_TOP}/libcore" 193 194 for f in $(ls "${package_full_path}"/*.java) 195 do 196 local class_name=$(basename -s .java ${f}) 197 local in_expected_upstream=$(is-class-in-expected-upstream "${package_path}" "${class_name}") 198 if [[ -n "${in_expected_upstream}" ]] 199 then 200 merge-class modify "${package}.${class_name}" "${version}" 201 else 202 merge-class add "${package}.${class_name}" "${version}" 203 fi 204 done 205 206 local version_id=$(echo "${version}" | grep -oE "^[^/]+") 207 local branch="aosp/upstream-open${version_id}" 208 local new_classes=$(git diff --name-only --diff-filter=D "${branch}" -- \ 209 "src/java.base/share/classes/${package_path}" \ 210 "ojluni/src/main/java/${package_path}") 211 212 for f in ${new_classes} 213 do 214 local class_name=$(basename -s .java ${f}) 215 local class_path="ojluni/src/main/java/${package_path}/${class_name}\.java" 216 merge-class add "${package}.${class_name}" "${version}" 217 done 218 219 do-merge "${package}" "${bug}" 220 221 popd 222} 223 224function ojluni-merge-class 225{ 226 local package="${1}" 227 local class="${2}" 228 local version="${3}" 229 local package_path=$(get-package-path "${package}") 230 local in_expected_upstream=$(is-class-in-expected-upstream "${package_path}" "${class}") 231 if [[ -n "${in_expected_upstream}" ]] 232 then 233 merge-class modify "${package}.${class}" "${version}" 234 else 235 merge-class add "${package}.${class}" "${version}" 236 fi 237} 238 239if [[ ${#CLASSES[@]} -eq 0 ]] 240then 241 for package in ${PACKAGES[@]} 242 do 243 echo "Merging '${package}' from ${TAG}" 244 ojluni-merge-package "${package}" "${TAG}" "${BUG}" 245 done 246elif [[ ${#PACKAGES[@]} -eq 1 ]] 247then 248 package=${PACKAGES[0]} 249 for class in ${CLASSES[@]} 250 do 251 echo "Merging ${package}.${class}" 252 ojluni-merge-class "${package}" "${class}" "${TAG}" 253 done 254 do-merge "${package}" "${BUG}" 255fi 256