Merge branch 'stable-2.15'

* stable-2.15:
  Update bazlets to latest revision on stable-2.15
  Update bazlets to latest revision on stable-2.14
  Update to latest bazlets on stable-2.15
  Update to latest bazlets on stable-2.14 branch
  Bazel: Switch to using release plugin API
  Ignore inactive reviewers in groups

Change-Id: Id49a47f32b88420276544dc6ae45ef91df2c555b
diff --git a/WORKSPACE b/WORKSPACE
index 5a0dae7..e2154a3 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,30 +3,30 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "d9abef15db0f934bfe9adcb40b0c475807fd12bf",
+    commit = "42bffc66c0e92753133e4cea2debe65abc359c4d",
     #    local_path = "/home/<user>/projects/bazlets",
 )
 
 # Release Plugin API
-load(
-    "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
-    "gerrit_api",
-)
+#load(
+#    "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
+#    "gerrit_api",
+#)
 
 # Snapshot Plugin API
-#load(
-#    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
-#    "gerrit_api_maven_local",
-#)
+load(
+    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
+    "gerrit_api_maven_local",
+)
 load(
     "@com_googlesource_gerrit_bazlets//:gerrit_gwt.bzl",
     "gerrit_gwt",
 )
 
 # Load release Plugin API
-gerrit_api()
+#gerrit_api()
 
 # Load snapshot Plugin API
-#gerrit_api_maven_local()
+gerrit_api_maven_local()
 
 gerrit_gwt()
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 47916a0..984c173 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/ChangeEventListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/ChangeEventListener.java
@@ -19,9 +19,6 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 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.common.AccountInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.events.RevisionCreatedListener;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
@@ -35,10 +32,9 @@
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.GroupMembers;
-import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.WorkQueue;
-import com.google.gerrit.server.group.GroupsCollection;
+import com.google.gerrit.server.restapi.group.GroupsCollection;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
@@ -55,7 +51,6 @@
 import java.util.Set;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,7 +60,7 @@
 
   private final AccountResolver accountResolver;
   private final Provider<GroupsCollection> groupsCollection;
-  private final GroupMembers.Factory groupMembersFactory;
+  private final GroupMembers groupMembers;
   private final DefaultReviewers.Factory reviewersFactory;
   private final GitRepositoryManager repoManager;
   private final WorkQueue workQueue;
@@ -81,7 +76,7 @@
   ChangeEventListener(
       final AccountResolver accountResolver,
       final Provider<GroupsCollection> groupsCollection,
-      final GroupMembers.Factory groupMembersFactory,
+      final GroupMembers groupMembers,
       final DefaultReviewers.Factory reviewersFactory,
       final GitRepositoryManager repoManager,
       final WorkQueue workQueue,
@@ -91,12 +86,10 @@
       final ChangeData.Factory changeDataFactory,
       final ReviewersConfig.Factory configFactory,
       final Provider<CurrentUser> user,
-      final ChangeQueryBuilder queryBuilder,
-      final PluginConfigFactory cfgFactory,
-      @PluginName String pluginName) {
+      final ChangeQueryBuilder queryBuilder) {
     this.accountResolver = accountResolver;
     this.groupsCollection = groupsCollection;
-    this.groupMembersFactory = groupMembersFactory;
+    this.groupMembers = groupMembers;
     this.reviewersFactory = reviewersFactory;
     this.repoManager = repoManager;
     this.workQueue = workQueue;
@@ -112,10 +105,10 @@
   @Override
   public void onRevisionCreated(RevisionCreatedListener.Event event) {
     ChangeInfo c = event.getChange();
-    onEvent(new Project.NameKey(c.project), c._number, event.getWho());
+    onEvent(new Project.NameKey(c.project), c._number);
   }
 
-  private void onEvent(Project.NameKey projectName, int changeNumber, AccountInfo uploader) {
+  private void onEvent(Project.NameKey projectName, int changeNumber) {
     // TODO(davido): we have to cache per project configuration
     ReviewersConfig config = configFactory.create(projectName);
     List<ReviewerFilterSection> sections = config.getReviewerFilterSections();
@@ -125,7 +118,6 @@
     }
 
     try (Repository git = repoManager.openRepository(projectName);
-        RevWalk rw = new RevWalk(git);
         ReviewDb reviewDb = schemaFactory.open()) {
       ChangeData changeData =
           changeDataFactory.create(reviewDb, projectName, new Change.Id(changeNumber));
@@ -135,8 +127,7 @@
       }
 
       final Change change = changeData.change();
-      final Runnable task =
-          reviewersFactory.create(change, toAccounts(reviewers, projectName, uploader));
+      final Runnable task = reviewersFactory.create(change, toAccounts(reviewers, projectName));
 
       workQueue
           .getDefaultQueue()
@@ -223,9 +214,8 @@
     return filterPredicate.asMatchable().match(changeData);
   }
 
-  private Set<Account> toAccounts(Set<String> in, Project.NameKey p, AccountInfo uploader) {
+  private Set<Account> toAccounts(Set<String> in, Project.NameKey p) {
     Set<Account> reviewers = Sets.newHashSetWithExpectedSize(in.size());
-    GroupMembers groupMembers = null;
     for (String r : in) {
       try {
         Account account = accountResolver.find(r);
@@ -239,41 +229,15 @@
         log.error("Failed to resolve account " + r, e);
         continue;
       }
-      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(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);
-        }
-
-        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);
-        }
+      try {
+        reviewers.addAll(
+            groupMembers.listAccounts(groupsCollection.get().parse(r).getGroupUUID(), p));
+      } catch (UnprocessableEntityException 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 e) {
+        log.warn(String.format("Failed to list accounts for group %s", r), e);
       }
     }
     return reviewers;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java
