Merge conflict votes are on original change.
Change-Id: I236451f9825c2638401c3d740cfc1534c8eb214c
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 fae8344..34b08eb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
@@ -317,7 +317,9 @@
createDownstreamMerges(mdsMergeInput);
reviewInput.message =
- "Automerging to "
+ "Automerging change "
+ + mdsMergeInput.changeNumber
+ + " to "
+ Joiner.on(", ").join(mdsMergeInput.dsBranchMap.keySet())
+ " succeeded!";
reviewInput.notify = NotifyHandling.NONE;
@@ -331,18 +333,16 @@
}
}
reviewInput.labels = labels;
+
+ // Make the vote on the original change
+ ChangeInfo originalChange =
+ getOriginalChange(mdsMergeInput.changeNumber, mdsMergeInput.currentRevision);
// if this fails, i.e. -2 is restricted, catch it and still post message without a vote.
try {
- gApi.changes()
- .id(mdsMergeInput.changeNumber)
- .revision(CURRENT)
- .review(reviewInput);
+ gApi.changes().id(originalChange._number).revision(CURRENT).review(reviewInput);
} catch (AuthException e) {
reviewInput.labels = null;
- gApi.changes()
- .id(mdsMergeInput.changeNumber)
- .revision(CURRENT)
- .review(reviewInput);
+ gApi.changes().id(originalChange._number).revision(CURRENT).review(reviewInput);
}
}
}
@@ -522,7 +522,6 @@
ChangeApi downstreamChange = gApi.changes().create(downstreamChangeInput);
tagChange(downstreamChange.get(), "Automerger change created!");
-
}
}
@@ -654,7 +653,7 @@
log.error("Automerger could not set label, but still continuing.", e);
}
}
-
+
private void tagChange(ChangeInfo change, String message) throws RestApiException {
ReviewInput reviewInput = new ReviewInput();
reviewInput.message(message);
@@ -715,6 +714,22 @@
return previousRevision;
}
+ private ChangeInfo getOriginalChange(int changeNumber, String currentRevision)
+ throws RestApiException, InvalidQueryParameterException {
+ List<String> parents = getChangeParents(changeNumber, currentRevision);
+ if (parents.size() >= 2) {
+ String secondParentRevision = parents.get(1);
+ String topic = gApi.changes().id(changeNumber).topic();
+ List<ChangeInfo> changesInTopic = getChangesInTopic(topic);
+ for (ChangeInfo change : changesInTopic) {
+ if (change.currentRevision.equals(secondParentRevision)) {
+ return getOriginalChange(change._number, secondParentRevision);
+ }
+ }
+ }
+ return gApi.changes().id(changeNumber).get();
+ }
+
private List<String> getChangeParents(int changeNumber, String currentRevision)
throws RestApiException {
ChangeApi change = gApi.changes().id(changeNumber);
@@ -755,12 +770,26 @@
return null;
}
- private List<ChangeInfo> getChangesInTopicAndBranch(String topic, String downstreamBranch)
- throws InvalidQueryParameterException, RestApiException {
+ private QueryBuilder constructTopicQuery(String topic) throws InvalidQueryParameterException {
QueryBuilder queryBuilder = new QueryBuilder();
queryBuilder.addParameter("topic", topic);
- queryBuilder.addParameter("branch", downstreamBranch);
queryBuilder.addParameter("status", "open");
+ return queryBuilder;
+ }
+
+ private List<ChangeInfo> getChangesInTopic(String topic)
+ throws InvalidQueryParameterException, RestApiException {
+ QueryBuilder queryBuilder = constructTopicQuery(topic);
+ return gApi.changes()
+ .query(queryBuilder.get())
+ .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
+ .get();
+ }
+
+ private List<ChangeInfo> getChangesInTopicAndBranch(String topic, String downstreamBranch)
+ throws InvalidQueryParameterException, RestApiException {
+ QueryBuilder queryBuilder = constructTopicQuery(topic);
+ queryBuilder.addParameter("branch", downstreamBranch);
return gApi.changes()
.query(queryBuilder.get())
.withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
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 cd36f2d..d04fd1d 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
@@ -83,7 +83,7 @@
.withOption(ListChangesOption.CURRENT_REVISION)
.get();
assertThat(changesInTopic).hasSize(3);
-
+
List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);
ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
@@ -112,7 +112,7 @@
.isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
assertThat(dsTwoChangeInfo.subject)
.isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
-
+
// +2 and submit
merge(result);
assertThat(getVote(masterChange, "Code-Review").value).isEqualTo(2);
@@ -917,6 +917,77 @@
assertThat(getVote(dsTwoChange, "Code-Review").value).isEqualTo(1);
}
+ @Test
+ public void testContextUser_mergeConflictOnDownstreamVotesOnTopLevel() throws Exception {
+ // Branch flow for contextUser is master -> ds_one -> ds_two
+ Project.NameKey manifestNameKey = defaultSetup();
+ // Create initial change
+ PushOneCommit.Result initialResult = createChange("subject", "filename", "echo Hello");
+ // Project name is scoped by test, so we need to get it from our initial change
+ Project.NameKey projectNameKey = initialResult.getChange().project();
+ String projectName = projectNameKey.get();
+ createBranch(new Branch.NameKey(projectName, "ds_one"));
+ createBranch(new Branch.NameKey(projectName, "ds_two"));
+ initialResult.assertOkStatus();
+ merge(initialResult);
+
+ // Reset to create a sibling
+ ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
+ PushOneCommit.Result ds1Result =
+ createChange(
+ testRepo, "ds_one", "subject", "filename", "echo \"Hello asdfsd World\"", "randtopic");
+ ds1Result.assertOkStatus();
+ merge(ds1Result);
+ // Reset to allow our merge conflict to come
+ testRepo.reset(initial);
+ // Set up a merge conflict between ds_one and ds_two
+ PushOneCommit.Result ds2Result =
+ createChange(
+ testRepo, "ds_two", "subject", "filename", "echo yo World wutup wutup", "randtopic");
+ ds2Result.assertOkStatus();
+ merge(ds2Result);
+ testRepo.reset(initial);
+
+ // Create normalUserGroup, containing current user, and contextUserGroup, containing contextUser
+ String normalUserGroup = createGroup("normalUserGroup");
+ gApi.groups().id(normalUserGroup).addMembers(user.get().getAccountId().toString());
+ AccountApi contextUserApi = gApi.accounts().create("asdfContextUser");
+ String contextUserGroup = createGroup("contextUserGroup");
+ gApi.groups().id(contextUserGroup).addMembers(contextUserApi.get().name);
+
+ // Grant +2 to context user, since it doesn't have it by default
+ grantLabel(
+ "Code-Review",
+ -2,
+ 2,
+ projectNameKey,
+ "refs/heads/*",
+ false,
+ AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
+ false);
+ pushContextUserConfig(manifestNameKey.get(), projectName, contextUserApi.get()._accountId);
+
+ // After we upload our config, we upload a new patchset to create the downstreams
+ PushOneCommit.Result result = createChange("subject", "filename2", "echo Hello", "sometopic");
+ result.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.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT)
+ .get();
+ // There should only be two, as ds_one to ds_two should be a merge conflict
+ assertThat(changesInTopic).hasSize(2);
+
+ List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);
+
+ // Check that master is at Code-Review -2
+ ChangeInfo masterChangeInfo = sortedChanges.get(1);
+ assertThat(masterChangeInfo.branch).isEqualTo("master");
+ ChangeApi masterChange = gApi.changes().id(masterChangeInfo._number);
+ assertThat(getVote(masterChange, "Code-Review").value).isEqualTo(-2);
+ }
+
private Project.NameKey defaultSetup() throws Exception {
Project.NameKey manifestNameKey = createProject("platform/manifest");
setupTestRepo("default.xml", manifestNameKey, "master", "default.xml");