Merge "Allow deletion of open and abandoned changes"
diff --git a/.bazelrc b/.bazelrc
index 00acd27..a991c76 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1 +1 @@
-build --strategy=Javac=worker
+build --workspace_status_command=./tools/workspace-status.sh --strategy=Javac=worker
diff --git a/BUILD b/BUILD
index 1373cd7..7ec32be 100644
--- a/BUILD
+++ b/BUILD
@@ -1,11 +1,11 @@
-load('//tools/bzl:genrule2.bzl', 'genrule2')
 load('//tools/bzl:pkg_war.bzl', 'pkg_war')
 
-genrule2(
-  name = 'version',
-  srcs = ['VERSION'],
-  cmd = "grep GERRIT_VERSION $< | cut -d \"'\" -f 2 >$@",
-  out = 'version.txt',
+genrule(
+  name = 'gen_version',
+  stamp = 1,
+  cmd = ("cat bazel-out/volatile-status.txt bazel-out/stable-status.txt | " +
+    "grep STABLE_BUILD_GERRIT_LABEL | cut -d ' ' -f 2 > $@"),
+  outs = ['version.txt'],
   visibility = ['//visibility:public'],
 )
 
diff --git a/WORKSPACE b/WORKSPACE
index 2ef3235..f01ad3f 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -223,8 +223,8 @@
 
 maven_jar(
   name = 'guava',
-  artifact = 'com.google.guava:guava:19.0',
-  sha1 = '6ce200f6b23222af3d8abb6b6459e6c44f4bb0e9',
+  artifact = 'com.google.guava:guava:20.0-rc1',
+  sha1 = '4c2a4581b69b16a57968da32fcadb8e362b639b2',
 )
 
 maven_jar(
@@ -235,8 +235,8 @@
 
 maven_jar(
   name = 'jsch',
-  artifact = 'com.jcraft:jsch:0.1.53',
-  sha1 = '658b682d5c817b27ae795637dfec047c63d29935',
+  artifact = 'com.jcraft:jsch:0.1.54',
+  sha1 = 'da3584329a263616e277e15462b387addd1b208d',
 )
 
 maven_jar(
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/TestAccount.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/TestAccount.java
index c1a815a..63e0fa7 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/TestAccount.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/TestAccount.java
@@ -14,7 +14,8 @@
 
 package com.google.gerrit.acceptance;
 
-import com.google.common.collect.FluentIterable;
+import static java.util.stream.Collectors.toList;
+
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.mail.Address;
 
@@ -24,22 +25,22 @@
 
 import java.io.ByteArrayOutputStream;
 import java.util.Arrays;
+import java.util.List;
 
 public class TestAccount {
-  public static FluentIterable<Account.Id> ids(
-      Iterable<TestAccount> accounts) {
-    return FluentIterable.from(accounts).transform(a -> a.id);
+  public static List<Account.Id> ids(List<TestAccount> accounts) {
+    return accounts.stream().map(a -> a.id).collect(toList());
   }
 
-  public static FluentIterable<Account.Id> ids(TestAccount... accounts) {
+  public static List<Account.Id> ids(TestAccount... accounts) {
     return ids(Arrays.asList(accounts));
   }
 
-  public static FluentIterable<String> names(Iterable<TestAccount> accounts) {
-    return FluentIterable.from(accounts).transform(a -> a.fullName);
+  public static List<String> names(List<TestAccount> accounts) {
+    return accounts.stream().map(a -> a.fullName).collect(toList());
   }
 
-  public static FluentIterable<String> names(TestAccount... accounts) {
+  public static List<String> names(TestAccount... accounts) {
     return names(Arrays.asList(accounts));
   }
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 78c0cda..620b9ea 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -17,10 +17,9 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.acceptance.api.group.GroupAssert.assertGroupInfo;
 import static com.google.gerrit.acceptance.rest.account.AccountAssert.assertAccountInfos;
+import static java.util.stream.Collectors.toList;
 
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterables;
-import com.google.common.collect.Ordering;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.TestAccount;
@@ -46,9 +45,12 @@
 
 import java.sql.Timestamp;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.StreamSupport;
 
 @NoHttpd
 public class GroupsIT extends AbstractDaemonTest {
@@ -397,10 +399,12 @@
 
   @Test
   public void testListAllGroups() throws Exception {
-    List<String> expectedGroups = FluentIterable
-          .from(groupCache.all())
-          .transform(AccountGroup::getName)
-          .toSortedList(Ordering.natural());
+    List<String> expectedGroups =
+        StreamSupport.stream(groupCache.all().spliterator(), false)
+          .map(a -> a.getName())
+          .collect(toList());
+    Collections.sort(expectedGroups, Comparator.naturalOrder());
+
     assertThat(expectedGroups.size()).isAtLeast(2);
     assertThat(gApi.groups().list().getAsMap().keySet())
         .containsExactlyElementsIn(expectedGroups).inOrder();
@@ -504,7 +508,7 @@
       throws Exception {
     assertMembers(
         gApi.groups().id(group).members(),
-        TestAccount.names(expectedMembers).toArray(String.class));
+        TestAccount.names(expectedMembers).stream().toArray(String[]::new));
     assertAccountInfos(
         Arrays.asList(expectedMembers),
         gApi.groups().id(group).members());
diff --git a/gerrit-gwtui-common/BUCK b/gerrit-gwtui-common/BUCK
index d4d97a6..729b7e7 100644
--- a/gerrit-gwtui-common/BUCK
+++ b/gerrit-gwtui-common/BUCK
@@ -8,7 +8,6 @@
 ]
 DEPS = ['//lib/gwt:user']
 SRC = 'src/main/java/com/google/gerrit/'
-DIFFY = glob(['src/main/resources/com/google/gerrit/client/diffy*.png'])
 
 gwt_module(
   name = 'client',
@@ -36,9 +35,9 @@
   visibility = ['PUBLIC'],
 )
 
-prebuilt_jar(
+java_library(
   name = 'diffy_logo',
-  binary_jar = ':diffy_image_files_ln',
+  resources = glob(['src/main/resources/com/google/gerrit/client/diffy*.png']),
   deps = [
     '//lib:LICENSE-diffy',
     '//lib:LICENSE-CC-BY3.0-unported',
@@ -46,17 +45,6 @@
   visibility = ['PUBLIC'],
 )
 
-genrule(
-  name = 'diffy_image_files_ln',
-  cmd = 'ln -s $(location :diffy_image_files) $OUT',
-  out = 'diffy_images.jar',
-)
-
-java_library(
-  name = 'diffy_image_files',
-  resources = DIFFY,
-)
-
 java_test(
   name = 'client_tests',
   srcs = glob(['src/test/java/**/*.java']),
diff --git a/gerrit-gwtui-common/BUILD b/gerrit-gwtui-common/BUILD
index 4bd2dfd..c13dbd2 100644
--- a/gerrit-gwtui-common/BUILD
+++ b/gerrit-gwtui-common/BUILD
@@ -13,7 +13,6 @@
 ]
 DEPS = ['//lib/gwt:user']
 SRC = 'src/main/java/com/google/gerrit/'
-DIFFY = glob(['src/main/resources/com/google/gerrit/client/diffy*.png'])
 
 gwt_module(
   name = 'client',
@@ -38,26 +37,14 @@
   visibility = ['//visibility:public'],
 )
 
-java_import(
+java_library(
   name = 'diffy_logo',
-  jars = [':diffy_image_files_ln'],
-  visibility = ['//visibility:public'],
+  resources = glob(['src/main/resources/com/google/gerrit/client/diffy*.png']),
   data = [
     '//lib:LICENSE-diffy',
     '//lib:LICENSE-CC-BY3.0-unported',
   ],
-)
-
-genrule2(
-  name = 'diffy_image_files_ln',
-  srcs = [':diffy_image_files'],
-  cmd = 'ln -s $$ROOT/$(location :diffy_image_files) $@',
-  out = 'diffy_images.jar',
-)
-
-java_library(
-  name = 'diffy_image_files',
-  resources = DIFFY,
+  visibility = ['//visibility:public'],
 )
 
 junit_tests(
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index f8f6baa..80adbb9 100644
--- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -399,7 +399,7 @@
         close();
         throw new OrmRuntimeException(e);
       } catch (ExecutionException e) {
-        Throwables.propagateIfPossible(e.getCause());
+        Throwables.throwIfUnchecked(e.getCause());
         throw new OrmRuntimeException(e.getCause());
       }
     }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java
index eec700a..7d6dc32 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java
@@ -29,7 +29,7 @@
 import com.google.gerrit.pgm.init.api.Section;
 import com.google.gerrit.pgm.init.api.Section.Factory;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.mail.send.OutgoingEmail;
+import com.google.gerrit.server.mail.EmailModule;
 import com.google.inject.Binding;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -156,7 +156,7 @@
 
   private void extractMailExample(String orig) throws Exception {
     Path ex = site.mail_dir.resolve(orig + ".example");
-    extract(ex, OutgoingEmail.class, orig);
+    extract(ex, EmailModule.class, orig);
     chmod(0444, ex);
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountLoader.java
index f84d399..89e9419 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountLoader.java
@@ -94,7 +94,7 @@
       directory.fillAccountInfo(
           Iterables.concat(created.values(), provided), options);
     } catch (DirectoryException e) {
-      Throwables.propagateIfPossible(e.getCause(), OrmException.class);
+      Throwables.throwIfInstanceOf(e.getCause(), OrmException.class);
       throw new OrmException(e);
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetDetail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetDetail.java
index 81c860e..e47ceb3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetDetail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetDetail.java
@@ -47,7 +47,7 @@
       directory.fillAccountInfo(Collections.singleton(info),
           EnumSet.allOf(FillOptions.class));
     } catch (DirectoryException e) {
-      Throwables.propagateIfPossible(e.getCause(), OrmException.class);
+      Throwables.throwIfInstanceOf(e.getCause(), OrmException.class);
       throw new OrmException(e);
     }
     return info;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
index 3567811..354dc62 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
@@ -154,8 +154,8 @@
           }
         });
     } catch (PrivilegedActionException e) {
-      Throwables.propagateIfPossible(e.getException(), NamingException.class);
-      Throwables.propagateIfPossible(e.getException(), RuntimeException.class);
+      Throwables.throwIfInstanceOf(e.getException(), NamingException.class);
+      Throwables.throwIfInstanceOf(e.getException(), RuntimeException.class);
       LdapRealm.log.warn("Internal error", e.getException());
       return null;
     } finally {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
index 6ea7eef..0d64e1c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
@@ -299,7 +299,7 @@
     } catch (PatchListNotAvailableException | GpgException | OrmException
         | IOException | RuntimeException e) {
       if (!has(CHECK)) {
-        Throwables.propagateIfPossible(e, OrmException.class);
+        Throwables.throwIfInstanceOf(e, OrmException.class);
         throw new OrmException(e);
       }
       return checkOnly(cd);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java
index 8a41ebc..61f6557 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java
@@ -490,7 +490,7 @@
       throw new ResourceNotFoundException(e.getMessage(), e);
 
     } catch (Exception e) {
-      Throwables.propagateIfPossible(e);
+      Throwables.throwIfUnchecked(e);
       throw new UpdateException(e);
     }
   }
@@ -693,7 +693,7 @@
         logDebug("No objects to flush");
       }
     } catch (Exception e) {
-      Throwables.propagateIfPossible(e, RestApiException.class);
+      Throwables.throwIfInstanceOf(e, RestApiException.class);
       throw new UpdateException(e);
     }
   }
@@ -778,8 +778,8 @@
         }
         success = true;
       } catch (ExecutionException | InterruptedException e) {
-        Throwables.propagateIfInstanceOf(e.getCause(), UpdateException.class);
-        Throwables.propagateIfInstanceOf(e.getCause(), RestApiException.class);
+        Throwables.throwIfInstanceOf(e.getCause(), UpdateException.class);
+        Throwables.throwIfInstanceOf(e.getCause(), RestApiException.class);
         throw new UpdateException(e);
       } catch (OrmException | IOException e) {
         throw new UpdateException(e);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
index 071e12c..e4a6f7c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
@@ -83,7 +83,8 @@
         .withStopStrategy(StopStrategies.stopAfterDelay(30, TimeUnit.SECONDS));
   }
 
-  private static Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();
+  private static final Retryer<RefUpdate.Result> RETRYER =
+      retryerBuilder().build();
 
   private final GitRepositoryManager repoManager;
   private final Project.NameKey projectName;
@@ -197,7 +198,9 @@
       limit = counter + count;
       acquireCount++;
     } catch (ExecutionException | RetryException e) {
-      Throwables.propagateIfInstanceOf(e.getCause(), OrmException.class);
+      if (e.getCause() != null) {
+        Throwables.throwIfInstanceOf(e.getCause(), OrmException.class);
+      }
       throw new OrmException(e);
     } catch (IOException e) {
       throw new OrmException(e);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
index dd15cfc..ae37c01 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
@@ -93,7 +93,7 @@
     } catch (ExecutionException e) {
       // If there was an error computing the result, carry it
       // up to the caller so the cache knows this key is invalid.
-      Throwables.propagateIfInstanceOf(e.getCause(), Exception.class);
+      Throwables.throwIfInstanceOf(e.getCause(), Exception.class);
       throw new Exception(e.getMessage(), e.getCause());
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
index 9616fc8..e1829bc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -279,7 +279,7 @@
     } catch (ExecutionException e) {
       // If there was an error computing the result, carry it
       // up to the caller so the cache knows this key is invalid.
-      Throwables.propagateIfInstanceOf(e.getCause(), IOException.class);
+      Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
       throw new IOException(e.getMessage(), e.getCause());
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index 6f85a28..41b8721 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -150,7 +150,7 @@
     } catch (ExecutionException e) {
       if (!(e.getCause() instanceof RepositoryNotFoundException)) {
         log.warn(String.format("Cannot read project %s", projectName.get()), e);
-        Throwables.propagateIfInstanceOf(e.getCause(), IOException.class);
+        Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
         throw new IOException(e);
       }
       return null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPattern.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPattern.java
index ed50a54..8c850fb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPattern.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefPattern.java
@@ -49,7 +49,7 @@
       try {
         return exampleCache.get(refPattern);
       } catch (ExecutionException e) {
-        Throwables.propagateIfPossible(e.getCause());
+        Throwables.throwIfUnchecked(e.getCause());
         throw new RuntimeException(e);
       }
     } else if (refPattern.endsWith("/*")) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/AndSource.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/AndSource.java
