README.md
1If you want to import files from the OpenJDK into `libcore/`, you are reading
2the right documentation.
3
4# Concept
5
6```text
7---------A----------C------------ expected_upstream
8 \ \
9-----------B----------D---------- main
10```
11
12The general idea is to get a change from OpenJDK into libcore in AOSP by
13`git merge` from an OpenJDK branch. However, each file in `ojluni/` can come
14from a different OpenJDK version. `expected_upstream` is a staging branch
15storing the OpenJDK version of each file. Thus, we can use `git merge` when
16we update an `ojluni/` file from a new upstream version, and the command should
17automatically merge the file if no merge conflict.
18
19# Workflow
20
21## Prerequisite
22* python3
23* python3-git
24 * Install it via `apt install python3-git`
25* A remote `aosp` is setup in your local git repository
26
27## 1. Setup
28```shell
29cd $ANDROID_BUILD_TOP/libcore
30source ./tools/expected_upstream/install_tools.sh
31```
32
33## 2. Upgrade a java class to a higher OpenJDK version
34For example, upgrade `java.lang.String` to 11.0.13-ga version:
35
36```shell
37ojluni_modify_expectation modify java.lang.String jdk11u/jdk-11.0.13-ga
38ojluni_merge_to_main # -b <bug id> if it fixes any bug
39```
40
41or if `java.lang.String` is missing in the EXPECTED_UPSTREAM file:
42```shell
43ojluni_modify_expectation add jdk11u/jdk-11.0.13-ga java.lang.String
44ojluni_merge_to_main # -b <bug id> if it fixes any bug
45```
46
47`ojluni_merge_to_main` will `git-merge` from the upstream branch.
48If you see any merge conflicts, please resolve the merge conflicts as usual,
49and then run `git commit` to finalize the commit.
50
51### Iteration
52You can build and test the change. If you need to import more files,
53```shell
54ojluni_modify_expectation ...
55# -a imports more files into the last merge commit instead of a new commit
56ojluni_merge_to_main -a
57```
58
59### Bash Autocompletion
60For auto-completion, `ojluni_modify_expectation` supports bash autocompletion.
61```shell
62$ ojluni_modify_expectation modify java.lang.Str # <tab>
63java.lang.StrictMath java.lang.StringBuilder java.lang.StringUTF16
64java.lang.String java.lang.StringCoding
65java.lang.StringBuffer java.lang.StringIndexOutOfBoundsException
66```
67
68## 2a. Add a java test from the upstream
69
70The process is similar to the above commands, but needs to run
71`ojluni_modify_expectation` with an `add` subcommand.
72
73For example, add a test for `String.isEmpty()` method:
74```shell
75ojluni_modify_expectation add jdk8u/jdk8u121-b13 java.lang.String.IsEmpty
76# -a imports more files into the last merge commit instead of a new commit
77ojluni_merge_to_main -a
78```
79Note: `java.lang.String.IsEmpty` is a test class in the upstream repository.
80
81# 3. Upload your changes for code reviews
82
83After you build and test, you are satisfied with your change, you can upload
84the change with the following commands
85
86```shell
87# Upload the original upstream files to the expected_upstream branch
88$ git push aosp HEAD^2:refs/for/expected_upstream
89# Upload the merge commit to the main branch
90$ repo upload --cbr .
91```
92
93# Directory Layout
94in the `aosp/expected_upstream` branch.
951. `ojluni/`
96 * It has the same layout as the ojluni/ files in `aosp/main`
972. `EXPECTED_UPSTREAM` file
98 * The table has 3 columns, i.e.
99 1. Destination path in `ojluni/`
100 2. Expected upstream version / an upstream git tag
101 3. Upstream source path
102 * The file format is like .csv file using a `,` separator
1033. `tools/expected_upstream/`
104 * Contains the tools
105
106# Understanding your change
107
108## Changes that should be made via the `aosp/expected_upstream` branch
1091. Add or upgrade a file from the upstream OpenJDK
110 * You are reading the right document! This documentation tells you how to
111 import the file from the upstream. Later, you can merge the file and
112 `expected_upstream` into `aosp/main` branch.
1132. Remove an `ojluni/` file that originally came from the OpenJDK
114 * Please remove the file on both `aosp/main` and `aosp/expected_upstream`
115 branches. Don't forget to remove the entry in the `EXPECTED_UPSTREAM` too.
1163. Revert the merge commit on `aosp/main` from `expected_upstream`
117 * If you don't plan to re-land your change on `aosp/main`, you should
118 probably revert the change `aosp/expected_upstream` as well.
119 * If you plan to re-land your change, your re-landing commit won't be
120 a merge commit, because `git` doesn't allow you to merge the same commit
121 twice into the same branch. You have 2 options
122 1. Revert your change on `expected_upsteam` too and start over again
123 when you reland your change
124 2. Just accept that the re-landing commit won't be a merge commit.
125
126## Changes that shouldn't happen in the `aosp/expected_upstream` branch
127In general, if you want to change an `ojluni/` file by a text editor / IDE
128manually, you should make the change on `aosp/main`.
129
1301. Changes to non-OpenJDK files
131 * Those files are usually under the `luni/` folder, you can make the change
132 directly on `aosp/main`
1332. Adding / updating a patch to an existing `ojluni/` file
134 * You can make the change directly on `aosp/main`. Please follow this
135 [patch style guideline](https://goto.google.com/libcore-openjdk8-verify).
1363. Cherry-picking a commit from upstream
137 * You should first try to update an `ojluni/` file to a particular upstream
138 version. If you can't but still want to cherry-pick a upstream fix, you
139 should do so on the `aosp/main` branch.
1404. Changes to non-OpenJDK files in `ojluni/`
141 * Files, e.g. Android.bp, don't come from the upstream. You can make the
142 change directly on `aosp/main`.
143
144
145
146# [Only relevant if using `ojluni_refresh_files`] Submit your change in [AOSP gerrit](http://r.android.com/)
147```text
148----11.0.13-ga---------------- openjdk/jdk11u
149 \
150 A
151 \
152------------B-----C------------ expected_upstream
153 \
154--------------------D---E------ main
155```
156Here are the order of events / votes required to submit your CL on gerrit as of
157Nov 2021.
1581. `Presubmit-Verified +2` on all 5 CLs
159 * Due to [b/204973624](http://b/204973624), you may `Bypass-Presubmit +1`
160 on commit `A` and `B` if the presubmit fails.
1612. `Code-review +2` on all 5 CLs from an Android Core Library team member
1623. If needed, `API-review +1` on commit `E` from an Android API council member
1634. Click the submit button / `Autosubmit +1` on commit `B`, `C` and `E`
164 * Never submit commit `A` individually without submitting `B` together.
165 * Otherwise, gerrit will create another merge commit from `A` without
166 submitting `B`.
167 * Due a Gerrit bug, you can't submit the commit `C` before submitting `B`
168 first manually, even though `B` is the direct parent of `C`. So just
169 submit `B` yourself manually.
170 * If you can't submit the CL due a permission issue, ask an Android Core
171 Library member to submit.
172
173## [Only relevant if using `ojluni_refresh_files`] Life of a typical change
174
175Commit graph of a typical change
176```text
177----11.0.13-ga---------------- openjdk/jdk11u
178 \
179 A
180 \
181------------B-----C------------ expected_upstream
182 \
183--------------------D---E------ main
184```
185
186Typically, you will need 5 CLs
187* Commit `A` imports the file and moves the file in the `ojluni/` folder
188* Commit `B` merges the file into the expected_upstream with other `ojluni`
189 files
190 * Commit `A` and `B` are created by the `ojluni_refresh_files` script
191* Commit `C` edits the entry in the `EXPECTED_UPSTREAM` file
192* Commit `D` is a merge commit created by `git merge`
193* Commit `E` adds Android patches
194 * Includes other changes to non-OpenJDK files, e.g. `Android.bp`,
195 `api/current.txt`.
196
197### Why can't have a single commit to replace the commits `A`, `B` and `C`?
198* Preserve the upstream history. We can later `git blame` with the upstream
199 history.
200
201# [Only relevant if using `ojluni_refresh_files`] Known bugs
202* `repo upload` may not succeed because gerrit returns error.
203 1. Just try to run `repo upload` again!
204 * The initial upload takes a long time because it tries to sync with the
205 remote AOSP gerrit server. The second upload is much faster because
206 the `git` objects have been uploaded.
207 2. `repo upload` returns TimeOutException, but the CL has been uploaded.
208 Just find your CL in http://r.android.com/. See http://b/202848945
209 3. Try to upload the merge commits 1 by 1
210 ```shell
211 git rev-parse HEAD # a sha is printed and you will need it later
212 git reset HEAD~1 # reset to a earlier commit
213 repo upload --cbr . # try to upload it again
214 git reset <the sha printed above>
215 ```
216* After `ojluni_modify_expectation add` and `ojluni_refresh_files`, a `git commit -a`
217 would include more files than just EXPECTED_UPSTREAM, because `git`, e.g. `git status`,
218 isn't aware of changes in the working tree / in the file system. This can lead to
219 an error when checking out the branch that is based on main.
220 1. Do a `git checkout --hard <initial commit before the add>`
221 2. Rerun the `ojluni_modify_expectation add` and `ojluni_refresh_files`
222 3. `git stash && git stash pop`
223 4. Commit the updated EXPECTED_UPSTREAM and proceed
224
225# Report bugs
226* Report bugs if the git repository is corrupted!
227 * Sometimes, you can recover the repository by running `git reset aosp/expected_upstream`
228