Merge "Merge branch 'stable-2.15'"
diff --git a/Documentation/BUILD b/Documentation/BUILD
index 2e6f4bc..4177f51 100644
--- a/Documentation/BUILD
+++ b/Documentation/BUILD
@@ -71,13 +71,13 @@
     name = "index",
     srcs = SRCS,
     outs = ["index.jar"],
-    cmd = "$(location //lib/asciidoctor:doc_indexer) " +
+    cmd = "$(location //java/com/google/gerrit/asciidoctor:doc_indexer) " +
           "-o $(OUTS) " +
           "--prefix \"%s/\" " % DOC_DIR +
           "--in-ext \".txt\" " +
           "--out-ext \".html\" " +
           "$(SRCS)",
-    tools = ["//lib/asciidoctor:doc_indexer"],
+    tools = ["//java/com/google/gerrit/asciidoctor:doc_indexer"],
 )
 
 # For the same srcs, we can have multiple genasciidoc_zip rules, but only one
diff --git a/Documentation/config-labels.txt b/Documentation/config-labels.txt
index 91e20cd..cf78c6d 100644
--- a/Documentation/config-labels.txt
+++ b/Documentation/config-labels.txt
@@ -275,8 +275,8 @@
 sticky approvals, reducing turn-around for trivial cleanups prior to
 submitting a change. Defaults to false.
 
-[[label_copyAllScoresOnMergeCommitFirstParentUpdate]]
-=== `label.Label-Name.copyAllScoresOnMergeCommitFirstParentUpdate`
+[[label_copyAllScoresOnMergeFirstParentUpdate]]
+=== `label.Label-Name.copyAllScoresOnMergeFirstParentUpdate`
 
 This policy is useful if you don't want to trigger CI or human
 verification again if your target branch moved on but the feature
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 5699e3f..6e5424c 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.lucene.LuceneIndexModule;
 import com.google.gerrit.pgm.Daemon;
 import com.google.gerrit.pgm.Init;
+import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePath;
 import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
@@ -44,6 +45,7 @@
 import com.google.gerrit.testing.NoteDbMode;
 import com.google.gerrit.testing.SshMode;
 import com.google.gerrit.testing.TempFileUtil;
+import com.google.inject.AbstractModule;
 import com.google.inject.Injector;
 import com.google.inject.Key;
 import com.google.inject.Module;
@@ -352,7 +354,13 @@
     daemon.setDatabaseForTesting(
         ImmutableList.<Module>of(
             new InMemoryTestingDatabaseModule(
-                cfg, site, inMemoryRepoManager, inMemoryDatabaseInstance)));
+                cfg, site, inMemoryRepoManager, inMemoryDatabaseInstance),
+            new AbstractModule() {
+              @Override
+              protected void configure() {
+                bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
+              }
+            }));
     daemon.start();
     return new GerritServer(desc, null, createTestInjector(daemon), daemon, null);
   }
diff --git a/lib/asciidoctor/java/AsciiDoctor.java b/java/com/google/gerrit/asciidoctor/AsciiDoctor.java
similarity index 98%
rename from lib/asciidoctor/java/AsciiDoctor.java
rename to java/com/google/gerrit/asciidoctor/AsciiDoctor.java
index 596fe66..3768ce7 100644
--- a/lib/asciidoctor/java/AsciiDoctor.java
+++ b/java/com/google/gerrit/asciidoctor/AsciiDoctor.java
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package com.google.gerrit.asciidoctor;
+
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.common.io.ByteStreams;
diff --git a/java/com/google/gerrit/asciidoctor/BUILD b/java/com/google/gerrit/asciidoctor/BUILD
new file mode 100644
index 0000000..b2b0f5d
--- /dev/null
+++ b/java/com/google/gerrit/asciidoctor/BUILD
@@ -0,0 +1,40 @@
+java_binary(
+    name = "asciidoc",
+    main_class = "com.google.gerrit.asciidoctor.AsciiDoctor",
+    visibility = ["//visibility:public"],
+    runtime_deps = [":asciidoc_lib"],
+)
+
+java_library(
+    name = "asciidoc_lib",
+    srcs = ["AsciiDoctor.java"],
+    visibility = ["//tools/eclipse:__pkg__"],
+    deps = [
+        "//lib:args4j",
+        "//lib:guava",
+        "//lib/asciidoctor",
+        "//lib/log:api",
+        "//lib/log:nop",
+    ],
+)
+
+java_binary(
+    name = "doc_indexer",
+    main_class = "com.google.gerrit.asciidoctor.DocIndexer",
+    visibility = ["//visibility:public"],
+    runtime_deps = [":doc_indexer_lib"],
+)
+
+java_library(
+    name = "doc_indexer_lib",
+    srcs = ["DocIndexer.java"],
+    visibility = ["//tools/eclipse:__pkg__"],
+    deps = [
+        ":asciidoc_lib",
+        "//java/com/google/gerrit/server:constants",
+        "//lib:args4j",
+        "//lib:guava",
+        "//lib/lucene:lucene-analyzers-common",
+        "//lib/lucene:lucene-core-and-backward-codecs",
+    ],
+)
diff --git a/lib/asciidoctor/java/DocIndexer.java b/java/com/google/gerrit/asciidoctor/DocIndexer.java
similarity index 98%
rename from lib/asciidoctor/java/DocIndexer.java
rename to java/com/google/gerrit/asciidoctor/DocIndexer.java
index c90c439..5dfde95 100644
--- a/lib/asciidoctor/java/DocIndexer.java
+++ b/java/com/google/gerrit/asciidoctor/DocIndexer.java
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package com.google.gerrit.asciidoctor;
+
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.gerrit.server.documentation.Constants;
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index 730f219..53e43a2 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -66,6 +66,7 @@
 import com.google.gerrit.server.config.GerritGlobalModule;
 import com.google.gerrit.server.config.GerritInstanceNameModule;
 import com.google.gerrit.server.config.GerritOptions;
