diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java index 2af3c25a15..9aa4b345d9 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java @@ -49,8 +49,10 @@ public class SubmitByFastForwardIT extends AbstractSubmit { PushOneCommit.Result change = createChange(); PushOneCommit.Result change2 = createChange(); - approve(change.getChangeId()); - submit(change2.getChangeId()); + String id1 = change.getChangeId(); + String id2 = change2.getChangeId(); + approve(id1); + submit(id2); RevCommit head = getRemoteHead(); assertThat(head.getId()).isEqualTo(change2.getCommitId()); @@ -59,6 +61,8 @@ public class SubmitByFastForwardIT extends AbstractSubmit { assertSubmitter(change2.getChangeId(), 1); assertPersonEquals(admin.getIdent(), head.getAuthorIdent()); assertPersonEquals(admin.getIdent(), head.getCommitterIdent()); + assertSubmittedTogether(id1, id1, id2); + assertSubmittedTogether(id2, id1, id2); } @Test diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java index ae1a608f81..9612f71736 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java @@ -228,11 +228,9 @@ public class RelatedChanges extends TabPanel { new TabChangeListCallback(Tab.SAME_TOPIC, info.project(), revision)); } else { // TODO(sbeller): show only on latest revision - if (info.status().isOpen()) { - ChangeApi.change(info.legacyId().get()).view("submitted_together") - .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER, - info.project(), revision)); - } + ChangeApi.change(info.legacyId().get()).view("submitted_together") + .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER, + info.project(), revision)); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/SubmittedTogether.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/SubmittedTogether.java index a4f9fef0e2..dec56a7937 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/SubmittedTogether.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/SubmittedTogether.java @@ -14,15 +14,20 @@ package com.google.gerrit.server.change; +import com.google.common.collect.Lists; +import com.google.gerrit.extensions.client.ChangeStatus; import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.RestReadView; +import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.git.ChangeSet; import com.google.gerrit.server.git.MergeSuperSet; +import com.google.gerrit.server.query.change.ChangeData; +import com.google.gerrit.server.query.change.InternalChangeQuery; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; @@ -43,14 +48,17 @@ public class SubmittedTogether implements RestReadView { private final ChangeJson.Factory json; private final Provider dbProvider; + private final Provider queryProvider; private final MergeSuperSet mergeSuperSet; @Inject SubmittedTogether(ChangeJson.Factory json, Provider dbProvider, + Provider queryProvider, MergeSuperSet mergeSuperSet) { this.json = json; this.dbProvider = dbProvider; + this.queryProvider = queryProvider; this.mergeSuperSet = mergeSuperSet; } @@ -59,16 +67,32 @@ public class SubmittedTogether implements RestReadView { throws AuthException, BadRequestException, ResourceConflictException, Exception { try { - ChangeSet cs = mergeSuperSet.completeChangeSet(dbProvider.get(), - resource.getChange()); - if (cs.size() > 1) { - return json.create(EnumSet.of( - ListChangesOption.CURRENT_REVISION, - ListChangesOption.CURRENT_COMMIT)) - .format(cs.ids()); + Change c = resource.getChange(); + List ids; + if (c.getStatus().isOpen()) { + ChangeSet cs = mergeSuperSet.completeChangeSet(dbProvider.get(), c); + ids = cs.ids().asList(); + } else if (c.getStatus().asChangeStatus() == ChangeStatus.MERGED) { + ids = Lists.newArrayList(); + String subId = c.getSubmissionId(); + if (subId.isEmpty()) { + ids = Collections.emptyList(); + } else { + for (ChangeData cd : queryProvider.get().bySubmissionId(subId)) { + ids.add(cd.getId()); + } + } } else { - return Collections.emptyList(); + // ABANDONED + ids = Collections.emptyList(); } + if (ids.size() <= 1) { + ids = Collections.emptyList(); + } + return json.create(EnumSet.of( + ListChangesOption.CURRENT_REVISION, + ListChangesOption.CURRENT_COMMIT)) + .format(ids); } catch (OrmException | IOException e) { log.error("Error on getting a ChangeSet", e); throw e; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeField.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeField.java index e711306d6c..4fa5cd3045 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeField.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeField.java @@ -207,6 +207,21 @@ public class ChangeField { } }; + /** Submission id assigned by MergeOp. */ + public static final FieldDef SUBMISSIONID = + new FieldDef.Single( + "submissionid", FieldType.EXACT, false) { + @Override + public String get(ChangeData input, FillArgs args) + throws OrmException { + Change c = input.change(); + if (c == null) { + return null; + } + return c.getSubmissionId(); + } + }; + /** Last update time since January 1, 1970. */ public static final FieldDef UPDATED = new FieldDef.Single( diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeSchemas.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeSchemas.java index a8a97a865c..4789a14a01 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeSchemas.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeSchemas.java @@ -377,6 +377,42 @@ public class ChangeSchemas { ChangeField.AUTHOR, ChangeField.COMMITTER); + static final Schema V25 = schema( + ChangeField.LEGACY_ID2, + ChangeField.ID, + ChangeField.STATUS, + ChangeField.PROJECT, + ChangeField.PROJECTS, + ChangeField.REF, + ChangeField.EXACT_TOPIC, + ChangeField.FUZZY_TOPIC, + ChangeField.UPDATED, + ChangeField.FILE_PART, + ChangeField.PATH, + ChangeField.OWNER, + ChangeField.REVIEWER, + ChangeField.COMMIT, + ChangeField.TR, + ChangeField.LABEL, + ChangeField.COMMIT_MESSAGE, + ChangeField.COMMENT, + ChangeField.CHANGE, + ChangeField.APPROVAL, + ChangeField.MERGEABLE, + ChangeField.ADDED, + ChangeField.DELETED, + ChangeField.DELTA, + ChangeField.HASHTAG, + ChangeField.COMMENTBY, + ChangeField.PATCH_SET, + ChangeField.GROUP, + ChangeField.SUBMISSIONID, + ChangeField.EDITBY, + ChangeField.REVIEWEDBY, + ChangeField.EXACT_COMMIT, + ChangeField.AUTHOR, + ChangeField.COMMITTER); + private static Schema schema(Collection> fields) { return new Schema<>(ImmutableList.copyOf(fields)); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java index 31c35c2c92..bb11c0554f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/InternalChangeQuery.java @@ -41,6 +41,7 @@ import org.eclipse.jgit.lib.ObjectId; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -194,6 +195,14 @@ public class InternalChangeQuery { return query(commit(schema(indexes), id.name())); } + public List bySubmissionId(String cs) throws OrmException { + if (cs.isEmpty()) { + return Collections.emptyList(); + } else { + return query(new SubmissionIdPredicate(cs)); + } + } + public List byProjectGroups(Project.NameKey project, Collection groups) throws OrmException { List groupPredicates = new ArrayList<>(groups.size()); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SubmissionIdPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SubmissionIdPredicate.java new file mode 100644 index 0000000000..3b2dd94a32 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SubmissionIdPredicate.java @@ -0,0 +1,44 @@ +// Copyright (C) 2015 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.change; + +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.server.index.ChangeField; +import com.google.gerrit.server.index.IndexPredicate; +import com.google.gwtorm.server.OrmException; + +class SubmissionIdPredicate extends IndexPredicate { + + SubmissionIdPredicate(String changeSet) { + super(ChangeField.SUBMISSIONID, changeSet); + } + + @Override + public boolean match(ChangeData object) throws OrmException { + Change change = object.change(); + if (change == null) { + return false; + } + if (change.getSubmissionId() == null) { + return false; + } + return getValue().equals(change.getSubmissionId()); + } + + @Override + public int getCost() { + return 1; + } +}