The JDK 9 project is experimenting with the idea of submission forests. A submission forest allows committers to submit a change for automatic build, test and integration with an upstream forest. Initially we plan a jdk9/hs-submit
forest which will integrate to jdk9/hs
. This will allow non-Oracle committers to make changes to jdk9/hs
directly while still observing the Hotspot team's conventions for pre-integration build & test. Of course all the usual rules about who may make changes and how they are reviewed and approved will still apply.
A test version of the Hotspot submission forest exists today. The submission forest is jdk9/hs-demo-submit and its upstream forest is jdk9/hs-demo, a throw-away clone of jdk9/hs. Currently, push access to hs-demo-submit is restricted to a few beta testers.
Basic Operation
Submission forests are modeled after the JDK9 sandbox forest. The default branch of the submission forest is automatically sync'd with its upstream forest. Committers do their work on named branches with one branch used per fix. When a branch is pushed to the submission forest, it is automatically run through a predefined set of builds and tests. If this succeeds, the changes on the branch are moved as a single changeset to the default branch of the upstream forest. If a branch fails to build, pass tests or merge successfully into the upstream forest, no changes are made upstream. At the end of the process a status email is sent to the committer.
A Simple Example
Say you need to make a simple fix to the hotspot README file in order to fix bug JDK-7000001. The following would do it:
$ hg tclone --branch default http://hg.openjdk.java.net/jdk9/hs-submit $ hg -R hs-submit tdefpath -du <OpenJDK id> $ cd hs-submit/hotspot $ hg branch "JDK-7000001" $ echo "Make the README longer." >> README $ hg commit $ # Get your code review here $ hg push --new-branch
A Note on the Examples
Many of the examples on this page use the trees.py
and defpath.py
Mercurial extensions. These extensions are available from the Code Tools project. These extensions are not necessary for using submission forests but they make handling multi-repo forests easier. Other methods for handling multiple repos, such as the common/bin/hgforest.sh
script, work as well.
FAQ
What should I call my branch?
We recommend you name your branch with the bug id of your fix. Since Mercurial branch names can't begin with a number, use the full bug id, like "JDK-4040458"
How should I create a branch?
Create a branch in each repository that you need to change. For example, if your fix requires changes in both the jdk and hotspot repos, you could do this:
$ # From the root of your local forest $ hg -R hotspot branch "JDK-7000001" $ hg -R jdk branch "JDK-7000001"
You can commit the empty branches immediately after they're created or wait until you have made code changes. Unlike the recommendation for the OpenJDK sandbox forest, you should not commit an empty branch in a repository that will not eventually have code changes. This will cause your fix to fail when it is merged with the upstream forest. This restriction will be removed in the future.
How do I supply a commit message for my change?
The commit message for the changeset at the head of your branch is used as the commit message for the changeset that is integrated to the default branch of the upstream forest.
How do I update my branch with the latest upstream changes?
Before you push a branch to the submission forest, you should merge in the latest upstream changes onto your branch.
$ # From local forest $ hg tpull # make sure the default branch has latest changes $ hg -R hotspot update "JDK-7000001" # make sure you are sitting on your branch $ hg -R jdk update "JDK-7000001" $ hg tmerge default $ hg tcommit
There is something to be careful about in the previous example. If you merge just prior to pushing your branch to the submission forest, then the commit message for your changeset when it is integrated upstream will be taken from your merge changeset. As such, your merge changeset should describe your fix, your reviewers etc. and should not be just the simple string "Merge". This is different from standard OpenJDK practice and some may find it odd.
If you'd like to avoid this oddity, you may prefer to rebase your change like this:
$ # From local forest $ hg tpull # make sure the default branch has latest changes $ hg -R hotspot update "JDK-7000001" # make sure you are sitting on your branch $ hg -R jdk update "JDK-7000001" $ hg -R hotspot rebase -d default --keepbranches $ hg -R jdk rebase -d default --keepbranches
Unfortunately the trees extension does not support a trebase command.
Note that the rebase extension may need to be enabled in your .hgrc
file prior to using the rebase command.
How should I push a branch?
The first time you push a new branch to the submission forest, you need to use the "--new-branch
" option like this:
$ hg tpush --new-branch
Subsequent pushes to your branch in the submission forest do not need the "--new-branch
" option.
If your local forest has several fixes under development and you're ready to push only one, you can do that with the "--branch
" option:
$ hg tpush --branch "JDK-4040458" --new-branch
What happens when I push my changes?
When changes are pushed to a branch in a submission forest, a job is created on an internal Oracle system to build and test those changes. Jobs which integrate to the same upstream forest are run sequentially in order to manage merge issues so it is possible that your job will wait for some time to get started. Once running, a successful job should take about <60> minutes to complete. Unsuccessful jobs will usually complete more quickly. When your job is finished you will get an email describing what happened. If you are subscribed to the change alias for the upstream forest, you should also see an email if your change successfully integrates upstream.
What if my submission fails?
Your submission may fail to integrate with the upstream forest for several reasons:
- it may fail to build on one or more platforms
- it may fail tests on one or more platforms
- it may not merge cleanly with the default branch of the upstream forest
You will get an email describing which of these things happened; however, these emails are brief. At this time we are not able to provide build or test logs which fully describe the problem. If you are unable to diagnose the problem yourself, contact an Oracle engineer and provide her with the token in your email message. She will be able to access internal logs and help you resolve the problem.
Once the problem is found, you may make further commits to your branch and push again to the submission forest. Remember that the commit message from the head of your branch will be the one that is eventually used when your change is merged upstream.
How are changes from upstream brought into the submission forest?
Changes from the default branch of the upstream forest are pulled into the submission forest automatically.
Can I work on the default branch?
You can not make changes directly on the default branch of the submission forest. Your changes will appear on the default branch of the submission forest after they have been integrated upstream then automatically pulled down. Adding your changes directly to the default branch could require merges when the default branch is updated automatically and would likely break the automation. For this reason, changes to the default branch of the submission forest are disabled.
Is jcheck turned on?
The jcheck
Mercurial extension is not enabled for the submission forest; however, it generally is enabled for the upstream forest. If so, your change must pass jcheck
when it is merged with the upstream forest.
How is my branch merged with the upstream forest?
When a change to branch B is pushed to the submission forest, the difference between the head of B and the latest common ancestor of B and the default branch is computed as a single patch. This patch is then applied to the default branch in a child of the upstream forest. The commit message for the patch is taken from the commit message at the head of branch B. If the patch applies cleanly without jcheck errors and without needing manual merging, the child of the upstream forest is built & tested. If all builds and tests succeed, the child of the upstream forest is pushed into the upstream forest and the job is complete.
Should I close my branch?
Once your branch has been integrated upstream, it will be closed automatically. This is the common case. Occasionally though, there may be a branch that needs to be abandoned. This might happen when a branch has been pushed to the submission forest but failed to integrate upstream. Let's say you have branch "JDK-7000001" in the jdk repository that needs to be closed. You could do the following:
$ # From the root of your local forest $ hg -R jdk update -C "JDK-7000001" $ hg -R jdk commit --close-branch -m "Abandoning changes." $ # Update repo to another branch to avoid mistakenly re-opening the closed branch. $ hg -R jdk update default
Note that for multi-repo fixes you need to close the branch in each repo where it exists and not in any repo where it doesn't. Solutions like the tree extension or the hgforest.sh script don't work well in this case. It may be easiest to close each branch individually by hand.
Can I reuse a branch for a different fix?
Branches are intended to be used for a single fix. They are automatically closed once the branch is integrated upstream and should not be reopened.
How can I show all changes for my branch?
To see all the changes for a branch named "JDK-4040458" you can do this:
$ hg tlog --branch "JDK-4040458"
How do I report problems?
If you have problems with submission forests, please send mail to ops@openjdk.java.net