+import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SysExecutorModule;
 import com.google.gerrit.server.events.EventBroker;
@@ -371,6 +372,11 @@
     manager.stop();
   }
 
+  @Override
+  protected GerritRuntime getGerritRuntime() {
+    return GerritRuntime.DAEMON;
+  }
+
   private boolean sshdOff() {
     return new SshAddressesModule().getListenAddresses(config).isEmpty();
   }
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index b59e085..45d2a5d 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.metrics.DisabledMetricMaker;
 import com.google.gerrit.metrics.MetricMaker;
 import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
+import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
@@ -155,6 +156,13 @@
         });
     Module configModule = new GerritServerConfigModule();
     modules.add(configModule);
+    modules.add(
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            bind(GerritRuntime.class).toInstance(getGerritRuntime());
+          }
+        });
     Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
     Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
     String dbType;
@@ -219,6 +227,11 @@
     }
   }
 
+  /** Returns the current runtime used by this Gerrit program. */
+  protected GerritRuntime getGerritRuntime() {
+    return GerritRuntime.BATCH;
+  }
+
   protected final String getConfiguredSecureStoreClass() {
     return getSecureStoreClassName(sitePath);
   }
diff --git a/java/com/google/gerrit/server/auth/ldap/Helper.java b/java/com/google/gerrit/server/auth/ldap/Helper.java
index 16c1724..fe57374 100644
--- a/java/com/google/gerrit/server/auth/ldap/Helper.java
+++ b/java/com/google/gerrit/server/auth/ldap/Helper.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.server.auth.NoSuchUserException;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.util.ssl.BlindHostnameVerifier;
 import com.google.gerrit.util.ssl.BlindSSLSocketFactory;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -139,6 +140,7 @@
       SSLSocketFactory sslfactory = null;
       if (!sslVerify) {
         sslfactory = (SSLSocketFactory) BlindSSLSocketFactory.getDefault();
+        tls.setHostnameVerifier(BlindHostnameVerifier.getInstance());
       }
       tls.negotiate(sslfactory);
       ctx.addToEnvironment(STARTTLS_PROPERTY, tls);
diff --git a/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java b/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
index b2eb62d..f3ab847 100644
--- a/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
+++ b/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.change;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.auto.value.AutoValue;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.cache.Cache;
 import com.google.common.cache.Weigher;
