Merge "Support load from ASSETS_PATH for plugins if provided"
diff --git a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
index 7038736..7767fe2 100644
--- a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
@@ -310,7 +310,8 @@
 
     allRefsWatcher = new AllRefsWatcher();
     receivePack.setAdvertiseRefsHook(
-        ReceiveCommitsAdvertiseRefsHookChain.create(allRefsWatcher, queryProvider, projectName));
+        ReceiveCommitsAdvertiseRefsHookChain.create(
+            allRefsWatcher, queryProvider, projectName, user.getAccountId()));
     resultChangeIds = new ResultChangeIds();
     receiveCommits =
         factory.create(
diff --git a/java/com/google/gerrit/server/git/receive/BUILD b/java/com/google/gerrit/server/git/receive/BUILD
index 2b04d4d..7402a37 100644
--- a/java/com/google/gerrit/server/git/receive/BUILD
+++ b/java/com/google/gerrit/server/git/receive/BUILD
@@ -15,6 +15,7 @@
         "//java/com/google/gerrit/exceptions",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/git",
+        "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/metrics",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/server/logging",
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java
index 83bf554..6c1f097 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java
@@ -18,14 +18,19 @@
 
 import com.google.common.collect.Sets;
 import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.exceptions.StorageException;
+import com.google.gerrit.index.query.Predicate;
 import com.google.gerrit.server.git.HookUtil;
 import com.google.gerrit.server.index.change.ChangeField;
 import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.ChangeStatusPredicate;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gerrit.server.query.change.OwnerPredicate;
+import com.google.gerrit.server.query.change.ProjectPredicate;
 import com.google.gerrit.server.util.MagicBranch;
 import com.google.inject.Provider;
 import java.io.IOException;
@@ -65,11 +70,13 @@
 
   private final Provider<InternalChangeQuery> queryProvider;
   private final Project.NameKey projectName;
+  private final Account.Id user;
 
   public ReceiveCommitsAdvertiseRefsHook(
-      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName) {
+      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName, Account.Id user) {
     this.queryProvider = queryProvider;
     this.projectName = projectName;
+    this.user = user;
   }
 
   @Override
@@ -90,7 +97,9 @@
 
   private Set<ObjectId> advertiseOpenChanges(Repository repo)
       throws ServiceMayNotContinueException {
-    // Advertise some recent open changes, in case a commit is based on one.
+    // Advertise the user's most recent open changes. It's likely that the user has one of these in
+    // their local repo and they can serve as starting points to figure out the common ancestor of
+    // what the client and server have in common.
     int limit = 32;
     try {
       Set<ObjectId> r = Sets.newHashSetWithExpectedSize(limit);
@@ -105,7 +114,11 @@
                   ChangeField.PATCH_SET)
               .enforceVisibility(true)
               .setLimit(limit)
-              .byProjectOpen(projectName)) {
+              .query(
+                  Predicate.and(
+                      new ProjectPredicate(projectName.get()),
+                      ChangeStatusPredicate.open(),
+                      new OwnerPredicate(user)))) {
         PatchSet ps = cd.currentPatchSet();
         if (ps != null) {
           // Ensure we actually observed a patch set ref pointing to this
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java
index 76f6b04..fae1401 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.git.receive;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
 import com.google.inject.Provider;
@@ -35,8 +36,9 @@
   public static AdvertiseRefsHook create(
       AllRefsWatcher allRefsWatcher,
       Provider<InternalChangeQuery> queryProvider,
-      Project.NameKey projectName) {
-    return create(allRefsWatcher, queryProvider, projectName, false);
+      Project.NameKey projectName,
+      Account.Id user) {
+    return create(allRefsWatcher, queryProvider, projectName, user, false);
   }
 
   /**
@@ -47,18 +49,19 @@
    */
   @VisibleForTesting
   public static AdvertiseRefsHook createForTest(
-      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName) {
-    return create(new AllRefsWatcher(), queryProvider, projectName, true);
+      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName, Account.Id user) {
+    return create(new AllRefsWatcher(), queryProvider, projectName, user, true);
   }
 
   private static AdvertiseRefsHook create(
       AllRefsWatcher allRefsWatcher,
       Provider<InternalChangeQuery> queryProvider,
       Project.NameKey projectName,
+      Account.Id user,
       boolean skipHackPushNegotiateHook) {
     List<AdvertiseRefsHook> advHooks = new ArrayList<>();
     advHooks.add(allRefsWatcher);
-    advHooks.add(new ReceiveCommitsAdvertiseRefsHook(queryProvider, projectName));
+    advHooks.add(new ReceiveCommitsAdvertiseRefsHook(queryProvider, projectName, user));
     if (!skipHackPushNegotiateHook) {
       advHooks.add(new HackPushNegotiateHook());
     }
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index c6beac4..78ca0fc 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -598,7 +598,11 @@
       committer = c.getCommitterIdent();
       parentCount = c.getParentCount();
     } catch (IOException e) {
-      throw new StorageException(e);
+      throw new StorageException(
+          String.format(
+              "Loading commit %s for ps %d of change %d failed.",
+              ps.commitId(), ps.id().get(), ps.id().changeId().get()),
+          e);
     }
     return true;
   }
diff --git a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index f0312de..d1d197b 100644
--- a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -1446,7 +1446,7 @@
   private TestRefAdvertiser.Result getReceivePackRefs() throws Exception {
     try (Repository repo = repoManager.openRepository(project)) {
       AdvertiseRefsHook adv =
-          ReceiveCommitsAdvertiseRefsHookChain.createForTest(queryProvider, project);
+          ReceiveCommitsAdvertiseRefsHookChain.createForTest(queryProvider, project, admin.id());
       ReceivePack rp = new ReceivePack(repo);
       rp.setAdvertiseRefsHook(adv);
       TestRefAdvertiser advertiser = new TestRefAdvertiser(repo);