Merge "ReceiveCommits: Log calling user when push is traced"
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 1d1f17e..c514321 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -834,7 +834,7 @@
 [[category_view_private_changes]]
 === View Private Changes
 
-This category permits users to view all private changes.
+This category permits users to view all private changes and all change edit refs.
 
 The change owner and any explicitly added reviewers can always see
 private changes (even without having the `View Private Changes` access
diff --git a/Documentation/dev-contributing.txt b/Documentation/dev-contributing.txt
index a1342d3..6dce1e6 100644
--- a/Documentation/dev-contributing.txt
+++ b/Documentation/dev-contributing.txt
@@ -321,16 +321,44 @@
 [[process]]
 == Process
 
+[[dev-in-stable-branches]]
+=== Development in stable branches
+
+As their name suggests stable branches are intended to be stable. This means that generally
+only bug-fixes should be done on stable branches, however this is not strictly enforced and
+exceptions may apply:
+
+  * When a stable branch is initially created to prepare a new release the Gerrit community
+    discusses on the mailing list if there are pending features which should still make it into the
+    release. Those features are blocking the release and should be implemented on the stable
+    branch before the first release candidate is created.
+  * To stabilize the code before doing a major release several release candidates are created. Once
+    the first release candidate was done no more features should be accepted on the stable branch.
+    If more features are found to be required they should be discussed with the Gerrit maintainers
+    and should only be allowed if the risk of breaking things is considered to be low.
+  * Once a major release is done only bug-fixes and documentation updates should be done on the
+    stable branch. These updates will be included in the next minor release.
+  * For minor releases new features are only acceptable if they are important to the Gerrit
+    community, if they are backwards compatible and the risk of breaking things is low and if there
+    are no objections from the Gerrit community.
+  * In cases of doubt it's the responsibility of the release maintainer to evaluate the risk of new
+    features and make a decision based on these rules and opinions from the Gerrit community.
+  * The older a stable branch is the more stable it should be. This means old stable branches
+    should only receive bug-fixes that are either important or low risk. Security fixes, including
+    security updates for third party dependencies, are always considered as important and hence can
+    always be done on stable branches.
+
 === Backporting to stable branches
 
 From time to time bug fix releases are made for existing stable branches.
 
-Developers concerned with stable branches are encouraged to backport or push
-patchsets to these branches, even if no new release is planned.
+Developers concerned with stable branches are encouraged to backport or push fixes to these
+branches, even if no new release is planned. Backporting features is only possible in compliance
+with the rules link:#dev-in-stable-branches[above].
 
-Fixes that are known to be needed for a particular release should be pushed
-for review on that release's stable branch.  It will then be included in
-the master branch when the stable branch is merged back.
+Fixes that are known to be needed for a particular release should be pushed for review on that
+release's stable branch. They will then be included into the master branch when the stable branch
+is merged back.
 
 === Finding starter projects to work on
 
@@ -363,20 +391,21 @@
 developers can agree and rely on.
 
 General process:
-* Make sure that the feature (e.g. a field on the API) is not needed anymore or blocks
-  further development or improvement. If in doubt, consult the mailing list.
-* If you can provide a schema migration that moves users to a comparable feature, do
-  so and stop here.
-* Mark the feature as deprecated in the documentation and release notes.
-* If possible, mark the feature deprecated in any user-visible interface. For example,
-  if you are deprecating a Git push option, add a message to the Git response if
-  the user provided the option informing them about deprecation.
-* Annotate the code with `@Deprecated` and `@RemoveAfter(x.xx)` if applicable.
-  Alternatively, use `// DEPRECATED, remove after x.xx` (where x.xx is the version
-  number that has to be branched off before removing the feature)
-* Gate the feature behind a config that is off by default (forcing admins to turn
-  the deprecated feature on explicitly).
-* After the next release was branched off, remove any code that backed the feature.
+
+  * Make sure that the feature (e.g. a field on the API) is not needed anymore or blocks
+    further development or improvement. If in doubt, consult the mailing list.
+  * If you can provide a schema migration that moves users to a comparable feature, do
+    so and stop here.
+  * Mark the feature as deprecated in the documentation and release notes.
+  * If possible, mark the feature deprecated in any user-visible interface. For example,
+    if you are deprecating a Git push option, add a message to the Git response if
+    the user provided the option informing them about deprecation.
+  * Annotate the code with `@Deprecated` and `@RemoveAfter(x.xx)` if applicable.
+    Alternatively, use `// DEPRECATED, remove after x.xx` (where x.xx is the version
+    number that has to be branched off before removing the feature)
+  * Gate the feature behind a config that is off by default (forcing admins to turn
+    the deprecated feature on explicitly).
+  * After the next release was branched off, remove any code that backed the feature.
 
 You can optionally consult the mailing list to ask if there are users of the feature you
 wish to deprecate. If there are no major users, you can remove the feature without
diff --git a/WORKSPACE b/WORKSPACE
index 274ae6f..8d82f1c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1009,8 +1009,8 @@
 # and httpasyncclient as necessary.
 maven_jar(
     name = "elasticsearch-rest-client",
-    artifact = "org.elasticsearch.client:elasticsearch-rest-client:6.5.3",
-    sha1 = "ac8df46fce1c01b61cbf1f84186bf910d12b577e",
+    artifact = "org.elasticsearch.client:elasticsearch-rest-client:6.5.4",
+    sha1 = "552175b06e34df96f114d1c8aaa908e535c8f1be",
 )
 
 JACKSON_VERSION = "2.9.8"
diff --git a/contrib/mitm-ui/README.md b/contrib/mitm-ui/README.md
new file mode 100644
index 0000000..c8df490
--- /dev/null
+++ b/contrib/mitm-ui/README.md
@@ -0,0 +1,47 @@
+# Scripts for PolyGerrit local development against prod using MitmProxy.
+
+## Installation (OSX)
+
+1. Install Docker from http://docker.com
+2. Start the proxy and create a new proxied browser instance
+   ```
+   cd ~/gerrit
+   ~/mitm-gerrit/mitm-serve-app-dev.sh
+   ```
+3. Install MITM certificates
+   - Open http://mitm.it in the proxied browser window
+   - Follow the instructions to install MITM certs
+
+## Usage
+
+### Add or replace a single plugin containing static content
+
+To develop unminified plugin that loads multiple files, use this.
+
+1. Create a new proxied browser window and start mitmproxy via Docker:
+   ```
+   ~/mitm-gerrit/mitm-single-plugin.sh ./path/to/static/plugin.html
+   ```
+2. Open any *.googlesource.com domain in proxied window
+3. plugin.html and ./path/to/static/* will be served
+
+### Add or replace a minified plugin for *.googlesource.com
+
+This flow assumes no additional .html/.js are needed, i.e. the plugin is a single file.
+
+1. Create a new proxied browser window and start mitmproxy via Docker:
+   ```
+   ~/mitm-gerrit/mitm-plugins.sh ./path/to/plugin.html,./maybe/one/more.js
+   ```
+2. Open any *.googlesource.com domain in proxied window
+3. plugin.html and more.js are served
+
+### Serve uncompiled PolyGerrit
+
+1. Create a new proxied browser window and start mitmproxy via Docker:
+   ```
+   cd ~/gerrit
+   ~/mitm-gerrit/mitm-serve-app-dev.sh
+   ```
+2. Open any *.googlesource.com domain in proxied window
+3. Instead of prod UI (gr-app.html, gr-app.js), local source files will be served
diff --git a/contrib/mitm-ui/add-header.py b/contrib/mitm-ui/add-header.py
new file mode 100644
index 0000000..f9b2b12
--- /dev/null
+++ b/contrib/mitm-ui/add-header.py
@@ -0,0 +1,5 @@
+# mitmdump -s add-header.py
+def response(flow):
+    if flow.request.host == 'gerrit-review.googlesource.com' and flow.request.path == "/c/92000?1":
+        #flow.response.headers['any'] = '<meta.rdf>; rel=meta'
+        flow.response.headers['Link'] = '</changes/98000/detail?O=11640c>;rel="preload";crossorigin;'
diff --git a/contrib/mitm-ui/dev-chrome.sh b/contrib/mitm-ui/dev-chrome.sh
new file mode 100755
index 0000000..adcb296
--- /dev/null
+++ b/contrib/mitm-ui/dev-chrome.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [[ "$OSTYPE" != "darwin"* ]]; then
+    echo Only works on OSX.
+    exit 1
+fi
+
+/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=${HOME}/devchrome --proxy-server="127.0.0.1:8888"
diff --git a/contrib/mitm-ui/force-version.py b/contrib/mitm-ui/force-version.py
new file mode 100644
index 0000000..a69c885
--- /dev/null
+++ b/contrib/mitm-ui/force-version.py
@@ -0,0 +1,22 @@
+# mitmdump -q -p 8888 -s "force-version.py --version $1"
+# Request URL is not changed, only the response context
+from mitmproxy import http
+import argparse
+import re
+
+class Server:
+    def __init__(self, version):
+        self.version = version
+
+    def request(self, flow: http.HTTPFlow) -> None:
+        if "gr-app." in flow.request.pretty_url:
+            flow.request.url = re.sub(
+                r"polygerrit_ui/([\d.]+)/elements",
+                "polygerrit_ui/" + self.version + "/elements",
+                flow.request.url)
+
+def start():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--version", type=str, help="Rapid release version, e.g. 432.0")
+    args = parser.parse_args()
+    return Server(args.version)
diff --git a/contrib/mitm-ui/mitm-docker.sh b/contrib/mitm-ui/mitm-docker.sh
new file mode 100755
index 0000000..77f209e
--- /dev/null
+++ b/contrib/mitm-ui/mitm-docker.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+extra_volume='/tmp:/tmp'
+
+POSITIONAL=()
+while [[ $# -gt 0 ]]
+do
+key="$1"
+
+case $key in
+    -v|--volume)
+    extra_volume="$2"
+    shift # past argument
+    shift # past value
+    ;;
+    *)    # unknown option
+    POSITIONAL+=("$1") # save it in an array for later
+    shift # past argument
+    ;;
+esac
+done
+set -- "${POSITIONAL[@]}" # restore positional parameters
+
+if [[ -z "$1" ]]; then
+    echo This is a runner for higher-level scripts, e.g. mitm-serve-app-dev.sh
+    echo Alternatively, pass mitmproxy script from the same dir as a parameter, e.g. serve-app-dev.py
+    exit 1
+fi
+
+gerrit_dir=$(pwd)
+mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+
+CMD="${mitm_dir}/$1"
+
+docker run --rm -it \
+       -v ~/.mitmproxy:/home/mitmproxy/.mitmproxy \
+       -v ${mitm_dir}:${mitm_dir} \
+       -v ${gerrit_dir}:${gerrit_dir} \
+       -v ${extra_volume} \
+       -p 8888:8888 \
+       mitmproxy/mitmproxy:2.0.2 \
+       mitmdump -q -p 8888 -s "${CMD}"
diff --git a/contrib/mitm-ui/mitm-plugins.sh b/contrib/mitm-ui/mitm-plugins.sh
new file mode 100755
index 0000000..992ef07
--- /dev/null
+++ b/contrib/mitm-ui/mitm-plugins.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+if [[ -z "$1" ]]; then
+    echo This script injects plugins for *.googlesource.com.
+    echo Provide plugin paths, comma-separated, as a parameter.
+    echo This script assumes files do not have dependencies, i.e. minified.
+    exit 1
+fi
+
+realpath() {
+    [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
+}
+
+join () {
+  local IFS="$1"
+  shift
+  echo "$*"
+}
+
+plugins=$1
+plugin_paths=()
+for plugin in $(echo ${plugins} | sed "s/,/ /g")
+do
+    plugin_paths+=($(realpath ${plugin}))
+done
+
+absolute_plugin_paths=$(join , "${plugin_paths[@]}")
+
+mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+
+${mitm_dir}/dev-chrome.sh &
+
+${mitm_dir}/mitm-docker.sh "serve-app-dev.py --plugins ${absolute_plugin_paths} --strip_assets"
diff --git a/contrib/mitm-ui/mitm-serve-app-dev.sh b/contrib/mitm-ui/mitm-serve-app-dev.sh
new file mode 100755
index 0000000..4fa8958
--- /dev/null
+++ b/contrib/mitm-ui/mitm-serve-app-dev.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+workspace="./WORKSPACE"
+if [[ ! -f ${workspace} ]] || [[ ! $(head -n 1 ${workspace}) == *"gerrit"* ]]; then
+    echo Please change to cloned Gerrit repo from https://gerrit.googlesource.com/gerrit/
+    exit 1
+fi
+
+mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+
+${mitm_dir}/dev-chrome.sh &
+
+${mitm_dir}/mitm-docker.sh "serve-app-dev.py --app $(pwd)/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-single-plugin.sh b/contrib/mitm-ui/mitm-single-plugin.sh
new file mode 100755
index 0000000..4acae7f
--- /dev/null
+++ b/contrib/mitm-ui/mitm-single-plugin.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+if [[ -z "$1" ]]; then
+    echo This script serves one plugin with the rest of static content.
+    echo Provide path to index plugin file, e.g. buildbucket.html for buildbucket plugin
+    exit 1
+fi
+
+realpath() {
+  OURPWD=$PWD
+  cd "$(dirname "$1")"
+  LINK=$(basename "$1")
+  while [ -L "$LINK" ]; do
+      LINK=$(readlink "$LINK")
+      cd "$(dirname "$LINK")"
+      LINK="$(basename "$1")"
+  done
+  REAL_DIR=`pwd -P`
+  RESULT=$REAL_DIR/$LINK
+  cd "$OURPWD"
+  echo "$RESULT"
+}
+
+plugin=$(realpath $1)
+plugin_root=$(dirname ${plugin})
+
+mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+
+${mitm_dir}/dev-chrome.sh &
+
+${mitm_dir}/mitm-docker.sh -v ${plugin_root}:${plugin_root} "serve-app-dev.py --plugins ${plugin} --strip_assets --plugin_root ${plugin_root}"
diff --git a/contrib/mitm-ui/serve-app-dev.py b/contrib/mitm-ui/serve-app-dev.py
new file mode 100644
index 0000000..bd054e5
--- /dev/null
+++ b/contrib/mitm-ui/serve-app-dev.py
@@ -0,0 +1,139 @@
+# 1. install and setup mitmproxy v2.0.2: https://mitmproxy.readthedocs.io/en/v2.0.2/install.html
+#   (In case of python versions trouble, use https://www.anaconda.com/)
+# 2. mitmdump -q -s -p 8888 \
+#   "serve-app-dev.py --app /path/to/polygerrit-ui/app/"
+# 3. start Chrome with --proxy-server="127.0.0.1:8888" --user-data-dir=/tmp/devchrome
+# 4. open, say, gerrit-review.googlesource.com. Or chromium-review.googlesource.com. Any.
+# 5. uncompiled source files are served and you can log in, too.
+# 6. enjoy!
+#
+# P.S. For replacing plugins, use --plugins or --plugin_root
+#
+# --plugin takes comma-separated list of plugins to add or replace.
+#
+# Example: Adding a new plugin to the server response:
+# --plugins ~/gerrit-testsite/plugins/myplugin.html
+#
+# Example: Replace all matching plugins with local versions:
+# --plugins ~/gerrit-testsite/plugins/
+# Following files will be served if they exist for /plugins/tricium/static/tricium.html:
+#  ~/gerrit-testsite/plugins/tricium.html
+#  ~/gerrit-testsite/plugins/tricium/static/tricium.html
+#
+# --assets takes assets bundle.html, expecting rest of the assets files to be in the same folder
+#
+# Example:
+#  --assets ~/gerrit-testsite/assets/a3be19f.html
+#
+
+from mitmproxy import http
+from mitmproxy.script import concurrent
+import re
+import argparse
+import os.path
+import json
+
+class Server:
+    def __init__(self, devpath, plugins, pluginroot, assets, strip_assets):
+        if devpath:
+            print("Serving app from " + devpath)
+        if pluginroot:
+            print("Serving plugins from " + pluginroot)
+        if assets:
+            self.assets_root, self.assets_file = os.path.split(assets)
+            print("Assets: using " + self.assets_file + " from " + self.assets_root)
+        else:
+            self.assets_root = None
+        if plugins:
+            self.plugins = {path.split("/")[-1:][0]: path for path in map(expandpath, plugins.split(","))}
+            for filename, path in self.plugins.items():
+                print("Serving " + filename + " from " + path)
+        else:
+            self.plugins = {}
+        self.devpath = devpath
+        self.pluginroot = pluginroot
+        self.strip_assets = strip_assets
+
+    def readfile(self, path):
+        with open(path, 'rb') as contentfile:
+            return contentfile.read()
+
+@concurrent
+def response(flow: http.HTTPFlow) -> None:
+    if server.strip_assets:
+        assets_bundle = 'googlesource.com/polygerrit_assets'
+        assets_pos = flow.response.text.find(assets_bundle)
+        if assets_pos != -1:
+            t = flow.response.text
+            flow.response.text = t[:t.rfind('<', 0, assets_pos)] + t[t.find('>', assets_pos) + 1:]
+            return
+
+    if server.assets_root:
+        marker = 'webcomponents-lite.js"></script>'
+        pos = flow.response.text.find(marker)
+        if pos != -1:
+            pos += len(marker)
+            flow.response.text = ''.join([
+                flow.response.text[:pos],
+                '<link rel="import" href="/gerrit_assets/123.0/' + server.assets_file + '">',
+                flow.response.text[pos:]
+            ])
+
+        assets_prefix = "/gerrit_assets/123.0/"
+        if flow.request.path.startswith(assets_prefix):
+            assets_file = flow.request.path[len(assets_prefix):]
+            flow.response.content = server.readfile(server.assets_root + '/' + assets_file)
+            flow.response.status_code = 200
+            if assets_file.endswith('.js'):
+                flow.response.headers['Content-type'] = 'text/javascript'
+            return
+    m = re.match(".+polygerrit_ui/\d+\.\d+/(.+)", flow.request.path)
+    pluginmatch = re.match("^/plugins/(.+)", flow.request.path)
+    localfile = ""
+    if flow.request.path == "/config/server/info":
+        config = json.loads(flow.response.content[5:].decode('utf8'))
+        for filename, path in server.plugins.items():
+            pluginname = filename.split(".")[0]
+            payload = config["plugin"]["js_resource_paths" if filename.endswith(".js") else "html_resource_paths"]
+            if list(filter(lambda url: filename in url, payload)):
+                continue
+            payload.append("plugins/" + pluginname + "/static/" + filename)
+        flow.response.content = str.encode(")]}'\n" + json.dumps(config))
+    if m is not None:
+        filepath = m.groups()[0]
+        localfile = server.devpath + filepath
+    elif pluginmatch is not None:
+        pluginfile = flow.request.path_components[-1]
+        if server.plugins and pluginfile in server.plugins:
+            if os.path.isfile(server.plugins[pluginfile]):
+                localfile = server.plugins[pluginfile]
+            else:
+                print("Can't find file " + server.plugins[pluginfile] + " for " + flow.request.path)
+        elif server.pluginroot:
+            pluginurl = pluginmatch.groups()[0]
+            if os.path.isfile(server.pluginroot + pluginfile):
+                localfile = server.pluginroot + pluginfile
+            elif os.path.isfile(server.pluginroot + pluginurl):
+                localfile = server.pluginroot + pluginurl
+    if localfile and os.path.isfile(localfile):
+        if pluginmatch is not None:
+            print("Serving " + flow.request.path + " from " + localfile)
+        flow.response.content = server.readfile(localfile)
+        flow.response.status_code = 200
+        if localfile.endswith('.js'):
+            flow.response.headers['Content-type'] = 'text/javascript'
+
+def expandpath(path):
+    return os.path.realpath(os.path.expanduser(path))
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--app", type=str, default="", help="Path to /polygerrit-ui/app/")
+parser.add_argument("--plugins", type=str, default="", help="Comma-separated list of plugin files to add/replace")
+parser.add_argument("--plugin_root", type=str, default="", help="Path containing individual plugin files to replace")
+parser.add_argument("--assets", type=str, default="", help="Path containing assets file to import.")
+parser.add_argument("--strip_assets", action="store_true", help="Strip plugin bundles from the response.")
+args = parser.parse_args()
+server = Server(expandpath(args.app) + '/',
+                args.plugins, expandpath(args.plugin_root) + '/',
+                args.assets and expandpath(args.assets),
+                args.strip_assets)
diff --git a/contrib/mitm-ui/serve-app-locally.py b/contrib/mitm-ui/serve-app-locally.py
new file mode 100644
index 0000000..636c684
--- /dev/null
+++ b/contrib/mitm-ui/serve-app-locally.py
@@ -0,0 +1,46 @@
+# bazel build polygerrit-ui/app:gr-app
+# mitmdump -s "serve-app-locally.py ~/gerrit/bazel-bin/polygerrit-ui/app"
+from mitmproxy import http
+import argparse
+import os
+import zipfile
+
+class Server:
+    def __init__(self, bundle):
+        self.bundle = bundle
+        self.bundlemtime = 0
+        self.files = {
+            'polygerrit_ui/elements/gr-app.js': '',
+            'polygerrit_ui/elements/gr-app.html': '',
+            'polygerrit_ui/styles/main.css': '',
+        }
+        self.read_files()
+
+    def read_files(self):
+        if not os.path.isfile(self.bundle):
+            print("bundle not found!")
+            return
+        mtime = os.stat(self.bundle).st_mtime
+        if mtime <= self.bundlemtime:
+            return
+        self.bundlemtime = mtime
+        with zipfile.ZipFile(self.bundle) as z:
+            for fname in self.files:
+                print('Reading new content for ' + fname)
+                with z.open(fname, 'r') as content_file:
+                    self.files[fname] = content_file.read()
+
+    def response(self, flow: http.HTTPFlow) -> None:
+        self.read_files()
+        for name in self.files:
+            if name.rsplit('/', 1)[1] in flow.request.pretty_url:
+                flow.response.content = self.files[name]
+
+def expandpath(path):
+    return os.path.expanduser(path)
+
+def start():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("bundle", type=str)
+    args = parser.parse_args()
+    return Server(expandpath(args.bundle))
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index d736446..5155e6c 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -125,7 +125,6 @@
 import com.google.gerrit.testing.ConfigSuite;
 import com.google.gerrit.testing.FakeEmailSender;
 import com.google.gerrit.testing.FakeEmailSender.Message;
-import com.google.gerrit.testing.FakeGroupAuditService;
 import com.google.gerrit.testing.SshMode;
 import com.google.gson.Gson;
 import com.google.gwtorm.server.OrmException;
@@ -242,7 +241,6 @@
   @Inject protected ChangeNoteUtil changeNoteUtil;
   @Inject protected ChangeResource.Factory changeResourceFactory;
   @Inject protected FakeEmailSender sender;
-  @Inject protected FakeGroupAuditService auditService;
   @Inject protected GerritApi gApi;
   @Inject protected GitRepositoryManager repoManager;
   @Inject protected GroupBackend groupBackend;
@@ -725,7 +723,7 @@
   }
 
   private static final List<Character> RANDOM =
-      Chars.asList(new char[] {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'});
+      Chars.asList('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
 
   protected PushOneCommit.Result amendChange(String changeId) throws Exception {
     return amendChange(changeId, "refs/for/master", admin, testRepo);
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 25315b6..794fe80 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -394,7 +394,7 @@
     daemon.setEnableHttpd(desc.httpd());
     daemon.setLuceneModule(LuceneIndexModule.singleVersionAllLatest(0, isSlave(baseConfig)));
     daemon.setDatabaseForTesting(
-        ImmutableList.<Module>of(
+        ImmutableList.of(
             new InMemoryTestingDatabaseModule(cfg, site, inMemoryRepoManager),
             new AbstractModule() {
               @Override
diff --git a/java/com/google/gerrit/asciidoctor/AsciiDoctor.java b/java/com/google/gerrit/asciidoctor/AsciiDoctor.java
index 5779070..73f0d5d 100644
--- a/java/com/google/gerrit/asciidoctor/AsciiDoctor.java
+++ b/java/com/google/gerrit/asciidoctor/AsciiDoctor.java
@@ -127,7 +127,7 @@
       int equalsIndex = attribute.indexOf('=');
       if (equalsIndex > -1) {
         String name = attribute.substring(0, equalsIndex);
-        String value = attribute.substring(equalsIndex + 1, attribute.length());
+        String value = attribute.substring(equalsIndex + 1);
 
         attributeValues.put(name, value);
       } else {
diff --git a/java/com/google/gerrit/common/data/CommentDetail.java b/java/com/google/gerrit/common/data/CommentDetail.java
index ed7c79b..1ae246f 100644
--- a/java/com/google/gerrit/common/data/CommentDetail.java
+++ b/java/com/google/gerrit/common/data/CommentDetail.java
@@ -84,7 +84,7 @@
 
   private static List<Comment> get(Map<Integer, List<Comment>> m, int i) {
     List<Comment> r = m.get(i);
-    return r != null ? orderComments(r) : Collections.<Comment>emptyList();
+    return r != null ? orderComments(r) : Collections.emptyList();
   }
 
   /**
diff --git a/java/com/google/gerrit/common/data/ParameterizedString.java b/java/com/google/gerrit/common/data/ParameterizedString.java
index 28e47ee..84bb535 100644
--- a/java/com/google/gerrit/common/data/ParameterizedString.java
+++ b/java/com/google/gerrit/common/data/ParameterizedString.java
@@ -40,7 +40,7 @@
   private ParameterizedString(Constant c) {
     pattern = c.text;
     rawPattern = c.text;
-    patternOps = Collections.<Format>singletonList(c);
+    patternOps = Collections.singletonList(c);
     parameters = Collections.emptyList();
   }
 
@@ -60,7 +60,7 @@
         break;
       }
 
-      raw.append(pattern.substring(i, b));
+      raw.append(pattern, i, b);
       ops.add(new Constant(pattern.substring(i, b)));
 
       // "${parameter[.functions...]}" -> "parameter[.functions...]"
diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index 7257da1..14e0ed7 100644
--- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -105,9 +105,13 @@
 
   void setPrivate(boolean value, @Nullable String message) throws RestApiException;
 
-  void setWorkInProgress(String message) throws RestApiException;
+  default void setPrivate(boolean value) throws RestApiException {
+    setPrivate(value, null);
+  }
 
-  void setReadyForReview(String message) throws RestApiException;
+  void setWorkInProgress(@Nullable String message) throws RestApiException;
+
+  void setReadyForReview(@Nullable String message) throws RestApiException;
 
   default void setWorkInProgress() throws RestApiException {
     setWorkInProgress(null);
diff --git a/java/com/google/gerrit/extensions/api/projects/CommitApi.java b/java/com/google/gerrit/extensions/api/projects/CommitApi.java
index 6084962..6b3c1fb 100644
--- a/java/com/google/gerrit/extensions/api/projects/CommitApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/CommitApi.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.CherryPickInput;
+import com.google.gerrit.extensions.api.changes.IncludedInInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 
@@ -23,11 +24,18 @@
 
   ChangeApi cherryPick(CherryPickInput input) throws RestApiException;
 
+  IncludedInInfo includedIn() throws RestApiException;
+
   /** A default implementation for source compatibility when adding new methods to the interface. */
   class NotImplemented implements CommitApi {
     @Override
     public ChangeApi cherryPick(CherryPickInput input) throws RestApiException {
       throw new NotImplementedException();
     }
+
+    @Override
+    public IncludedInInfo includedIn() throws RestApiException {
+      throw new NotImplementedException();
+    }
   }
 }
