Return fallback code owners setting via the get config REST endpoints

Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: Iebe2d6a2be8a5930b8cfb04897dd6d696fd4d697
diff --git a/java/com/google/gerrit/plugins/codeowners/api/GeneralInfo.java b/java/com/google/gerrit/plugins/codeowners/api/GeneralInfo.java
index 8562057..8caa0fe 100644
--- a/java/com/google/gerrit/plugins/codeowners/api/GeneralInfo.java
+++ b/java/com/google/gerrit/plugins/codeowners/api/GeneralInfo.java
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.plugins.codeowners.api;
 
+import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
+
 /**
  * Representation of the general code owners configuration in the REST API.
  *
@@ -43,4 +45,7 @@
    * code owner override.
    */
   public String overrideInfoUrl;
+
+  /** Policy that controls who should own paths that have no code owners defined. */
+  public FallbackCodeOwners fallbackCodeOwners;
 }
diff --git a/java/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJson.java b/java/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJson.java
index 65d93e8..d034419 100644
--- a/java/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJson.java
+++ b/java/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJson.java
@@ -116,6 +116,8 @@
         codeOwnersPluginConfiguration.areImplicitApprovalsEnabled(projectName) ? true : null;
     generalInfo.overrideInfoUrl =
         codeOwnersPluginConfiguration.getOverrideInfoUrl(projectName).orElse(null);
+    generalInfo.fallbackCodeOwners =
+        codeOwnersPluginConfiguration.getFallbackCodeOwners(projectName);
     return generalInfo;
   }
 
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerBranchConfigIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerBranchConfigIT.java
index 37d0d23..7b2dae6 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerBranchConfigIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerBranchConfigIT.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.plugins.codeowners.api.MergeCommitStrategy;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackendId;
+import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
 import com.google.gerrit.plugins.codeowners.config.BackendConfig;
 import com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfiguration;
 import com.google.gerrit.plugins.codeowners.config.GeneralConfig;
@@ -88,6 +89,8 @@
     assertThat(codeOwnerBranchConfigInfo.general.fileExtension).isNull();
     assertThat(codeOwnerBranchConfigInfo.general.mergeCommitStrategy)
         .isEqualTo(MergeCommitStrategy.ALL_CHANGED_FILES);
+    assertThat(codeOwnerBranchConfigInfo.general.fallbackCodeOwners)
+        .isEqualTo(FallbackCodeOwners.NONE);
     assertThat(codeOwnerBranchConfigInfo.general.implicitApprovals).isNull();
     assertThat(codeOwnerBranchConfigInfo.general.overrideInfoUrl).isNull();
     assertThat(codeOwnerBranchConfigInfo.disabled).isNull();
@@ -128,6 +131,15 @@
   }
 
   @Test
+  public void getConfigWithConfiguredFallbackCodeOwners() throws Exception {
+    configureFallbackCodeOwners(project, FallbackCodeOwners.ALL_USERS);
+    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
+        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
+    assertThat(codeOwnerBranchConfigInfo.general.fallbackCodeOwners)
+        .isEqualTo(FallbackCodeOwners.ALL_USERS);
+  }
+
+  @Test
   public void getConfigForBranchOfDisabledProject() throws Exception {
     disableCodeOwnersForProject(project);
     CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
@@ -244,6 +256,11 @@
     setConfig(project, null, GeneralConfig.KEY_MERGE_COMMIT_STRATEGY, mergeCommitStrategy.name());
   }
 
