• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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