Merge "CreateChange: Fix matching project check for projects with trailing slash"
diff --git a/Documentation/pg-plugin-endpoints.txt b/Documentation/pg-plugin-endpoints.txt
index 41f544d..dd82f27 100644
--- a/Documentation/pg-plugin-endpoints.txt
+++ b/Documentation/pg-plugin-endpoints.txt
@@ -132,6 +132,10 @@
=== settings-screen
This endpoint is situated at the end of the body of the settings screen.
+=== profile
+This endpoint is situated at the top of the Profile section of the settings
+screen below the section description text.
+
=== reply-text
This endpoint wraps the textarea in the reply dialog.
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index 0073ec2..df2c5cb 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -55,6 +55,7 @@
import com.google.gerrit.server.account.externalids.ExternalIdCaseSensitivityMigrator;
import com.google.gerrit.server.api.GerritApiModule;
import com.google.gerrit.server.api.PluginApiModule;
+import com.google.gerrit.server.api.projects.ProjectQueryBuilderModule;
import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.cache.h2.H2CacheModule;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
@@ -308,6 +309,7 @@
modules.add(new MimeUtil2Module());
modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
modules.add(new GerritApiModule());
+ modules.add(new ProjectQueryBuilderModule());
modules.add(new PluginApiModule());
modules.add(new SearchingChangeCacheImplModule());
modules.add(new InternalAccountDirectoryModule());
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index 75891fe..0342fe5 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -64,6 +64,7 @@
import com.google.gerrit.server.account.externalids.ExternalIdCaseSensitivityMigrator;
import com.google.gerrit.server.api.GerritApiModule;
import com.google.gerrit.server.api.PluginApiModule;
+import com.google.gerrit.server.api.projects.ProjectQueryBuilderModule;
import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.cache.h2.H2CacheModule;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
@@ -446,6 +447,7 @@
modules.add(new MimeUtil2Module());
modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
modules.add(new GerritApiModule());
+ modules.add(new ProjectQueryBuilderModule());
modules.add(new PluginApiModule());
modules.add(new SearchingChangeCacheImplModule(replica));
diff --git a/java/com/google/gerrit/server/account/AccountsUpdate.java b/java/com/google/gerrit/server/account/AccountsUpdate.java
index 8d5fea4..d6ea294 100644
--- a/java/com/google/gerrit/server/account/AccountsUpdate.java
+++ b/java/com/google/gerrit/server/account/AccountsUpdate.java
@@ -202,7 +202,6 @@
private ExternalIdNotes externalIdNotes;
@AssistedInject
- @SuppressWarnings("BindingAnnotationWithoutInject")
AccountsUpdate(
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
@@ -228,7 +227,6 @@
}
@AssistedInject
- @SuppressWarnings("BindingAnnotationWithoutInject")
AccountsUpdate(
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
diff --git a/java/com/google/gerrit/server/account/GroupCache.java b/java/com/google/gerrit/server/account/GroupCache.java
index 1e28d7d..46c730c 100644
--- a/java/com/google/gerrit/server/account/GroupCache.java
+++ b/java/com/google/gerrit/server/account/GroupCache.java
@@ -14,11 +14,15 @@
package com.google.gerrit.server.account;
+import com.google.gerrit.common.UsedAt;
+import com.google.gerrit.common.UsedAt.Project;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
+import com.google.gerrit.exceptions.StorageException;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
+import org.eclipse.jgit.lib.ObjectId;
/** Tracks group objects in memory for efficient access. */
public interface GroupCache {
@@ -62,6 +66,22 @@
Map<AccountGroup.UUID, InternalGroup> get(Collection<AccountGroup.UUID> groupUuids);
/**
+ * Returns an {@code InternalGroup} instance for the given {@code AccountGroup.UUID} at the given
+ * {@code metaId} of {@link com.google.gerrit.entities.RefNames#refsGroups} ref.
+ *
+ * <p>The caller is responsible to ensure the presence of {@code metaId} and the corresponding
+ * meta ref.
+ *
+ * @param groupUuid the UUID of the internal group
+ * @param metaId the sha1 of commit in {@link com.google.gerrit.entities.RefNames#refsGroups} ref.
+ * @return the internal group at specific sha1 {@code metaId}
+ * @throws StorageException if no internal group with this UUID exists on this server at the
+ * specific sha1, or if an error occurred during lookup.
+ */
+ @UsedAt(Project.GOOGLE)
+ InternalGroup getFromMetaId(AccountGroup.UUID groupUuid, ObjectId metaId) throws StorageException;
+
+ /**
* Removes the association of the given ID with a group.
*
* <p>The next call to {@link #get(AccountGroup.Id)} won't provide a cached value.
diff --git a/java/com/google/gerrit/server/account/GroupCacheImpl.java b/java/com/google/gerrit/server/account/GroupCacheImpl.java
index 2d947ba..6f4fce9 100644
--- a/java/com/google/gerrit/server/account/GroupCacheImpl.java
+++ b/java/com/google/gerrit/server/account/GroupCacheImpl.java
@@ -27,6 +27,7 @@
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.proto.Protos;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.proto.Cache;
@@ -122,15 +123,19 @@
private final LoadingCache<AccountGroup.Id, Optional<InternalGroup>> byId;
private final LoadingCache<String, Optional<InternalGroup>> byName;
private final LoadingCache<String, Optional<InternalGroup>> byUUID;
+ private final LoadingCache<Cache.GroupKeyProto, InternalGroup> persistedByUuidCache;
@Inject
GroupCacheImpl(
@Named(BYID_NAME) LoadingCache<AccountGroup.Id, Optional<InternalGroup>> byId,
@Named(BYNAME_NAME) LoadingCache<String, Optional<InternalGroup>> byName,
- @Named(BYUUID_NAME) LoadingCache<String, Optional<InternalGroup>> byUUID) {
+ @Named(BYUUID_NAME) LoadingCache<String, Optional<InternalGroup>> byUUID,
+ @Named(BYUUID_NAME_PERSISTED)
+ LoadingCache<Cache.GroupKeyProto, InternalGroup> persistedByUuidCache) {
this.byId = byId;
this.byName = byName;
this.byUUID = byUUID;
+ this.persistedByUuidCache = persistedByUuidCache;
}
@Override
@@ -185,6 +190,21 @@
}
@Override
+ public InternalGroup getFromMetaId(AccountGroup.UUID groupUuid, ObjectId metaId)
+ throws StorageException {
+ Cache.GroupKeyProto key =
+ Cache.GroupKeyProto.newBuilder()
+ .setUuid(groupUuid.get())
+ .setRevision(ObjectIdConverter.create().toByteString(metaId))
+ .build();
+ try {
+ return persistedByUuidCache.get(key);
+ } catch (ExecutionException e) {
+ throw new StorageException(e);
+ }
+ }
+
+ @Override
public void evict(AccountGroup.Id groupId) {
if (groupId != null) {
logger.atFine().log("Evict group %s by ID", groupId.get());
diff --git a/java/com/google/gerrit/server/api/projects/ProjectQueryBuilderModule.java b/java/com/google/gerrit/server/api/projects/ProjectQueryBuilderModule.java
new file mode 100644
index 0000000..8ed1175
--- /dev/null
+++ b/java/com/google/gerrit/server/api/projects/ProjectQueryBuilderModule.java
@@ -0,0 +1,26 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.api.projects;
+
+import com.google.gerrit.server.query.project.ProjectQueryBuilder;
+import com.google.gerrit.server.query.project.ProjectQueryBuilderImpl;
+import com.google.inject.AbstractModule;
+
+public class ProjectQueryBuilderModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(ProjectQueryBuilder.class).to(ProjectQueryBuilderImpl.class);
+ }
+}
diff --git a/java/com/google/gerrit/server/group/db/GroupsUpdate.java b/java/com/google/gerrit/server/group/db/GroupsUpdate.java
index c0c934b..87d8db1 100644
--- a/java/com/google/gerrit/server/group/db/GroupsUpdate.java
+++ b/java/com/google/gerrit/server/group/db/GroupsUpdate.java
@@ -115,7 +115,6 @@
private final RetryHelper retryHelper;
@AssistedInject
- @SuppressWarnings("BindingAnnotationWithoutInject")
GroupsUpdate(
GitRepositoryManager repoManager,
AllUsersName allUsersName,
@@ -150,7 +149,6 @@
}
@AssistedInject
- @SuppressWarnings("BindingAnnotationWithoutInject")
GroupsUpdate(
GitRepositoryManager repoManager,
AllUsersName allUsersName,
@@ -185,7 +183,6 @@
Optional.of(currentUser));
}
- @SuppressWarnings("BindingAnnotationWithoutInject")
private GroupsUpdate(
GitRepositoryManager repoManager,
AllUsersName allUsersName,
diff --git a/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index 7fdd113..6498d1b 100644
--- a/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -300,17 +300,21 @@
@Override
public Set<AccountGroup.UUID> guessRelevantGroupUUIDs() {
try (Timer0.Context ignored = guessRelevantGroupsLatency.start()) {
- return Streams.concat(
- Arrays.stream(config.getStringList("groups", /* subsection= */ null, "relevantGroup"))
- .map(AccountGroup::uuid),
- all().stream()
- .map(n -> inMemoryProjectCache.getIfPresent(n))
- .filter(Objects::nonNull)
- .flatMap(p -> p.getAllGroupUUIDs().stream())
- // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
- // against them just in case there is a bug or corner case.
- .filter(id -> id != null && id.get() != null))
- .collect(toSet());
+ Set<AccountGroup.UUID> relevantGroupUuids =
+ Streams.concat(
+ Arrays.stream(
+ config.getStringList("groups", /* subsection= */ null, "relevantGroup"))
+ .map(AccountGroup::uuid),
+ all().stream()
+ .map(n -> inMemoryProjectCache.getIfPresent(n))
+ .filter(Objects::nonNull)
+ .flatMap(p -> p.getAllGroupUUIDs().stream())
+ // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
+ // against them just in case there is a bug or corner case.
+ .filter(id -> id != null && id.get() != null))
+ .collect(toSet());
+ logger.atFine().log("relevant group UUIDs: %s", relevantGroupUuids);
+ return relevantGroupUuids;
}
}
diff --git a/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java b/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
index e31411c..d5c4a97 100644
--- a/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
@@ -159,7 +159,7 @@
return AccountPredicates.preferredEmail(email);
}
- throw new QueryParseException("'email' operator is not supported by account index version");
+ throw new QueryParseException("'email' operator is not supported on this gerrit host");
}
@Operator
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 24d205d..da75057 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -694,7 +694,8 @@
if ("mergeable".equalsIgnoreCase(value)) {
if (!args.indexMergeable) {
- throw new QueryParseException("'is:mergeable' operator is not supported by server");
+ throw new QueryParseException(
+ "'is:mergeable' operator is not supported on this gerrit host");
}
return new BooleanPredicate(ChangeField.MERGEABLE_SPEC);
}
@@ -775,7 +776,7 @@
@Operator
public Predicate<ChangeData> conflicts(String value) throws QueryParseException {
if (!args.conflictsPredicateEnabled) {
- throw new QueryParseException("'conflicts:' operator is not supported by server");
+ throw new QueryParseException("'conflicts:' operator is not supported on this gerrit host");
}
List<Change> changes = parseChange(value);
List<Predicate<ChangeData>> or = new ArrayList<>(changes.size());
@@ -1140,7 +1141,10 @@
@Operator
public Predicate<ChangeData> message(String text) throws QueryParseException {
if (text.startsWith("^")) {
- checkFieldAvailable(ChangeField.COMMIT_MESSAGE_EXACT, "messageexact");
+ if (!args.index.getSchema().hasField(ChangeField.COMMIT_MESSAGE_EXACT)) {
+ throw new QueryParseException(
+ "'message' operator with regular expression is not supported on this gerrit host");
+ }
return new RegexMessagePredicate(text);
}
return ChangePredicates.message(text);
@@ -1645,7 +1649,7 @@
throws QueryParseException {
if (!args.index.getSchema().hasField(field)) {
throw new QueryParseException(
- String.format("'%s' operator is not supported by change index version", operator));
+ String.format("'%s' operator is not supported on this gerrit host", operator));
}
}
diff --git a/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java b/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java
index d234546..edb12ec 100644
--- a/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 The Android Open Source Project
+// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,93 +14,21 @@
package com.google.gerrit.server.query.project;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.common.primitives.Ints;
-import com.google.gerrit.entities.Project;
-import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.index.project.ProjectData;
-import com.google.gerrit.index.query.LimitPredicate;
import com.google.gerrit.index.query.Predicate;
-import com.google.gerrit.index.query.QueryBuilder;
import com.google.gerrit.index.query.QueryParseException;
-import com.google.inject.Inject;
import java.util.List;
-/** Parses a query string meant to be applied to project objects. */
-public class ProjectQueryBuilder extends QueryBuilder<ProjectData, ProjectQueryBuilder> {
- public static final String FIELD_LIMIT = "limit";
+/**
+ * Provides methods required for parsing projects queries.
+ *
+ * <p>Internally (at google), this interface has a different implementation, comparing to upstream.
+ */
+public interface ProjectQueryBuilder {
+ String FIELD_LIMIT = "limit";
- private static final QueryBuilder.Definition<ProjectData, ProjectQueryBuilder> mydef =
- new QueryBuilder.Definition<>(ProjectQueryBuilder.class);
-
- @Inject
- ProjectQueryBuilder() {
- super(mydef, null);
- }
-
- @Operator
- public Predicate<ProjectData> name(String name) {
- return ProjectPredicates.name(Project.nameKey(name));
- }
-
- @Operator
- public Predicate<ProjectData> parent(String parentName) {
- return ProjectPredicates.parent(Project.nameKey(parentName));
- }
-
- @Operator
- public Predicate<ProjectData> inname(String namePart) {
- if (namePart.isEmpty()) {
- return name(namePart);
- }
- return ProjectPredicates.inname(namePart);
- }
-
- @Operator
- public Predicate<ProjectData> description(String description) throws QueryParseException {
- if (Strings.isNullOrEmpty(description)) {
- throw error("description operator requires a value");
- }
-
- return ProjectPredicates.description(description);
- }
-
- @Operator
- public Predicate<ProjectData> state(String state) throws QueryParseException {
- if (Strings.isNullOrEmpty(state)) {
- throw error("state operator requires a value");
- }
- ProjectState parsedState;
- try {
- parsedState = ProjectState.valueOf(state.replace('-', '_').toUpperCase());
- } catch (IllegalArgumentException e) {
- throw error("state operator must be either 'active' or 'read-only'", e);
- }
- if (parsedState == ProjectState.HIDDEN) {
- throw error("state operator must be either 'active' or 'read-only'");
- }
- return ProjectPredicates.state(parsedState);
- }
-
- @Override
- protected Predicate<ProjectData> defaultField(String query) throws QueryParseException {
- // Adapt the capacity of this list when adding more default predicates.
- List<Predicate<ProjectData>> preds = Lists.newArrayListWithCapacity(3);
- preds.add(name(query));
- preds.add(inname(query));
- if (!Strings.isNullOrEmpty(query)) {
- preds.add(description(query));
- }
- return Predicate.or(preds);
- }
-
- @Operator
- public Predicate<ProjectData> limit(String query) throws QueryParseException {
- Integer limit = Ints.tryParse(query);
- if (limit == null) {
- throw error("Invalid limit: " + query);
- }
- return new LimitPredicate<>(FIELD_LIMIT, limit);
- }
+ /** See {@link com.google.gerrit.index.query.QueryBuilder#parse(String)}. */
+ Predicate<ProjectData> parse(String query) throws QueryParseException;
+ /** See {@link com.google.gerrit.index.query.QueryBuilder#parse(List<String>)}. */
+ List<Predicate<ProjectData>> parse(List<String> queries) throws QueryParseException;
}
diff --git a/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java b/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java
new file mode 100644
index 0000000..f7135982
--- /dev/null
+++ b/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java
@@ -0,0 +1,105 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.query.project;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.extensions.client.ProjectState;
+import com.google.gerrit.index.project.ProjectData;
+import com.google.gerrit.index.query.LimitPredicate;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.index.query.QueryBuilder;
+import com.google.gerrit.index.query.QueryParseException;
+import com.google.inject.Inject;
+import java.util.List;
+
+/** Parses a query string meant to be applied to project objects. */
+public class ProjectQueryBuilderImpl extends QueryBuilder<ProjectData, ProjectQueryBuilderImpl>
+ implements ProjectQueryBuilder {
+ private static final QueryBuilder.Definition<ProjectData, ProjectQueryBuilderImpl> mydef =
+ new QueryBuilder.Definition<>(ProjectQueryBuilderImpl.class);
+
+ @Inject
+ ProjectQueryBuilderImpl() {
+ super(mydef, null);
+ }
+
+ @Operator
+ public Predicate<ProjectData> name(String name) {
+ return ProjectPredicates.name(Project.nameKey(name));
+ }
+
+ @Operator
+ public Predicate<ProjectData> parent(String parentName) {
+ return ProjectPredicates.parent(Project.nameKey(parentName));
+ }
+
+ @Operator
+ public Predicate<ProjectData> inname(String namePart) {
+ if (namePart.isEmpty()) {
+ return name(namePart);
+ }
+ return ProjectPredicates.inname(namePart);
+ }
+
+ @Operator
+ public Predicate<ProjectData> description(String description) throws QueryParseException {
+ if (Strings.isNullOrEmpty(description)) {
+ throw error("description operator requires a value");
+ }
+
+ return ProjectPredicates.description(description);
+ }
+
+ @Operator
+ public Predicate<ProjectData> state(String state) throws QueryParseException {
+ if (Strings.isNullOrEmpty(state)) {
+ throw error("state operator requires a value");
+ }
+ ProjectState parsedState;
+ try {
+ parsedState = ProjectState.valueOf(state.replace('-', '_').toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw error("state operator must be either 'active' or 'read-only'", e);
+ }
+ if (parsedState == ProjectState.HIDDEN) {
+ throw error("state operator must be either 'active' or 'read-only'");
+ }
+ return ProjectPredicates.state(parsedState);
+ }
+
+ @Override
+ protected Predicate<ProjectData> defaultField(String query) throws QueryParseException {
+ // Adapt the capacity of this list when adding more default predicates.
+ List<Predicate<ProjectData>> preds = Lists.newArrayListWithCapacity(3);
+ preds.add(name(query));
+ preds.add(inname(query));
+ if (!Strings.isNullOrEmpty(query)) {
+ preds.add(description(query));
+ }
+ return Predicate.or(preds);
+ }
+
+ @Operator
+ public Predicate<ProjectData> limit(String query) throws QueryParseException {
+ Integer limit = Ints.tryParse(query);
+ if (limit == null) {
+ throw error("Invalid limit: " + query);
+ }
+ return new LimitPredicate<>(FIELD_LIMIT, limit);
+ }
+}
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index aadf6d4..b828037 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -44,6 +44,7 @@
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.api.GerritApiModule;
import com.google.gerrit.server.api.PluginApiModule;
+import com.google.gerrit.server.api.projects.ProjectQueryBuilderModule;
import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.cache.h2.H2CacheModule;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
@@ -191,6 +192,7 @@
AuthConfig authConfig = cfgInjector.getInstance(AuthConfig.class);
install(new AuthModule(authConfig));
install(new GerritApiModule());
+ install(new ProjectQueryBuilderModule());
factory(PluginUser.Factory.class);
install(new PluginApiModule());
install(new DefaultPermissionBackendModule());
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index d630296..04bdf15 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -601,6 +601,20 @@
}
@Test
+ public void getGroupFromMetaId() throws Exception {
+ AccountGroup.UUID uuid = groupOperations.newGroup().create();
+ InternalGroup preUpdateState = groupCache.get(uuid).get();
+ gApi.groups().id(uuid.toString()).description("New description");
+
+ InternalGroup postUpdateState = groupCache.get(uuid).get();
+ assertThat(postUpdateState).isNotEqualTo(preUpdateState);
+ assertThat(groupCache.getFromMetaId(uuid, preUpdateState.getRefState()))
+ .isEqualTo(preUpdateState);
+ assertThat(groupCache.getFromMetaId(uuid, postUpdateState.getRefState()))
+ .isEqualTo(postUpdateState);
+ }
+
+ @Test
@GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
public void getSystemGroupByConfiguredName() throws Exception {
GroupReference anonymousUsersGroup = systemGroupBackend.getGroup(ANONYMOUS_USERS);
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 5d38c55..fbf9c87 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -4064,7 +4064,7 @@
assertThat(thrown.getCause()).isInstanceOf(QueryParseException.class);
assertThat(thrown)
.hasMessageThat()
- .contains("'is:mergeable' operator is not supported by server");
+ .contains("'is:mergeable' operator is not supported on this gerrit host");
}
protected ChangeInserter newChangeForCommit(TestRepository<Repository> repo, RevCommit commit)
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
index 1549da5..0e75abb 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
@@ -95,12 +95,26 @@
.lengthCounter {
font-weight: var(--font-weight-normal);
}
+ p {
+ max-width: 65ch;
+ margin-bottom: var(--spacing-m);
+ }
`,
];
override render() {
if (!this.account || this.loading) return nothing;
return html`<div class="gr-form-styles">
+ <p>
+ All profile fields below may be publicly displayed to others, including
+ on changes you are associated with, as well as in search and
+ autocompletion.
+ <a
+ href="https://gerrit-review.googlesource.com/Documentation/user-privacy.html"
+ >Learn more</a
+ >
+ </p>
+ <gr-endpoint-decorator name="profile"></gr-endpoint-decorator>
<section>
<span class="title"></span>
<span class="value">
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
index e968b12..f954960 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
@@ -69,6 +69,16 @@
element,
/* HTML */ `
<div class="gr-form-styles">
+ <p>
+ All profile fields below may be publicly displayed to others,
+ including on changes you are associated with, as well as in search
+ and autocompletion.
+ <a
+ href="https://gerrit-review.googlesource.com/Documentation/user-privacy.html"
+ >Learn more</a
+ >
+ </p>
+ <gr-endpoint-decorator name="profile"></gr-endpoint-decorator>
<section>
<span class="title"></span>
<span class="value">
@@ -134,7 +144,8 @@
</span>
</section>
</div>
- `
+ `,
+ {ignoreChildren: ['p']}
);
});
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.ts b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.ts
index 1460246..f8ae38c 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.ts
@@ -553,7 +553,7 @@
assert.deepEqual(indentCommand.args[0], ['insertText', false, '\n ']);
});
- test('emoji dropdown is closed when iron-overlay-closed is fired', async () => {
+ test('emoji dropdown is closed when dropdown-closed is fired', async () => {
const resetSpy = sinon.spy(element, 'closeDropdown');
element.emojiSuggestions!.dispatchEvent(
new CustomEvent('dropdown-closed', {