+  private void configureFallbackCodeOwners(
+      Project.NameKey project, FallbackCodeOwners fallbackCodeOwners) throws Exception {
+    setConfig(project, null, GeneralConfig.KEY_FALLBACK_CODE_OWNERS, fallbackCodeOwners.name());
+  }
+
   private void configureDisabledBranch(Project.NameKey project, String disabledBranch)
       throws Exception {
     setCodeOwnersConfig(project, null, StatusConfig.KEY_DISABLED_BRANCH, disabledBranch);
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerProjectConfigIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerProjectConfigIT.java
index e936dda..4f61669 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerProjectConfigIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnerProjectConfigIT.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.plugins.codeowners.api.MergeCommitStrategy;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackendId;
+import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
 import com.google.gerrit.plugins.codeowners.config.BackendConfig;
 import com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfiguration;
 import com.google.gerrit.plugins.codeowners.config.GeneralConfig;
@@ -87,6 +88,8 @@
     assertThat(codeOwnerProjectConfigInfo.general.fileExtension).isNull();
     assertThat(codeOwnerProjectConfigInfo.general.mergeCommitStrategy)
         .isEqualTo(MergeCommitStrategy.ALL_CHANGED_FILES);
+    assertThat(codeOwnerProjectConfigInfo.general.fallbackCodeOwners)
+        .isEqualTo(FallbackCodeOwners.NONE);
     assertThat(codeOwnerProjectConfigInfo.general.implicitApprovals).isNull();
     assertThat(codeOwnerProjectConfigInfo.general.overrideInfoUrl).isNull();
     assertThat(codeOwnerProjectConfigInfo.status.disabled).isNull();
@@ -129,6 +132,15 @@
   }
 
   @Test
+  public void getConfigWithConfiguredFallbackCodeOwners() throws Exception {
+    configureFallbackCodeOwners(project, FallbackCodeOwners.ALL_USERS);
+    CodeOwnerProjectConfigInfo codeOwnerProjectConfigInfo =
+        projectCodeOwnersApiFactory.project(project).getConfig();
+    assertThat(codeOwnerProjectConfigInfo.general.fallbackCodeOwners)
+        .isEqualTo(FallbackCodeOwners.ALL_USERS);
+  }
+
+  @Test
   public void getConfigForDisabledProject() throws Exception {
     disableCodeOwnersForProject(project);
     CodeOwnerProjectConfigInfo codeOwnerProjectConfigInfo =
@@ -263,6 +275,11 @@
     setConfig(project, null, GeneralConfig.KEY_MERGE_COMMIT_STRATEGY, mergeCommitStrategy.name());
   }
 
