Rebase:chain - skip merged ancestors
Bug: Google b/279914754
Release-Notes: skip
Change-Id: Iaaefef7901b84e10faf7b38b80bdc227866edc07
diff --git a/java/com/google/gerrit/server/restapi/change/RebaseChain.java b/java/com/google/gerrit/server/restapi/change/RebaseChain.java
index b8afcb7..343fb72 100644
--- a/java/com/google/gerrit/server/restapi/change/RebaseChain.java
+++ b/java/com/google/gerrit/server/restapi/change/RebaseChain.java
@@ -317,10 +317,18 @@
private List<PatchSetData> getChainForCurrentPatchSet(ChangeResource rsrc)
throws PermissionBackendException, IOException {
- return Lists.reverse(
- getRelatedChangesUtil.getAncestors(
- changeDataFactory.create(rsrc.getNotes()),
- patchSetUtil.current(rsrc.getNotes()),
- true));
+ List<PatchSetData> ancestors =
+ Lists.reverse(
+ getRelatedChangesUtil.getAncestors(
+ changeDataFactory.create(rsrc.getNotes()),
+ patchSetUtil.current(rsrc.getNotes()),
+ true));
+ int eldestOpenAncestor = 0;
+ for (PatchSetData ps : ancestors) {
+ if (ps.data().change().isMerged()) {
+ eldestOpenAncestor++;
+ }
+ }
+ return ancestors.subList(eldestOpenAncestor, ancestors.size());
}
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
index fd37fb0..5ecb5a7 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
@@ -986,7 +986,7 @@
public void rebaseChain() throws Exception {
// Create changes with the following hierarchy:
// * HEAD
- // * r1
+ // * r (merged)
// * r2
// * r3
// * r4
@@ -1043,7 +1043,7 @@
final String newContent = "new content";
// Create changes with the following revision hierarchy:
// * HEAD
- // * r1
+ // * r (merged)
// * r2
// * r3/1 r3/2
// * r4
@@ -1079,6 +1079,71 @@
}
@Test
+ public void rebaseChainWithMergedAncestor() throws Exception {
+ final String file = "modified_file.txt";
+ final String newContent = "new content";
+
+ // Create changes with the following hierarchy:
+ // * HEAD
+ // * r (merged)
+ // * r2.1 r2.2 (merged)
+ // * r3
+ // * r4
+ // *r5
+ PushOneCommit.Result r = createChange();
+ PushOneCommit.Result r2 = createChange();
+ PushOneCommit.Result r3 = createChange();
+ PushOneCommit.Result r4 = createChange();
+ PushOneCommit.Result r5 = createChange();
+
+ // Approve and submit the first change
+ RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
+ revision.review(ReviewInput.approve());
+ revision.submit();
+ testRepo.reset("HEAD~1");
+
+ // Create r2.2
+ gApi.changes()
+ .id(r2.getChangeId())
+ .edit()
+ .modifyFile(file, RawInputUtil.create(newContent.getBytes(UTF_8)));
+ gApi.changes().id(r2.getChangeId()).edit().publish();
+ // Approve and submit r2.2
+ revision = gApi.changes().id(r2.getChangeId()).current();
+ revision.review(ReviewInput.approve());
+ revision.submit();
+
+ // Add an approval whose score should be copied on trivial rebase
+ gApi.changes().id(r3.getChangeId()).current().review(ReviewInput.recommend());
+
+ // Rebase the chain through r4.
+ verifyRebaseChainResponse(gApi.changes().id(r4.getChangeId()).rebaseChain(), false, r3, r4);
+
+ // Only r3 and r4 are rebased.
+ verifyRebaseForChange(r3.getChange().getId(), r2.getChange().getId(), true);
+ verifyRebaseForChange(r4.getChange().getId(), r3.getChange().getId(), false);
+
+ verifyChangeIsUpToDate(r2);
+ verifyChangeIsUpToDate(r3);
+ verifyChangeIsUpToDate(r4);
+
+ // r5 wasn't rebased.
+ assertThat(
+ gApi.changes()
+ .id(r5.getChangeId())
+ .get(CURRENT_REVISION)
+ .getCurrentRevision()
+ ._number)
+ .isEqualTo(1);
+
+ // Rebasing r5
+ verifyRebaseChainResponse(
+ gApi.changes().id(r5.getChangeId()).rebaseChain(), false, r3, r4, r5);
+
+ verifyRebaseForChange(r5.getChange().getId(), r4.getChange().getId(), false);
+ }
+
+ @Test
public void rebaseChainWithConflicts_conflictsForbidden() throws Exception {
PushOneCommit.Result r1 = createChange();
gApi.changes()