diff --git a/java/com/google/gerrit/extensions/registration/DynamicSet.java b/java/com/google/gerrit/extensions/registration/DynamicSet.java
index dcd0d8f..9491f72 100644
--- a/java/com/google/gerrit/extensions/registration/DynamicSet.java
+++ b/java/com/google/gerrit/extensions/registration/DynamicSet.java
@@ -135,7 +135,7 @@
   }
 
   public static <T> DynamicSet<T> emptySet() {
-    return new DynamicSet<>(Collections.<AtomicReference<Extension<T>>>emptySet());
+    return new DynamicSet<>(Collections.emptySet());
   }
 
   private final CopyOnWriteArrayList<AtomicReference<Extension<T>>> items;
diff --git a/java/com/google/gerrit/gpg/CheckResult.java b/java/com/google/gerrit/gpg/CheckResult.java
index da891aa..8655b2a 100644
--- a/java/com/google/gerrit/gpg/CheckResult.java
+++ b/java/com/google/gerrit/gpg/CheckResult.java
@@ -31,14 +31,14 @@
   }
 
   static CheckResult trusted() {
-    return new CheckResult(Status.TRUSTED, Collections.<String>emptyList());
+    return new CheckResult(Status.TRUSTED, Collections.emptyList());
   }
 
   static CheckResult create(Status status, String... problems) {
     List<String> problemList =
         problems.length > 0
             ? Collections.unmodifiableList(Arrays.asList(problems))
-            : Collections.<String>emptyList();
+            : Collections.emptyList();
     return new CheckResult(status, problemList);
   }
 
diff --git a/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/java/com/google/gerrit/httpd/GitOverHttpServlet.java
index 7fbb8d7..ac5386c 100644
--- a/java/com/google/gerrit/httpd/GitOverHttpServlet.java
+++ b/java/com/google/gerrit/httpd/GitOverHttpServlet.java
@@ -212,7 +212,7 @@
     }
     // Explicit cast is required to compile under Servlet API 2.5, where the return type is raw Map.
     @SuppressWarnings("cast")
-    Map<String, String[]> parameterMap = (Map<String, String[]>) request.getParameterMap();
+    Map<String, String[]> parameterMap = request.getParameterMap();
     ImmutableListMultimap.Builder<String, String> b = ImmutableListMultimap.builder();
     parameterMap.forEach(b::putAll);
     return b.build();
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 26fa07c..4057d54 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -1361,9 +1361,7 @@
     // generated.
     TraceContext traceContext =
         TraceContext.newTrace(
-            doTrace,
-            traceId1,
-            (tagName, traceId) -> res.setHeader(X_GERRIT_TRACE, traceId.toString()));
+            doTrace, traceId1, (tagName, traceId) -> res.setHeader(X_GERRIT_TRACE, traceId));
     // If a second trace ID was specified, add a tag for it as well.
     if (traceId2 != null) {
       traceContext.addTag(RequestId.Type.TRACE_ID, traceId2);
diff --git a/java/com/google/gerrit/index/query/QueryProcessor.java b/java/com/google/gerrit/index/query/QueryProcessor.java
index 6f10750..c3e1f63 100644
--- a/java/com/google/gerrit/index/query/QueryProcessor.java
+++ b/java/com/google/gerrit/index/query/QueryProcessor.java
@@ -323,7 +323,7 @@
       return requestedFields;
     }
     Index<?, T> index = indexes.getSearchIndex();