+  private void configureFallbackCodeOwners(
+      Project.NameKey project, FallbackCodeOwners fallbackCodeOwners) throws Exception {
+    setConfig(project, null, GeneralConfig.KEY_FALLBACK_CODE_OWNERS, fallbackCodeOwners.name());
+  }
+
   private void configureDisabledBranch(Project.NameKey project, String disabledBranch)
       throws Exception {
     setCodeOwnersConfig(project, null, StatusConfig.KEY_DISABLED_BRANCH, disabledBranch);
diff --git a/javatests/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJsonTest.java b/javatests/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJsonTest.java
index 30f8454..deba4b3 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJsonTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/restapi/CodeOwnerProjectConfigJsonTest.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.plugins.codeowners.api.RequiredApprovalInfo;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackendId;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigScanner;
+import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
 import com.google.gerrit.plugins.codeowners.backend.findowners.FindOwnersBackend;
 import com.google.gerrit.plugins.codeowners.backend.proto.ProtoBackend;
 import com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfiguration;
@@ -160,6 +161,8 @@
         .thenReturn(Optional.of("http://foo.example.com"));
     when(codeOwnersPluginConfiguration.getMergeCommitStrategy(project))
         .thenReturn(MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
+    when(codeOwnersPluginConfiguration.getFallbackCodeOwners(project))
+        .thenReturn(FallbackCodeOwners.ALL_USERS);
     when(codeOwnersPluginConfiguration.areImplicitApprovalsEnabled(project)).thenReturn(true);
     when(codeOwnersPluginConfiguration.getRequiredApproval(project))
         .thenReturn(RequiredApproval.create(getDefaultCodeReviewLabel(), (short) 2));
@@ -178,6 +181,8 @@
         .isEqualTo("http://foo.example.com");
     assertThat(codeOwnerProjectConfigInfo.general.mergeCommitStrategy)
         .isEqualTo(MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
+    assertThat(codeOwnerProjectConfigInfo.general.fallbackCodeOwners)
+        .isEqualTo(FallbackCodeOwners.ALL_USERS);
     assertThat(codeOwnerProjectConfigInfo.general.implicitApprovals).isTrue();
     assertThat(codeOwnerProjectConfigInfo.backend.id)
         .isEqualTo(CodeOwnerBackendId.FIND_OWNERS.getBackendId());
@@ -246,6 +251,8 @@
         .thenReturn(Optional.of("http://foo.example.com"));
     when(codeOwnersPluginConfiguration.getMergeCommitStrategy(project))
         .thenReturn(MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
+    when(codeOwnersPluginConfiguration.getFallbackCodeOwners(project))
+        .thenReturn(FallbackCodeOwners.ALL_USERS);
     when(codeOwnersPluginConfiguration.areImplicitApprovalsEnabled(project)).thenReturn(true);
     when(codeOwnersPluginConfiguration.getRequiredApproval(project))
         .thenReturn(RequiredApproval.create(getDefaultCodeReviewLabel(), (short) 2));
@@ -263,6 +270,8 @@
         .isEqualTo("http://foo.example.com");
     assertThat(codeOwnerBranchConfigInfo.general.mergeCommitStrategy)
         .isEqualTo(MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
+    assertThat(codeOwnerBranchConfigInfo.general.fallbackCodeOwners)
+        .isEqualTo(FallbackCodeOwners.ALL_USERS);
     assertThat(codeOwnerBranchConfigInfo.general.implicitApprovals).isTrue();
     assertThat(codeOwnerBranchConfigInfo.backendId)
         .isEqualTo(CodeOwnerBackendId.FIND_OWNERS.getBackendId());
@@ -299,6 +308,8 @@
         .thenReturn(Optional.of("http://foo.example.com"));
     when(codeOwnersPluginConfiguration.getMergeCommitStrategy(project))
         .thenReturn(MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
+    when(codeOwnersPluginConfiguration.getFallbackCodeOwners(project))
+        .thenReturn(FallbackCodeOwners.ALL_USERS);
     when(codeOwnersPluginConfiguration.areImplicitApprovalsEnabled(project)).thenReturn(true);
     when(codeOwnersPluginConfiguration.getRequiredApproval(project))
         .thenReturn(RequiredApproval.create(getDefaultCodeReviewLabel(), (short) 2));
diff --git a/resources/Documentation/rest-api.md b/resources/Documentation/rest-api.md
index 3fd9f84..058d1ff 100644
--- a/resources/Documentation/rest-api.md
+++ b/resources/Documentation/rest-api.md
@@ -685,6 +685,7 @@
 | `merge_commit_strategy` || Strategy that defines for merge commits which files require code owner approvals. Can be `ALL_CHANGED_FILES` or `FILES_WITH_CONFLICT_RESOLUTION` (see [mergeCommitStrategy](config.html#pluginCodeOwnersMergeCommitStrategy) for an explanation of these values).
 | `implicit_approvals` | optional |  Whether an implicit code owner approval from the last uploader is assumed (see [enableImplicitApprovals](config.html#pluginCodeOwnersEnableImplicitApprovals) for details). When unset, `false`.
 | `override_info_url` | optional | Optional URL for a page that provides project/host-specific information about how to request a code owner override.
+|`fallback_code_owners` || Policy that controls who should own paths that have no code owners defined. Possible values are: `NONE`: Paths for which no code owners are defined are owned by no one. `ALL_USER`: Paths for which no code owners are defined are owned by all users.
 
 ### <a id="path-code-owner-status-info"> PathCodeOwnerStatusInfo
 The `PathCodeOwnerStatusInfo` entity describes the code owner status for a path