Merge branch 'stable-2.15' into stable-2.16

* stable-2.15:
  Extend JGitHealthcheck to check for multiple repos

Adapt to the latest signature of the ListProjects constructor
in v2.16.5.

Change-Id: Ic638029b010830b6aeeaca84f1b13a90192b947d
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java
index 6c93e91..98df366 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java
@@ -18,10 +18,16 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Config;
 
@@ -32,12 +38,20 @@
   private static final long HEALTHCHECK_TIMEOUT_DEFAULT = 500L;
   private static final String QUERY_DEFAULT = "status:open";
   private static final int LIMIT_DEFAULT = 10;
+  private final AllProjectsName allProjectsName;
+  private final AllUsersName allUsersName;
 
   private final Config config;
 
   @Inject
-  public HealthCheckConfig(PluginConfigFactory configFactory, @PluginName String pluginName) {
+  public HealthCheckConfig(
+      PluginConfigFactory configFactory,
+      @PluginName String pluginName,
+      AllProjectsName allProjectsName,
+      AllUsersName allUsersName) {
     config = configFactory.getGlobalPluginConfig(pluginName);
+    this.allProjectsName = allProjectsName;
+    this.allUsersName = allUsersName;
   }
 
   @VisibleForTesting
@@ -50,6 +64,8 @@
         throw new IllegalArgumentException("Invalid configuration " + configText, e);
       }
     }
+    allProjectsName = new AllProjectsName("All-Projects");
+    allUsersName = new AllUsersName("All-Users");
   }
 
   public long getTimeout() {
@@ -72,4 +88,14 @@
     int defaultLimit = healthCheckName == null ? LIMIT_DEFAULT : getLimit(null);
     return config.getInt(HEALTHCHECK, healthCheckName, "limit", defaultLimit);
   }
