Merge "ListBranchesIT: Make assertions on received refs more strict" into stable-2.16
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index b19e295..1b7637d 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3093,6 +3093,19 @@
   groupMemberPattern = (&(objectClass=group)(member=${dn}))
 ----
 
+[[ldap.guessRelevantGroups]]ldap.guessRelevantGroups::
++
+Filter the groups found in LDAP by guessing the ones relevant to
+Gerrit and removing the others from list completions and ACL evaluations.
+The guess is based on two elements: the projects most recently
+accessed in the cache and the list of LDAP groups included in their ACLs.
++
+Please note that projects rarely used and thus not cached may be
+temporarily inaccessible by users even with LDAP membership and grants
+referenced in the ACLs.
++
+By default, true.
+
 [[ldap.server]]ldap.server::
 +
 URL of the organization's LDAP server to query for user information
diff --git a/WORKSPACE b/WORKSPACE
index 3f21e02..bd7b95c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -48,8 +48,8 @@
 # Golang support for PolyGerrit local dev server.
 http_archive(
     name = "io_bazel_rules_go",
-    sha256 = "97cf62bdef33519412167fd1e4b0810a318a7c234f5f8dc4f53e2da86241c492",
-    urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.15.3/rules_go-0.15.3.tar.gz"],
+    sha256 = "ee5fe78fe417c685ecb77a0a725dc9f6040ae5beb44a0ba4ddb55453aad23a8a",
+    url = "https://github.com/bazelbuild/rules_go/releases/download/0.16.0/rules_go-0.16.0.tar.gz",
 )
 
 load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
diff --git a/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java b/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java
index c338cd3..87a4abf 100644
--- a/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java
+++ b/java/com/google/gerrit/server/auth/ldap/LdapGroupBackend.java
@@ -34,6 +34,7 @@
 import com.google.gerrit.server.account.GroupMembership;
 import com.google.gerrit.server.account.externalids.ExternalId;
 import com.google.gerrit.server.auth.ldap.Helper.LdapSchema;
