When B is rebased on A, B' rebases on A'.
Change-Id: I00790459c8a2abb418b9d001f5f6e02b634d1d5b
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
index d03c744..7de0782 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
@@ -365,7 +365,9 @@
mdsMergeInput.currentRevision,
mdsMergeInput.subject,
dsChangeNumber,
- mdsMergeInput.dsBranchMap.get(downstreamBranch));
+ mdsMergeInput.dsBranchMap.get(downstreamBranch),
+ mdsMergeInput.changeNumber,
+ downstreamBranch);
createDownstreams = false;
} catch (MergeConflictException e) {
failedMergeBranchMap.put(downstreamBranch, e.getMessage());
@@ -641,8 +643,13 @@
}
private void updateDownstreamMerge(
- String newParentRevision, String upstreamSubject, Integer sourceNum, boolean doMerge)
- throws RestApiException {
+ String newParentRevision,
+ String upstreamSubject,
+ Integer sourceNum,
+ boolean doMerge,
+ Integer upstreamChangeNumber,
+ String downstreamBranch)
+ throws RestApiException, InvalidQueryParameterException {
MergeInput mergeInput = new MergeInput();
mergeInput.source = newParentRevision;
@@ -658,6 +665,10 @@
}
mergePatchSetInput.merge = mergeInput;
+ mergePatchSetInput.baseChange =
+ getBaseChangeId(
+ getChangeParents(upstreamChangeNumber, newParentRevision), downstreamBranch);
+
ChangeApi originalChange = gApi.changes().id(sourceNum);
if (originalChange.info().status == ChangeStatus.ABANDONED) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
index 94bc972..0a05996 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
@@ -24,6 +24,7 @@
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.extensions.api.accounts.AccountApi;
import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ApprovalInfo;
@@ -349,6 +350,71 @@
}
@Test
+ public void testChangeStack_rebaseAfterUpload() throws Exception {
+ Project.NameKey manifestNameKey = defaultSetup();
+ // Save initial ref at HEAD
+ ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
+ // Create initial change
+ PushOneCommit.Result result = createChange("subject", "filename", "content", "testtopic");
+ // Project name is scoped by test, so we need to get it from our initial change
+ String projectName = result.getChange().project().get();
+ createBranch(new Branch.NameKey(projectName, "ds_one"));
+ pushSimpleConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one");
+ // After we upload our config, we upload a new patchset to create the downstreams
+ amendChange(result.getChangeId());
+ result.assertOkStatus();
+
+ // Reset to initial ref to create a sibling
+ testRepo.reset(initial);
+
+ PushOneCommit.Result result2 =
+ createChange(testRepo, "master", "subject2", "filename2", "content2", "testtopic");
+ result2.assertOkStatus();
+ // Check that there are the correct number of changes in the topic
+ List<ChangeInfo> changesInTopic =
+ gApi.changes()
+ .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
+ .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
+ .get();
+ assertThat(changesInTopic).hasSize(4);
+ List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);
+
+ // Check the first downstream change A'
+ ChangeInfo aPrime = sortedChanges.get(0);
+ assertThat(aPrime.branch).isEqualTo("ds_one");
+ // Check the second downstream change B'
+ ChangeInfo bPrime = sortedChanges.get(1);
+ assertThat(bPrime.branch).isEqualTo("ds_one");
+ // Check that B' does not have a first parent of A' yet
+ String bPrimeFirstParent = getParent(bPrime, 0);
+ assertThat(aPrime.currentRevision).isNotEqualTo(bPrimeFirstParent);
+
+ // Change A
+ ChangeInfo a = sortedChanges.get(2);
+ assertThat(a.branch).isEqualTo("master");
+ // Change B
+ ChangeInfo b = sortedChanges.get(3);
+ assertThat(b.branch).isEqualTo("master");
+ String masterChangeInfo2FirstParentSha = getParent(b, 0);
+ // Check that first parent of B is not A
+ assertThat(a.currentRevision).isNotEqualTo(masterChangeInfo2FirstParentSha);
+
+ // Rebase B on A
+ RebaseInput rebaseInput = new RebaseInput();
+ rebaseInput.base = a.currentRevision;
+ gApi.changes().id(b.changeId).rebase(rebaseInput);
+
+ // Check that B is now based on A, and B' is now based on A'
+ ChangeInfo bAfterRebase = gApi.changes().id(b.changeId).get();
+ String bAfterRebaseFirstParent = getParent(bAfterRebase, 0);
+ assertThat(bAfterRebaseFirstParent).isEqualTo(a.currentRevision);
+
+ ChangeInfo bPrimeAfterRebase = gApi.changes().id(bPrime.changeId).get();
+ String bPrimeAfterRebaseFirstParent = getParent(bPrimeAfterRebase, 0);
+ assertThat(bPrimeAfterRebaseFirstParent).isEqualTo(aPrime.currentRevision);
+ }
+
+ @Test
public void testBlankMerge() throws Exception {
Project.NameKey manifestNameKey = defaultSetup();
// Create initial change