@@ -50,6 +50,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import org.eclipse.jgit.errors.LargeObjectException;
+import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
@@ -104,7 +105,7 @@
         ObjectId prior,
         ObjectId next) {
       try {
-        Key key = new Key(prior, next, useRecursiveMerge);
+        Key key = Key.create(prior, next, useRecursiveMerge);
         return new Loader(key, repoManager, project, rw, repoConfig).call();
       } catch (IOException e) {
         log.warn(
@@ -125,52 +126,21 @@
     }
   }
 
-  public static class Key {
-    private transient ObjectId prior;
-    private transient ObjectId next;
-    private transient String strategyName;
-
-    private Key(ObjectId prior, ObjectId next, boolean useRecursiveMerge) {
-      checkNotNull(next, "next");
-      String strategyName = MergeUtil.mergeStrategyName(true, useRecursiveMerge);
-      this.prior = prior.copy();
-      this.next = next.copy();
-      this.strategyName = strategyName;
+  @AutoValue
+  public abstract static class Key {
+    public static Key create(AnyObjectId prior, AnyObjectId next, String strategyName) {
+      return new AutoValue_ChangeKindCacheImpl_Key(prior.copy(), next.copy(), strategyName);
     }
 
-    public Key(ObjectId prior, ObjectId next, String strategyName) {
-      this.prior = prior;
-      this.next = next;
-      this.strategyName = strategyName;
+    private static Key create(AnyObjectId prior, AnyObjectId next, boolean useRecursiveMerge) {
+      return create(prior, next, MergeUtil.mergeStrategyName(true, useRecursiveMerge));
     }
 
-    public ObjectId getPrior() {
-      return prior;
-    }
+    public abstract ObjectId prior();
 
-    public ObjectId getNext() {
-      return next;
-    }
+    public abstract ObjectId next();
 
-    public String getStrategyName() {
-      return strategyName;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (o instanceof Key) {
-        Key k = (Key) o;
-        return Objects.equals(prior, k.prior)
-            && Objects.equals(next, k.next)
-            && Objects.equals(strategyName, k.strategyName);
-      }
-      return false;
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hash(prior, next, strategyName);
-    }
+    public abstract String strategyName();
 
     @VisibleForTesting
     static class Serializer implements CacheSerializer<Key> {
@@ -179,9 +149,9 @@
         ObjectIdConverter idConverter = ObjectIdConverter.create();
         return ProtoCacheSerializers.toByteArray(
             ChangeKindKeyProto.newBuilder()
-                .setPrior(idConverter.toByteString(object.getPrior()))
-                .setNext(idConverter.toByteString(object.getNext()))
-                .setStrategyName(object.getStrategyName())
+                .setPrior(idConverter.toByteString(object.prior()))
+                .setNext(idConverter.toByteString(object.next()))
+                .setStrategyName(object.strategyName())
                 .build());
       }
 
@@ -190,7 +160,7 @@
         ChangeKindKeyProto proto =
             ProtoCacheSerializers.parseUnchecked(ChangeKindKeyProto.parser(), in);
         ObjectIdConverter idConverter = ObjectIdConverter.create();
-        return new Key(
+        return create(
             idConverter.fromByteString(proto.getPrior()),
             idConverter.fromByteString(proto.getNext()),
             proto.getStrategyName());
@@ -226,7 +196,7 @@
     @SuppressWarnings("resource") // Resources are manually managed.
     @Override
     public ChangeKind call() throws IOException {
-      if (Objects.equals(key.prior, key.next)) {
+      if (Objects.equals(key.prior(), key.next())) {
         return ChangeKind.NO_CODE_CHANGE;
       }
 
@@ -239,9 +209,9 @@
         config = repo.getConfig();
       }
       try {
-        RevCommit prior = rw.parseCommit(key.prior);
+        RevCommit prior = rw.parseCommit(key.prior());
         rw.parseBody(prior);
-        RevCommit next = rw.parseCommit(key.next);
+        RevCommit next = rw.parseCommit(key.next());
         rw.parseBody(next);
 
         if (!next.getFullMessage().equals(prior.getFullMessage())) {
@@ -272,7 +242,7 @@
         // having the same tree as would exist when the prior commit is
         // cherry-picked onto the next commit's new first parent.
         try (ObjectInserter ins = new InMemoryInserter(rw.getObjectReader())) {
-          ThreeWayMerger merger = MergeUtil.newThreeWayMerger(ins, config, key.strategyName);
+          ThreeWayMerger merger = MergeUtil.newThreeWayMerger(ins, config, key.strategyName());
           merger.setBase(prior.getParent(0));
           if (merger.merge(next.getParent(0), prior)
               && merger.getResultTreeId().equals(next.getTree())) {
@@ -316,7 +286,7 @@
     }
 
     private static boolean isSameDeltaAndTree(RevCommit prior, RevCommit next) {
-      if (next.getTree() != prior.getTree()) {
+      if (!Objects.equals(next.getTree(), prior.getTree())) {
         return false;
       }
 
@@ -329,7 +299,7 @@
       // Make sure that the prior/next delta is the same - not just the tree.
       // This is done by making sure that the parent trees are equal.
       for (int i = 0; i < prior.getParentCount(); i++) {
-        if (next.getParent(i).getTree() != prior.getParent(i).getTree()) {
+        if (!Objects.equals(next.getParent(i).getTree(), prior.getParent(i).getTree())) {
           return false;
         }
       }
@@ -342,7 +312,7 @@
     public int weigh(Key key, ChangeKind changeKind) {
       return 16
           + 2 * 36
-          + 2 * key.strategyName.length() // Size of Key, 64 bit JVM
+          + 2 * key.strategyName().length() // Size of Key, 64 bit JVM
           + 2 * changeKind.name().length(); // Size of ChangeKind, 64 bit JVM
     }
   }
@@ -372,7 +342,7 @@
       ObjectId prior,
       ObjectId next) {
     try {
-      Key key = new Key(prior, next, useRecursiveMerge);
+      Key key = Key.create(prior, next, useRecursiveMerge);
       return cache.get(key, new Loader(key, repoManager, project, rw, repoConfig));
     } catch (ExecutionException e) {
       log.warn("Cannot check trivial rebase of new patch set " + next.name() + " in " + project, e);
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index cb0cdf9..57255a3 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -76,7 +76,6 @@
 import com.google.gerrit.server.CmdLineParserModule;
 import com.google.gerrit.server.CreateGroupPermissionSyncer;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.PluginUser;
 import com.google.gerrit.server.Sequences;
 import com.google.gerrit.server.account.AccountCacheImpl;
 import com.google.gerrit.server.account.AccountControl;
@@ -262,7 +261,6 @@
     factory(MergedSender.Factory.class);
     factory(MergeUtil.Factory.class);
     factory(PatchScriptFactory.Factory.class);
-    factory(PluginUser.Factory.class);
     factory(ProjectState.Factory.class);
     factory(RegisterNewEmailSender.Factory.class);
     factory(ReplacePatchSetSender.Factory.class);
diff --git a/java/com/google/gerrit/server/config/GerritRuntime.java b/java/com/google/gerrit/server/config/GerritRuntime.java
new file mode 100644
index 0000000..ac4cede
--- /dev/null
+++ b/java/com/google/gerrit/server/config/GerritRuntime.java
@@ -0,0 +1,24 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.config;
+
+/** Represents the current runtime environment in which Gerrit is running. */
+public enum GerritRuntime {
+  /** Gerrit is running as a server, with all its features. */
+  DAEMON,
+
+  /** Gerrit is running from the command line, in batch mode (reindex, ...). */
+  BATCH
+}
diff --git a/java/com/google/gerrit/server/plugins/JarPluginProvider.java b/java/com/google/gerrit/server/plugins/JarPluginProvider.java
index 4a37599..cf54bf4 100644
--- a/java/com/google/gerrit/server/plugins/JarPluginProvider.java
+++ b/java/com/google/gerrit/server/plugins/JarPluginProvider.java
@@ -152,7 +152,8 @@
               jarScanner,
               description.dataDir,
               pluginLoader,
-              pluginConfig.getString("metricsPrefix", null));
+              pluginConfig.getString("metricsPrefix", null),
+              description.gerritRuntime);
       plugin.setCleanupHandle(new CleanupHandle(tmp, jarFile));
       keep = true;
       return plugin;
diff --git a/java/com/google/gerrit/server/plugins/PluginLoader.java b/java/com/google/gerrit/server/plugins/PluginLoader.java
index 96fd550..73f2cb2 100644
--- a/java/com/google/gerrit/server/plugins/PluginLoader.java
+++ b/java/com/google/gerrit/server/plugins/PluginLoader.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.server.cache.PersistentCacheFactory;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.ConfigUtil;
+import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.plugins.ServerPluginProvider.PluginDescription;
@@ -89,6 +90,7 @@
   private final PersistentCacheFactory persistentCacheFactory;
   private final boolean remoteAdmin;
   private final UniversalServerPluginProvider serverPluginFactory;
+  private final GerritRuntime gerritRuntime;
 
   @Inject
   public PluginLoader(
@@ -100,7 +102,8 @@
       @GerritServerConfig Config cfg,
       @CanonicalWebUrl Provider<String> provider,
       PersistentCacheFactory cacheFactory,
-      UniversalServerPluginProvider pluginFactory) {
+      UniversalServerPluginProvider pluginFactory,
+      GerritRuntime gerritRuntime) {
     pluginsDir = sitePaths.plugins_dir;
     dataDir = sitePaths.data_dir;
     tempDir = sitePaths.tmp_dir;
@@ -113,6 +116,7 @@
     serverPluginFactory = pluginFactory;
 
     remoteAdmin = cfg.getBoolean("plugins", null, "allowRemoteAdmin", false);
+    this.gerritRuntime = gerritRuntime;
 
     long checkFrequency =
         ConfigUtil.getTimeUnit(
@@ -606,7 +610,8 @@
         new PluginDescription(
             pluginUserFactory.create(name),
             getPluginCanonicalWebUrl(name),
-            getPluginDataDir(name)));
+            getPluginDataDir(name),
+            gerritRuntime));
   }
 
   // Only one active plugin per plugin name can exist for each plugin name.
diff --git a/java/com/google/gerrit/server/plugins/PluginModule.java b/java/com/google/gerrit/server/plugins/PluginModule.java
index db18470..6bc37bd 100644
--- a/java/com/google/gerrit/server/plugins/PluginModule.java
+++ b/java/com/google/gerrit/server/plugins/PluginModule.java
@@ -17,10 +17,15 @@
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.systemstatus.ServerInformation;
 import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.server.PluginUser;
+import com.google.gerrit.server.config.GerritRuntime;
 
 public class PluginModule extends LifecycleModule {
   @Override
   protected void configure() {
+    requireBinding(GerritRuntime.class);
+
+    factory(PluginUser.Factory.class);
     bind(ServerInformationImpl.class);
     bind(ServerInformation.class).to(ServerInformationImpl.class);
 
diff --git a/java/com/google/gerrit/server/plugins/PluginRestApiModule.java b/java/com/google/gerrit/server/plugins/PluginRestApiModule.java
index 8e162ba..cad0e1e 100644
--- a/java/com/google/gerrit/server/plugins/PluginRestApiModule.java
+++ b/java/com/google/gerrit/server/plugins/PluginRestApiModule.java
@@ -18,10 +18,13 @@
 
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.RestApiModule;
+import com.google.gerrit.server.PluginUser;
+import com.google.inject.Key;
 
 public class PluginRestApiModule extends RestApiModule {
   @Override
   protected void configure() {
+    requireBinding(Key.get(PluginUser.Factory.class));
     bind(PluginsCollection.class);
     DynamicMap.mapOf(binder(), PLUGIN_KIND);
     put(PLUGIN_KIND).to(InstallPlugin.Overwrite.class);
diff --git a/java/com/google/gerrit/server/plugins/ServerPlugin.java b/java/com/google/gerrit/server/plugins/ServerPlugin.java
index b46ecf5..3e6589c 100644
--- a/java/com/google/gerrit/server/plugins/ServerPlugin.java
+++ b/java/com/google/gerrit/server/plugins/ServerPlugin.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.server.PluginUser;
+import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -44,6 +45,7 @@
   private final String pluginCanonicalWebUrl;
   private final ClassLoader classLoader;
   private final String metricsPrefix;
+  private final GerritRuntime gerritRuntime;
   protected Class<? extends Module> sysModule;
   protected Class<? extends Module> sshModule;
   protected Class<? extends Module> httpModule;
@@ -63,7 +65,8 @@
       PluginContentScanner scanner,
       Path dataDir,
       ClassLoader classLoader,
-      String metricsPrefix)
+      String metricsPrefix,
+      GerritRuntime gerritRuntime)
       throws InvalidPluginException {
     super(
         name,
@@ -77,33 +80,12 @@
     this.classLoader = classLoader;
     this.manifest = scanner == null ? null : getPluginManifest(scanner);
     this.metricsPrefix = metricsPrefix;
+    this.gerritRuntime = gerritRuntime;
     if (manifest != null) {
       loadGuiceModules(manifest, classLoader);
     }
   }
 
-  public ServerPlugin(
-      String name,
-      String pluginCanonicalWebUrl,
-      PluginUser pluginUser,
-      Path srcJar,
-      FileSnapshot snapshot,
-      PluginContentScanner scanner,
-      Path dataDir,
-      ClassLoader classLoader)
-      throws InvalidPluginException {
-    this(
-        name,
-        pluginCanonicalWebUrl,
-        pluginUser,
-        srcJar,
-        snapshot,
-        scanner,
-        dataDir,
-        classLoader,
-        null);
-  }
-
   private void loadGuiceModules(Manifest manifest, ClassLoader classLoader)
       throws InvalidPluginException {
     Attributes main = manifest.getMainAttributes();
diff --git a/java/com/google/gerrit/server/plugins/ServerPluginProvider.java b/java/com/google/gerrit/server/plugins/ServerPluginProvider.java
index 632f838..f2f64c2 100644
--- a/java/com/google/gerrit/server/plugins/ServerPluginProvider.java
+++ b/java/com/google/gerrit/server/plugins/ServerPluginProvider.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.extensions.annotations.ExtensionPoint;
 import com.google.gerrit.server.PluginUser;
+import com.google.gerrit.server.config.GerritRuntime;
 import java.nio.file.Path;
 import org.eclipse.jgit.internal.storage.file.FileSnapshot;
 
@@ -36,6 +37,7 @@
     public final PluginUser user;
     public final String canonicalUrl;
     public final Path dataDir;
+    final GerritRuntime gerritRuntime;
 
     /**
      * Creates a new PluginDescription for ServerPluginProvider.
@@ -43,11 +45,14 @@
      * @param user Gerrit user for interacting with plugins
      * @param canonicalUrl plugin root Web URL
      * @param dataDir directory for plugin data
+     * @param gerritRuntime current Gerrit runtime (daemon, batch, ...)
      */
-    public PluginDescription(PluginUser user, String canonicalUrl, Path dataDir) {
+    public PluginDescription(
+        PluginUser user, String canonicalUrl, Path dataDir, GerritRuntime gerritRuntime) {
       this.user = user;
       this.canonicalUrl = canonicalUrl;
       this.dataDir = dataDir;
+      this.gerritRuntime = gerritRuntime;
     }
   }
 
diff --git a/java/com/google/gerrit/server/plugins/TestServerPlugin.java b/java/com/google/gerrit/server/plugins/TestServerPlugin.java
index dbdc576..3751c3f 100644
--- a/java/com/google/gerrit/server/plugins/TestServerPlugin.java
+++ b/java/com/google/gerrit/server/plugins/TestServerPlugin.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.plugins;
 
 import com.google.gerrit.server.PluginUser;
+import com.google.gerrit.server.config.GerritRuntime;
 import java.nio.file.Path;
 
 public class TestServerPlugin extends ServerPlugin {
@@ -33,7 +34,17 @@
       String sshName,
       Path dataDir)
       throws InvalidPluginException {
-    super(name, pluginCanonicalWebUrl, user, null, null, null, dataDir, classloader);
+    super(
+        name,
+        pluginCanonicalWebUrl,
+        user,
+        null,
+        null,
+        null,
+        dataDir,
+        classloader,
+        null,
+        GerritRuntime.DAEMON);
     this.classLoader = classloader;
     this.sysName = sysName;
     this.httpName = httpName;
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index b472857..700eb83 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -32,6 +32,7 @@
 import com.google.gerrit.server.FanOutExecutor;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.GerritPersonIdentProvider;
+import com.google.gerrit.server.PluginUser;
 import com.google.gerrit.server.api.GerritApiModule;
 import com.google.gerrit.server.api.PluginApiModule;
 import com.google.gerrit.server.cache.h2.H2CacheModule;
@@ -48,6 +49,7 @@
 import com.google.gerrit.server.config.GerritGlobalModule;
 import com.google.gerrit.server.config.GerritInstanceNameModule;
 import com.google.gerrit.server.config.GerritOptions;
+import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.GerritServerId;
 import com.google.gerrit.server.config.GerritServerIdProvider;
@@ -168,9 +170,11 @@
                 bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg);
               }
             });
+    bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
     bind(MetricMaker.class).to(DisabledMetricMaker.class);
     install(cfgInjector.getInstance(GerritGlobalModule.class));
     install(new GerritApiModule());
+    factory(PluginUser.Factory.class);
     install(new PluginApiModule());
     install(new DefaultPermissionBackendModule());
     install(new SearchingChangeCacheImpl.Module());
diff --git a/java/com/google/gerrit/util/ssl/BlindHostnameVerifier.java b/java/com/google/gerrit/util/ssl/BlindHostnameVerifier.java
new file mode 100644
index 0000000..ac758690
--- /dev/null
+++ b/java/com/google/gerrit/util/ssl/BlindHostnameVerifier.java
@@ -0,0 +1,33 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.util.ssl;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+
+/** HostnameVerifier that ignores host name. */
+public class BlindHostnameVerifier implements HostnameVerifier {
+
+  private static final HostnameVerifier INSTANCE = new BlindHostnameVerifier();
+
+  public static HostnameVerifier getInstance() {
+    return INSTANCE;
+  }
+
+  @Override
+  public boolean verify(String hostname, SSLSession session) {
+    return true;
+  }
+}
diff --git a/javatests/com/google/gerrit/acceptance/pgm/ReindexIT.java b/javatests/com/google/gerrit/acceptance/pgm/ReindexIT.java
index 4b6f8b2..41640a9 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/ReindexIT.java
+++ b/javatests/com/google/gerrit/acceptance/pgm/ReindexIT.java
@@ -80,6 +80,9 @@
                   .flatMap(g -> g.members.stream())
                   .map(a -> a._accountId))
           .containsExactly(adminId.get());
+      // Query project index
+      assertThat(gApi.projects().query(project.get()).get().stream().map(p -> p.name))
+          .containsExactly(project.get());
     }
   }
 
@@ -220,7 +223,7 @@
   }
 
   private void setUpChange() throws Exception {
-    project = new Project.NameKey("project");
+    project = new Project.NameKey("reindex-project-test");
     try (ServerContext ctx = startServer()) {
       GerritApi gApi = ctx.getInjector().getInstance(GerritApi.class);
       gApi.projects().create(project.get());
diff --git a/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java b/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
index b0d7ae4..03e0d4e 100644
--- a/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
+++ b/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
@@ -22,6 +22,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.server.cache.CacheSerializer;
 import com.google.gerrit.server.cache.proto.Cache.ChangeKindKeyProto;
+import com.google.gerrit.server.change.ChangeKindCacheImpl.Key;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 
@@ -29,7 +30,7 @@
   @Test
   public void keySerializer() throws Exception {
     ChangeKindCacheImpl.Key key =
-        new ChangeKindCacheImpl.Key(
+        Key.create(
             ObjectId.zeroId(),
             ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
             "aStrategy");
@@ -55,7 +56,7 @@
   @Test
   public void keyFields() throws Exception {
     assertThatSerializedClass(ChangeKindCacheImpl.Key.class)
-        .hasFields(
+        .hasAutoValueMethods(
             ImmutableMap.of(
                 "prior", ObjectId.class, "next", ObjectId.class, "strategyName", String.class));
   }
diff --git a/lib/asciidoctor/BUILD b/lib/asciidoctor/BUILD
index da05dd1..62b1114 100644
--- a/lib/asciidoctor/BUILD
+++ b/lib/asciidoctor/BUILD
@@ -1,48 +1,7 @@
-java_binary(
-    name = "asciidoc",
-    main_class = "AsciiDoctor",
-    visibility = ["//visibility:public"],
-    runtime_deps = [":asciidoc_lib"],
-)
-
-java_library(
-    name = "asciidoc_lib",
-    srcs = ["java/AsciiDoctor.java"],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":asciidoctor",
-        "//lib:args4j",
-        "//lib:guava",
-        "//lib/log:api",
-        "//lib/log:nop",
-    ],
-)
-
-java_binary(
-    name = "doc_indexer",
-    main_class = "DocIndexer",
-    visibility = ["//visibility:public"],
-    runtime_deps = [":doc_indexer_lib"],
-)
-
-java_library(
-    name = "doc_indexer_lib",
-    srcs = ["java/DocIndexer.java"],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":asciidoc_lib",
-        "//java/com/google/gerrit/server:constants",
-        "//lib:args4j",
-        "//lib:guava",
-        "//lib/lucene:lucene-analyzers-common",
-        "//lib/lucene:lucene-core-and-backward-codecs",
-    ],
-)
-
 java_library(
     name = "asciidoctor",
     data = ["//lib:LICENSE-asciidoctor"],
-    visibility = ["//visibility:public"],
+    visibility = ["//java/com/google/gerrit/asciidoctor:__pkg__"],
     exports = ["@asciidoctor//jar"],
     runtime_deps = [":jruby"],
 )
diff --git a/lib/guava.bzl b/lib/guava.bzl
index e90c2b3..069149b 100644
--- a/lib/guava.bzl
+++ b/lib/guava.bzl
@@ -1,5 +1,5 @@
-GUAVA_VERSION = "25.0-jre"
+GUAVA_VERSION = "25.1-jre"
 
-GUAVA_BIN_SHA1 = "7319c34fa5866a85b6bad445adad69d402323129"
+GUAVA_BIN_SHA1 = "6c57e4b22b44e89e548b5c9f70f0c45fe10fb0b4"
 
 GUAVA_DOC_URL = "https://google.github.io/guava/releases/" + GUAVA_VERSION + "/api/docs/"
diff --git a/lib/js/bower_archives.bzl b/lib/js/bower_archives.bzl
index 5ee3535..6b4e003 100644
--- a/lib/js/bower_archives.bzl
+++ b/lib/js/bower_archives.bzl
@@ -65,8 +65,8 @@
   bower_archive(
     name = "iron-menu-behavior",
     package = "PolymerElements/iron-menu-behavior",
-    version = "2.0.1",
-    sha1 = "139528ee1e8d86257e2aa445de7761b8ec70ae91")
+    version = "2.1.1",
+    sha1 = "1504997f6eb9aec490b855dadee473cac064f38c")
   bower_archive(
     name = "iron-meta",
     package = "PolymerElements/iron-meta",
@@ -105,8 +105,8 @@
   bower_archive(
     name = "paper-icon-button",
     package = "PolymerElements/paper-icon-button",
-    version = "2.1.0",
-    sha1 = "caead6a276877888d128ace809376980c3f3fe42")
+    version = "2.2.0",
+    sha1 = "9525e76ef433428bb9d6ec4fa65c4ef83156a803")
   bower_archive(
     name = "paper-ripple",
     package = "PolymerElements/paper-ripple",
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
index ac12d71..704974d 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
@@ -30,7 +30,7 @@
 
 <dom-module id="gr-repo">
   <template>
-    <style="shared-styles"></style>
+    <style include="shared-styles"></style>
     <style include="gr-subpage-styles">
       h2.edited:after {
         color: var(--deemphasized-text-color);
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index 8af7301..6adc286 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -113,16 +113,21 @@
     CHANGE_NUMBER_LEGACY: /^\/(\d+)\/?/,
 
     // Matches
-    // /c/<project>/+/<changeNum>/
-    //     [<basePatchNum|edit>..][<patchNum|edit>]/[path].
+    // /c/<project>/+/<changeNum>/[<basePatchNum|edit>..][<patchNum|edit>].
     // TODO(kaspern): Migrate completely to project based URLs, with backwards
     // compatibility for change-only.
-    // eslint-disable-next-line max-len
-    CHANGE_OR_DIFF: /^\/c\/(.+)\/\+\/(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?(\/(.+))?))?\/?$/,
+    CHANGE: /^\/c\/(.+)\/\+\/(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,
 
     // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>],edit
     CHANGE_EDIT: /^\/c\/(.+)\/\+\/(\d+)(\/(\d+))?,edit\/?$/,
 
+    // Matches
+    // /c/<project>/+/<changeNum>/[<basePatchNum|edit>..]<patchNum|edit>/<path>.
+    // TODO(kaspern): Migrate completely to project based URLs, with backwards
+    // compatibility for change-only.
+    // eslint-disable-next-line max-len
+    DIFF: /^\/c\/(.+)\/\+\/(\d+)(\/((-?\d+|edit)(\.\.(\d+|edit))?(\/(.+))))\/?$/,
+
     // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>]/<path>,edit
     DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/(\d+|edit)\/(.+),edit$/,
 
@@ -642,24 +647,13 @@
         return;
       }
       page(pattern, this._loadUserMiddleware.bind(this), data => {
-        this.$.reporting.locationChanged(this._getPageName(handlerName, data));
+        this.$.reporting.locationChanged(handlerName);
         const promise = opt_authRedirect ?
           this._redirectIfNotLoggedIn(data) : Promise.resolve();
         promise.then(() => { this[handlerName](data); });
       });
     },
 
-    _getPageName(handlerName, ctx) {
-      switch (handlerName) {
-        case '_handleChangeOrDiffRoute': {
-          const isDiffView = ctx.params[8];
-          return isDiffView ? Gerrit.Nav.View.DIFF : Gerrit.Nav.View.CHANGE;
-        }
-        default:
-          return handlerName;
-      }
-    },
-
     _startRouter() {
       const base = this.getBaseUrl();
       if (base) {
@@ -806,7 +800,9 @@
 
       this._mapRoute(RoutePattern.CHANGE_EDIT, '_handleChangeEditRoute', true);
 
-      this._mapRoute(RoutePattern.CHANGE_OR_DIFF, '_handleChangeOrDiffRoute');
+      this._mapRoute(RoutePattern.DIFF, '_handleDiffRoute');
+
+      this._mapRoute(RoutePattern.CHANGE, '_handleChangeRoute');
 
       this._mapRoute(RoutePattern.CHANGE_LEGACY, '_handleChangeLegacyRoute');
 
@@ -1245,9 +1241,20 @@
       this._redirect('/c/' + encodeURIComponent(ctx.params[0]));
     },
 
-    _handleChangeOrDiffRoute(ctx) {
-      const isDiffView = ctx.params[8];
+    _handleChangeRoute(ctx) {
+      // Parameter order is based on the regex group number matched.
+      const params = {
+        project: ctx.params[0],
+        changeNum: ctx.params[1],
+        basePatchNum: ctx.params[4],
+        patchNum: ctx.params[6],
+        view: Gerrit.Nav.View.CHANGE,
+      };
 
+      this._redirectOrNavigate(params);
+    },
+
+    _handleDiffRoute(ctx) {
       // Parameter order is based on the regex group number matched.
       const params = {
         project: ctx.params[0],
@@ -1255,15 +1262,13 @@
         basePatchNum: ctx.params[4],
         patchNum: ctx.params[6],
         path: ctx.params[8],
-        view: isDiffView ? Gerrit.Nav.View.DIFF : Gerrit.Nav.View.CHANGE,
+        view: Gerrit.Nav.View.DIFF,
       };
 
-      if (isDiffView) {
-        const address = this._parseLineAddress(ctx.hash);
-        if (address) {
-          params.leftSide = address.leftSide;
-          params.lineNum = address.lineNum;
-        }
+      const address = this._parseLineAddress(ctx.hash);
+      if (address) {
+        params.leftSide = address.leftSide;
+        params.lineNum = address.lineNum;
       }
 
       this._redirectOrNavigate(params);
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
index e0a7e46..b68a5e9 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
@@ -152,7 +152,8 @@
         '_handleBranchListFilterRoute',
         '_handleBranchListOffsetRoute',
         '_handleChangeNumberLegacyRoute',
-        '_handleChangeOrDiffRoute',
+        '_handleChangeRoute',
+        '_handleDiffRoute',
         '_handleDefaultRoute',
         '_handleChangeLegacyRoute',
         '_handleDiffLegacyRoute',
@@ -1267,7 +1268,57 @@
               '/c/1234/3..8/foo/bar#b123'));
         });
 
-        suite('_handleChangeOrDiffRoute', () => {
+        suite('_handleChangeRoute', () => {
+          let normalizeRangeStub;
+
+          function makeParams(path, hash) {
+            return {
+              params: [
+                'foo/bar', // 0 Project
+                1234, // 1 Change number
+                null, // 2 Unused
+                null, // 3 Unused
+                4, // 4 Base patch number
+                null, // 5 Unused
+                7, // 6 Patch number
+              ],
+            };
+          }
+
+          setup(() => {
+            normalizeRangeStub = sandbox.stub(element,
+                '_normalizePatchRangeParams');
+            sandbox.stub(element.$.restAPI, 'setInProjectLookup');
+          });
+
+          test('needs redirect', () => {
+            normalizeRangeStub.returns(true);
+            sandbox.stub(element, '_generateUrl').returns('foo');
+            const ctx = makeParams(null, '');
+            element._handleChangeRoute(ctx);
+            assert.isTrue(normalizeRangeStub.called);
+            assert.isFalse(setParamsStub.called);
+            assert.isTrue(redirectStub.calledOnce);
+            assert.isTrue(redirectStub.calledWithExactly('foo'));
+          });
+
+          test('change view', () => {
+            normalizeRangeStub.returns(false);
+            sandbox.stub(element, '_generateUrl').returns('foo');
+            const ctx = makeParams(null, '');
+            assertDataToParams(ctx, '_handleChangeRoute', {
+              view: Gerrit.Nav.View.CHANGE,
+              project: 'foo/bar',
+              changeNum: 1234,
+              basePatchNum: 4,
+              patchNum: 7,
+            });
+            assert.isFalse(redirectStub.called);
+            assert.isTrue(normalizeRangeStub.called);
+          });
+        });
+
+        suite('_handleDiffRoute', () => {
           let normalizeRangeStub;
 
           function makeParams(path, hash) {
@@ -1297,40 +1348,18 @@
             normalizeRangeStub.returns(true);
             sandbox.stub(element, '_generateUrl').returns('foo');
             const ctx = makeParams(null, '');
-            element._handleChangeOrDiffRoute(ctx);
+            element._handleDiffRoute(ctx);
             assert.isTrue(normalizeRangeStub.called);
             assert.isFalse(setParamsStub.called);
             assert.isTrue(redirectStub.calledOnce);
             assert.isTrue(redirectStub.calledWithExactly('foo'));
           });
 
-          test('change view', () => {
-            normalizeRangeStub.returns(false);
-            sandbox.stub(element, '_generateUrl').returns('foo');
-            const ctx = makeParams(null, '');
-            assertDataToParams(ctx, '_handleChangeOrDiffRoute', {
-              view: Gerrit.Nav.View.CHANGE,
-              project: 'foo/bar',
-              changeNum: 1234,
-              basePatchNum: 4,
-              patchNum: 7,
-              path: null,
-            });
-            assert.isFalse(redirectStub.called);
-            assert.isTrue(normalizeRangeStub.called);
-          });
-
-          test('gr-reporting recognizes change page', () => {
-            const ctx = makeParams(null, '');
-            assert.equal(element._getPageName('_handleChangeOrDiffRoute', ctx),
-                Gerrit.Nav.View.CHANGE);
-          });
-
           test('diff view', () => {
             normalizeRangeStub.returns(false);
             sandbox.stub(element, '_generateUrl').returns('foo');
             const ctx = makeParams('foo/bar/baz', 'b44');
-            assertDataToParams(ctx, '_handleChangeOrDiffRoute', {
+            assertDataToParams(ctx, '_handleDiffRoute', {
               view: Gerrit.Nav.View.DIFF,
               project: 'foo/bar',
               changeNum: 1234,
@@ -1343,12 +1372,6 @@
             assert.isFalse(redirectStub.called);
             assert.isTrue(normalizeRangeStub.called);
           });
-
-          test('gr-reporting recognizes diff page', () => {
-            const ctx = makeParams('foo/bar/baz', 'b44');
-            assert.equal(element._getPageName('_handleChangeOrDiffRoute', ctx),
-                Gerrit.Nav.View.DIFF);
-          });
         });
 
         test('_handleDiffEditRoute', () => {
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index 53ffc60..3b66ae8 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -197,7 +197,8 @@
     },
 
     _computeShowGwtUiLink(config) {
-      return config.gerrit.web_uis && config.gerrit.web_uis.includes('GWT');
+      return !window.DEPRECATE_GWT_UI &&
+          config.gerrit.web_uis && config.gerrit.web_uis.includes('GWT');
     },
 
     _handlePageError(e) {
diff --git a/polygerrit-ui/app/styles/gr-change-list-styles.html b/polygerrit-ui/app/styles/gr-change-list-styles.html
index db8aa70..e485a52 100644
--- a/polygerrit-ui/app/styles/gr-change-list-styles.html
+++ b/polygerrit-ui/app/styles/gr-change-list-styles.html
@@ -68,7 +68,6 @@
       }
       .topHeader th {
         background-color: var(--table-header-background-color);
-        font-size: var(--font-size-large);
         height: 3rem;
         position: -webkit-sticky;
         position: sticky;
diff --git a/polygerrit-ui/app/styles/gr-table-styles.html b/polygerrit-ui/app/styles/gr-table-styles.html
index 5e40735..cf4e84e 100644
--- a/polygerrit-ui/app/styles/gr-table-styles.html
+++ b/polygerrit-ui/app/styles/gr-table-styles.html
@@ -71,11 +71,11 @@
       }
       .genericList .topHeader {
         background-color: var(--table-header-background-color);
-        font-size: var(--font-size-large);
         height: 3rem;
       }
       .genericList .groupHeader {
         background-color: var(--table-subheader-background-color);
+        font-size: var(--font-size-large);
       }
       .genericList a {
         color: var(--primary-text-color);
diff --git a/polygerrit-ui/app/styles/themes/app-theme.html b/polygerrit-ui/app/styles/themes/app-theme.html
index 4500e10..21db329 100644
--- a/polygerrit-ui/app/styles/themes/app-theme.html
+++ b/polygerrit-ui/app/styles/themes/app-theme.html
@@ -53,7 +53,7 @@
   /* Font sizes */
   --font-size-normal: 1rem;
   --font-size-small: .92rem;
-  --font-size-large: 1.076rem;
+  --font-size-large: 1.154rem;
 
   --link-color: #2a66d9;
   --primary-button-background-color: var(--link-color);
@@ -78,14 +78,14 @@
 
   /* Diff colors */
   --diff-selection-background-color: #c7dbf9;
-  --light-remove-highlight-color: #fee;
-  --light-add-highlight-color: #efe;
-  --light-remove-add-highlight-color: #fff6ea;
-  --light-rebased-add-highlight-color: #edfffa;
-  --dark-remove-highlight-color: rgba(255, 0, 0, 0.15);
-  --dark-add-highlight-color: rgba(0, 255, 0, 0.15);
-  --dark-rebased-remove-highlight-color: rgba(255, 139, 6, 0.15);
-  --dark-rebased-add-highlight-color: rgba(11, 255, 155, 0.15);
+  --light-remove-highlight-color: #FFEBEE;
+  --light-add-highlight-color: #D8FED8;
+  --light-remove-add-highlight-color: #FFF8DC;
+  --light-rebased-add-highlight-color: #EEEEFF;
+  --dark-remove-highlight-color: #FFCDD2;
+  --dark-add-highlight-color: #AAF2AA;
+  --dark-rebased-remove-highlight-color: #F7E8B7;
+  --dark-rebased-add-highlight-color: #D7D7F9;
   --diff-context-control-color: #fff7d4;
   --diff-context-control-border-color: #f6e6a5;
   --diff-tab-indicator-color: var(--deemphasized-text-color);
diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
index c51e9dc..3dd6360 100644
--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
+++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
@@ -21,6 +21,7 @@
  * @param staticResourcePath
  * @param? faviconPath
  * @param? versionInfo
+ * @param? deprecateGwtUi
  */
 {template .Index}
   <!DOCTYPE html>{\n}
@@ -32,6 +33,7 @@
   <script>
     window.CLOSURE_NO_DEPS = true;
     {if $canonicalPath != ''}window.CANONICAL_PATH = '{$canonicalPath}';{/if}
+    {if $deprecateGwtUi}window.DEPRECATE_GWT_UI = true;{/if}
     {if $versionInfo}window.VERSION_INFO = '{$versionInfo}';{/if}
     {if $staticResourcePath != ''}window.STATIC_RESOURCE_PATH = '{$staticResourcePath}';{/if}
   </script>{\n}
diff --git a/tools/bzl/asciidoc.bzl b/tools/bzl/asciidoc.bzl
index 62fa4c6..e20624d 100644
--- a/tools/bzl/asciidoc.bzl
+++ b/tools/bzl/asciidoc.bzl
@@ -103,7 +103,7 @@
 
 _asciidoc_attrs = {
     "_exe": attr.label(
-        default = Label("//lib/asciidoctor:asciidoc"),
+        default = Label("//java/com/google/gerrit/asciidoctor:asciidoc"),
         cfg = "host",
         allow_files = True,
         executable = True,
diff --git a/tools/eclipse/BUILD b/tools/eclipse/BUILD
index 67763e2..546c75e 100644
--- a/tools/eclipse/BUILD
+++ b/tools/eclipse/BUILD
@@ -18,8 +18,8 @@
     "//gerrit-plugin-gwtui:gwtui-api-lib",
     "//java/com/google/gerrit/acceptance:lib",
     "//java/com/google/gerrit/server",
-    "//lib/asciidoctor:asciidoc_lib",
-    "//lib/asciidoctor:doc_indexer_lib",
+    "//java/com/google/gerrit/asciidoctor:asciidoc_lib",
+    "//java/com/google/gerrit/asciidoctor:doc_indexer_lib",
     "//lib/auto:auto-value",
     "//lib/gwt:ant",
     "//lib/gwt:colt",