Special case hiding refs/meta/config from Git clients
VisibleRefFilter requires a lot of server CPU to accurately provide
the correct listing to clients when they cannot read refs/*.
Since the default configuration is now to hide refs/meta/config,
use a special case in VisibleRefFilter that permits showing every
reference except refs/meta/config if a user can read every other
reference in the repository.
Change-Id: Iba12ee5ea1babcfeb71d378139ce2fcfb121b949
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
index fc47f10..cb88f1e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.git;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
@@ -60,6 +62,13 @@
}
public Map<String, Ref> filter(Map<String, Ref> refs, boolean filterTagsSeperately) {
+ if (projectCtl.allRefsAreVisibleExcept(
+ ImmutableSet.of(GitRepositoryManager.REF_CONFIG))) {
+ Map<String, Ref> r = Maps.newHashMap(refs);
+ r.remove(GitRepositoryManager.REF_CONFIG);
+ return r;
+ }
+
final Set<Change.Id> visibleChanges = visibleChanges();
final Map<String, Ref> result = new HashMap<String, Ref>();
final List<Ref> deferredTags = new ArrayList<Ref>();
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 67d91d5..513f1b1 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
@@ -38,6 +38,7 @@
import com.google.inject.assistedinject.Assisted;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -196,8 +197,12 @@
/** Can this user see all the refs in this projects? */
public boolean allRefsAreVisible() {
+ return allRefsAreVisibleExcept(Collections.<String> emptySet());
+ }
+
+ public boolean allRefsAreVisibleExcept(Set<String> except) {
return user instanceof InternalUser
- || canPerformOnAllRefs(Permission.READ);
+ || canPerformOnAllRefs(Permission.READ, except);
}
/** Is this user a project owner? Ownership does not imply {@link #isVisible()} */
@@ -347,7 +352,7 @@
return false;
}
- private boolean canPerformOnAllRefs(String permission) {
+ private boolean canPerformOnAllRefs(String permission, Set<String> except) {
boolean canPerform = false;
Set<String> patterns = allRefPatterns(permission);
if (patterns.contains(AccessSection.ALL)) {
@@ -358,6 +363,8 @@
for (final String pattern : patterns) {
if (controlForRef(pattern).canPerform(permission)) {
canPerform = true;
+ } else if (except.contains(pattern)) {
+ continue;
} else {
return false;
}