During merge use existing author identity values

Rather than always using the user's preferred contact information
in their user account, try to reuse the information they stored
in a commit object that is being merged.  This permits a user who
has an @android.com address in their Git commits but has chosen
to use an @example.com address as their preferred contact to have
merge commits created on their behalf use @android.com instead of
@example.com.

Change-Id: Ic7d450977b68de1566a470953eb32aec32f2daa2
Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index 25c93d7..4ef7495 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -76,6 +76,7 @@
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -86,6 +87,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 
 import javax.annotation.Nullable;
 
@@ -518,10 +520,37 @@
       }
     }
 
+    // Try to use the submitter's identity for the merge commit author.
+    // If all of the commits being merged are created by the submitter,
+    // prefer the identity line they used in the commits rather than the
+    // preferred identity stored in the user account. This way the Git
+    // commit records are more consistent internally.
+    //
+    PersonIdent authorIdent;
+    if (submitter != null) {
+      IdentifiedUser who =
+          identifiedUserFactory.create(submitter.getAccountId());
+      Set<String> emails = new HashSet<String>();
+      for (RevCommit c : merged) {
+        emails.add(c.getAuthorIdent().getEmailAddress());
+      }
+
+      final Timestamp dt = submitter.getGranted();
+      final TimeZone tz = myIdent.getTimeZone();
+      if (emails.size() == 1
+          && who.getEmailAddresses().contains(emails.iterator().next())) {
+        authorIdent = new PersonIdent(merged.get(0).getAuthorIdent(), dt, tz);
+      } else {
+        authorIdent = who.newCommitterIdent(dt, tz);
+      }
+    } else {
+      authorIdent = myIdent;
+    }
+
     final Commit mergeCommit = new Commit(db);
     mergeCommit.setTreeId(m.getResultTreeId());
     mergeCommit.setParentIds(new ObjectId[] {mergeTip, n});
-    mergeCommit.setAuthor(toCommitterIdent(submitter));
+    mergeCommit.setAuthor(authorIdent);
     mergeCommit.setCommitter(myIdent);
     mergeCommit.setMessage(msgbuf.toString());