+
+  public Set<Project.NameKey> getJGITRepositories(String healthCheckName) {
+    Set<Project.NameKey> repos =
+        Stream.of(config.getStringList(HEALTHCHECK, healthCheckName, "project"))
+            .map(Project.NameKey::new)
+            .collect(Collectors.toSet());
+    repos.add(allProjectsName);
+    repos.add(allUsersName);
+    return repos;
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java
index 73fa88d..fe59bbb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java
@@ -17,37 +17,37 @@
 import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.JGIT;
 
 import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.healthcheck.HealthCheckConfig;
-import org.eclipse.jgit.lib.ObjectId;
+import java.util.Set;
 import org.eclipse.jgit.lib.Repository;
 
 @Singleton
 public class JGitHealthCheck extends AbstractHealthCheck {
   private final GitRepositoryManager repositoryManager;
-  private final AllProjectsName allProjectsName;
+  private final Set<Project.NameKey> repositoryNameKeys;
 
   @Inject
   public JGitHealthCheck(
       ListeningExecutorService executor,
       HealthCheckConfig config,
-      GitRepositoryManager repositoryManager,
-      AllProjectsName allProjectsName) {
+      GitRepositoryManager repositoryManager) {
     super(executor, config, JGIT);
 
     this.repositoryManager = repositoryManager;
-    this.allProjectsName = allProjectsName;
+    this.repositoryNameKeys = config.getJGITRepositories(JGIT);
   }
 
   @Override
   protected Result doCheck() throws Exception {
-    try (Repository allProjects = repositoryManager.openRepository(allProjectsName)) {
-      ObjectId headObj = allProjects.resolve("refs/meta/config");
-      allProjects.open(headObj).getType();
-      return Result.PASSED;
+    for (Project.NameKey repoNameKey : repositoryNameKeys) {
+      try (Repository repo = repositoryManager.openRepository(repoNameKey)) {
+        repo.open(repo.resolve("refs/meta/config")).getType();
+      }
     }
+    return Result.PASSED;
   }
 }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 74ad62c..c064bc3 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -63,4 +63,10 @@
 - `healthcheck.<checkName>.limit` : Maximum number of elements to retrieve from
   the the check results.
 
-  Default: 10
\ No newline at end of file
+  Default: 10
+
+- `healthcheck.jgit.project` : A project name to check for accessibility of its refs/meta/config.
+   Multiple occurrences are allowed to configure more projects, in addition
+   to the default ones that are always included.
+
+  Default: All-Projects, All-Users
\ No newline at end of file
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java
index 50a748f..1a8ec63 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java
@@ -16,11 +16,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.googlesource.gerrit.plugins.healthcheck.HealthCheckConfig.DEFAULT_CONFIG;
+import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.JGIT;
 import static org.eclipse.jgit.lib.RefUpdate.Result.NEW;
 
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.RepositoryCaseMismatchException;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
@@ -44,6 +46,7 @@
 
 public class JGitHealthCheckTest {
   private AllProjectsName allProjectsName = new AllProjectsName("All-Projects");
+  private AllUsersName allUsersName = new AllUsersName("All-Users");
   private InMemoryRepositoryManager inMemoryRepositoryManager = new InMemoryRepositoryManager();
   private PersonIdent personIdent = new PersonIdent("Gerrit Rietveld", "gerrit@rietveld.nl");
 
@@ -53,24 +56,40 @@
   public void setupAllProjects() throws Exception {
     Guice.createInjector(new HealthCheckModule()).injectMembers(this);
 
-    InMemoryRepositoryManager.Repo repo =
+    InMemoryRepositoryManager.Repo allProjects =
         inMemoryRepositoryManager.createRepository(allProjectsName);
-    createCommit(repo, "refs/meta/config");
+    createCommit(allProjects, "refs/meta/config");
+
+    InMemoryRepositoryManager.Repo allUsers =
+        inMemoryRepositoryManager.createRepository(allUsersName);
+    createCommit(allUsers, "refs/meta/config");
   }
 
   @Test
   public void shouldBeHealthyWhenJGitIsWorking() {
     JGitHealthCheck reviewDbCheck =
-        new JGitHealthCheck(
-            executor, DEFAULT_CONFIG, getWorkingRepositoryManager(), allProjectsName);
+        new JGitHealthCheck(executor, DEFAULT_CONFIG, getWorkingRepositoryManager());
     assertThat(reviewDbCheck.run().result).isEqualTo(Result.PASSED);
   }
 
   @Test
-  public void shouldBeUnhealthyWhenJGitIsFailing() {
+  public void shouldBeUnhealthyWhenJGitIsFailingForAllRepos() {
     JGitHealthCheck jGitHealthCheck =
-        new JGitHealthCheck(
-            executor, DEFAULT_CONFIG, getFailingGitRepositoryManager(), allProjectsName);
+        new JGitHealthCheck(executor, DEFAULT_CONFIG, getFailingGitRepositoryManager());
+    assertThat(jGitHealthCheck.run().result).isEqualTo(Result.FAILED);
+  }
+
+  @Test
+  public void shouldBeUnhealthyWhenJGitIsFailingSomeRepos() {
+    HealthCheckConfig config =
+        new HealthCheckConfig(
+            "[healthcheck \""
+                + JGIT
+                + "\"]\n"
+                + "  project = All-Users\n"
+                + "  project = Not-Existing-Repo");
+    JGitHealthCheck jGitHealthCheck =
+        new JGitHealthCheck(executor, config, getWorkingRepositoryManager());
     assertThat(jGitHealthCheck.run().result).isEqualTo(Result.FAILED);
   }
 
@@ -80,7 +99,7 @@
       @Override
       public Repository openRepository(Project.NameKey name)
           throws RepositoryNotFoundException, IOException {
-        throw new RepositoryNotFoundException("Can't fine repository " + name);
+        throw new RepositoryNotFoundException("Can't find repository " + name);
       }
 
       @Override
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java
index eefce0a..3adee84 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java
@@ -61,7 +61,7 @@
   }
 
   private ListProjects getFailingProjectList() {
-    return new ListProjects(null, null, null, null, null, null, null, null) {
+    return new ListProjects(null, null, null, null, null, null, null, null, null) {
       @Override
       public SortedMap<String, ProjectInfo> apply() throws BadRequestException {
         throw new IllegalArgumentException("Unable to return project list");
@@ -70,7 +70,7 @@
   }
 
   private ListProjects getWorkingProjectList(long execTime) {
-    return new ListProjects(null, null, null, null, null, null, null, null) {
+    return new ListProjects(null, null, null, null, null, null, null, null, null) {
       @Override
       public SortedMap<String, ProjectInfo> apply() throws BadRequestException {
         SortedMap<String, ProjectInfo> projects = new TreeMap<>();