index 9f0bf89..4acd2ba 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/AndSource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/AndSource.java
@@ -83,7 +83,9 @@
     try {
       return readImpl();
     } catch (OrmRuntimeException err) {
-      Throwables.propagateIfInstanceOf(err.getCause(), OrmException.class);
+      if (err.getCause() != null) {
+        Throwables.throwIfInstanceOf(err.getCause(), OrmException.class);
+      }
       throw new OrmException(err);
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryProcessor.java
index ae88887..a0f66db 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryProcessor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryProcessor.java
@@ -136,7 +136,9 @@
     } catch (OrmRuntimeException e) {
       throw new OrmException(e.getMessage(), e);
     } catch (OrmException e) {
-      Throwables.propagateIfInstanceOf(e.getCause(), QueryParseException.class);
+      if (e.getCause() != null) {
+        Throwables.throwIfInstanceOf(e.getCause(), QueryParseException.class);
+      }
       throw e;
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java
index 13142fa..ac69ecf 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java
@@ -130,7 +130,7 @@
           try {
             wrapped.call();
           } catch (Exception e) {
-            Throwables.propagateIfPossible(e);
+            Throwables.throwIfUnchecked(e);
             throw new RuntimeException(e); // Not possible.
           }
         }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index dcf0a40..5686dc3 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -15,9 +15,9 @@
 package com.google.gerrit.server.query.account;
 
 import static com.google.common.truth.Truth.assertThat;