+import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.inject.Inject;
@@ -52,6 +53,7 @@
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 import javax.security.auth.login.LoginException;
+import org.eclipse.jgit.lib.Config;
 
 /** Implementation of GroupBackend for the LDAP group system. */
 public class LdapGroupBackend implements GroupBackend {
@@ -65,6 +67,7 @@
   private final LoadingCache<String, Boolean> existsCache;
   private final ProjectCache projectCache;
   private final Provider<CurrentUser> userProvider;
+  private final Config gerritConfig;
 
   @Inject
   LdapGroupBackend(
@@ -72,12 +75,14 @@
       @Named(GROUP_CACHE) LoadingCache<String, Set<AccountGroup.UUID>> membershipCache,
       @Named(GROUP_EXIST_CACHE) LoadingCache<String, Boolean> existsCache,
       ProjectCache projectCache,
-      Provider<CurrentUser> userProvider) {
+      Provider<CurrentUser> userProvider,
+      @GerritServerConfig Config gerritConfig) {
     this.helper = helper;
     this.membershipCache = membershipCache;
     this.projectCache = projectCache;
     this.existsCache = existsCache;
     this.userProvider = userProvider;
+    this.gerritConfig = gerritConfig;
   }
 
   private boolean isLdapUUID(AccountGroup.UUID uuid) {
@@ -178,7 +183,7 @@
     if (id == null) {
       return GroupMembership.EMPTY;
     }
-    return new LdapGroupMembership(membershipCache, projectCache, id);
+    return new LdapGroupMembership(membershipCache, projectCache, id, gerritConfig);
   }
 
   private static String findId(Collection<ExternalId> extIds) {
diff --git a/java/com/google/gerrit/server/auth/ldap/LdapGroupMembership.java b/java/com/google/gerrit/server/auth/ldap/LdapGroupMembership.java
index 7f0bd7b..f5406c2 100644
--- a/java/com/google/gerrit/server/auth/ldap/LdapGroupMembership.java
+++ b/java/com/google/gerrit/server/auth/ldap/LdapGroupMembership.java
@@ -22,20 +22,24 @@
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
+import org.eclipse.jgit.lib.Config;
 
 class LdapGroupMembership implements GroupMembership {
   private final LoadingCache<String, Set<AccountGroup.UUID>> membershipCache;
   private final ProjectCache projectCache;
   private final String id;
+  private final boolean guessRelevantGroups;
   private GroupMembership membership;
 
   LdapGroupMembership(
       LoadingCache<String, Set<AccountGroup.UUID>> membershipCache,
       ProjectCache projectCache,
-      String id) {
+      String id,
+      Config gerritConfig) {
     this.membershipCache = membershipCache;
     this.projectCache = projectCache;
     this.id = id;
+    this.guessRelevantGroups = gerritConfig.getBoolean("ldap", "guessRelevantGroups", true);
   }
 
   @Override
@@ -56,7 +60,9 @@
   @Override
   public Set<AccountGroup.UUID> getKnownGroups() {
     Set<AccountGroup.UUID> g = new HashSet<>(get().getKnownGroups());
-    g.retainAll(projectCache.guessRelevantGroupUUIDs());
+    if (guessRelevantGroups) {
+      g.retainAll(projectCache.guessRelevantGroupUUIDs());
+    }
     return g;
   }
 
diff --git a/java/com/google/gerrit/server/query/change/HashtagPredicate.java b/java/com/google/gerrit/server/query/change/HashtagPredicate.java
index bea5688..95ecf89 100644
--- a/java/com/google/gerrit/server/query/change/HashtagPredicate.java
+++ b/java/com/google/gerrit/server/query/change/HashtagPredicate.java
@@ -20,7 +20,9 @@
 
 public class HashtagPredicate extends ChangeIndexPredicate {
   public HashtagPredicate(String hashtag) {
-    super(ChangeField.HASHTAG, HashtagsUtil.cleanupHashtag(hashtag));
+    // Use toLowerCase without locale to match behavior in ChangeField.
+    // TODO(dborowitz): Change both.
+    super(ChangeField.HASHTAG, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase());
   }
 
   @Override
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 8d57946..7cf148d 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -1597,7 +1597,7 @@
     in.add = ImmutableSet.of("foo");
     gApi.changes().id(change1.getId().get()).setHashtags(in);
 
-    in.add = ImmutableSet.of("foo", "bar", "a tag");
+    in.add = ImmutableSet.of("foo", "bar", "a tag", "ACamelCaseTag");
     gApi.changes().id(change2.getId().get()).setHashtags(in);
 
     return ImmutableList.of(change1, change2);
@@ -1614,6 +1614,8 @@
     assertQuery("hashtag:\" a tag \"", changes.get(1));
     assertQuery("hashtag:\"#a tag\"", changes.get(1));
     assertQuery("hashtag:\"# #a tag\"", changes.get(1));
+    assertQuery("hashtag:acamelcasetag", changes.get(1));
+    assertQuery("hashtag:ACamelCaseTAg", changes.get(1));
   }
 
   @Test
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index f9e22f4..ec5b604 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -44,6 +44,9 @@
       <name>Edwin Kempin</name>
     </developer>
     <developer>
+      <name>Han-Wen Nienhuys</name>
+    </developer>
+    <developer>
       <name>Hugo Arès</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index 04f8bb3..6f3058f 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -44,6 +44,9 @@
       <name>Edwin Kempin</name>
     </developer>
     <developer>
+      <name>Han-Wen Nienhuys</name>
+    </developer>
+    <developer>
       <name>Hugo Arès</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index 4bb20dc..ef5ee8f 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -44,6 +44,9 @@
       <name>Edwin Kempin</name>
     </developer>
     <developer>
+      <name>Han-Wen Nienhuys</name>
+    </developer>
+    <developer>
       <name>Hugo Arès</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-plugin-gwtui_pom.xml b/tools/maven/gerrit-plugin-gwtui_pom.xml
index 1008b74..7bad711 100644
--- a/tools/maven/gerrit-plugin-gwtui_pom.xml
+++ b/tools/maven/gerrit-plugin-gwtui_pom.xml
@@ -44,6 +44,9 @@
       <name>Edwin Kempin</name>
     </developer>
     <developer>
+      <name>Han-Wen Nienhuys</name>
+    </developer>
+    <developer>
       <name>Hugo Arès</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index f90d3ac..4eecff5 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -44,6 +44,9 @@
       <name>Edwin Kempin</name>
     </developer>
     <developer>
+      <name>Han-Wen Nienhuys</name>
+    </developer>
+    <developer>
       <name>Hugo Arès</name>
     </developer>
     <developer>