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");