+import static java.util.stream.Collectors.toList;
 import static org.junit.Assert.fail;
 
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.extensions.api.GerritApi;
 import com.google.gerrit.extensions.api.accounts.Accounts.QueryRequest;
@@ -478,7 +478,7 @@
     return ids(Arrays.asList(accounts));
   }
 
-  protected static Iterable<Integer> ids(Iterable<AccountInfo> accounts) {
-    return FluentIterable.from(accounts).transform(a -> a._accountId);
+  protected static Iterable<Integer> ids(List<AccountInfo> accounts) {
+    return accounts.stream().map(a -> a._accountId).collect(toList());
   }
 }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java
index fde3a66..4ddca0c 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java
@@ -97,7 +97,7 @@
       try {
         cmd.destroy();
       } catch (Exception e) {
-        Throwables.propagateIfPossible(e);
+        Throwables.throwIfUnchecked(e);
         throw new RuntimeException(e);
       }
     }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java
index f2911dc..f3243c6 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java
@@ -136,7 +136,7 @@
       try {
         cmd.destroy();
       } catch (Exception e) {
-        Throwables.propagateIfPossible(e);
+        Throwables.throwIfUnchecked(e);
         throw new RuntimeException(e);
       }
     }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
index 24bd8c2..c88a02c 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
@@ -153,7 +153,7 @@
       try {
         cmd.destroy();
       } catch (Exception e) {
-        Throwables.propagateIfPossible(e);
+        Throwables.throwIfUnchecked(e);
         throw new RuntimeException(e);
       }
     }
