Migrate submit requirements to `stable-3.6`
The following changes were applied:
* code was adjusted to the API changes
* submit requirements feature flag was removed - it is no longer
experimental
* switched to batch-ref-update event handling for keys invalidation
in PathOwnersEntriesCache
Bug: Issue 15556
Change-Id: I4643bc826500d6d2dfa83a1bba7429bd118c4d93
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java
index c2ec085..69584ab 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwnersEntriesCache.java
@@ -17,7 +17,7 @@
import com.google.common.cache.RemovalNotification;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.CacheRemovalListener;
@@ -38,7 +38,7 @@
protected void configure() {
cache(CACHE_NAME, Key.class, PathOwnersEntry.class);
bind(PathOwnersEntriesCache.class).to(PathOwnersEntriesCacheImpl.class);
- DynamicSet.bind(binder(), GitReferenceUpdatedListener.class)
+ DynamicSet.bind(binder(), GitBatchRefUpdateListener.class)
.to(OwnersRefUpdateListener.class);
DynamicSet.bind(binder(), CacheRemovalListener.class).to(OwnersCacheRemovalListener.class);
}
@@ -103,7 +103,7 @@
}
@Singleton
- class OwnersRefUpdateListener implements GitReferenceUpdatedListener {
+ class OwnersRefUpdateListener implements GitBatchRefUpdateListener {
private final PathOwnersEntriesCache cache;
private final String allUsersName;
@@ -114,16 +114,17 @@
}
@Override
- public void onGitReferenceUpdated(Event event) {
- if (supportedEvent(allUsersName, event)) {
- cache.invalidate(event.getProjectName(), event.getRefName());
+ public void onGitBatchRefUpdate(GitBatchRefUpdateListener.Event event) {
+ String projectName = event.getProjectName();
+ if (!allUsersName.equals(projectName)) {
+ event.getUpdatedRefs().stream()
+ .filter(refUpdate -> supportedEvent(refUpdate.getRefName()))
+ .forEach(refUpdate -> cache.invalidate(projectName, refUpdate.getRefName()));
}
}
- static boolean supportedEvent(String allUsersName, Event event) {
- String refName = event.getRefName();
- return !allUsersName.equals(event.getProjectName())
- && (refName.equals(RefNames.REFS_CONFIG) || !RefNames.isGerritRef(refName));
+ private boolean supportedEvent(String refName) {
+ return (refName.equals(RefNames.REFS_CONFIG) || !RefNames.isGerritRef(refName));
}
}
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersBatchRefUpdateListenerTest.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersBatchRefUpdateListenerTest.java
new file mode 100644
index 0000000..fe99ad3
--- /dev/null
+++ b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersBatchRefUpdateListenerTest.java
@@ -0,0 +1,99 @@
+// 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.googlesource.gerrit.owners.common;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
+import com.google.gerrit.server.config.AllProjectsNameProvider;
+import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.AllUsersNameProvider;
+import com.googlesource.gerrit.owners.common.PathOwnersEntriesCache.OwnersRefUpdateListener;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class OwnersBatchRefUpdateListenerTest {
+ @Parameterized.Parameters
+ public static Collection<Object[]> events() {
+ return Arrays.asList(
+ new Object[][] {
+ {mockEvent(ALL_USERS_NAME.get(), RefNames.REFS_CONFIG), 0},
+ {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_CHANGES), 0},
+ {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_SEQUENCES), 0},
+ {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_CONFIG), 1},
+ {
+ mockEvent(
+ AllProjectsNameProvider.DEFAULT, RefNames.REFS_CONFIG, RefNames.REFS_SEQUENCES),
+ 1
+ },
+ {mockEvent("foo", RefNames.fullName("bar")), 1},
+ {mockEvent("foo", RefNames.REFS_CONFIG), 1},
+ {mockEvent("foo", RefNames.REFS_CONFIG, RefNames.fullName("bar")), 2}
+ });
+ }
+
+ private static AllUsersName ALL_USERS_NAME = new AllUsersName(AllUsersNameProvider.DEFAULT);
+
+ private final GitBatchRefUpdateListener.Event input;
+ private final int expectedTimes;
+
+ public OwnersBatchRefUpdateListenerTest(
+ GitBatchRefUpdateListener.Event input, int expectedTimes) {
+ this.input = input;
+ this.expectedTimes = expectedTimes;
+ }
+
+ @Test
+ public void shouldTriggerCacheInvalidationAccordingly() {
+ // given
+ PathOwnersEntriesCache cachMock = mock(PathOwnersEntriesCache.class);
+ OwnersRefUpdateListener listener = new OwnersRefUpdateListener(cachMock, ALL_USERS_NAME);
+
+ // when
+ listener.onGitBatchRefUpdate(input);
+
+ // then
+ verify(cachMock, times(expectedTimes)).invalidate(anyString(), anyString());
+ }
+
+ private static GitBatchRefUpdateListener.Event mockEvent(String project, String... refs) {
+ GitBatchRefUpdateListener.Event eventMock = mock(GitBatchRefUpdateListener.Event.class);
+ when(eventMock.getProjectName()).thenReturn(project);
+ Set<GitBatchRefUpdateListener.UpdatedRef> updatedRefs =
+ Stream.of(refs)
+ .map(
+ ref -> {
+ GitBatchRefUpdateListener.UpdatedRef updatedRef =
+ mock(GitBatchRefUpdateListener.UpdatedRef.class);
+ when(updatedRef.getRefName()).thenReturn(ref);
+ return updatedRef;
+ })
+ .collect(Collectors.toSet());
+ when(eventMock.getUpdatedRefs()).thenReturn(updatedRefs);
+ return eventMock;
+ }
+}
diff --git a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersRefUpdateListenerTest.java b/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersRefUpdateListenerTest.java
deleted file mode 100644
index fa20c79..0000000
--- a/owners-common/src/test/java/com/googlesource/gerrit/owners/common/OwnersRefUpdateListenerTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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.googlesource.gerrit.owners.common;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import com.google.gerrit.entities.RefNames;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
-import com.google.gerrit.server.config.AllProjectsNameProvider;
-import com.google.gerrit.server.config.AllUsersNameProvider;
-import com.googlesource.gerrit.owners.common.PathOwnersEntriesCache.OwnersRefUpdateListener;
-import java.util.Arrays;
-import java.util.Collection;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-public class OwnersRefUpdateListenerTest {
- @Parameterized.Parameters
- public static Collection<Object[]> events() {
- return Arrays.asList(
- new Object[][] {
- {mockEvent(ALL_USERS_NAME, null), false},
- {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_CHANGES), false},
- {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_SEQUENCES), false},
- {mockEvent(AllProjectsNameProvider.DEFAULT, RefNames.REFS_CONFIG), true},
- {mockEvent("foo", RefNames.fullName("bar")), true},
- {mockEvent("foo", RefNames.REFS_CONFIG), true}
- });
- }
-
- private static String ALL_USERS_NAME = AllUsersNameProvider.DEFAULT;
-
- private final GitReferenceUpdatedListener.Event input;
- private final boolean expected;
-
- public OwnersRefUpdateListenerTest(GitReferenceUpdatedListener.Event input, boolean expected) {
- this.input = input;
- this.expected = expected;
- }
-
- @Test
- public void shouldParseLabelDefinition() {
- // when
- boolean result = OwnersRefUpdateListener.supportedEvent(ALL_USERS_NAME, input);
-
- // then
- assertThat(result).isEqualTo(expected);
- }
-
- private static GitReferenceUpdatedListener.Event mockEvent(String project, String ref) {
- GitReferenceUpdatedListener.Event eventMock = mock(GitReferenceUpdatedListener.Event.class);
- when(eventMock.getProjectName()).thenReturn(project);
- when(eventMock.getRefName()).thenReturn(ref);
- return eventMock;
- }
-}
diff --git a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersSubmitRequirement.java b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersSubmitRequirement.java
index 97d8098..f26ae71 100644
--- a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersSubmitRequirement.java
+++ b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersSubmitRequirement.java
@@ -37,6 +37,7 @@
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffOperations;
+import com.google.gerrit.server.patch.DiffOptions;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
@@ -348,7 +349,8 @@
// For merge commits the default base is the auto-merge commit which should be used as base IOW
// only the changes from it should be reviewed as changes against the parent 1 were already
// reviewed
- return diffOperations.listModifiedFilesAgainstParent(project, revision, 0);
+ return diffOperations.listModifiedFilesAgainstParent(
+ project, revision, 0, DiffOptions.DEFAULTS);
}
private static SubmitRecord notReady(String ownersLabel, String missingApprovals) {
diff --git a/owners/src/test/java/com/googlesource/gerrit/owners/OwnersApprovalHasOperandIT.java b/owners/src/test/java/com/googlesource/gerrit/owners/OwnersApprovalHasOperandIT.java
index 667227c..9a65c45 100644
--- a/owners/src/test/java/com/googlesource/gerrit/owners/OwnersApprovalHasOperandIT.java
+++ b/owners/src/test/java/com/googlesource/gerrit/owners/OwnersApprovalHasOperandIT.java
@@ -30,30 +30,14 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.SubmitRequirementResultInfo;
import com.google.gerrit.extensions.common.SubmitRequirementResultInfo.Status;
-import com.google.gerrit.server.experiments.ExperimentFeaturesConstants;
-import com.google.gerrit.testing.ConfigSuite;
import com.googlesource.gerrit.owners.common.LabelDefinition;
import java.util.Collection;
-import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;
public class OwnersApprovalHasOperandIT extends OwnersSubmitRequirementIT {
private static final String REQUIREMENT_NAME = "Owner-Approval";
- // This configuration is needed on 3.5 only and should be removed during/after the merge to
- // stable-3.6 as it is enabled there by default.
- @ConfigSuite.Default
- public static Config defaultConfig() {
- Config cfg = new Config();
- cfg.setString(
- "experiments",
- null,
- "enabled",
- ExperimentFeaturesConstants.GERRIT_BACKEND_REQUEST_FEATURE_ENABLE_SUBMIT_REQUIREMENTS);
- return cfg;
- }
-
@Before
public void setup() throws Exception {
configSubmitRequirement(
diff --git a/owners/src/test/java/com/googlesource/gerrit/owners/OwnersSubmitRequirementTest.java b/owners/src/test/java/com/googlesource/gerrit/owners/OwnersSubmitRequirementTest.java
index 97113c0..bd6c232 100644
--- a/owners/src/test/java/com/googlesource/gerrit/owners/OwnersSubmitRequirementTest.java
+++ b/owners/src/test/java/com/googlesource/gerrit/owners/OwnersSubmitRequirementTest.java
@@ -38,7 +38,6 @@
import com.google.gerrit.entities.Project;
import com.googlesource.gerrit.owners.OwnersSubmitRequirement.LabelAndScore;
import com.googlesource.gerrit.owners.common.LabelDefinition;
-import java.sql.Timestamp;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
@@ -456,7 +455,7 @@
private static final PatchSetApproval approvedBy(Account.Id approving, String label, int value) {
return PatchSetApproval.builder()
.key(PatchSetApproval.key(mock(PatchSet.Id.class), approving, LabelId.create(label)))
- .granted(Timestamp.from(Instant.now()))
+ .granted(Instant.now())
.realAccountId(approving)
.value(value)
.build();