-    return index != null ? index.getSchema().getStoredFields().keySet() : ImmutableSet.<String>of();
+    return index != null ? index.getSchema().getStoredFields().keySet() : ImmutableSet.of();
   }
 
   /**
diff --git a/java/com/google/gerrit/launcher/GerritLauncher.java b/java/com/google/gerrit/launcher/GerritLauncher.java
index 868c1d5..30d4e15 100644
--- a/java/com/google/gerrit/launcher/GerritLauncher.java
+++ b/java/com/google/gerrit/launcher/GerritLauncher.java
@@ -324,7 +324,7 @@
     }
 
     String name = ze.getName();
-    jars.put(name.substring(name.lastIndexOf('/'), name.length()), tmp.toURI().toURL());
+    jars.put(name.substring(name.lastIndexOf('/')), tmp.toURI().toURL());
   }
 
   private static void move(SortedMap<String, URL> jars, String prefix, List<URL> extapi) {
diff --git a/java/com/google/gerrit/mail/MailHeaderParser.java b/java/com/google/gerrit/mail/MailHeaderParser.java
index 8eb4d97..a4a6a03 100644
--- a/java/com/google/gerrit/mail/MailHeaderParser.java
+++ b/java/com/google/gerrit/mail/MailHeaderParser.java
@@ -103,6 +103,6 @@
   }
 
   private static String extractFooter(String key, String line) {
-    return line.substring(line.indexOf(key) + key.length(), line.length()).trim();
+    return line.substring(line.indexOf(key) + key.length()).trim();
   }
 }
diff --git a/java/com/google/gerrit/metrics/MetricMaker.java b/java/com/google/gerrit/metrics/MetricMaker.java
index 401a6d6..42ec8a0 100644
--- a/java/com/google/gerrit/metrics/MetricMaker.java
+++ b/java/com/google/gerrit/metrics/MetricMaker.java
@@ -136,7 +136,7 @@
    * @return registration handle
    */
   public RegistrationHandle newTrigger(CallbackMetric<?> metric1, Runnable trigger) {
-    return newTrigger(ImmutableSet.<CallbackMetric<?>>of(metric1), trigger);
+    return newTrigger(ImmutableSet.of(metric1), trigger);
   }
 
   public RegistrationHandle newTrigger(
diff --git a/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java b/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
index ee87397..e33c242 100644
--- a/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
+++ b/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
@@ -120,7 +120,7 @@
 
   @Override
   public Map<Object, Metric> getCells() {
-    return Maps.transformValues(cells, in -> (Metric) in);
+    return Maps.transformValues(cells, in -> in);
   }
 
   final class ValueGauge implements Gauge<V> {
diff --git a/java/com/google/gerrit/metrics/dropwizard/MetricJson.java b/java/com/google/gerrit/metrics/dropwizard/MetricJson.java
index 2080623..20f4fa3 100644
--- a/java/com/google/gerrit/metrics/dropwizard/MetricJson.java
+++ b/java/com/google/gerrit/metrics/dropwizard/MetricJson.java
@@ -137,7 +137,7 @@
       p99_9 = s.get999thPercentile();
 
       min = (double) s.getMin();
-      avg = (double) s.getMean();
+      avg = s.getMean();
       max = (double) s.getMax();
       sum = s.getMean() * m.getCount();
       std_dev = s.getStdDev();
diff --git a/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java b/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java
index 10d589a..35c147e 100644
--- a/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java
+++ b/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java
@@ -51,10 +51,9 @@
   private OperatingSystemMXBeanProvider(OperatingSystemMXBean sys)
       throws ReflectiveOperationException {
     this.sys = sys;
-    getProcessCpuTime = sys.getClass().getMethod("getProcessCpuTime", new Class<?>[] {});
+    getProcessCpuTime = sys.getClass().getMethod("getProcessCpuTime");
     getProcessCpuTime.setAccessible(true);
-    getOpenFileDescriptorCount =
-        sys.getClass().getMethod("getOpenFileDescriptorCount", new Class<?>[] {});
+    getOpenFileDescriptorCount = sys.getClass().getMethod("getOpenFileDescriptorCount");
     getOpenFileDescriptorCount.setAccessible(true);
   }
 
diff --git a/java/com/google/gerrit/metrics/proc/ProcMetricModule.java b/java/com/google/gerrit/metrics/proc/ProcMetricModule.java
index 6b9176b..5b7dbe3 100644
--- a/java/com/google/gerrit/metrics/proc/ProcMetricModule.java
+++ b/java/com/google/gerrit/metrics/proc/ProcMetricModule.java
@@ -18,7 +18,6 @@
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.common.Version;
-import com.google.gerrit.metrics.CallbackMetric;
 import com.google.gerrit.metrics.CallbackMetric0;
 import com.google.gerrit.metrics.CallbackMetric1;
 import com.google.gerrit.metrics.Description;
@@ -135,7 +134,7 @@
 
     MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
     metrics.newTrigger(
-        ImmutableSet.<CallbackMetric<?>>of(
+        ImmutableSet.of(
             heapCommitted, heapUsed, nonHeapCommitted, nonHeapUsed, objectPendingFinalizationCount),
         () -> {
           try {
diff --git a/java/com/google/gerrit/pgm/Init.java b/java/com/google/gerrit/pgm/Init.java
index f31fb2c..0537fe9 100644
--- a/java/com/google/gerrit/pgm/Init.java
+++ b/java/com/google/gerrit/pgm/Init.java
@@ -144,7 +144,9 @@
         });
     modules.add(new GerritServerConfigModule());
     Guice.createInjector(modules).injectMembers(this);
-    reindexProjects();
+    if (!run.flags.cfg.getBoolean("container", "slave", false)) {
+      reindexProjects();
+    }
     start(run);
   }
 
@@ -190,7 +192,7 @@
 
   @Override
   protected List<String> getSkippedDownloads() {
-    return skippedDownloads != null ? skippedDownloads : Collections.<String>emptyList();
+    return skippedDownloads != null ? skippedDownloads : Collections.emptyList();
   }
 
   @Override
diff --git a/java/com/google/gerrit/pgm/init/InitLabels.java b/java/com/google/gerrit/pgm/init/InitLabels.java
index 3d1ec7b..0797cf9 100644
--- a/java/com/google/gerrit/pgm/init/InitLabels.java
+++ b/java/com/google/gerrit/pgm/init/InitLabels.java
@@ -61,7 +61,7 @@
           KEY_LABEL,
           LABEL_VERIFIED,
           KEY_VALUE,
-          Arrays.asList(new String[] {"-1 Fails", "0 No score", "+1 Verified"}));
+          Arrays.asList("-1 Fails", "0 No score", "+1 Verified"));
       cfg.setBoolean(KEY_LABEL, LABEL_VERIFIED, KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE, true);
       allProjectsConfig.save("Configure 'Verified' label");
     }
diff --git a/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java b/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java
index 0d73089..80de1e5 100644
--- a/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java
+++ b/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java
@@ -46,8 +46,7 @@
   static final String INDEX_MANAGER = "IndexModuleOnInit/IndexManager";
 
   private static final ImmutableCollection<SchemaDefinitions<?>> ALL_SCHEMA_DEFS =
