Merge branch 'stable-2.14'

* stable-2.14:
  Handle when uploader email matches more than one account

Change-Id: Ib7d6eba42d26e18ac580751ed0c69fac48bc2093
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/ChangeEventListener.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/ChangeEventListener.java
index ddecdb4..9be9dc4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/ChangeEventListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/ChangeEventListener.java
@@ -18,11 +18,11 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.client.ChangeStatus;
+import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.events.DraftPublishedListener;
 import com.google.gerrit.extensions.events.RevisionCreatedListener;
@@ -36,7 +36,6 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResolver;
-import com.google.gerrit.server.account.Emails;
 import com.google.gerrit.server.account.GroupMembers;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.git.GitRepositoryManager;
@@ -67,7 +66,6 @@
   private static final Logger log = LoggerFactory.getLogger(ChangeEventListener.class);
 
   private final AccountResolver accountResolver;
-  private final Emails emails;
   private final Provider<GroupsCollection> groupsCollection;
   private final GroupMembers.Factory groupMembersFactory;
   private final DefaultReviewers.Factory reviewersFactory;
@@ -85,7 +83,6 @@
   @Inject
   ChangeEventListener(
       final AccountResolver accountResolver,
-      final Emails emails,
       final Provider<GroupsCollection> groupsCollection,
       final GroupMembers.Factory groupMembersFactory,
       final DefaultReviewers.Factory reviewersFactory,
@@ -101,7 +98,6 @@
       final PluginConfigFactory cfgFactory,
       @PluginName String pluginName) {
     this.accountResolver = accountResolver;
-    this.emails = emails;
     this.groupsCollection = groupsCollection;
     this.groupMembersFactory = groupMembersFactory;
     this.reviewersFactory = reviewersFactory;
@@ -127,16 +123,16 @@
       log.debug("Ignoring draft change");
       return;
     }
-    onEvent(new Project.NameKey(c.project), c._number, event.getWho().email);
+    onEvent(new Project.NameKey(c.project), c._number, event.getWho());
   }
 
   @Override
   public void onDraftPublished(DraftPublishedListener.Event event) {
     ChangeInfo c = event.getChange();
-    onEvent(new Project.NameKey(c.project), c._number, event.getWho().email);
+    onEvent(new Project.NameKey(c.project), c._number, event.getWho());
   }
 
-  private void onEvent(Project.NameKey projectName, int changeNumber, String email) {
+  private void onEvent(Project.NameKey projectName, int changeNumber, AccountInfo uploader) {
     // TODO(davido): we have to cache per project configuration
     ReviewersConfig config = configFactory.create(projectName);
     List<ReviewerFilterSection> sections = config.getReviewerFilterSections();
@@ -157,7 +153,7 @@
 
       final Change change = changeData.change();
       final Runnable task =
-          reviewersFactory.create(change, toAccounts(reviewDb, reviewers, projectName, email));
+          reviewersFactory.create(change, toAccounts(reviewDb, reviewers, projectName, uploader));
 
       workQueue
           .getDefaultQueue()
@@ -245,7 +241,7 @@
   }
 
   private Set<Account> toAccounts(
-      ReviewDb reviewDb, Set<String> in, Project.NameKey p, String uploaderEMail) {
+      ReviewDb reviewDb, Set<String> in, Project.NameKey p, AccountInfo uploader) {
     Set<Account> reviewers = Sets.newHashSetWithExpectedSize(in.size());
     GroupMembers groupMembers = null;
     for (String r : in) {
@@ -261,21 +257,41 @@
         log.error("Failed to resolve account " + r, e);
         continue;
       }
-      try {
-        if (groupMembers == null) {
-          groupMembers =
-              groupMembersFactory.create(
-                  identifiedUserFactory.create(
-                      Iterables.getOnlyElement(emails.getAccountFor(uploaderEMail))));
+      if (groupMembers == null) {
+        // email is not unique to one account, try to locate the account using
+        // "Full name <email>" to increase chance of finding only one.
+        String uploaderNameEmail = String.format("%s <%s>", uploader.name, uploader.email);
+        try {
+          Account uploaderAccount = accountResolver.findByNameOrEmail(reviewDb, uploaderNameEmail);
+          if (uploaderAccount != null) {
+            groupMembers =
+                groupMembersFactory.create(identifiedUserFactory.create(uploaderAccount.getId()));
+          }
+        } catch (OrmException | IOException e) {
+          log.warn(
+              String.format(
+                  "Failed to list accounts for group %s, cannot retrieve uploader account %s",
+                  r, uploaderNameEmail),
+              e);
         }
-        reviewers.addAll(
-            groupMembers.listAccounts(groupsCollection.get().parse(r).getGroupUUID(), p));
-      } catch (UnprocessableEntityException | NoSuchGroupException e) {
-        log.warn(String.format("Reviewer %s is neither an account nor a group", r));
-      } catch (NoSuchProjectException e) {
-        log.warn(String.format("Failed to list accounts for group %s and project %s", r, p));
-      } catch (IOException | OrmException e) {
-        log.warn(String.format("Failed to list accounts for group %s", r), e);
+
+        try {
+          if (groupMembers != null) {
+            reviewers.addAll(
+                groupMembers.listAccounts(groupsCollection.get().parse(r).getGroupUUID(), p));
+          } else {
+            log.warn(
+                String.format(
+                    "Failed to list accounts for group %s; cannot retrieve uploader account for %s",
+                    r, uploader.email));
+          }
+        } catch (UnprocessableEntityException | NoSuchGroupException e) {
+          log.warn(String.format("Reviewer %s is neither an account nor a group", r));
+        } catch (NoSuchProjectException e) {
+          log.warn(String.format("Failed to list accounts for group %s and project %s", r, p));
+        } catch (IOException | OrmException e) {
+          log.warn(String.format("Failed to list accounts for group %s", r), e);
+        }
       }
     }
     return reviewers;