Merge branch 'stable-2.6' into stable-2.7

* stable-2.6:
  Fix compilation failure in RefControlTest
  Verify access to source ref during add branch operation

Change-Id: I4a6c61e924baa44142ed0ade771a08bd20d09f79
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
index 56d4be3..937f843 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
@@ -28,16 +28,26 @@
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.InternalUser;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.GitReceivePackGroups;
 import com.google.gerrit.server.config.GitUploadPackGroups;
+import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
 
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -45,6 +55,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Map.Entry;
 
 import javax.annotation.Nullable;
 
@@ -53,6 +64,8 @@
   public static final int VISIBLE = 1 << 0;
   public static final int OWNER = 1 << 1;
 
+  private static final Logger log = LoggerFactory.getLogger(ProjectControl.class);
+
   public static class GenericFactory {
     private final ProjectCache projectCache;
 
@@ -117,6 +130,7 @@
   private final String canonicalWebUrl;
   private final CurrentUser user;
   private final ProjectState state;
+  private final GitRepositoryManager repoManager;
   private final PermissionCollection.Factory permissionFilter;
   private final Collection<ContributorAgreement> contributorAgreements;
 
@@ -130,8 +144,10 @@
   ProjectControl(@GitUploadPackGroups Set<AccountGroup.UUID> uploadGroups,
       @GitReceivePackGroups Set<AccountGroup.UUID> receiveGroups,
       final ProjectCache pc, final PermissionCollection.Factory permissionFilter,
+      final GitRepositoryManager repoManager,
       @CanonicalWebUrl @Nullable final String canonicalWebUrl,
       @Assisted CurrentUser who, @Assisted ProjectState ps) {
+    this.repoManager = repoManager;
     this.uploadGroups = uploadGroups;
     this.receiveGroups = receiveGroups;
     this.permissionFilter = permissionFilter;
@@ -445,4 +461,29 @@
     }
     return false;
   }
+
+  public boolean canReadCommit(RevWalk rw, RevCommit commit) {
+    NameKey projName = state.getProject().getNameKey();
+    try {
+      Repository repo = repoManager.openRepository(projName);
+      try {
+        for (Entry<String, Ref> entry : repo.getAllRefs().entrySet()) {
+          RevCommit tip = rw.parseCommit(entry.getValue().getObjectId());
+          if (rw.isMergedInto(commit, tip)
+              && controlForRef(entry.getKey()).canPerform(Permission.READ)) {
+            return true;
+          }
+        }
+      } finally {
+        repo.close();
+      }
+    } catch (IOException e) {
+      String msg =
+          String.format(
+              "Cannot verify permissions to commit object %s in repository %s",
+              commit.name(), projName.get());
+      log.error(msg, e);
+    }
+    return controlForRef("refs/*").canPerform(Permission.READ);
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index 59b7670..7c465cd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -247,8 +247,9 @@
     }
 
     if (object instanceof RevCommit) {
-      return owner || canPerform(Permission.CREATE);
-
+      return owner
+          || (canPerform(Permission.CREATE) && projectControl.canReadCommit(rw,
+              (RevCommit) object));
     } else if (object instanceof RevTag) {
       final RevTag tag = (RevTag) object;
       try {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
index f1bb7de..a64039c 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
@@ -529,7 +529,7 @@
 
     return new ProjectControl(Collections.<AccountGroup.UUID> emptySet(),
         Collections.<AccountGroup.UUID> emptySet(), projectCache,
-        sectionSorter,
+        sectionSorter, null,
         canonicalWebUrl, new MockUser(name, memberOf),
         newProjectState());
   }