index 69eba6a..491014b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java
@@ -15,6 +15,7 @@
 package com.googlesource.gerrit.plugins.reviewers;
 
 import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
@@ -22,10 +23,12 @@
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.group.GroupsCollection;
+import com.google.gerrit.server.restapi.group.GroupsCollection;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.permissions.ProjectPermission;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gwtorm.server.OrmException;
@@ -56,6 +59,7 @@
   private final ProjectCache projectCache;
   private final AccountResolver accountResolver;
   private final Provider<GroupsCollection> groupsCollection;
+  private final PermissionBackend permissionBackend;
 
   @Inject
   PutReviewers(
@@ -65,21 +69,31 @@
       ProjectCache projectCache,
       AccountResolver accountResolver,
       Provider<GroupsCollection> groupsCollection,
-      Provider<ReviewDb> reviewDbProvider) {
+      PermissionBackend permissionBackend) {
     this.pluginName = pluginName;
     this.configFactory = configFactory;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
     this.projectCache = projectCache;
     this.accountResolver = accountResolver;
     this.groupsCollection = groupsCollection;
+    this.permissionBackend = permissionBackend;
   }
 
   @Override
   public List<ReviewerFilterSection> apply(ProjectResource rsrc, Input input)
-      throws RestApiException {
+      throws RestApiException, PermissionBackendException {
     Project.NameKey projectName = rsrc.getNameKey();
     ReviewersConfig cfg = configFactory.create(projectName);
-    if (!rsrc.getControl().isOwner() || cfg == null) {
+    try {
+      permissionBackend
+          .user(rsrc.getUser())
+          .project(rsrc.getNameKey())
+          .check(ProjectPermission.WRITE_CONFIG);
+    } catch (AuthException e) {
+      throw new ResourceNotFoundException("Project" + projectName.get() + " not found");
+    }
+
+    if (cfg == null) {
       throw new ResourceNotFoundException("Project" + projectName.get() + " not found");
     }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/SuggestProjectReviewers.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/SuggestProjectReviewers.java
index 4212e61..6e44e39 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/SuggestProjectReviewers.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/SuggestProjectReviewers.java
@@ -21,11 +21,12 @@
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.ReviewersUtil;
-import com.google.gerrit.server.ReviewersUtil.VisibilityControl;
-import com.google.gerrit.server.change.SuggestReviewers;
+import com.google.gerrit.server.restapi.change.ReviewersUtil;
+import com.google.gerrit.server.restapi.change.ReviewersUtil.VisibilityControl;
+import com.google.gerrit.server.restapi.change.SuggestReviewers;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.permissions.ProjectPermission;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gwtorm.server.OrmException;
@@ -54,7 +55,8 @@
 
   @Override
   public List<SuggestedReviewerInfo> apply(ProjectResource rsrc)
-      throws BadRequestException, OrmException, IOException, ConfigInvalidException {
+      throws BadRequestException, OrmException, IOException, ConfigInvalidException,
+          PermissionBackendException {
     return reviewersUtil.suggestReviewers(
         null, this, rsrc.getProjectState(), getVisibility(rsrc), true);
   }