diff --git a/gerrit-war/BUILD b/gerrit-war/BUILD
index 3604e88..9262ad4 100644
--- a/gerrit-war/BUILD
+++ b/gerrit-war/BUILD
@@ -63,9 +63,9 @@
   cmd = ' && '.join([
     'cd $$TMP',
     'mkdir -p com/google/gerrit/common',
-    'cat $$ROOT/$(location //:version) >com/google/gerrit/common/Version',
+    'cat $$ROOT/$(location //:version.txt) >com/google/gerrit/common/Version',
     'zip -9Dqr $$ROOT/$@ .',
   ]),
-  tools = ['//:version'],
+  tools = ['//:version.txt'],
   out = 'gen_version.jar',
 )
diff --git a/lib/BUCK b/lib/BUCK
index 5ec54f7..e17bd89 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -70,7 +70,7 @@
 maven_jar(
   name = 'guava',
   id = 'com.google.guava:guava:' + GUAVA_VERSION,
-  sha1 = '6ce200f6b23222af3d8abb6b6459e6c44f4bb0e9',
+  sha1 = '4c2a4581b69b16a57968da32fcadb8e362b639b2',
   license = 'Apache2.0',
 )
 
@@ -113,8 +113,8 @@
 
 maven_jar(
   name = 'jsch',
-  id = 'com.jcraft:jsch:0.1.53',
-  sha1 = '658b682d5c817b27ae795637dfec047c63d29935',
+  id = 'com.jcraft:jsch:0.1.54',
+  sha1 = 'da3584329a263616e277e15462b387addd1b208d',
   license = 'jsch',
 )
 
