Merge branch 'stable-2.14' into stable-2.15

* stable-2.14:
  Upgrade bazlets to latest stable-2.14 to build with 2.14.21 API

Change-Id: I05455d9d9b91bce1fa7f771a4f8fe6262e87775b
diff --git a/README.md b/README.md
index 2c9d9b4..8060e8b 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,5 @@
 
 Gerrit plugin to provide information via SSH commands to Gerrit Administrators.
 
-[![Build Status](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-admin-console-master/badge/icon)](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-admin-console-master/)
\ No newline at end of file
+[![Build Status](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-admin-console-bazel-master/badge/icon
+)](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-admin-console-bazel-master/)
diff --git a/WORKSPACE b/WORKSPACE
index d9791ed..d345b04 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "78c35a7eb33ee5ea0980923e246c7dba37347193",
+    commit = "f53f51fb660552d0581aa0ba52c3836ed63d56a3",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ListUsersCommand.java b/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ListUsersCommand.java
index 926db63..96b9c77 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ListUsersCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ListUsersCommand.java
@@ -18,21 +18,21 @@
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.extensions.annotations.CapabilityScope;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.index.query.Predicate;
 import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.account.AccountResolver;
+import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.query.account.AccountPredicates;
+import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.sshd.CommandMetaData;
 import com.google.gerrit.sshd.SshCommand;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import org.kohsuke.args4j.Option;
 
 @RequiresCapability(value = GlobalCapability.ADMINISTRATE_SERVER, scope = CapabilityScope.CORE)
 @CommandMetaData(name = "ls-users", description = "List users")
 public final class ListUsersCommand extends SshCommand {
-  private ReviewDb db;
-  private final AccountResolver accountResolver;
+  private final Provider<InternalAccountQuery> accountQueryProvider;
 
   @Option(name = "--active-only", usage = "show only active users")
   private boolean activeOnly = false;
@@ -41,27 +41,37 @@
   private boolean inactiveOnly = false;
 
   @Inject
-  ListUsersCommand(ReviewDb db, AccountResolver accountResolver) {
-    this.db = db;
-    this.accountResolver = accountResolver;
+  ListUsersCommand(Provider<InternalAccountQuery> accountQueryProvider) {
+    this.accountQueryProvider = accountQueryProvider;
   }
 
   @Override
   protected void run() throws UnloggedFailure, Failure, Exception {
-    ResultSet<Account> accounts = db.accounts().all();
-    for (Account account : accounts) {
-      if (activeOnly && !account.isActive()) {
-        continue;
-      }
-      if (inactiveOnly && account.isActive()) {
-        continue;
-      }
-      String username = getUsername(account);
+    if (activeOnly && inactiveOnly) {
+      throw die("--active-only and --inactive-only are mutually exclusive");
+    }
+
+    Predicate<AccountState> queryPredicate;
+    if (activeOnly) {
+      queryPredicate = AccountPredicates.isActive();
+    } else if (inactiveOnly) {
+      queryPredicate = AccountPredicates.isNotActive();
+    } else {
+      // This is a work-around to get all the account from the index, querying
+      // active and inactive users returns all the users. Another option is to
+      // use the Accounts class which will list all the account ids from notedb
+      // and then query the secondary index for each user but this way is less
+      // efficient.
+      queryPredicate = Predicate.or(AccountPredicates.isActive(), AccountPredicates.isNotActive());
+    }
+    for (AccountState accountState : accountQueryProvider.get().query(queryPredicate)) {
+      Account account = accountState.getAccount();
       String out =
           new StringBuilder()
               .append(account.getId().toString())
               .append(" |")
-              .append(Strings.isNullOrEmpty(username) ? "" : " " + username)
+              .append(
+                  Strings.isNullOrEmpty(account.getUserName()) ? "" : " " + account.getUserName())
               .append(" |")
               .append(
                   Strings.isNullOrEmpty(account.getFullName()) ? "" : " " + account.getFullName())
@@ -76,10 +86,4 @@
       stdout.println(out);
     }
   }
-
-  private String getUsername(Account account) throws OrmException {
-    String id = account.getId().toString();
-    Account accountFromResolver = accountResolver.find(db, id);
-    return accountFromResolver == null ? null : accountFromResolver.getUserName();
-  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowAccountCommand.java b/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowAccountCommand.java
index aa086f0..512828e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowAccountCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowAccountCommand.java
@@ -22,17 +22,16 @@
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Account.Id;
-import com.google.gerrit.reviewdb.client.AccountExternalId;
-import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.AccountResource;
 import com.google.gerrit.server.account.GetGroups;
 import com.google.gerrit.server.account.GetSshKeys;
+import com.google.gerrit.server.account.externalids.ExternalId;
+import com.google.gerrit.server.account.externalids.ExternalIds;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.sshd.CommandMetaData;
 import com.google.gerrit.sshd.SshCommand;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import java.io.IOException;
@@ -63,10 +62,10 @@
   private boolean showKeys = false;
 
   private final AccountResolver accountResolver;
-  private final SchemaFactory<ReviewDb> schema;
   private final Provider<GetGroups> accountGetGroups;
   private final IdentifiedUser.GenericFactory userFactory;
   private final Provider<GetSshKeys> getSshKeys;
+  private final ExternalIds externalIds;
 
   @Inject
   ShowAccountCommand(
@@ -74,16 +73,16 @@
       Provider<GetGroups> accountGetGroups,
       IdentifiedUser.GenericFactory userFactory,
       Provider<GetSshKeys> getSshKeys,
-      SchemaFactory<ReviewDb> schema) {
+      ExternalIds externalIds) {
     this.accountResolver = accountResolver;
     this.accountGetGroups = accountGetGroups;
     this.userFactory = userFactory;
-    this.schema = schema;
     this.getSshKeys = getSshKeys;
+    this.externalIds = externalIds;
   }
 
   @Override
-  public void run() throws UnloggedFailure, OrmException {
+  public void run() throws UnloggedFailure, Exception {
     Account account;
 
     if (name.isEmpty()) {
@@ -92,92 +91,92 @@
           "You need to tell me who to find:  LastName,\\\\ Firstname, email@address.com, account id or an user name.  "
               + "Be sure to double-escape spaces, for example: \"show-account Last,\\\\ First\"");
     }
-    try (ReviewDb db = schema.open()) {
-      Set<Id> idList = accountResolver.findAll(db, name);
-      if (idList.isEmpty()) {
-        throw new UnloggedFailure(
-            1,
-            "No accounts found for your query: \""
-                + name
-                + "\""
-                + " Tip: Try double-escaping spaces, for example: \"show-account Last,\\\\ First\"");
-      }
-      stdout.println(
-          "Found "
-              + idList.size()
-              + " result"
-              + (idList.size() > 1 ? "s" : "")
-              + ": for query: \""
+    Set<Id> idList = accountResolver.findAll(name);
+    if (idList.isEmpty()) {
+      throw new UnloggedFailure(
+          1,
+          "No accounts found for your query: \""
               + name
-              + "\"");
-      stdout.println();
+              + "\""
+              + " Tip: Try double-escaping spaces, for example: \"show-account Last,\\\\ First\"");
+    }
+    stdout.println(
+        "Found "
+            + idList.size()
+            + " result"
+            + (idList.size() > 1 ? "s" : "")
+            + ": for query: \""
+            + name
+            + "\"");
+    stdout.println();
 
-      for (Id id : idList) {
-        account = accountResolver.find(db, id.toString());
-        if (account == null) {
-          throw new UnloggedFailure("Account " + id.toString() + " does not exist.");
-        }
-        stdout.println("Full name:         " + account.getFullName());
-        stdout.println("Account Id:        " + id.toString());
-        stdout.println("Preferred Email:   " + account.getPreferredEmail());
-        stdout.println("User Name:         " + account.getUserName());
-        stdout.println("Active:            " + account.isActive());
-        stdout.println("Registered on:     " + account.getRegisteredOn());
+    for (Id id : idList) {
+      account = accountResolver.find(id.toString());
+      if (account == null) {
+        throw new UnloggedFailure("Account " + id.toString() + " does not exist.");
+      }
+      stdout.println("Full name:         " + account.getFullName());
+      stdout.println("Account Id:        " + id.toString());
+      stdout.println("Preferred Email:   " + account.getPreferredEmail());
+      stdout.println("User Name:         " + account.getUserName());
+      stdout.println("Active:            " + account.isActive());
+      stdout.println("Registered on:     " + account.getRegisteredOn());
 
-        stdout.println("");
-        stdout.println("External Ids:");
-        stdout.println(String.format("%-50s %s", "Email Address:", "External Id:"));
-        for (AccountExternalId accountExternalId :
-            db.accountExternalIds().byAccount(account.getId())) {
+      stdout.println("");
+      stdout.println("External Ids:");
+      stdout.println(String.format("%-50s %s", "Email Address:", "External Id:"));
+      try {
+        for (ExternalId externalId : externalIds.byAccount(account.getId())) {
           stdout.println(
               String.format(
                   "%-50s %s",
-                  (accountExternalId.getEmailAddress() == null
-                      ? ""
-                      : accountExternalId.getEmailAddress()),
-                  accountExternalId.getExternalId()));
+                  (externalId.email() == null ? "" : externalId.email()), externalId.key()));
         }
-
-        if (showKeys) {
-          stdout.println("");
-          stdout.println("Public Keys:");
-          List<SshKeyInfo> sshKeys;
-          try {
-            sshKeys = getSshKeys.get().apply(new AccountResource(userFactory.create(id)));
-          } catch (AuthException | IOException | ConfigInvalidException e) {
-            throw new UnloggedFailure(1, "Error getting sshkeys: " + e.getMessage(), e);
-          }
-          if (sshKeys == null || sshKeys.isEmpty()) {
-            stdout.println("None");
-          } else {
-            stdout.println(String.format("%-9s %s", "Status:", "Key:"));
-            for (SshKeyInfo sshKey : sshKeys) {
-              stdout.println(
-                  String.format(
-                      "%-9s %s", (sshKey.valid ? "Active" : "Inactive"), sshKey.sshPublicKey));
-            }
-          }
-        }
-
-        if (showGroups) {
-          stdout.println();
-          stdout.println(
-              "Member of groups"
-                  + (filterGroups == null ? "" : " (Filtering on \"" + filterGroups + "\")")
-                  + ":");
-          List<GroupInfo> groupInfos =
-              accountGetGroups.get().apply(new AccountResource(userFactory.create(id)));
-
-          Collections.sort(groupInfos, new CustomComparator());
-          for (GroupInfo groupInfo : groupInfos) {
-            if (null == filterGroups
-                || groupInfo.name.toLowerCase().contains(filterGroups.toLowerCase())) {
-              stdout.println(groupInfo.name);
-            }
-          }
-        }
-        stdout.println("");
+      } catch (IOException e) {
+        throw new UnloggedFailure(1, "Error getting external Ids: " + e.getMessage(), e);
       }
+      if (showKeys) {
+        stdout.println("");
+        stdout.println("Public Keys:");
+        List<SshKeyInfo> sshKeys;
+        try {
+          sshKeys = getSshKeys.get().apply(new AccountResource(userFactory.create(id)));
+        } catch (AuthException
+            | IOException
+            | ConfigInvalidException
+            | PermissionBackendException e) {
+          throw new UnloggedFailure(1, "Error getting sshkeys: " + e.getMessage(), e);
+        }
+        if (sshKeys == null || sshKeys.isEmpty()) {
+          stdout.println("None");
+        } else {
+          stdout.println(String.format("%-9s %s", "Status:", "Key:"));
+          for (SshKeyInfo sshKey : sshKeys) {
+            stdout.println(
+                String.format(
+                    "%-9s %s", (sshKey.valid ? "Active" : "Inactive"), sshKey.sshPublicKey));
+          }
+        }
+      }
+
+      if (showGroups) {
+        stdout.println();
+        stdout.println(
+            "Member of groups"
+                + (filterGroups == null ? "" : " (Filtering on \"" + filterGroups + "\")")
+                + ":");
+        List<GroupInfo> groupInfos =
+            accountGetGroups.get().apply(new AccountResource(userFactory.create(id)));
+
+        Collections.sort(groupInfos, new CustomComparator());
+        for (GroupInfo groupInfo : groupInfos) {
+          if (null == filterGroups
+              || groupInfo.name.toLowerCase().contains(filterGroups.toLowerCase())) {
+            stdout.println(groupInfo.name);
+          }
+        }
+      }
+      stdout.println("");
     }
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowRepoAccountAccessCommand.java b/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowRepoAccountAccessCommand.java
index dca6eb9..6b59bc1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowRepoAccountAccessCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/adminconsole/ShowRepoAccountAccessCommand.java
@@ -24,7 +24,6 @@
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Account.Id;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.AccountResource;
@@ -33,7 +32,6 @@
 import com.google.gerrit.server.git.ProjectConfig;
 import com.google.gerrit.sshd.CommandMetaData;
 import com.google.gerrit.sshd.SshCommand;
-import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import java.util.HashSet;
@@ -67,20 +65,17 @@
       MetaDataUpdate.Server metaDataUpdateFactory,
       Provider<GetGroups> accountGetGroups,
       AccountResolver accountResolver,
-      IdentifiedUser.GenericFactory userFactory,
-      SchemaFactory<ReviewDb> schema) {
+      IdentifiedUser.GenericFactory userFactory) {
     this.metaDataUpdateFactory = metaDataUpdateFactory;
     this.accountGetGroups = accountGetGroups;
     this.accountResolver = accountResolver;
     this.userFactory = userFactory;
-    this.schema = schema;
   }
 
   private final MetaDataUpdate.Server metaDataUpdateFactory;
   private final AccountResolver accountResolver;
   private final Provider<GetGroups> accountGetGroups;
   private final IdentifiedUser.GenericFactory userFactory;
-  private final SchemaFactory<ReviewDb> schema;
   private int columns = 80;
   private int permissionGroupWidth;
 
@@ -104,82 +99,80 @@
           "You need to tell me who to find:  LastName,\\\\ Firstname, email@address.com, account id or an user name.  "
               + "Be sure to double-escape spaces, for example: \"show-repo-account-access All-Projects --user Last,\\\\ First\"");
     }
-    try (ReviewDb db = schema.open()) {
-      Set<Id> idList = accountResolver.findAll(db, name);
-      if (idList.isEmpty()) {
-        throw new UnloggedFailure(
-            1,
-            "No accounts found for your query: \""
-                + name
-                + "\""
-                + " Tip: Try double-escaping spaces, for example: \"--user Last,\\\\ First\"");
-      }
+    Set<Id> idList = accountResolver.findAll(name);
+    if (idList.isEmpty()) {
+      throw new UnloggedFailure(
+          1,
+          "No accounts found for your query: \""
+              + name
+              + "\""
+              + " Tip: Try double-escaping spaces, for example: \"--user Last,\\\\ First\"");
+    }
 
-      Project.NameKey nameKey = new Project.NameKey(projectName);
+    Project.NameKey nameKey = new Project.NameKey(projectName);
 
-      try {
-        MetaDataUpdate md = metaDataUpdateFactory.create(nameKey);
-        ProjectConfig config;
-        config = ProjectConfig.read(md);
+    try {
+      MetaDataUpdate md = metaDataUpdateFactory.create(nameKey);
+      ProjectConfig config;
+      config = ProjectConfig.read(md);
 
-        permissionGroupWidth = wide ? Integer.MAX_VALUE : columns - 9 - 5 - 9;
+      permissionGroupWidth = wide ? Integer.MAX_VALUE : columns - 9 - 5 - 9;
 
-        for (Id id : idList) {
-          userHasPermissionsInProject = false;
-          account = accountResolver.find(db, id.toString());
-          stdout.println("Full name:         " + account.getFullName());
-          // Need to know what groups the user is in. This is not a great
-          // solution, but it does work.
-          List<GroupInfo> groupInfos =
-              accountGetGroups.get().apply(new AccountResource(userFactory.create(id)));
-          HashSet<String> groupHash = new HashSet<>();
+      for (Id id : idList) {
+        userHasPermissionsInProject = false;
+        account = accountResolver.find(id.toString());
+        stdout.println("Full name:         " + account.getFullName());
+        // Need to know what groups the user is in. This is not a great
+        // solution, but it does work.
+        List<GroupInfo> groupInfos =
+            accountGetGroups.get().apply(new AccountResource(userFactory.create(id)));
+        HashSet<String> groupHash = new HashSet<>();
 
-          for (GroupInfo groupInfo : groupInfos) {
-            groupHash.add(groupInfo.name);
-          }
+        for (GroupInfo groupInfo : groupInfos) {
+          groupHash.add(groupInfo.name);
+        }
 
-          for (AccessSection accessSection : config.getAccessSections()) {
-            StringBuilder sb = new StringBuilder();
-            sb.append((String.format(sectionNameFormatter, accessSection.getName().toString())));
-            // This is a solution to prevent displaying a section heading unless
-            // the user has permissions for it
-            // not the best solution, but I haven't been able to find
-            // "Is user a member of this group" based on the information I have
-            // in a more efficient manner yet.
-            userHasPermissionsInSection = false;
-            for (Permission permission : accessSection.getPermissions()) {
+        for (AccessSection accessSection : config.getAccessSections()) {
+          StringBuilder sb = new StringBuilder();
+          sb.append((String.format(sectionNameFormatter, accessSection.getName().toString())));
+          // This is a solution to prevent displaying a section heading unless
+          // the user has permissions for it
+          // not the best solution, but I haven't been able to find
+          // "Is user a member of this group" based on the information I have
+          // in a more efficient manner yet.
+          userHasPermissionsInSection = false;
+          for (Permission permission : accessSection.getPermissions()) {
 
-              for (PermissionRule rule : permission.getRules()) {
+            for (PermissionRule rule : permission.getRules()) {
 
-                if (groupHash.contains(rule.getGroup().getName())) {
-                  sb.append(String.format(ruleNameFormatter, permission.getName()));
-                  sb.append(
-                      String.format(
-                          permissionNameFormatter,
-                          (!rule.getMin().equals(rule.getMax()))
-                              ? "" + rule.getMin() + " " + rule.getMax()
-                              : rule.getAction(),
-                          (permission.getExclusiveGroup() ? "EXCLUSIVE" : ""),
-                          format(rule.getGroup().getName())));
-                  userHasPermissionsInSection = true;
-                }
+              if (groupHash.contains(rule.getGroup().getName())) {
+                sb.append(String.format(ruleNameFormatter, permission.getName()));
+                sb.append(
+                    String.format(
+                        permissionNameFormatter,
+                        (!rule.getMin().equals(rule.getMax()))
+                            ? "" + rule.getMin() + " " + rule.getMax()
+                            : rule.getAction(),
+                        (permission.getExclusiveGroup() ? "EXCLUSIVE" : ""),
+                        format(rule.getGroup().getName())));
+                userHasPermissionsInSection = true;
               }
             }
-
-            if (userHasPermissionsInSection) {
-              stdout.print(sb.toString());
-
-              userHasPermissionsInProject = true;
-            }
           }
 
-          if (!userHasPermissionsInProject) {
-            stdout.println("  No access found for this user on this repository");
+          if (userHasPermissionsInSection) {
+            stdout.print(sb.toString());
+
+            userHasPermissionsInProject = true;
           }
         }
-      } catch (RepositoryNotFoundException e) {
-        throw new UnloggedFailure(1, "Repository not found");
+
+        if (!userHasPermissionsInProject) {
+          stdout.println("  No access found for this user on this repository");
+        }
       }
+    } catch (RepositoryNotFoundException e) {
+      throw new UnloggedFailure(1, "Repository not found");
     }
   }