Merge "Extract logic from GetRelated to another class"
diff --git a/java/com/google/gerrit/server/restapi/change/GetRelated.java b/java/com/google/gerrit/server/restapi/change/GetRelated.java
index ba1a1dc..57291e8e 100644
--- a/java/com/google/gerrit/server/restapi/change/GetRelated.java
+++ b/java/com/google/gerrit/server/restapi/change/GetRelated.java
@@ -14,10 +14,6 @@
package com.google.gerrit.server.restapi.change;
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.stream.Collectors.toSet;
-
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
@@ -29,56 +25,37 @@
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CommonConverters;
-import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.change.RevisionResource;
-import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.revwalk.RevCommit;
@Singleton
public class GetRelated implements RestReadView<RevisionResource> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- private final Provider<InternalChangeQuery> queryProvider;
- private final PatchSetUtil psUtil;
- private final RelatedChangesSorter sorter;
- private final IndexConfig indexConfig;
private final ChangeData.Factory changeDataFactory;
+ private final GetRelatedUtil getRelatedUtil;
@Inject
- GetRelated(
- Provider<InternalChangeQuery> queryProvider,
- PatchSetUtil psUtil,
- RelatedChangesSorter sorter,
- IndexConfig indexConfig,
- ChangeData.Factory changeDataFactory) {
- this.queryProvider = queryProvider;
- this.psUtil = psUtil;
- this.sorter = sorter;
- this.indexConfig = indexConfig;
+ GetRelated(ChangeData.Factory changeDataFactory, GetRelatedUtil getRelatedUtil) {
this.changeDataFactory = changeDataFactory;
+ this.getRelatedUtil = getRelatedUtil;
}
@Override
public Response<RelatedChangesInfo> apply(RevisionResource rsrc)
- throws RepositoryNotFoundException, IOException, NoSuchProjectException,
- PermissionBackendException {
+ throws IOException, NoSuchProjectException, PermissionBackendException {
RelatedChangesInfo relatedChangesInfo = new RelatedChangesInfo();
relatedChangesInfo.changes = getRelated(rsrc);
return Response.ok(relatedChangesInfo);
@@ -86,30 +63,15 @@
public List<RelatedChangeAndCommitInfo> getRelated(RevisionResource rsrc)
throws IOException, PermissionBackendException {
- Set<String> groups = getAllGroups(rsrc.getNotes(), psUtil);
- logger.atFine().log("groups = %s", groups);
- if (groups.isEmpty()) {
- return Collections.emptyList();
- }
-
- List<ChangeData> cds =
- InternalChangeQuery.byProjectGroups(
- queryProvider, indexConfig, rsrc.getChange().getProject(), groups);
- if (cds.isEmpty()) {
- return Collections.emptyList();
- }
- if (cds.size() == 1 && cds.get(0).getId().equals(rsrc.getChange().getId())) {
- return Collections.emptyList();
- }
- List<RelatedChangeAndCommitInfo> result = new ArrayList<>(cds.size());
-
boolean isEdit = rsrc.getEdit().isPresent();
PatchSet basePs = isEdit ? rsrc.getEdit().get().getBasePatchSet() : rsrc.getPatchSet();
logger.atFine().log("isEdit = %s, basePs = %s", isEdit, basePs);
- cds = reloadChangeIfStale(cds, rsrc.getChange(), basePs);
+ List<RelatedChangesSorter.PatchSetData> sortedResult =
+ getRelatedUtil.getRelated(changeDataFactory.create(rsrc.getNotes()), basePs);
- for (RelatedChangesSorter.PatchSetData d : sorter.sort(cds, basePs)) {
+ List<RelatedChangeAndCommitInfo> result = new ArrayList<>(sortedResult.size());
+ for (RelatedChangesSorter.PatchSetData d : sortedResult) {
PatchSet ps = d.patchSet();
RevCommit commit;
if (isEdit && ps.id().equals(basePs.id())) {
@@ -134,37 +96,6 @@
return result;
}
- @VisibleForTesting
- public static Set<String> getAllGroups(ChangeNotes notes, PatchSetUtil psUtil) {
- return psUtil.byChange(notes).stream().flatMap(ps -> ps.groups().stream()).collect(toSet());
- }
-
- private List<ChangeData> reloadChangeIfStale(
- List<ChangeData> changeDatasFromIndex, Change wantedChange, PatchSet wantedPs) {
- checkArgument(
- wantedChange.getId().equals(wantedPs.id().changeId()),
- "change of wantedPs (%s) doesn't match wantedChange (%s)",
- wantedPs.id().changeId(),
- wantedChange.getId());
-
- List<ChangeData> changeDatas = new ArrayList<>(changeDatasFromIndex.size() + 1);
- changeDatas.addAll(changeDatasFromIndex);
-
- // Reload the change in case the patch set is absent.
- changeDatas.stream()
- .filter(
- cd -> cd.getId().equals(wantedPs.id().changeId()) && cd.patchSet(wantedPs.id()) == null)
- .forEach(ChangeData::reloadChange);
-
- if (changeDatas.stream().noneMatch(cd -> cd.getId().equals(wantedPs.id().changeId()))) {
- // The change of the wanted patch set is missing in the result from the index.
- // Load it from NoteDb and add it to the result.
- changeDatas.add(changeDataFactory.create(wantedChange));
- }
-
- return changeDatas;
- }
-
static RelatedChangeAndCommitInfo newChangeAndCommit(
Project.NameKey project, @Nullable Change change, @Nullable PatchSet ps, RevCommit c) {
RelatedChangeAndCommitInfo info = new RelatedChangeAndCommitInfo();
diff --git a/java/com/google/gerrit/server/restapi/change/GetRelatedUtil.java b/java/com/google/gerrit/server/restapi/change/GetRelatedUtil.java
new file mode 100644
index 0000000..c08e3ed
--- /dev/null
+++ b/java/com/google/gerrit/server/restapi/change/GetRelatedUtil.java
@@ -0,0 +1,119 @@
+// Copyright (C) 2021 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.restapi.change;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.stream.Collectors.toSet;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.PatchSet;
+import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/** Utility class that gets the ancestor changes and the descendent changes of a specific change. */
+@Singleton
+public class GetRelatedUtil {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private final Provider<InternalChangeQuery> queryProvider;
+ private final RelatedChangesSorter sorter;
+ private final IndexConfig indexConfig;
+ private final ChangeData.Factory changeDataFactory;
+
+ @Inject
+ GetRelatedUtil(
+ Provider<InternalChangeQuery> queryProvider,
+ RelatedChangesSorter sorter,
+ IndexConfig indexConfig,
+ ChangeData.Factory changeDataFactory) {
+ this.queryProvider = queryProvider;
+ this.sorter = sorter;
+ this.indexConfig = indexConfig;
+ this.changeDataFactory = changeDataFactory;
+ }
+
+ /**
+ * Gets related changes of a specific change revision.
+ *
+ * @param changeData the change of the inputted revision.
+ * @param basePs the revision that the method checks for related changes.
+ * @return list of related changes, sorted via {@link RelatedChangesSorter}
+ */
+ public List<RelatedChangesSorter.PatchSetData> getRelated(ChangeData changeData, PatchSet basePs)
+ throws IOException, PermissionBackendException {
+ Set<String> groups = getAllGroups(changeData.patchSets());
+ logger.atFine().log("groups = %s", groups);
+ if (groups.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List<ChangeData> cds =
+ InternalChangeQuery.byProjectGroups(
+ queryProvider, indexConfig, changeData.project(), groups);
+ if (cds.isEmpty()) {
+ return Collections.emptyList();
+ }
+ if (cds.size() == 1 && cds.get(0).getId().equals(changeData.getId())) {
+ return Collections.emptyList();
+ }
+
+ cds = reloadChangeIfStale(cds, changeData, basePs);
+
+ return sorter.sort(cds, basePs);
+ }
+
+ private List<ChangeData> reloadChangeIfStale(
+ List<ChangeData> changeDatasFromIndex, ChangeData wantedChange, PatchSet wantedPs) {
+ checkArgument(
+ wantedChange.getId().equals(wantedPs.id().changeId()),
+ "change of wantedPs (%s) doesn't match wantedChange (%s)",
+ wantedPs.id().changeId(),
+ wantedChange.getId());
+
+ List<ChangeData> changeDatas = new ArrayList<>(changeDatasFromIndex.size() + 1);
+ changeDatas.addAll(changeDatasFromIndex);
+
+ // Reload the change in case the patch set is absent.
+ changeDatas.stream()
+ .filter(
+ cd -> cd.getId().equals(wantedPs.id().changeId()) && cd.patchSet(wantedPs.id()) == null)
+ .forEach(ChangeData::reloadChange);
+
+ if (changeDatas.stream().noneMatch(cd -> cd.getId().equals(wantedPs.id().changeId()))) {
+ // The change of the wanted patch set is missing in the result from the index.
+ // Load it from NoteDb and add it to the result.
+ changeDatas.add(changeDataFactory.create(wantedChange.change()));
+ }
+
+ return changeDatas;
+ }
+
+ @VisibleForTesting
+ public static Set<String> getAllGroups(Collection<PatchSet> patchSets) {
+ return patchSets.stream().flatMap(ps -> ps.groups().stream()).collect(toSet());
+ }
+}
diff --git a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index 74dfa04..b605594 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -47,7 +47,7 @@
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.restapi.change.ChangesCollection;
-import com.google.gerrit.server.restapi.change.GetRelated;
+import com.google.gerrit.server.restapi.change.GetRelatedUtil;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -573,7 +573,7 @@
ChangeData cd = getChange(last);
assertThat(cd.patchSets()).hasSize(n);
- assertThat(GetRelated.getAllGroups(cd.notes(), psUtil)).hasSize(n);
+ assertThat(GetRelatedUtil.getAllGroups(cd.notes().getPatchSets().values())).hasSize(n);
assertRelated(cd.change().currentPatchSetId());
}