diff --git a/lib/GUAVA_VERSION b/lib/GUAVA_VERSION
index f889e2b..2bfe0be 100644
--- a/lib/GUAVA_VERSION
+++ b/lib/GUAVA_VERSION
@@ -1,2 +1,2 @@
-GUAVA_VERSION = '19.0'
+GUAVA_VERSION = '20.0-rc1'
 GUAVA_DOC_URL = 'https://google.github.io/guava/releases/' + GUAVA_VERSION + '/api/docs/'
diff --git a/plugins/replication b/plugins/replication
index bc37211..3212bcd 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit bc37211df3cc7b7516974142d78232197c49ce29
+Subproject commit 3212bcd4f2c0dc791a99af97ee98df70746f2306
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 362a42b..580dcd4 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -17,16 +17,13 @@
   name = "gr-app",
   app = 'elements/gr-app.html',
   srcs = glob(
-  ['**'],
+  ['**/*.html', '**/*.js'],
   exclude = [
-    '**/BUCK',
-    '**/BUILD',
-    '*~',
-    '#*',
+    'bower_components/**',
     'index.html',
     'test/**',
     '**/*_test.html',
-    "polygerrit_wct_tests.py"]),
+    ]),
   deps = [ "//polygerrit-ui:polygerrit_components"],
 )
 
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
index be6d1c6..007c0fc 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
@@ -138,7 +138,6 @@
         box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
         display: block;
         margin: .25em 0 1em;