-      ImmutableList.<SchemaDefinitions<?>>of(
-          AccountSchemaDefinitions.INSTANCE, GroupSchemaDefinitions.INSTANCE);
+      ImmutableList.of(AccountSchemaDefinitions.INSTANCE, GroupSchemaDefinitions.INSTANCE);
 
   @Override
   protected void configure() {
@@ -76,7 +75,7 @@
 
     bind(new TypeLiteral<Map<String, Integer>>() {})
         .annotatedWith(Names.named(SingleVersionModule.SINGLE_VERSIONS))
-        .toInstance(ImmutableMap.<String, Integer>of());
+        .toInstance(ImmutableMap.of());
     bind(LifecycleListener.class)
         .annotatedWith(Names.named(INDEX_MANAGER))
         .to(SingleVersionListener.class);
@@ -85,8 +84,7 @@
   @Provides
   Collection<IndexDefinition<?, ?, ?>> getIndexDefinitions(
       AccountIndexDefinition accounts, GroupIndexDefinition groups) {
-    Collection<IndexDefinition<?, ?, ?>> result =
-        ImmutableList.<IndexDefinition<?, ?, ?>>of(accounts, groups);
+    Collection<IndexDefinition<?, ?, ?>> result = ImmutableList.of(accounts, groups);
     Set<String> expected =
         FluentIterable.from(ALL_SCHEMA_DEFS).transform(SchemaDefinitions::getName).toSet();
     Set<String> actual = FluentIterable.from(result).transform(IndexDefinition::getName).toSet();
diff --git a/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index 740d08f..b0c1c25 100644
--- a/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -107,17 +107,15 @@
 
     // We're just running through each change
     // once, so don't worry about cache removal.
-    bind(new TypeLiteral<DynamicSet<CacheRemovalListener>>() {})
-        .toInstance(DynamicSet.<CacheRemovalListener>emptySet());
-    bind(new TypeLiteral<DynamicMap<Cache<?, ?>>>() {})
-        .toInstance(DynamicMap.<Cache<?, ?>>emptyMap());
+    bind(new TypeLiteral<DynamicSet<CacheRemovalListener>>() {}).toInstance(DynamicSet.emptySet());
+    bind(new TypeLiteral<DynamicMap<Cache<?, ?>>>() {}).toInstance(DynamicMap.emptyMap());
     bind(new TypeLiteral<List<CommentLinkInfo>>() {})
         .toProvider(CommentLinkProvider.class)
         .in(SINGLETON);
     bind(new TypeLiteral<DynamicMap<ChangeQueryProcessor.ChangeAttributeFactory>>() {})
-        .toInstance(DynamicMap.<ChangeQueryProcessor.ChangeAttributeFactory>emptyMap());
+        .toInstance(DynamicMap.emptyMap());
     bind(new TypeLiteral<DynamicMap<RestView<CommitResource>>>() {})
-        .toInstance(DynamicMap.<RestView<CommitResource>>emptyMap());
+        .toInstance(DynamicMap.emptyMap());
     bind(String.class)
         .annotatedWith(CanonicalWebUrl.class)
         .toProvider(CanonicalWebUrlProvider.class);
@@ -126,9 +124,8 @@
         .toProvider(DisableReverseDnsLookupProvider.class)
         .in(SINGLETON);
     bind(Realm.class).to(FakeRealm.class);
-    bind(IdentifiedUser.class).toProvider(Providers.<IdentifiedUser>of(null));
-    bind(ReplacePatchSetSender.Factory.class)
-        .toProvider(Providers.<ReplacePatchSetSender.Factory>of(null));
+    bind(IdentifiedUser.class).toProvider(Providers.of(null));
+    bind(ReplacePatchSetSender.Factory.class).toProvider(Providers.of(null));
     bind(CurrentUser.class).to(IdentifiedUser.class);
     factory(MergeUtil.Factory.class);
     factory(PatchSetInserter.Factory.class);
@@ -136,17 +133,17 @@
 
     // As Reindex is a batch program, don't assume the index is available for
     // the change cache.
-    bind(SearchingChangeCacheImpl.class).toProvider(Providers.<SearchingChangeCacheImpl>of(null));
+    bind(SearchingChangeCacheImpl.class).toProvider(Providers.of(null));
 
     bind(new TypeLiteral<ImmutableSet<GroupReference>>() {})
         .annotatedWith(AdministrateServerGroups.class)
-        .toInstance(ImmutableSet.<GroupReference>of());
+        .toInstance(ImmutableSet.of());
     bind(new TypeLiteral<Set<AccountGroup.UUID>>() {})
         .annotatedWith(GitUploadPackGroups.class)
-        .toInstance(Collections.<AccountGroup.UUID>emptySet());
+        .toInstance(Collections.emptySet());
     bind(new TypeLiteral<Set<AccountGroup.UUID>>() {})
         .annotatedWith(GitReceivePackGroups.class)
-        .toInstance(Collections.<AccountGroup.UUID>emptySet());
+        .toInstance(Collections.emptySet());
 
     install(new BatchGitModule());
     install(new DefaultPermissionBackendModule());
@@ -174,8 +171,8 @@
     install(new DefaultSubmitRule.Module());
     install(new IgnoreSelfApprovalRule.Module());
 
-    bind(ChangeJson.Factory.class).toProvider(Providers.<ChangeJson.Factory>of(null));
-    bind(EventUtil.class).toProvider(Providers.<EventUtil>of(null));
+    bind(ChangeJson.Factory.class).toProvider(Providers.of(null));
+    bind(EventUtil.class).toProvider(Providers.of(null));
     bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
     bind(RevisionCreated.class).toInstance(RevisionCreated.DISABLED);
     bind(AccountVisibility.class).toProvider(AccountVisibilityProvider.class).in(SINGLETON);
diff --git a/java/com/google/gerrit/reviewdb/client/PatchSet.java b/java/com/google/gerrit/reviewdb/client/PatchSet.java
index 68653a2..a2c7010 100644
--- a/java/com/google/gerrit/reviewdb/client/PatchSet.java
+++ b/java/com/google/gerrit/reviewdb/client/PatchSet.java
@@ -65,7 +65,7 @@
     while (true) {
       int idx = joinedGroups.indexOf(',', i);
       if (idx < 0) {
-        groups.add(joinedGroups.substring(i, joinedGroups.length()));
+        groups.add(joinedGroups.substring(i));
         break;
       }
       groups.add(joinedGroups.substring(i, idx));
diff --git a/java/com/google/gerrit/reviewdb/client/RefNames.java b/java/com/google/gerrit/reviewdb/client/RefNames.java
index 5e45088..9e1fcca 100644
--- a/java/com/google/gerrit/reviewdb/client/RefNames.java
+++ b/java/com/google/gerrit/reviewdb/client/RefNames.java
@@ -432,7 +432,7 @@
     if (i == 0) {
       return null;
     }
-    return Integer.valueOf(name.substring(i, name.length()));
+    return Integer.valueOf(name.substring(i));
   }
 
   private static StringBuilder newStringBuilder() {
diff --git a/java/com/google/gerrit/server/ApprovalCopier.java b/java/com/google/gerrit/server/ApprovalCopier.java
index 163788a..45588a3 100644
--- a/java/com/google/gerrit/server/ApprovalCopier.java
+++ b/java/com/google/gerrit/server/ApprovalCopier.java
@@ -75,7 +75,7 @@
   Iterable<PatchSetApproval> getForPatchSet(
       ChangeNotes notes, PatchSet.Id psId, @Nullable RevWalk rw, @Nullable Config repoConfig)
       throws OrmException {
-    return getForPatchSet(notes, psId, rw, repoConfig, Collections.<PatchSetApproval>emptyList());
+    return getForPatchSet(notes, psId, rw, repoConfig, Collections.emptyList());
   }
 
   Iterable<PatchSetApproval> getForPatchSet(
diff --git a/java/com/google/gerrit/server/IdentifiedUser.java b/java/com/google/gerrit/server/IdentifiedUser.java
index b1761f4..005a2b3 100644
--- a/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/java/com/google/gerrit/server/IdentifiedUser.java
@@ -96,13 +96,13 @@
           accountCache,
           groupBackend,
           disableReverseDnsLookup,
-          Providers.of((SocketAddress) null),
+          Providers.of(null),
           state,
           null);
     }
 
     public IdentifiedUser create(Account.Id id) {
-      return create((SocketAddress) null, id);
+      return create(null, id);
     }
 
     public IdentifiedUser create(SocketAddress remotePeer, Account.Id id) {
diff --git a/java/com/google/gerrit/server/ReviewerSet.java b/java/com/google/gerrit/server/ReviewerSet.java
index 67b1d9d..f36e3ab 100644
--- a/java/com/google/gerrit/server/ReviewerSet.java
+++ b/java/com/google/gerrit/server/ReviewerSet.java
@@ -34,8 +34,7 @@
  * state {@link ReviewerStateInternal#REMOVED} are ever exposed by this interface.
  */
 public class ReviewerSet {
-  private static final ReviewerSet EMPTY =
-      new ReviewerSet(ImmutableTable.<ReviewerStateInternal, Account.Id, Timestamp>of());
+  private static final ReviewerSet EMPTY = new ReviewerSet(ImmutableTable.of());
 
   public static ReviewerSet fromApprovals(Iterable<PatchSetApproval> approvals) {
     PatchSetApproval first = null;
diff --git a/java/com/google/gerrit/server/account/CapabilityCollection.java b/java/com/google/gerrit/server/account/CapabilityCollection.java
index 1abc33f..b52d616 100644
--- a/java/com/google/gerrit/server/account/CapabilityCollection.java
+++ b/java/com/google/gerrit/server/account/CapabilityCollection.java
@@ -81,7 +81,7 @@
     }
     configureDefaults(tmp, section);
     if (!tmp.containsKey(GlobalCapability.ADMINISTRATE_SERVER) && !admins.isEmpty()) {
-      tmp.put(GlobalCapability.ADMINISTRATE_SERVER, ImmutableList.<PermissionRule>of());
+      tmp.put(GlobalCapability.ADMINISTRATE_SERVER, ImmutableList.of());
     }
 
     ImmutableMap.Builder<String, ImmutableList<PermissionRule>> m = ImmutableMap.builder();
@@ -123,7 +123,7 @@
 
   public ImmutableList<PermissionRule> getPermission(String permissionName) {
     ImmutableList<PermissionRule> r = permissions.get(permissionName);
-    return r != null ? r : ImmutableList.<PermissionRule>of();
+    return r != null ? r : ImmutableList.of();
   }
 
   private void configureDefaults(Map<String, List<PermissionRule>> out, AccessSection section) {
diff --git a/java/com/google/gerrit/server/account/GroupMembership.java b/java/com/google/gerrit/server/account/GroupMembership.java
index cc73222..b59b989 100644
--- a/java/com/google/gerrit/server/account/GroupMembership.java
+++ b/java/com/google/gerrit/server/account/GroupMembership.java
@@ -24,7 +24,7 @@
  * <p>Different accounts systems (eg. LDAP, gerrit groups) provide concrete implementations.
  */
 public interface GroupMembership {
-  GroupMembership EMPTY = new ListGroupMembership(Collections.<AccountGroup.UUID>emptySet());
+  GroupMembership EMPTY = new ListGroupMembership(Collections.emptySet());
 
   /**
    * Returns {@code true} when the user this object was created for is a member of the specified
diff --git a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index 0f731ed..8588dfa 100644
--- a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -314,7 +314,7 @@
   }
 
   @Override
-  public void setWorkInProgress(String message) throws RestApiException {
+  public void setWorkInProgress(@Nullable String message) throws RestApiException {
     try {
       setWip.apply(change, new WorkInProgressOp.Input(message));
     } catch (Exception e) {
@@ -323,7 +323,7 @@
   }
 
   @Override
-  public void setReadyForReview(String message) throws RestApiException {
+  public void setReadyForReview(@Nullable String message) throws RestApiException {
     try {
       setReady.apply(change, new WorkInProgressOp.Input(message));
     } catch (Exception e) {
diff --git a/java/com/google/gerrit/server/api/projects/CommitApiImpl.java b/java/com/google/gerrit/server/api/projects/CommitApiImpl.java
index a81e0de..49eec6e 100644
--- a/java/com/google/gerrit/server/api/projects/CommitApiImpl.java
+++ b/java/com/google/gerrit/server/api/projects/CommitApiImpl.java
@@ -19,10 +19,12 @@
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.Changes;
 import com.google.gerrit.extensions.api.changes.CherryPickInput;
+import com.google.gerrit.extensions.api.changes.IncludedInInfo;
 import com.google.gerrit.extensions.api.projects.CommitApi;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.server.project.CommitResource;
 import com.google.gerrit.server.restapi.change.CherryPickCommit;
+import com.google.gerrit.server.restapi.project.CommitIncludedIn;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -33,13 +35,18 @@
 
   private final Changes changes;
   private final CherryPickCommit cherryPickCommit;
+  private final CommitIncludedIn includedIn;
   private final CommitResource commitResource;
 
   @Inject
   CommitApiImpl(
-      Changes changes, CherryPickCommit cherryPickCommit, @Assisted CommitResource commitResource) {
+      Changes changes,
+      CherryPickCommit cherryPickCommit,
+      CommitIncludedIn includedIn,
+      @Assisted CommitResource commitResource) {
     this.changes = changes;
     this.cherryPickCommit = cherryPickCommit;
+    this.includedIn = includedIn;
     this.commitResource = commitResource;
   }
 
@@ -51,4 +58,13 @@
       throw asRestApiException("Cannot cherry pick", e);
     }
   }
+
+  @Override
+  public IncludedInInfo includedIn() throws RestApiException {
+    try {
+      return includedIn.apply(commitResource);
+    } catch (Exception e) {
+      throw asRestApiException("Could not extract IncludedIn data", e);
+    }
+  }
 }
diff --git a/java/com/google/gerrit/server/auth/ldap/Helper.java b/java/com/google/gerrit/server/auth/ldap/Helper.java
index a53a8c2..63e5b0a 100644
--- a/java/com/google/gerrit/server/auth/ldap/Helper.java
+++ b/java/com/google/gerrit/server/auth/ldap/Helper.java
@@ -402,7 +402,7 @@
                   groupBase,
                   groupScope,
                   new ParameterizedString(groupMemberPattern),
-                  Collections.<String>emptySet());
+                  Collections.emptySet());
           if (groupMemberQuery.getParameters().isEmpty()) {
             throw new IllegalArgumentException("No variables in ldap.groupMemberPattern");
           }
diff --git a/java/com/google/gerrit/server/cache/CacheMetrics.java b/java/com/google/gerrit/server/cache/CacheMetrics.java
index c652d50..f2dd00e 100644
--- a/java/com/google/gerrit/server/cache/CacheMetrics.java
+++ b/java/com/google/gerrit/server/cache/CacheMetrics.java
@@ -67,7 +67,7 @@
             F_NAME);
 
     Set<CallbackMetric<?>> cacheMetrics =
-        ImmutableSet.<CallbackMetric<?>>of(memEnt, memHit, memEvict, perDiskEnt, perDiskHit);
+        ImmutableSet.of(memEnt, memHit, memEvict, perDiskEnt, perDiskHit);
 
     metrics.newTrigger(
         cacheMetrics,
diff --git a/java/com/google/gerrit/server/change/ReviewerJson.java b/java/com/google/gerrit/server/change/ReviewerJson.java
index fc79522..fd5772d 100644
--- a/java/com/google/gerrit/server/change/ReviewerJson.java
+++ b/java/com/google/gerrit/server/change/ReviewerJson.java
@@ -90,7 +90,7 @@
 
   public List<ReviewerInfo> format(ReviewerResource rsrc)
       throws OrmException, PermissionBackendException {
-    return format(ImmutableList.<ReviewerResource>of(rsrc));
+    return format(ImmutableList.of(rsrc));
   }
 
   public ReviewerInfo format(ReviewerInfo out, Account.Id reviewerAccountId, ChangeData cd)
diff --git a/java/com/google/gerrit/server/git/MergeUtil.java b/java/com/google/gerrit/server/git/MergeUtil.java
index cc60b10..ee4d71e 100644
--- a/java/com/google/gerrit/server/git/MergeUtil.java
+++ b/java/com/google/gerrit/server/git/MergeUtil.java
@@ -83,7 +83,6 @@
 import org.eclipse.jgit.errors.NoMergeBaseException;
 import org.eclipse.jgit.errors.NoMergeBaseException.MergeBaseFailureReason;
 import org.eclipse.jgit.errors.RevisionSyntaxException;
-import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Constants;
@@ -624,7 +623,7 @@
     }
 
     try (ObjectInserter ins = new InMemoryInserter(repo)) {
-      return newThreeWayMerger(ins, repo.getConfig()).merge(new AnyObjectId[] {mergeTip, toMerge});
+      return newThreeWayMerger(ins, repo.getConfig()).merge(mergeTip, toMerge);
     } catch (LargeObjectException e) {
       logger.atWarning().log("Cannot merge due to LargeObjectException: %s", toMerge.name());
       return false;
@@ -722,7 +721,7 @@
       throws IntegrationException {
     ThreeWayMerger m = newThreeWayMerger(inserter, repoConfig);
     try {
-      if (m.merge(new AnyObjectId[] {mergeTip, n})) {
+      if (m.merge(mergeTip, n)) {
         return writeMergeCommit(
             author, committer, rw, inserter, destBranch, mergeTip, m.getResultTreeId(), n);
       }
diff --git a/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java b/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java
index 53d5bef..0692ccf 100644
--- a/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java
+++ b/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java
@@ -64,8 +64,7 @@
     @Override
     protected void configure() {
       if (slave) {
-        bind(SearchingChangeCacheImpl.class)
-            .toProvider(Providers.<SearchingChangeCacheImpl>of(null));
+        bind(SearchingChangeCacheImpl.class).toProvider(Providers.of(null));
       } else {
         cache(ID_CACHE, Project.NameKey.class, new TypeLiteral<List<CachedChange>>() {})
             .maximumWeight(0)
diff --git a/java/com/google/gerrit/server/git/WorkQueue.java b/java/com/google/gerrit/server/git/WorkQueue.java
index a7336f0..e2b7697 100644
--- a/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/java/com/google/gerrit/server/git/WorkQueue.java
@@ -407,7 +407,7 @@
           new Supplier<Long>() {
             @Override
             public Long get() {
-              return (long) getTaskCount();
+              return getTaskCount();
             }
           });
       metrics.newCallbackMetric(
@@ -419,7 +419,7 @@
           new Supplier<Long>() {
             @Override
             public Long get() {
-              return (long) getCompletedTaskCount();
+              return getCompletedTaskCount();
             }
           });
     }
@@ -674,7 +674,7 @@
                 for (Field innerField : innerObj.getClass().getDeclaredFields()) {
                   if (innerField.getType().isAssignableFrom(Callable.class)) {
                     innerField.setAccessible(true);
-                    return ((Callable<?>) innerField.get(innerObj)).toString();
+                    return innerField.get(innerObj).toString();
                   }
                 }
               }
diff --git a/java/com/google/gerrit/server/git/receive/ReplaceOp.java b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
index 42720a0..0f68ba5 100644
--- a/java/com/google/gerrit/server/git/receive/ReplaceOp.java
+++ b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
@@ -252,7 +252,7 @@
     }
     if (groups.isEmpty()) {
       PatchSet prevPs = psUtil.current(notes);
-      groups = prevPs != null ? prevPs.getGroups() : ImmutableList.<String>of();
+      groups = prevPs != null ? prevPs.getGroups() : ImmutableList.of();
     }
 
     ChangeData cd = changeDataFactory.create(ctx.getNotes());
diff --git a/java/com/google/gerrit/server/index/IndexModule.java b/java/com/google/gerrit/server/index/IndexModule.java
index c599d90..3d5c1a7 100644
--- a/java/com/google/gerrit/server/index/IndexModule.java
+++ b/java/com/google/gerrit/server/index/IndexModule.java
@@ -76,7 +76,7 @@
   }
 
   public static final ImmutableCollection<SchemaDefinitions<?>> ALL_SCHEMA_DEFS =
-      ImmutableList.<SchemaDefinitions<?>>of(
+      ImmutableList.of(
           AccountSchemaDefinitions.INSTANCE,
           ChangeSchemaDefinitions.INSTANCE,
           GroupSchemaDefinitions.INSTANCE,
@@ -160,7 +160,7 @@
     }
 
     Collection<IndexDefinition<?, ?, ?>> result =
-        ImmutableList.<IndexDefinition<?, ?, ?>>of(accounts, groups, changes, projects);
+        ImmutableList.of(accounts, groups, changes, projects);
     Set<String> expected =
         FluentIterable.from(ALL_SCHEMA_DEFS).transform(SchemaDefinitions::getName).toSet();
     Set<String> actual = FluentIterable.from(result).transform(IndexDefinition::getName).toSet();
diff --git a/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java b/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java
index e1b0edd..f1b8591 100644
--- a/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java
+++ b/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java
@@ -121,6 +121,6 @@
       return indexes.getWriteIndexes();
     }
 
-    return index != null ? Collections.singleton(index) : ImmutableSet.<AccountIndex>of();
+    return index != null ? Collections.singleton(index) : ImmutableSet.of();
   }
 }
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java
index 03da9a2..9e8f111 100644
--- a/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -297,7 +297,7 @@
         continue;
       }
 
-      Long l = Longs.tryParse(v.substring(i2 + 1, v.length()));
+      Long l = Longs.tryParse(v.substring(i2 + 1));
       if (l == null) {
         logger.atWarning().log(
             "Failed to parse timestamp of reviewer field from change %s: %s", changeId.get(), v);
@@ -350,7 +350,7 @@
         continue;
       }
 
-      Long l = Longs.tryParse(v.substring(i2 + 1, v.length()));
+      Long l = Longs.tryParse(v.substring(i2 + 1));
       if (l == null) {
         logger.atWarning().log(
             "Failed to parse timestamp of reviewer by email field from change %s: %s",
diff --git a/java/com/google/gerrit/server/index/change/IndexedChangeQuery.java b/java/com/google/gerrit/server/index/change/IndexedChangeQuery.java
index 38ea730..8088837 100644
--- a/java/com/google/gerrit/server/index/change/IndexedChangeQuery.java
+++ b/java/com/google/gerrit/server/index/change/IndexedChangeQuery.java
@@ -52,7 +52,7 @@
 public class IndexedChangeQuery extends IndexedQuery<Change.Id, ChangeData>
     implements ChangeDataSource, Matchable<ChangeData> {
   public static QueryOptions oneResult() {
-    return createOptions(IndexConfig.createDefault(), 0, 1, ImmutableSet.<String>of());
+    return createOptions(IndexConfig.createDefault(), 0, 1, ImmutableSet.of());
   }
 
   public static QueryOptions createOptions(
diff --git a/java/com/google/gerrit/server/mail/MailUtil.java b/java/com/google/gerrit/server/mail/MailUtil.java
index 507b53f..185e7f0 100644
--- a/java/com/google/gerrit/server/mail/MailUtil.java
+++ b/java/com/google/gerrit/server/mail/MailUtil.java
@@ -124,7 +124,7 @@
       return Pattern.compile(".*");
     }
 
-    StringBuilder sb = new StringBuilder("");
+    StringBuilder sb = new StringBuilder();
     for (String domain : domains) {
       String quoted = "\\Q" + domain.replace("\\E", "\\E\\\\E\\Q") + "\\E|";
       sb.append(quoted.replace("*", "\\E.*\\Q"));
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index ddfaa4e..f807dd6 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -459,7 +459,7 @@
       throws ConfigInvalidException {
     String line = parseOneFooter(commit, footerKey);
     if (line == null) {
-      throw expectedOneFooter(footerKey, Collections.<String>emptyList());
+      throw expectedOneFooter(footerKey, Collections.emptyList());
     }
     return line;
   }
diff --git a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
index 8720c36..507b45c 100644
--- a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
+++ b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
@@ -15,7 +15,6 @@
 package com.google.gerrit.server.notedb;
 
 import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.gerrit.server.notedb.RevisionNote.MAX_NOTE_SZ;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 
 import com.google.common.collect.ImmutableList;
@@ -40,6 +39,7 @@
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectLoader;
 import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
@@ -222,7 +222,11 @@
       NoteMap noteMap = NoteMap.read(reader, c);
       for (Note note : noteMap) {
         // Match pre-parsing logic in RevisionNote#parse().
-        byte[] raw = reader.open(note.getData(), OBJ_BLOB).getCachedBytes(MAX_NOTE_SZ);
+        ObjectLoader objectLoader = reader.open(note.getData(), OBJ_BLOB);
+        if (objectLoader.isLarge()) {
+          throw new IOException(String.format("Comment note %s is too large", note.name()));
+        }
+        byte[] raw = objectLoader.getCachedBytes();
         MutableInteger p = new MutableInteger();
         RevisionNote.trimLeadingEmptyLines(raw, p);
         if (!ChangeRevisionNote.isJson(raw, p.value)) {
diff --git a/java/com/google/gerrit/server/notedb/NoteDbModule.java b/java/com/google/gerrit/server/notedb/NoteDbModule.java
index cf12d84..d8a5fd5 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbModule.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbModule.java
@@ -50,7 +50,7 @@
     } else {
       bind(new TypeLiteral<Cache<ChangeNotesCache.Key, ChangeNotesState>>() {})
           .annotatedWith(Names.named(ChangeNotesCache.CACHE_NAME))
-          .toInstance(CacheBuilder.newBuilder().<ChangeNotesCache.Key, ChangeNotesState>build());
+          .toInstance(CacheBuilder.newBuilder().build());
     }
   }
 }
diff --git a/java/com/google/gerrit/server/notedb/NoteDbUtil.java b/java/com/google/gerrit/server/notedb/NoteDbUtil.java
index 21fada8..667ceab 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbUtil.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbUtil.java
@@ -33,7 +33,7 @@
     String email = ident.getEmailAddress();
     int at = email.indexOf('@');
     if (at >= 0) {
-      String host = email.substring(at + 1, email.length());
+      String host = email.substring(at + 1);
       if (host.equals(serverId)) {
         Integer id = Ints.tryParse(email.substring(0, at));
         if (id != null) {
diff --git a/java/com/google/gerrit/server/notedb/RevisionNoteMap.java b/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
index 17a061a..da790e2 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
@@ -64,7 +64,7 @@
   }
 
   static <T extends RevisionNote<? extends Comment>> RevisionNoteMap<T> emptyMap() {
-    return new RevisionNoteMap<>(NoteMap.newEmptyMap(), ImmutableMap.<RevId, T>of());
+    return new RevisionNoteMap<>(NoteMap.newEmptyMap(), ImmutableMap.of());
   }
 
   private RevisionNoteMap(NoteMap noteMap, ImmutableMap<RevId, T> revisionNotes) {
diff --git a/java/com/google/gerrit/server/plugins/JarScanner.java b/java/com/google/gerrit/server/plugins/JarScanner.java
index 486e264..7fde766 100644
--- a/java/com/google/gerrit/server/plugins/JarScanner.java
+++ b/java/com/google/gerrit/server/plugins/JarScanner.java
@@ -114,7 +114,7 @@
     for (Class<? extends Annotation> annotoation : annotations) {
       String descr = classObjToClassDescr.get(annotoation);
       Collection<ClassData> discoverdData = rawMap.get(descr);
-      Collection<ClassData> values = firstNonNull(discoverdData, Collections.<ClassData>emptySet());
+      Collection<ClassData> values = firstNonNull(discoverdData, Collections.emptySet());
 
       result.put(
           annotoation,
@@ -144,7 +144,7 @@
         continue;
       }
 
-      ClassData def = new ClassData(Collections.<String>emptySet());
+      ClassData def = new ClassData(Collections.emptySet());
       try {
         new ClassReader(read(jarFile, entry)).accept(def, SKIP_ALL);
       } catch (RuntimeException err) {
diff --git a/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java b/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java
index 87845d4..b698181 100644
--- a/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java
+++ b/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java
@@ -95,7 +95,7 @@
     if (user.isIdentifiedUser()) {
       return user.asIdentifiedUser().state().getProjectWatches().keySet();
     }
-    return Collections.<ProjectWatchKey>emptySet();
+    return Collections.emptySet();
   }
 
   protected static List<Predicate<ChangeData>> none() {
diff --git a/java/com/google/gerrit/server/restapi/account/AddSshKey.java b/java/com/google/gerrit/server/restapi/account/AddSshKey.java
index 4bdf52c..e47540d 100644
--- a/java/com/google/gerrit/server/restapi/account/AddSshKey.java
+++ b/java/com/google/gerrit/server/restapi/account/AddSshKey.java
@@ -109,7 +109,7 @@
       }
 
       user.getUserName().ifPresent(sshKeyCache::evict);
-      return Response.<SshKeyInfo>created(GetSshKeys.newSshKeyInfo(sshKey));
+      return Response.created(GetSshKeys.newSshKeyInfo(sshKey));
     } catch (InvalidSshKeyException e) {
       throw new BadRequestException(e.getMessage());
     }
diff --git a/java/com/google/gerrit/server/restapi/account/PutHttpPassword.java b/java/com/google/gerrit/server/restapi/account/PutHttpPassword.java
index 4bbd8fc..a465002 100644
--- a/java/com/google/gerrit/server/restapi/account/PutHttpPassword.java
+++ b/java/com/google/gerrit/server/restapi/account/PutHttpPassword.java
@@ -117,7 +117,7 @@
                     ExternalId.createWithPassword(
                         extId.key(), extId.accountId(), extId.email(), newPassword)));
 
-    return Strings.isNullOrEmpty(newPassword) ? Response.<String>none() : Response.ok(newPassword);
+    return Strings.isNullOrEmpty(newPassword) ? Response.none() : Response.ok(newPassword);
   }
 
   @UsedAt(UsedAt.Project.PLUGIN_SERVICEUSER)
diff --git a/java/com/google/gerrit/server/restapi/change/GetMergeList.java b/java/com/google/gerrit/server/restapi/change/GetMergeList.java
index 8e7e693..0c18a8f 100644
--- a/java/com/google/gerrit/server/restapi/change/GetMergeList.java
+++ b/java/com/google/gerrit/server/restapi/change/GetMergeList.java
@@ -76,7 +76,7 @@
       }
 
       if (commit.getParentCount() < 2) {
-        return createResponse(rsrc, ImmutableList.<CommitInfo>of());
+        return createResponse(rsrc, ImmutableList.of());
       }
 
       List<RevCommit> commits = MergeListBuilder.build(rw, commit, uninterestingParent);
diff --git a/java/com/google/gerrit/server/restapi/change/PostHashtags.java b/java/com/google/gerrit/server/restapi/change/PostHashtags.java
index a7a88ae..da499a9 100644
--- a/java/com/google/gerrit/server/restapi/change/PostHashtags.java
+++ b/java/com/google/gerrit/server/restapi/change/PostHashtags.java
@@ -55,7 +55,7 @@
       SetHashtagsOp op = hashtagsFactory.create(input);
       bu.addOp(req.getId(), op);
       bu.execute();
-      return Response.<ImmutableSortedSet<String>>ok(op.getUpdatedHashtags());
+      return Response.ok(op.getUpdatedHashtags());
     }
   }
 
diff --git a/java/com/google/gerrit/server/restapi/group/CreateGroup.java b/java/com/google/gerrit/server/restapi/group/CreateGroup.java
index 0572114..2fb668f 100644
--- a/java/com/google/gerrit/server/restapi/group/CreateGroup.java
+++ b/java/com/google/gerrit/server/restapi/group/CreateGroup.java
@@ -156,7 +156,7 @@
       args.initialMembers =
           ownerUuid == null
               ? Collections.singleton(self.get().getAccountId())
-              : Collections.<Account.Id>emptySet();
+              : Collections.emptySet();
     }
 
     try {
diff --git a/java/com/google/gerrit/server/restapi/group/PutDescription.java b/java/com/google/gerrit/server/restapi/group/PutDescription.java
index d407f69..dbc124b 100644
--- a/java/com/google/gerrit/server/restapi/group/PutDescription.java
+++ b/java/com/google/gerrit/server/restapi/group/PutDescription.java
@@ -72,7 +72,7 @@
     }
 
     return Strings.isNullOrEmpty(input.description)
-        ? Response.<String>none()
+        ? Response.none()
         : Response.ok(input.description);
   }
 }
diff --git a/java/com/google/gerrit/server/restapi/project/PutDescription.java b/java/com/google/gerrit/server/restapi/project/PutDescription.java
index 081669a..cd0bd5c 100644
--- a/java/com/google/gerrit/server/restapi/project/PutDescription.java
+++ b/java/com/google/gerrit/server/restapi/project/PutDescription.java
@@ -88,7 +88,7 @@
       md.getRepository().setGitwebDescription(project.getDescription());
 
       return Strings.isNullOrEmpty(project.getDescription())
-          ? Response.<String>none()
+          ? Response.none()
           : Response.ok(project.getDescription());
     } catch (RepositoryNotFoundException notFound) {
       throw new ResourceNotFoundException(resource.getName());
diff --git a/java/com/google/gerrit/server/schema/AllProjectsCreator.java b/java/com/google/gerrit/server/schema/AllProjectsCreator.java
index da07797..0f1caa8 100644
--- a/java/com/google/gerrit/server/schema/AllProjectsCreator.java
+++ b/java/com/google/gerrit/server/schema/AllProjectsCreator.java
@@ -47,7 +47,6 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.notedb.NoteDbSchemaVersionManager;
 import com.google.gerrit.server.notedb.RepoSequence;
 import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gwtorm.server.OrmException;
diff --git a/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java b/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
index 2c40170..b31710e 100644
--- a/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
@@ -25,7 +25,6 @@
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.NoteDbSchemaVersionManager;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import java.io.IOException;
diff --git a/java/com/google/gerrit/server/schema/NoteDbSchemaVersionCheck.java b/java/com/google/gerrit/server/schema/NoteDbSchemaVersionCheck.java
index be9aacd..63bffec 100644
--- a/java/com/google/gerrit/server/schema/NoteDbSchemaVersionCheck.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaVersionCheck.java
@@ -17,7 +17,6 @@
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.lifecycle.LifecycleModule;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.notedb.NoteDbSchemaVersionManager;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Module;
diff --git a/java/com/google/gerrit/server/notedb/NoteDbSchemaVersionManager.java b/java/com/google/gerrit/server/schema/NoteDbSchemaVersionManager.java
similarity index 86%
rename from java/com/google/gerrit/server/notedb/NoteDbSchemaVersionManager.java
rename to java/com/google/gerrit/server/schema/NoteDbSchemaVersionManager.java
index a8355c3..5be98d2 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbSchemaVersionManager.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaVersionManager.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.server.notedb;
+package com.google.gerrit.server.schema;
 
 import static com.google.gerrit.reviewdb.client.RefNames.REFS_VERSION;
 
@@ -20,6 +20,7 @@
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.notedb.IntBlob;
 import com.google.gwtorm.server.OrmException;
 import java.io.IOException;
 import java.util.Optional;
@@ -67,13 +68,7 @@
           allProjectsName,
           REFS_VERSION,
           old.map(IntBlob::id).orElse(ObjectId.zeroId()),
-          // TODO(dborowitz): Find some way to not hard-code this constant here. We can't depend on
-          // NoteDbSchemaVersions from this package, because the schema java_library depends on the
-          // server java_library, so that would add a circular dependency. But *this* class must
-          // live in the server library, because it's used by things like NoteDbMigrator. One
-          // option: once NoteDbMigrator goes away, this class could move back to the schema
-          // subpackage.
-          180,
+          NoteDbSchemaVersions.LATEST,
           GitReferenceUpdated.DISABLED);
     }
   }
diff --git a/java/com/google/gerrit/server/submit/ChangeSet.java b/java/com/google/gerrit/server/submit/ChangeSet.java
index 8c94a21..422e1b9 100644
--- a/java/com/google/gerrit/server/submit/ChangeSet.java
+++ b/java/com/google/gerrit/server/submit/ChangeSet.java
@@ -61,14 +61,12 @@
   }
 
   public ChangeSet(Iterable<ChangeData> changes, Iterable<ChangeData> hiddenChanges) {
-    changeData = index(changes, ImmutableList.<Change.Id>of());
+    changeData = index(changes, ImmutableList.of());
     nonVisibleChanges = index(hiddenChanges, changeData.keySet());
   }
 
   public ChangeSet(ChangeData change, boolean visible) {
-    this(
-        visible ? ImmutableList.of(change) : ImmutableList.<ChangeData>of(),
-        ImmutableList.of(change));
+    this(visible ? ImmutableList.of(change) : ImmutableList.of(), ImmutableList.of(change));
   }
 
   public ImmutableSet<Change.Id> ids() {
diff --git a/java/com/google/gerrit/server/submit/CherryPick.java b/java/com/google/gerrit/server/submit/CherryPick.java
index 844b3d4..afc9e7d 100644
--- a/java/com/google/gerrit/server/submit/CherryPick.java
+++ b/java/com/google/gerrit/server/submit/CherryPick.java
@@ -164,7 +164,7 @@
               ctx.getUpdate(psId),
               psId,
               newCommit,
-              prevPs != null ? prevPs.getGroups() : ImmutableList.<String>of(),
+              prevPs != null ? prevPs.getGroups() : ImmutableList.of(),
               null,
               null);
       ctx.getChange().setCurrentPatchSet(patchSetInfo);
diff --git a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
index 026a717..f24ee9c 100644
--- a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
@@ -233,7 +233,7 @@
                 ctx.getUpdate(newPatchSetId),
                 newPatchSetId,
                 newCommit,
-                prevPs != null ? prevPs.getGroups() : ImmutableList.<String>of(),
+                prevPs != null ? prevPs.getGroups() : ImmutableList.of(),
                 null,
                 null);
       }
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategyListener.java b/java/com/google/gerrit/server/submit/SubmitStrategyListener.java
index d1f847b..782cd7b 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategyListener.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategyListener.java
@@ -99,7 +99,7 @@
           args.rw,
           args.canMergeFlag,
           args.mergeTip.getCurrentTip(),
-          initialTip == null ? ImmutableSet.<RevCommit>of() : ImmutableSet.of(initialTip));
+          initialTip == null ? ImmutableSet.of() : ImmutableSet.of(initialTip));
     }
   }
 
diff --git a/java/com/google/gerrit/sshd/SshDaemon.java b/java/com/google/gerrit/sshd/SshDaemon.java
index ef356f1..639a7ba 100644
--- a/java/com/google/gerrit/sshd/SshDaemon.java
+++ b/java/com/google/gerrit/sshd/SshDaemon.java
@@ -66,7 +66,6 @@
 import org.apache.mina.transport.socket.SocketSessionConfig;
 import org.apache.sshd.common.BaseBuilder;
 import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.channel.RequestHandler;
 import org.apache.sshd.common.cipher.Cipher;
 import org.apache.sshd.common.compression.BuiltinCompressions;
 import org.apache.sshd.common.compression.Compression;
@@ -87,7 +86,6 @@
 import org.apache.sshd.common.mac.Mac;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.random.SingletonRandomFactory;
-import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
@@ -100,7 +98,6 @@
 import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
 import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
 import org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory;
-import org.apache.sshd.server.command.Command;
 import org.apache.sshd.server.command.CommandFactory;
 import org.apache.sshd.server.forward.ForwardingFilter;
 import org.apache.sshd.server.global.CancelTcpipForwardHandler;
@@ -293,7 +290,7 @@
           }
         });
     setGlobalRequestHandlers(
-        Arrays.<RequestHandler<ConnectionService>>asList(
+        Arrays.asList(
             new KeepAliveHandler(),
             new NoMoreSessionsHandler(),
             new TcpipForwardHandler(),
@@ -654,7 +651,7 @@
   }
 
   private void initSubsystems() {
-    setSubsystemFactories(Collections.<NamedFactory<Command>>emptyList());
+    setSubsystemFactories(Collections.emptyList());
   }
 
   private void initUserAuth(
diff --git a/java/com/google/gerrit/sshd/commands/UploadArchive.java b/java/com/google/gerrit/sshd/commands/UploadArchive.java
index ac914a5..24f82a7 100644
--- a/java/com/google/gerrit/sshd/commands/UploadArchive.java
+++ b/java/com/google/gerrit/sshd/commands/UploadArchive.java
@@ -238,7 +238,7 @@
                   options.level9)
               .indexOf(true);
       if (value >= 0) {
-        return ImmutableMap.<String, Object>of("level", Integer.valueOf(value));
+        return ImmutableMap.of("level", Integer.valueOf(value));
       }
     }
     return Collections.emptyMap();
diff --git a/java/com/google/gerrit/testing/TestChanges.java b/java/com/google/gerrit/testing/TestChanges.java
index a14ca2d..fd097d3 100644
--- a/java/com/google/gerrit/testing/TestChanges.java
+++ b/java/com/google/gerrit/testing/TestChanges.java
@@ -95,7 +95,7 @@
                     .load(),
                 user,
                 TimeUtil.nowTs(),
-                Ordering.<String>natural());
+                Ordering.natural());
 
     ChangeNotes notes = update.getNotes();
     boolean hasPatchSets = notes.getPatchSets() != null && !notes.getPatchSets().isEmpty();
diff --git a/java/gerrit/PRED_commit_edits_2.java b/java/gerrit/PRED_commit_edits_2.java
index f46a6487..6ca5338 100644
--- a/java/gerrit/PRED_commit_edits_2.java
+++ b/java/gerrit/PRED_commit_edits_2.java
@@ -97,11 +97,7 @@
 
         if (fileRegex.matcher(newName).find()
             || (oldName != null && fileRegex.matcher(oldName).find())) {
-          // This cast still seems to be needed on JDK 8 as workaround for:
-          // https://bugs.openjdk.java.net/browse/JDK-8039214
-          @SuppressWarnings("cast")
-          List<Edit> edits = (List<Edit>) entry.getEdits();
-
+          List<Edit> edits = entry.getEdits();
           if (edits.isEmpty()) {
             continue;
           }
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 58a8a03..b0380b8 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -1931,7 +1931,7 @@
       addExternalIdEmail(admin, PushCertificateIdent.parse(key.getFirstUserId()).getEmailAddress());
       toAdd.add(key.getPublicKeyArmored());
     }
-    gApi.accounts().self().putGpgKeys(toAdd, ImmutableList.<String>of());
+    gApi.accounts().self().putGpgKeys(toAdd, ImmutableList.of());
     assertKeys(keys);
     accountIndexedCounter.assertReindexOf(admin);
   }
@@ -2869,13 +2869,13 @@
 
   private Map<String, GpgKeyInfo> addGpgKey(String armored) throws Exception {
     Map<String, GpgKeyInfo> gpgKeys =
-        gApi.accounts().self().putGpgKeys(ImmutableList.of(armored), ImmutableList.<String>of());
+        gApi.accounts().self().putGpgKeys(ImmutableList.of(armored), ImmutableList.of());
     accountIndexedCounter.assertReindexOf(gApi.accounts().self().get());
     return gpgKeys;
   }
 
   private Map<String, GpgKeyInfo> addGpgKeyNoReindex(String armored) throws Exception {
-    return gApi.accounts().self().putGpgKeys(ImmutableList.of(armored), ImmutableList.<String>of());
+    return gApi.accounts().self().putGpgKeys(ImmutableList.of(armored), ImmutableList.of());
   }
 
   private void assertUser(AccountInfo info, TestAccount account) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CommitIncludedInIT.java b/javatests/com/google/gerrit/acceptance/api/project/CommitIncludedInIT.java
similarity index 88%
rename from javatests/com/google/gerrit/acceptance/rest/project/CommitIncludedInIT.java
rename to javatests/com/google/gerrit/acceptance/api/project/CommitIncludedInIT.java
index c0a413b..4b5fe1e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/CommitIncludedInIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/CommitIncludedInIT.java
@@ -12,14 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.rest.project;
+package com.google.gerrit.acceptance.api.project;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.eclipse.jgit.lib.Constants.R_TAGS;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit.Result;
-import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.changes.IncludedInInfo;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -28,6 +28,7 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
+@NoHttpd
 public class CommitIncludedInIT extends AbstractDaemonTest {
   @Test
   public void includedInOpenChange() throws Exception {
@@ -60,10 +61,6 @@
   }
 
   private IncludedInInfo getIncludedIn(ObjectId id) throws Exception {
-    RestResponse r =
-        userRestSession.get("/projects/" + project.get() + "/commits/" + id.name() + "/in");
-    IncludedInInfo result = newGson().fromJson(r.getReader(), IncludedInInfo.class);
-    r.consume();
-    return result;
+    return gApi.projects().name(project.get()).commit(id.name()).includedIn();
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java b/javatests/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java
index 90f4134..26ace25 100644
--- a/javatests/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java
@@ -16,8 +16,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.gerrit.acceptance.Sandboxed;
 import com.google.gerrit.server.AuditEvent;
 import com.google.gerrit.server.audit.HttpAuditEvent;
+import com.google.gerrit.testing.FakeGroupAuditService;
 import java.util.Collections;
 import javax.servlet.http.HttpServletResponse;
 import org.eclipse.jgit.transport.CredentialsProvider;
@@ -34,18 +36,19 @@
     CredentialsProvider.setDefault(
         new UsernamePasswordCredentialsProvider(admin.username, admin.httpPassword));
     selectProtocol(AbstractPushForReview.Protocol.HTTP);
-    auditService.clearEvents();
   }
 
   @Test
+  @Sandboxed
   public void receivePackAuditEventLog() throws Exception {
+    FakeGroupAuditService auditService = clearAuditService();
     testRepo
         .git()
         .push()
         .setRemote("origin")
         .setRefSpecs(new RefSpec("HEAD:refs/for/master"))
         .call();
-    waitForAudit();
+    waitForAudit(auditService);
 
     // Git smart protocol makes two requests:
     // https://github.com/git/git/blob/master/Documentation/technical/http-protocol.txt
@@ -59,9 +62,11 @@
   }
 
   @Test
+  @Sandboxed
   public void uploadPackAuditEventLog() throws Exception {
+    FakeGroupAuditService auditService = clearAuditService();
     testRepo.git().fetch().call();
-    waitForAudit();
+    waitForAudit(auditService);
 
     assertThat(auditService.auditEvents.size()).isEqualTo(1);
 
@@ -73,7 +78,14 @@
     assertThat(((HttpAuditEvent) e).httpStatus).isEqualTo(HttpServletResponse.SC_OK);
   }
 
-  private void waitForAudit() throws InterruptedException {
+  private FakeGroupAuditService clearAuditService() {
+    FakeGroupAuditService auditService =
+        server.getTestInjector().getInstance(FakeGroupAuditService.class);
+    auditService.clearEvents();
+    return auditService;
+  }
+
+  private void waitForAudit(FakeGroupAuditService auditService) throws InterruptedException {
     synchronized (auditService.auditEvents) {
       auditService.auditEvents.wait(AUDIT_EVENT_TIMEOUT);
     }
diff --git a/javatests/com/google/gerrit/acceptance/git/GitmodulesIT.java b/javatests/com/google/gerrit/acceptance/git/GitmodulesIT.java
index a13c8c8..ac0cbd8 100644
--- a/javatests/com/google/gerrit/acceptance/git/GitmodulesIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/GitmodulesIT.java
@@ -47,7 +47,7 @@
         .commit()
         .insertChangeId()
         .message("subject: adding new subscription")
-        .add(".gitmodules", config.toText().toString())
+        .add(".gitmodules", config.toText())
         .create();
 
     exception.expectMessage(expectedErrorMessage);
diff --git a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index 01169aa3..1a0f256 100644
--- a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -20,6 +20,7 @@
 import static com.google.gerrit.acceptance.GitUtil.fetch;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
@@ -53,10 +54,12 @@
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.testing.ConfigSuite;
 import com.google.inject.Inject;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.junit.TestRepository;
@@ -79,14 +82,21 @@
   private AccountGroup.UUID admins;
   private AccountGroup.UUID nonInteractiveUsers;
 
-  private ChangeData c1;
-  private ChangeData c2;
-  private ChangeData c3;
-  private ChangeData c4;
-  private String r1;
-  private String r2;
-  private String r3;
-  private String r4;
+  private ChangeData cd1;
+  private String psRef1;
+  private String metaRef1;
+
+  private ChangeData cd2;
+  private String psRef2;
+  private String metaRef2;
+
+  private ChangeData cd3;
+  private String psRef3;
+  private String metaRef3;
+
+  private ChangeData cd4;
+  private String psRef4;
+  private String metaRef4;
 
   @ConfigSuite.Config
   public static Config enableFullRefEvaluation() {
@@ -103,9 +113,9 @@
     setUpChanges();
   }
 
+  // This method is idempotent, so it is safe to call it on every test setup.
   private void setUpPermissions() throws Exception {
-    // Remove read permissions for all users besides admin. This method is idempotent, so is safe
-    // to call on every test setup.
+    // Remove read permissions for all users besides admin.
     try (ProjectConfigUpdate u = updateProject(allProjects)) {
       for (AccessSection sec : u.getConfig().getAccessSections()) {
         sec.removePermission(Permission.READ);
@@ -114,8 +124,7 @@
       u.save();
     }
 
-    // Remove all read permissions on All-Users. This method is idempotent, so is safe to call on
-    // every test setup.
+    // Remove all read permissions on All-Users.
     try (ProjectConfigUpdate u = updateProject(allUsers)) {
       for (AccessSection sec : u.getConfig().getAccessSections()) {
         sec.removePermission(Permission.READ);
@@ -124,11 +133,6 @@
     }
   }
 
-  private static String changeRefPrefix(Change.Id id) {
-    String ps = new PatchSet.Id(id, 1).toRefName();
-    return ps.substring(0, ps.length() - 1);
-  }
-
   private void setUpChanges() throws Exception {
     gApi.projects().name(project.get()).branch("branch").create(new BranchInput());
 
@@ -138,23 +142,27 @@
     PushOneCommit.Result mr =
         pushFactory.create(admin.getIdent(), testRepo).to("refs/for/master%submit");
     mr.assertOkStatus();
-    c1 = mr.getChange();
-    r1 = changeRefPrefix(c1.getId());
+    cd1 = mr.getChange();
+    psRef1 = cd1.currentPatchSet().getId().toRefName();
+    metaRef1 = RefNames.changeMetaRef(cd1.getId());
     PushOneCommit.Result br =
         pushFactory.create(admin.getIdent(), testRepo).to("refs/for/branch%submit");
     br.assertOkStatus();
-    c2 = br.getChange();
-    r2 = changeRefPrefix(c2.getId());
+    cd2 = br.getChange();
+    psRef2 = cd2.currentPatchSet().getId().toRefName();
+    metaRef2 = RefNames.changeMetaRef(cd2.getId());
 
     // Second 2 changes are unmerged.
     mr = pushFactory.create(admin.getIdent(), testRepo).to("refs/for/master");
     mr.assertOkStatus();
-    c3 = mr.getChange();
-    r3 = changeRefPrefix(c3.getId());
+    cd3 = mr.getChange();
+    psRef3 = cd3.currentPatchSet().getId().toRefName();
+    metaRef3 = RefNames.changeMetaRef(cd3.getId());
     br = pushFactory.create(admin.getIdent(), testRepo).to("refs/for/branch");
     br.assertOkStatus();
-    c4 = br.getChange();
-    r4 = changeRefPrefix(c4.getId());
+    cd4 = br.getChange();
+    psRef4 = cd4.currentPatchSet().getId().toRefName();
+    metaRef4 = RefNames.changeMetaRef(cd4.getId());
 
     try (Repository repo = repoManager.openRepository(project)) {
       // master-tag -> master
@@ -183,14 +191,14 @@
     setApiUser(user);
     assertUploadPackRefs(
         "HEAD",
-        r1 + "1",
-        r1 + "meta",
-        r2 + "1",
-        r2 + "meta",
-        r3 + "1",
-        r3 + "meta",
-        r4 + "1",
-        r4 + "meta",
+        psRef1,
+        metaRef1,
+        psRef2,
+        metaRef2,
+        psRef3,
+        metaRef3,
+        psRef4,
+        metaRef4,
         "refs/heads/branch",
         "refs/heads/master",
         "refs/tags/branch-tag",
@@ -204,14 +212,14 @@
 
     assertUploadPackRefs(
         "HEAD",
-        r1 + "1",
-        r1 + "meta",
-        r2 + "1",
-        r2 + "meta",
-        r3 + "1",
-        r3 + "meta",
-        r4 + "1",
-        r4 + "meta",
+        psRef1,
+        metaRef1,
+        psRef2,
+        metaRef2,
+        psRef3,
+        metaRef3,
+        psRef4,
+        metaRef4,
         "refs/heads/branch",
         "refs/heads/master",
         RefNames.REFS_CONFIG,
@@ -226,13 +234,7 @@
 
     setApiUser(user);
     assertUploadPackRefs(
-        "HEAD",
-        r1 + "1",
-        r1 + "meta",
-        r3 + "1",
-        r3 + "meta",
-        "refs/heads/master",
-        "refs/tags/master-tag");
+        "HEAD", psRef1, metaRef1, psRef3, metaRef3, "refs/heads/master", "refs/tags/master-tag");
   }
 
   @Test
@@ -242,10 +244,10 @@
 
     setApiUser(user);
     assertUploadPackRefs(
-        r2 + "1",
-        r2 + "meta",
-        r4 + "1",
-        r4 + "meta",
+        psRef2,
+        metaRef2,
+        psRef4,
+        metaRef4,
         "refs/heads/branch",
         "refs/tags/branch-tag",
         // master branch is not visible but master-tag is reachable from branch
@@ -257,27 +259,24 @@
   public void uploadPackSubsetOfBranchesVisibleWithEdit() throws Exception {
     allow("refs/heads/master", Permission.READ, REGISTERED_USERS);
 
-    Change c = notesFactory.createChecked(project, c3.getId()).getChange();
-    String changeId = c.getKey().get();
-
     // Admin's edit is not visible.
     setApiUser(admin);
-    gApi.changes().id(changeId).edit().create();
+    gApi.changes().id(cd3.getId().get()).edit().create();
 
     // User's edit is visible.
     setApiUser(user);
-    gApi.changes().id(changeId).edit().create();
+    gApi.changes().id(cd3.getId().get()).edit().create();
 
     assertUploadPackRefs(
         "HEAD",
-        r1 + "1",
-        r1 + "meta",
-        r3 + "1",
-        r3 + "meta",
+        psRef1,
+        metaRef1,
+        psRef3,
+        metaRef3,
         "refs/heads/master",
         "refs/tags/master-tag",
         "refs/tags/branch-tag",
-        "refs/users/01/1000001/edit-" + c3.getId() + "/1");
+        "refs/users/01/1000001/edit-" + cd3.getId() + "/1");
   }
 
   @Test
@@ -285,33 +284,28 @@
     allow("refs/heads/master", Permission.READ, REGISTERED_USERS);
     allow("refs/*", Permission.VIEW_PRIVATE_CHANGES, REGISTERED_USERS);
 
-    Change change3 = notesFactory.createChecked(project, c3.getId()).getChange();
-    String changeId3 = change3.getKey().get();
-    Change change4 = notesFactory.createChecked(project, c4.getId()).getChange();
-    String changeId4 = change4.getKey().get();
-
     // Admin's edit on change3 is visible.
     setApiUser(admin);
-    gApi.changes().id(changeId3).edit().create();
+    gApi.changes().id(cd3.getId().get()).edit().create();
 
     // Admin's edit on change4 is not visible since user cannot see the change.
-    gApi.changes().id(changeId4).edit().create();
+    gApi.changes().id(cd4.getId().get()).edit().create();
 
     // User's edit is visible.
     setApiUser(user);
-    gApi.changes().id(changeId3).edit().create();
+    gApi.changes().id(cd3.getId().get()).edit().create();
 
     assertUploadPackRefs(
         "HEAD",
-        r1 + "1",
-        r1 + "meta",
-        r3 + "1",
-        r3 + "meta",
+        psRef1,
+        metaRef1,
+        psRef3,
+        metaRef3,
         "refs/heads/master",
         "refs/tags/master-tag",
         "refs/tags/branch-tag",
-        "refs/users/00/1000000/edit-" + c3.getId() + "/1",
-        "refs/users/01/1000001/edit-" + c3.getId() + "/1");
+        "refs/users/00/1000000/edit-" + cd3.getId() + "/1",
+        "refs/users/01/1000001/edit-" + cd3.getId() + "/1");
   }
 
   @Test
@@ -320,28 +314,27 @@
     deny("refs/heads/master", Permission.READ, REGISTERED_USERS);
     allow("refs/heads/branch", Permission.READ, REGISTERED_USERS);
 
-    String changeId = c3.change().getKey().get();
     setApiUser(admin);
-    gApi.changes().id(changeId).edit().create();
+    gApi.changes().id(cd3.getId().get()).edit().create();
     setApiUser(user);
 
     assertUploadPackRefs(
         // Change 1 is visible due to accessDatabase capability, even though
         // refs/heads/master is not.
-        r1 + "1",
-        r1 + "meta",
-        r2 + "1",
-        r2 + "meta",
-        r3 + "1",
-        r3 + "meta",
-        r4 + "1",
-        r4 + "meta",
+        psRef1,
+        metaRef1,
+        psRef2,
+        metaRef2,
+        psRef3,
+        metaRef3,
+        psRef4,
+        metaRef4,
         "refs/heads/branch",
         "refs/tags/branch-tag",
         // See comment in subsetOfBranchesVisibleNotIncludingHead.
         "refs/tags/master-tag",
         // All edits are visible due to accessDatabase capability.
-        "refs/users/00/1000000/edit-" + c3.getId() + "/1");
+        "refs/users/00/1000000/edit-" + cd3.getId() + "/1");
   }
 
   @Test
@@ -356,14 +349,14 @@
           // Can't use stored values from the index so DB must be enabled.
           false,
           "HEAD",
-          r1 + "1",
-          r1 + "meta",
-          r2 + "1",
-          r2 + "meta",
-          r3 + "1",
-          r3 + "meta",
-          r4 + "1",
-          r4 + "meta",
+          psRef1,
+          metaRef1,
+          psRef2,
+          metaRef2,
+          psRef3,
+          metaRef3,
+          psRef4,
+          metaRef4,
           "refs/heads/branch",
           "refs/heads/master",
           "refs/tags/branch-tag",
@@ -385,19 +378,19 @@
   public void uploadPackAllRefsAreVisibleOrphanedTag() throws Exception {
     allow("refs/*", Permission.READ, REGISTERED_USERS);
     // Delete the pending change on 'branch' and 'branch' itself so that the tag gets orphaned
-    gApi.changes().id(c4.getId().id).delete();
+    gApi.changes().id(cd4.getId().id).delete();
     gApi.projects().name(project.get()).branch("refs/heads/branch").delete();
 
     setApiUser(user);
     assertUploadPackRefs(
         "HEAD",
         "refs/meta/config",
-        r1 + "1",
-        r1 + "meta",
-        r2 + "1",
-        r2 + "meta",
-        r3 + "1",
-        r3 + "meta",
+        psRef1,
+        metaRef1,
+        psRef2,
+        metaRef2,
+        psRef3,
+        metaRef3,
         "refs/heads/master",
         "refs/tags/branch-tag",
         "refs/tags/master-tag");
@@ -408,14 +401,14 @@
     ReceiveCommitsAdvertiseRefsHook.Result r = getReceivePackRefs();
     assertThat(r.allRefs().keySet())
         .containsExactly(
-            // meta refs are excluded even when NoteDb is enabled.
+            // meta refs are excluded
             "HEAD",
             "refs/heads/branch",
             "refs/heads/master",
             "refs/meta/config",
             "refs/tags/branch-tag",
             "refs/tags/master-tag");
-    assertThat(r.additionalHaves()).containsExactly(obj(c3, 1), obj(c4, 1));
+    assertThat(r.additionalHaves()).containsExactly(obj(cd3, 1), obj(cd4, 1));
   }
 
   @Test
@@ -424,16 +417,16 @@
     deny("refs/heads/branch", Permission.READ, REGISTERED_USERS);
     setApiUser(user);
 
-    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(c3, 1));
+    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(cd3, 1));
   }
 
   @Test
   public void receivePackListsOnlyLatestPatchSet() throws Exception {
-    testRepo.reset(obj(c3, 1));
-    PushOneCommit.Result r = amendChange(c3.change().getKey().get());
+    testRepo.reset(obj(cd3, 1));
+    PushOneCommit.Result r = amendChange(cd3.change().getKey().get());
     r.assertOkStatus();
-    c3 = r.getChange();
-    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(c3, 2), obj(c4, 1));
+    cd3 = r.getChange();
+    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(cd3, 2), obj(cd4, 1));
   }
 
   @Test
@@ -442,14 +435,14 @@
     try (Repository repo = repoManager.openRepository(project)) {
       TestRepository<?> tr = new TestRepository<>(repo);
       String subject = "Subject for missing commit";
-      Change c = new Change(c3.change());
-      PatchSet.Id psId = new PatchSet.Id(c3.getId(), 2);
+      Change c = new Change(cd3.change());
+      PatchSet.Id psId = new PatchSet.Id(cd3.getId(), 2);
       c.setCurrentPatchSet(psId, subject, c.getOriginalSubject());
 
       PersonIdent committer = serverIdent.get();
       PersonIdent author =
           noteUtil.newIdent(getAccount(admin.getId()), committer.getWhen(), committer);
-      tr.branch(RefNames.changeMetaRef(c3.getId()))
+      tr.branch(RefNames.changeMetaRef(cd3.getId()))
           .commit()
           .author(author)
           .committer(committer)
@@ -471,7 +464,7 @@
       indexer.index(c.getProject(), c.getId());
     }
 
-    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(c4, 1));
+    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(cd4, 1));
   }
 
   @Test
@@ -504,7 +497,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void advertisedReferencesDontShowGroupBranchToOwnerWithoutRead() throws Exception {
     createSelfOwnedGroup("Foos", user);
     TestRepository<?> userTestRepository = cloneProject(allUsers, user);
@@ -514,7 +506,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void advertisedReferencesOmitGroupBranchesOfNonOwnedGroups() throws Exception {
     allow(allUsersName, RefNames.REFS_GROUPS + "*", Permission.READ, REGISTERED_USERS);
     AccountGroup.UUID users = createGroup("Users", admins, user);
@@ -528,7 +519,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void advertisedReferencesIncludeAllGroupBranchesWithAccessDatabase() throws Exception {
     allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
     AccountGroup.UUID users = createGroup("Users", admins);
@@ -543,7 +533,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void advertisedReferencesIncludeAllGroupBranchesForAdmins() throws Exception {
     allow(allUsersName, RefNames.REFS_GROUPS + "*", Permission.READ, REGISTERED_USERS);
     allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ADMINISTRATE_SERVER);
@@ -559,7 +548,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void advertisedReferencesOmitNoteDbNotesBranches() throws Exception {
     allow(allUsersName, RefNames.REFS + "*", Permission.READ, REGISTERED_USERS);
     TestRepository<?> userTestRepository = cloneProject(allUsers, user);
@@ -574,10 +562,10 @@
 
     TestRepository<?> userTestRepository = cloneProject(project, user);
     try (Git git = userTestRepository.git()) {
-      String change3RefName = c3.currentPatchSet().getRefName();
+      String change3RefName = cd3.currentPatchSet().getRefName();
       assertWithMessage("Precondition violated").that(getRefs(git)).contains(change3RefName);
 
-      gApi.changes().id(c3.getId().get()).setPrivate(true, null);
+      gApi.changes().id(cd3.getId().get()).setPrivate(true, null);
       assertThat(getRefs(git)).doesNotContain(change3RefName);
     }
   }
@@ -591,10 +579,10 @@
 
     TestRepository<?> userTestRepository = cloneProject(project, user);
     try (Git git = userTestRepository.git()) {
-      String change3RefName = c3.currentPatchSet().getRefName();
+      String change3RefName = cd3.currentPatchSet().getRefName();
       assertWithMessage("Precondition violated").that(getRefs(git)).contains(change3RefName);
 
-      gApi.changes().id(c3.getId().get()).setPrivate(true, null);
+      gApi.changes().id(cd3.getId().get()).setPrivate(true, null);
       assertThat(getRefs(git)).contains(change3RefName);
     }
   }
@@ -607,10 +595,10 @@
 
     TestRepository<?> userTestRepository = cloneProject(project, user);
     try (Git git = userTestRepository.git()) {
-      String change3RefName = c3.currentPatchSet().getRefName();
+      String change3RefName = cd3.currentPatchSet().getRefName();
       assertWithMessage("Precondition violated").that(getRefs(git)).contains(change3RefName);
 
-      gApi.changes().id(c3.getId().get()).setPrivate(true, null);
+      gApi.changes().id(cd3.getId().get()).setPrivate(true, null);
       assertThat(getRefs(git)).doesNotContain(change3RefName);
     }
   }
@@ -625,8 +613,8 @@
     draftInput.line = 1;
     draftInput.message = "nit: trailing whitespace";
     draftInput.path = Patch.COMMIT_MSG;
-    gApi.changes().id(c3.getId().get()).current().createDraft(draftInput);
-    String draftCommentRef = RefNames.refsDraftComments(c3.getId(), user.id);
+    gApi.changes().id(cd3.getId().get()).current().createDraft(draftInput);
+    String draftCommentRef = RefNames.refsDraftComments(cd3.getId(), user.id);
 
     // user can see the draft comment ref of the own draft comment
     assertThat(lsRemote(allUsersName, user)).contains(draftCommentRef);
@@ -641,8 +629,8 @@
     allow(allUsersName, "refs/*", Permission.READ, REGISTERED_USERS);
 
     setApiUser(user);
-    gApi.accounts().self().starChange(c3.getId().toString());
-    String starredChangesRef = RefNames.refsStarredChanges(c3.getId(), user.id);
+    gApi.accounts().self().starChange(cd3.getId().toString());
+    String starredChangesRef = RefNames.refsStarredChanges(cd3.getId(), user.id);
 
     // user can see the starred changes ref of the own star
     assertThat(lsRemote(allUsersName, user)).contains(starredChangesRef);
@@ -652,7 +640,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void hideMetadata() throws Exception {
     allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
     // create change
@@ -681,13 +668,13 @@
 
     List<String> expectedMetaRefs =
         new ArrayList<>(ImmutableList.of(mr.getPatchSetId().toRefName()));
-    expectedMetaRefs.add(changeRefPrefix(mr.getChange().getId()) + "meta");
+    expectedMetaRefs.add(RefNames.changeMetaRef(mr.getChange().getId()));
 
     List<String> expectedAllRefs = new ArrayList<>(expectedNonMetaRefs);
     expectedAllRefs.addAll(expectedMetaRefs);
 
     try (Repository repo = repoManager.openRepository(allUsers)) {
-      Map<String, Ref> all = repo.getAllRefs();
+      Map<String, Ref> all = getAllRefs(repo);
 
       PermissionBackend.ForProject forProject = newFilter(allUsers, admin);
       assertThat(forProject.filter(all, repo, RefFilterOptions.defaults()).keySet())
@@ -724,16 +711,14 @@
   }
 
   /**
-   * Assert that refs seen by a non-admin user match expected.
+   * Assert that refs seen by a non-admin user match the expected refs.
    *
-   * @param expectedWithMeta expected refs, in order. If NoteDb is disabled by the configuration,
-   *     any NoteDb refs (i.e. ending in "/meta") are removed from the expected list before
-   *     comparing to the actual results.
+   * @param expectedRefs expected refs.
    * @throws Exception
    */
-  private void assertUploadPackRefs(String... expectedWithMeta) throws Exception {
+  private void assertUploadPackRefs(String... expectedRefs) throws Exception {
     try (Repository repo = repoManager.openRepository(project)) {
-      assertRefs(repo, permissionBackend.user(user(user)).project(project), true, expectedWithMeta);
+      assertRefs(repo, permissionBackend.user(user(user)).project(project), true, expectedRefs);
     }
   }
 
@@ -741,21 +726,16 @@
       Repository repo,
       PermissionBackend.ForProject forProject,
       boolean disableDb,
-      String... expectedWithMeta)
+      String... expectedRefs)
       throws Exception {
-    List<String> expected = new ArrayList<>(expectedWithMeta.length);
-    for (String r : expectedWithMeta) {
-      expected.add(r);
-    }
-
     AcceptanceTestRequestScope.Context ctx = null;
     if (disableDb) {
       ctx = disableDb();
     }
     try {
-      Map<String, Ref> all = repo.getAllRefs();
+      Map<String, Ref> all = getAllRefs(repo);
       assertThat(forProject.filter(all, repo, RefFilterOptions.defaults()).keySet())
-          .containsExactlyElementsIn(expected);
+          .containsExactlyElementsIn(expectedRefs);
     } finally {
       if (disableDb) {
         enableDb(ctx);
@@ -767,7 +747,7 @@
     ReceiveCommitsAdvertiseRefsHook hook =
         new ReceiveCommitsAdvertiseRefsHook(queryProvider, project);
     try (Repository repo = repoManager.openRepository(project)) {
-      return hook.advertiseRefs(repo.getAllRefs());
+      return hook.advertiseRefs(getAllRefs(repo));
     }
   }
 
@@ -797,4 +777,11 @@
         Arrays.stream(members).map(m -> String.valueOf(m.id.get())).collect(toList());
     return new AccountGroup.UUID(gApi.groups().create(groupInput).get().id);
   }
+
+  private static Map<String, Ref> getAllRefs(Repository repo) throws IOException {
+    return repo.getRefDatabase()
+        .getRefs()
+        .stream()
+        .collect(toMap(Ref::getName, Function.identity()));
+  }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitResolvingMergeCommitIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitResolvingMergeCommitIT.java
index 2a19d5e..a3b891e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitResolvingMergeCommitIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitResolvingMergeCommitIT.java
@@ -366,8 +366,7 @@
 
   @Override
   protected PushOneCommit.Result createChange(String subject) throws Exception {
-    return createChange(
-        testRepo, subject, "", "", Collections.<RevCommit>emptyList(), "refs/for/master");
+    return createChange(testRepo, subject, "", "", Collections.emptyList(), "refs/for/master");
   }
 
   private PushOneCommit.Result createChange(String subject, List<RevCommit> parents)
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java b/javatests/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java
index df89686..0aaf016 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java
@@ -21,7 +21,6 @@
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.projects.BranchApi;
@@ -116,7 +115,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void createGroupBranch_Conflict() throws Exception {
     allow(allUsers, RefNames.REFS_GROUPS + "*", Permission.CREATE, REGISTERED_USERS);
     allow(allUsers, RefNames.REFS_GROUPS + "*", Permission.PUSH, REGISTERED_USERS);
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
index d673f83..31cf3fe 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
@@ -20,7 +20,6 @@
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.common.data.Permission;
@@ -141,7 +140,6 @@
   }
 
   @Test
-  @GerritConfig(name = "noteDb.groups.write", value = "true")
   public void deleteGroupBranch_Conflict() throws Exception {
     allow(allUsers, RefNames.REFS_GROUPS + "*", Permission.CREATE, REGISTERED_USERS);
     allow(allUsers, RefNames.REFS_GROUPS + "*", Permission.PUSH, REGISTERED_USERS);
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java
index 2ada724..5691e36 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java
@@ -154,6 +154,6 @@
   }
 
   private void assertTagsDeleted() throws Exception {
-    assertTags(ImmutableList.<String>of());
+    assertTags(ImmutableList.of());
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index 9ef4ff6..ac0a499 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -608,7 +608,7 @@
             @Override
             public boolean updateChange(ChangeContext ctx) throws OrmException {
               PatchSet ps = psUtil.get(ctx.getNotes(), psId);
-              psUtil.setGroups(ctx.getUpdate(psId), ps, ImmutableList.<String>of());
+              psUtil.setGroups(ctx.getUpdate(psId), ps, ImmutableList.of());
               return true;
             }
           });
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
index 49c66c0..f617488 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
@@ -45,7 +45,7 @@
       case V6_4:
         return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.3";
       case V6_5:
-        return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.5.3";
+        return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.5.4";
       case V7_0:
         return "docker.elastic.co/elasticsearch/elasticsearch-oss:7.0.0-alpha1";
     }
diff --git a/javatests/com/google/gerrit/index/query/FieldPredicateTest.java b/javatests/com/google/gerrit/index/query/FieldPredicateTest.java
index 8fe90fc..805f31c 100644
--- a/javatests/com/google/gerrit/index/query/FieldPredicateTest.java
+++ b/javatests/com/google/gerrit/index/query/FieldPredicateTest.java
@@ -58,7 +58,7 @@
   @Test
   public void testCopy() {
     final OperatorPredicate<String> f = f("author", "alice");
-    assertSame(f, f.copy(Collections.<Predicate<String>>emptyList()));
+    assertSame(f, f.copy(Collections.emptyList()));
     assertSame(f, f.copy(f.getChildren()));
 
     exception.expect(IllegalArgumentException.class);
diff --git a/javatests/com/google/gerrit/index/query/NotPredicateTest.java b/javatests/com/google/gerrit/index/query/NotPredicateTest.java
index 74eac61..d10d2df 100644
--- a/javatests/com/google/gerrit/index/query/NotPredicateTest.java
+++ b/javatests/com/google/gerrit/index/query/NotPredicateTest.java
@@ -113,7 +113,7 @@
     assertEquals(sb, n.copy(sb).getChildren());
 
     try {
-      n.copy(Collections.<Predicate>emptyList());
+      n.copy(Collections.emptyList());
       fail("Expected IllegalArgumentException");
     } catch (IllegalArgumentException e) {
       assertEquals("Expected exactly one child", e.getMessage());
diff --git a/javatests/com/google/gerrit/pgm/init/LibrariesTest.java b/javatests/com/google/gerrit/pgm/init/LibrariesTest.java
index 1f42373..3eb4dac7 100644
--- a/javatests/com/google/gerrit/pgm/init/LibrariesTest.java
+++ b/javatests/com/google/gerrit/pgm/init/LibrariesTest.java
@@ -44,7 +44,7 @@
                 return new LibraryDownloader(ui, site, remover);
               }
             },
-            Collections.<String>emptyList(),
+            Collections.emptyList(),
             false);
 
     assertNotNull(lib.mysqlDriver);
diff --git a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
index 036ca30..cf43511 100644
--- a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
+++ b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
@@ -208,6 +208,6 @@
   }
 
   private static List<PatchSetApproval> list(PatchSetApproval... psas) {
-    return ImmutableList.<PatchSetApproval>copyOf(psas);
+    return ImmutableList.copyOf(psas);
   }
 }
diff --git a/javatests/com/google/gerrit/server/index/change/ChangeIndexRewriterTest.java b/javatests/com/google/gerrit/server/index/change/ChangeIndexRewriterTest.java
index 53994a6..7117485 100644
--- a/javatests/com/google/gerrit/server/index/change/ChangeIndexRewriterTest.java
+++ b/javatests/com/google/gerrit/server/index/change/ChangeIndexRewriterTest.java
@@ -255,7 +255,7 @@
   }
 
   private static QueryOptions options(int start, int limit) {
-    return IndexedChangeQuery.createOptions(CONFIG, start, limit, ImmutableSet.<String>of());
+    return IndexedChangeQuery.createOptions(CONFIG, start, limit, ImmutableSet.of());
   }
 
   private Set<Change.Status> status(String query) throws QueryParseException {
diff --git a/javatests/com/google/gerrit/server/index/change/FakeChangeIndex.java b/javatests/com/google/gerrit/server/index/change/FakeChangeIndex.java
index faee233..efe6a5a 100644
--- a/javatests/com/google/gerrit/server/index/change/FakeChangeIndex.java
+++ b/javatests/com/google/gerrit/server/index/change/FakeChangeIndex.java
@@ -15,7 +15,6 @@
 package com.google.gerrit.server.index.change;
 
 import com.google.common.collect.ImmutableList;
-import com.google.gerrit.index.FieldDef;
 import com.google.gerrit.index.QueryOptions;
 import com.google.gerrit.index.Schema;
 import com.google.gerrit.index.query.FieldBundle;
@@ -30,8 +29,7 @@
 
 @Ignore
 public class FakeChangeIndex implements ChangeIndex {
-  static final Schema<ChangeData> V1 =
-      new Schema<>(1, ImmutableList.<FieldDef<ChangeData, ?>>of(ChangeField.STATUS));
+  static final Schema<ChangeData> V1 = new Schema<>(1, ImmutableList.of(ChangeField.STATUS));
 
   static final Schema<ChangeData> V2 =
       new Schema<>(2, ImmutableList.of(ChangeField.STATUS, ChangeField.PATH, ChangeField.UPDATED));
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index 5d5e3df..be523d8 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -138,7 +138,7 @@
                 bind(AllUsersName.class).toProvider(AllUsersNameProvider.class);
                 bind(String.class).annotatedWith(GerritServerId.class).toInstance("gerrit");
                 bind(GitRepositoryManager.class).toInstance(repoManager);
-                bind(ProjectCache.class).toProvider(Providers.<ProjectCache>of(null));
+                bind(ProjectCache.class).toProvider(Providers.of(null));
                 bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(testConfig);
                 bind(String.class)
                     .annotatedWith(AnonymousCowardName.class)
diff --git a/javatests/com/google/gerrit/server/permissions/RefControlTest.java b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
index bf0d70e..186553f 100644
--- a/javatests/com/google/gerrit/server/permissions/RefControlTest.java
+++ b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
@@ -973,8 +973,8 @@
   private ProjectControl user(
       ProjectConfig local, @Nullable String name, AccountGroup.UUID... memberOf) {
     return new ProjectControl(
-        Collections.<AccountGroup.UUID>emptySet(),
-        Collections.<AccountGroup.UUID>emptySet(),
+        Collections.emptySet(),
+        Collections.emptySet(),
         sectionSorter,
         changeControlFactory,
         permissionBackend,
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index bed94db..25374ab 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -1409,9 +1409,7 @@
     ReviewInput.CommentInput commentInput = new ReviewInput.CommentInput();
     commentInput.line = 1;
     commentInput.message = "inline";
-    input.comments =
-        ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
-            Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(commentInput));
+    input.comments = ImmutableMap.of(Patch.COMMIT_MSG, ImmutableList.of(commentInput));
     gApi.changes().id(change.getId().get()).current().review(input);
 
     Map<String, List<CommentInfo>> comments =
@@ -1600,7 +1598,7 @@
     Change change4 = insert(repo, ins4);
     ReviewInput ri4 = new ReviewInput();
     ri4.message = "toplevel";
-    ri4.labels = ImmutableMap.<String, Short>of("Code-Review", (short) 1);
+    ri4.labels = ImmutableMap.of("Code-Review", (short) 1);
     gApi.changes().id(change4.getId().get()).current().review(ri4);
 
     ChangeInserter ins5 = newChangeWithTopic(repo, "feature5");
@@ -1672,9 +1670,7 @@
     ReviewInput.CommentInput comment = new ReviewInput.CommentInput();
     comment.line = 1;
     comment.message = "inline";
-    input.comments =
-        ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
-            Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
+    input.comments = ImmutableMap.of(Patch.COMMIT_MSG, ImmutableList.of(comment));
     gApi.changes().id(change1.getId().get()).current().review(input);
 
     input = new ReviewInput();
@@ -1839,9 +1835,7 @@
     ReviewInput.CommentInput comment = new ReviewInput.CommentInput();
     comment.line = 1;
     comment.message = "inline";
-    input.comments =
-        ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
-            Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
+    input.comments = ImmutableMap.of(Patch.COMMIT_MSG, ImmutableList.of(comment));
     gApi.changes().id(change2.getId().get()).current().review(input);
 
     assertQuery("from:" + userId.get(), change2, change1);
@@ -3103,9 +3097,7 @@
     comment.line = 1;
     comment.message = message;
     comment.unresolved = unresolved;
-    input.comments =
-        ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
-            Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
+    input.comments = ImmutableMap.of(Patch.COMMIT_MSG, ImmutableList.of(comment));
     gApi.changes().id(changeId).current().review(input);
   }
 
diff --git a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
index fe8500a..0d45d43 100644
--- a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
+++ b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
@@ -29,7 +29,6 @@
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.notedb.IntBlob;
-import com.google.gerrit.server.notedb.NoteDbSchemaVersionManager;
 import com.google.gerrit.server.notedb.RepoSequence;
 import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
diff --git a/javatests/com/google/gerrit/server/notedb/NoteDbSchemaVersionManagerTest.java b/javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionManagerTest.java
similarity index 98%
rename from javatests/com/google/gerrit/server/notedb/NoteDbSchemaVersionManagerTest.java
rename to javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionManagerTest.java
index c8900309..5ea2a7a 100644
--- a/javatests/com/google/gerrit/server/notedb/NoteDbSchemaVersionManagerTest.java
+++ b/javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionManagerTest.java
@@ -1,4 +1,4 @@
-package com.google.gerrit.server.notedb;
+package com.google.gerrit.server.schema;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assert_;
diff --git a/plugins/BUILD b/plugins/BUILD
index 30a30dd..bddff41 100644
--- a/plugins/BUILD
+++ b/plugins/BUILD
@@ -33,6 +33,7 @@
     "//java/com/google/gerrit/extensions:api",
     "//java/com/google/gerrit/git",
     "//java/com/google/gerrit/index",
+    "//java/com/google/gerrit/index/project",
     "//java/com/google/gerrit/index:query_exception",
     "//java/com/google/gerrit/json",
     "//java/com/google/gerrit/lifecycle",
diff --git a/plugins/reviewnotes b/plugins/reviewnotes
index 5d607a4..a9456bf 160000
--- a/plugins/reviewnotes
+++ b/plugins/reviewnotes
@@ -1 +1 @@
-Subproject commit 5d607a4193fb41b4ad8fe01622f7e002fd4208c0
+Subproject commit a9456bfdb862dfa7197583decac3c22149ae8109
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
index 78fba83..e0c7c37 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
@@ -441,11 +441,11 @@
 
     test('installing preloaded plugin', () => {
       let plugin;
-      window.ASSETS_PATH = 'http://blips.com/chitz';
+      window.ASSETS_PATH = 'http://blips.com/chitz/';
       Gerrit.install(p => { plugin = p; }, '0.1', 'preloaded:foo');
       assert.strictEqual(plugin.getPluginName(), 'foo');
       assert.strictEqual(plugin.url('/some/thing.html'),
-          'http://blips.com/chitz/plugins/foo/some/thing.html');
+          'http://blips.com/plugins/foo/some/thing.html');
       delete window.ASSETS_PATH;
     });
 
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index 8bf4a2d..36a428d 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -217,14 +217,9 @@
   };
 
   Plugin.prototype.url = function(opt_path) {
-    const relPath = '/plugins/' + this._name + (opt_path || '/');
-    if (window.location.origin === this._url.origin) {
-      // Plugin loaded from the same origin as gr-app, getBaseUrl in effect.
-      return this._url.origin + Gerrit.BaseUrlBehavior.getBaseUrl() + relPath;
-    } else {
-      // Plugin loaded from assets bundle, expect assets placed along with it.
-      return this._url.href.split('/plugins/' + this._name)[0] + relPath;
-    }
+    const base = Gerrit.BaseUrlBehavior.getBaseUrl();
+    return this._url.origin + base + '/plugins/' +
+        this._name + (opt_path || '/');
   };
 
   Plugin.prototype.screenUrl = function(opt_screenName) {