-        overflow: auto;
       }
       @media screen and (max-width: 50em) {
         .row[selected] {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index f995b22..7ae5c34 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -31,26 +31,17 @@
     <style>
       :host {
         background-color: var(--view-background-color);
-        display: flex;
-        flex-direction: column;
-        height: 100%;
+        display: block;
       }
-      .titleHeader,
-      .patchRangeHeader {
+      header,
+      .subHeader {
         align-items: center;
         display: flex;
         justify-content: space-between;
       }
-      .titleHeader {
+      header {
         padding: .75em var(--default-horizontal-margin);
       }
-      .patchRangeHeader {
-        margin: 0 var(--default-horizontal-margin) .75em;
-      }
-      #diff {
-        flex: 1;
-        overflow: auto;
-      }
       .navLink:not([href]) {
         color: #999;
       }
@@ -115,6 +106,9 @@
         padding: 0 var(--default-horizontal-margin) 1em;
         color: #666;
       }
+      .subHeader {
+        margin: 0 var(--default-horizontal-margin) .75em;
+      }
       .prefsButton {
         text-align: right;
       }
@@ -141,61 +135,59 @@
       }
     </style>
     <header>
-      <div class="titleHeader">
-        <h3>
-          <a href$="[[_computeChangePath(_changeNum, _patchRange.*, _change.revisions)]]">
-            [[_changeNum]]</a><span>:</span>
-          <span>[[_change.subject]]</span>
-          <span class="dash">—</span>
-          <input
-              id="reviewed"
-              class="reviewed"
-              type="checkbox"
-              on-change="_handleReviewedChange"
-              hidden$="[[!_loggedIn]]"
-              hidden>
-          <div class="jumpToFileContainer">
-            <gr-button link class="dropdown-trigger" id="trigger" on-tap="_showDropdownTapHandler">
-              <span>[[_computeFileDisplayName(_path)]]</span>
-              <span class="downArrow">&#9660;</span>
-            </gr-button>
-            <iron-dropdown id="dropdown" vertical-align="top" vertical-offset="25">
-              <div class="dropdown-content">
-                <template
-                    is="dom-repeat"
-                    items="[[_fileList]]"
-                    as="path"
-                    initial-count="75">
-                  <a href$="[[_computeDiffURL(_changeNum, _patchRange.*, path)]]"
-                     selected$="[[_computeFileSelected(path, _path)]]"
-                     data-key-nav$="[[_computeKeyNav(path, _path, _fileList)]]"
-                     on-tap="_handleFileTap">[[_computeFileDisplayName(path)]]</a>
-                </template>
-              </div>
-            </iron-dropdown>
-          </div>
-          <div class="mobileJumpToFileContainer">
-            <select on-change="_handleMobileSelectChange">
-              <template is="dom-repeat" items="[[_fileList]]" as="path">
-                <option
-                    value$="[[path]]"
-                    selected$="[[_computeFileSelected(path, _path)]]">
-                  [[_computeTruncatedFileDisplayName(path)]]
-                </option>
+      <h3>
+        <a href$="[[_computeChangePath(_changeNum, _patchRange.*, _change.revisions)]]">
+          [[_changeNum]]</a><span>:</span>
+        <span>[[_change.subject]]</span>
+        <span class="dash">—</span>
+        <input id="reviewed"
+            class="reviewed"
+            type="checkbox"
+            on-change="_handleReviewedChange"
+            hidden$="[[!_loggedIn]]" hidden>
+        <div class="jumpToFileContainer">
+          <gr-button link class="dropdown-trigger" id="trigger" on-tap="_showDropdownTapHandler">
+            <span>[[_computeFileDisplayName(_path)]]</span>
+            <span class="downArrow">&#9660;</span>
+          </gr-button>
+          <iron-dropdown id="dropdown" vertical-align="top" vertical-offset="25">
+            <div class="dropdown-content">
+              <template
+                  is="dom-repeat"
+                  items="[[_fileList]]"
+                  as="path"
+                  initial-count="75">
+                <a href$="[[_computeDiffURL(_changeNum, _patchRange.*, path)]]"
+                   selected$="[[_computeFileSelected(path, _path)]]"
+                   data-key-nav$="[[_computeKeyNav(path, _path, _fileList)]]"
+                   on-tap="_handleFileTap">[[_computeFileDisplayName(path)]]</a>
               </template>
-            </select>
-          </div>
-        </h3>
-        <div>
-          <a class="navLink"
-             href$="[[_computeNavLinkURL(_path, _fileList, -1, 1)]]">Prev</a>
-          /
-          <a class="navLink"
-             href$="[[_computeNavLinkURL(_path, _fileList, 1, 1)]]">Next</a>
+            </div>
+          </iron-dropdown>
         </div>
+        <div class="mobileJumpToFileContainer">
+          <select on-change="_handleMobileSelectChange">
+            <template is="dom-repeat" items="[[_fileList]]" as="path">
+              <option
+                  value$="[[path]]"
+                  selected$="[[_computeFileSelected(path, _path)]]">
+                [[_computeTruncatedFileDisplayName(path)]]
+              </option>
+            </template>
+          </select>
+        </div>
+      </h3>
+      <div>
+        <a class="navLink"
+            href$="[[_computeNavLinkURL(_path, _fileList, -1, 1)]]">Prev</a>
+        /
+        <a class="navLink"
+            href$="[[_computeNavLinkURL(_path, _fileList, 1, 1)]]">Next</a>
       </div>
-      <div class="loading" hidden$="[[!_loading]]">Loading...</div>
-      <div class="patchRangeHeader" hidden hidden$="[[_loading]]">
+    </header>
+    <div class="loading" hidden$="[[!_loading]]">Loading...</div>
+    <div hidden$="[[_loading]]" hidden>
+      <div class="subHeader">
         <gr-patch-range-select
             path="[[_path]]"
             change-num="[[_changeNum]]"
@@ -216,38 +208,35 @@
           <span hidden$="[[_computePrefsButtonHidden(_prefs, _loggedIn)]]">
             <span
                 hidden$="[[_computeModeSelectHidden(_isImageDiff)]]">/</span>
-            <gr-button
-                link
+            <gr-button link
                 class="prefsButton"
                 on-tap="_handlePrefsTap">Preferences</gr-button>
           </span>
         </div>
-        <gr-overlay id="prefsOverlay" with-backdrop>
-          <gr-diff-preferences
-              id="diffPreferences"
-              prefs="{{_prefs}}"
-              local-prefs="{{_localPrefs}}"
-              on-save="_handlePrefsSave"
-              on-cancel="_handlePrefsCancel"></gr-diff-preferences>
-        </gr-overlay>
       </div>
-    </header>
-    <gr-diff
-        id="diff"
-        hidden
-        hidden$="[[_loading]]"
-        project="[[_change.project]]"
-        commit="[[_change.current_revision]]"
-        is-image-diff="{{_isImageDiff}}"
-        files-weblinks="{{_filesWeblinks}}"
-        change-num="[[_changeNum]]"
-        patch-range="[[_patchRange]]"
-        path="[[_path]]"
-        prefs="[[_prefs]]"
-        project-config="[[_projectConfig]]"
-        view-mode="[[_diffMode]]"
-        on-line-selected="_onLineSelected">
-    </gr-diff>
+      <gr-overlay id="prefsOverlay" with-backdrop>
+        <gr-diff-preferences
+            id="diffPreferences"
+            prefs="{{_prefs}}"
+            local-prefs="{{_localPrefs}}"
+            on-save="_handlePrefsSave"
+            on-cancel="_handlePrefsCancel"></gr-diff-preferences>
+      </gr-overlay>
+      <gr-diff
+          id="diff"
+          project="[[_change.project]]"
+          commit="[[_change.current_revision]]"
+          is-image-diff="{{_isImageDiff}}"
+          files-weblinks="{{_filesWeblinks}}"
+          change-num="[[_changeNum]]"
+          patch-range="[[_patchRange]]"
+          path="[[_path]]"
+          prefs="[[_prefs]]"
+          project-config="[[_projectConfig]]"
+          view-mode="[[_diffMode]]"
+          on-line-selected="_onLineSelected">
+      </gr-diff>
+    </div>
     <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
     <gr-storage id="storage"></gr-storage>
     <gr-diff-cursor id="cursor"></gr-diff-cursor>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index a4dff00..14c2bb5 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -44,6 +44,7 @@
         border-top: 1px solid #eee;
         display: flex;
         font: 12px var(--monospace-font-family);
+        overflow-x: auto;
         will-change: transform;
       }
       table {
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index acee383..a403e6c 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -41,8 +41,8 @@
     <style>
       :host {
         display: flex;
+        min-height: 100vh;
         flex-direction: column;
-        height: 100vh;
       }
       gr-main-header,
       footer {
@@ -58,7 +58,6 @@
       main {
         flex: 1;
         position: relative;
-        overflow: scroll;
       }
       .errorView {
         align-items: center;
diff --git a/tools/bzl/asciidoc.bzl b/tools/bzl/asciidoc.bzl
index db6ea86..326e51f0 100644
--- a/tools/bzl/asciidoc.bzl
+++ b/tools/bzl/asciidoc.bzl
@@ -260,7 +260,8 @@
   tmpdir = ctx.outputs.out.path + "_tmpdir"
   cmd = [
     "p=$PWD",
-    "mkdir -p %s" % tmpdir,
+    "rm -rf %s" % tmpdir,
+    "mkdir %s" % tmpdir,
     "unzip -q %s -d %s/%s/" % (ctx.file.src.path, tmpdir, ctx.attr.directory),
   ]
   for r in ctx.files.resources:
diff --git a/tools/bzl/javadoc.bzl b/tools/bzl/javadoc.bzl
index c9ff05d..dcaa611 100644
--- a/tools/bzl/javadoc.bzl
+++ b/tools/bzl/javadoc.bzl
@@ -26,9 +26,12 @@
   transitive_jar_paths = [j.path for j in transitive_jar_set]
   dir = ctx.outputs.zip.path + ".dir"
   source = ctx.outputs.zip.path + ".source"
+  external_docs = ["http://docs.oracle.com/javase/8/docs/api"] + ctx.attr.external_docs
   cmd = [
+      "rm -rf %s" % source,
       "mkdir %s" % source,
       " && ".join(["unzip -qud %s %s" % (source, j.path) for j in source_jars]),
+      "rm -rf %s" % dir,
       "mkdir %s" % dir,
       " ".join([
         ctx.file._javadoc.path,
@@ -39,7 +42,7 @@
         "-notimestamp",
         "-quiet",
         "-windowtitle '%s'" % ctx.attr.title,
-        "-link", "http://docs.oracle.com/javase/8/docs/api",
+        " ".join(['-link %s' % url for url in external_docs]),
         "-sourcepath %s" % source,
         "-subpackages ",
         ":".join(ctx.attr.pkgs),
@@ -59,6 +62,7 @@
       "libs": attr.label_list(allow_files = False),
       "pkgs": attr.string_list(),
       "title": attr.string(),
+      "external_docs": attr.string_list(),
       "_javadoc": attr.label(
         default = Label("@local_jdk//:bin/javadoc"),
         single_file = True,
diff --git a/tools/workspace-status.sh b/tools/workspace-status.sh
new file mode 100755
index 0000000..506330c
--- /dev/null
+++ b/tools/workspace-status.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# This script will be run by bazel when the build process starts to
+# generate key-value information that represents the status of the
+# workspace. The output should be like
+#
+# KEY1 VALUE1
+# KEY2 VALUE2
+#
+# If the script exits with non-zero code, it's considered as a failure
+# and the output will be discarded.
+
+git_rev=$(git describe --always --match "v[0-9].*" --dirty)
+
+echo "STABLE_BUILD_GERRIT_LABEL ${git_rev}"