]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9616 Handle branch in api/settings/values
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 25 Aug 2017 08:05:09 +0000 (10:05 +0200)
committerJanos Gyerik <janos.gyerik@sonarsource.com>
Tue, 12 Sep 2017 09:34:53 +0000 (11:34 +0200)
server/sonar-server/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/setting/SettingsService.java
sonar-ws/src/main/java/org/sonarqube/ws/client/setting/ValuesRequest.java
sonar-ws/src/test/java/org/sonarqube/ws/client/setting/SettingsServiceTest.java
sonar-ws/src/test/java/org/sonarqube/ws/client/setting/ValuesRequestTest.java

index 836e944cb1bf2f988888ba0949d33b45da9a5543..db6e2c21e31437b28be2550d8a7ab683cbd502dc 100644 (file)
@@ -49,9 +49,11 @@ import static java.util.stream.Stream.concat;
 import static org.apache.commons.lang.StringUtils.isEmpty;
 import static org.sonar.api.PropertyType.PROPERTY_SET;
 import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_VALUES;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_BRANCH;
 import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT;
 import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;
 
@@ -95,12 +97,17 @@ public class ValuesAction implements SettingsWsAction {
       .setResponseExample(getClass().getResource("values-example.json"))
       .setSince("6.3")
       .setHandler(this);
-    action.createParam(PARAM_COMPONENT)
-      .setDescription("Component key")
-      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
     action.createParam(PARAM_KEYS)
       .setDescription("List of setting keys")
       .setExampleValue("sonar.test.inclusions,sonar.dbcleaner.cleanDirectory");
+    action.createParam(PARAM_COMPONENT)
+      .setDescription("Component key")
+      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+    action.createParam(PARAM_BRANCH)
+      .setDescription("Branch key")
+      .setExampleValue(KEY_BRANCH_EXAMPLE_001)
+      .setInternal(true)
+      .setSince("6.6");
   }
 
   @Override
@@ -122,7 +129,8 @@ public class ValuesAction implements SettingsWsAction {
 
   private static ValuesRequest toWsRequest(Request request) {
     ValuesRequest.Builder builder = ValuesRequest.builder()
-      .setComponent(request.param(PARAM_COMPONENT));
+      .setComponent(request.param(PARAM_COMPONENT))
+      .setBranch(request.param(PARAM_BRANCH));
     if (request.hasParam(PARAM_KEYS)) {
       builder.setKeys(request.paramAsStrings(PARAM_KEYS));
     }
@@ -142,16 +150,20 @@ public class ValuesAction implements SettingsWsAction {
     if (componentKey == null) {
       return Optional.empty();
     }
-    ComponentDto component = componentFinder.getByKey(dbSession, componentKey);
+    ComponentDto component = componentFinder.getByKeyAndOptionalBranch(dbSession, componentKey, valuesRequest.getBranch());
     userSession.checkComponentPermission(USER, component);
     return Optional.of(component);
   }
 
   private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys) {
-    // List of settings must be kept in the following orders : default -> global -> component
+    // List of settings must be kept in the following orders : default -> global -> component -> branch
     List<Setting> settings = new ArrayList<>();
     settings.addAll(loadDefaultSettings(keys));
     settings.addAll(settingsFinder.loadGlobalSettings(dbSession, keys));
+    if (component.isPresent() && component.get().getBranch() != null && component.get().getMainBranchProjectUuid() != null) {
+      ComponentDto project = dbClient.componentDao().selectOrFailByUuid(dbSession, component.get().getMainBranchProjectUuid());
+      settings.addAll(settingsFinder.loadComponentSettings(dbSession, keys, project).values());
+    }
     component.ifPresent(componentDto -> settings.addAll(settingsFinder.loadComponentSettings(dbSession, keys, componentDto).values()));
     return settings.stream()
       .filter(settingsWsSupport.isSettingVisible(component))
index 1624a068e857d2559f9a30ff58c1d36eb807d555..951d74abe7ef610551289f470c4d41267b7f9756 100644 (file)
@@ -727,6 +727,42 @@ public class ValuesActionTest {
     assertThat(result.getSettings(0).getValue()).isEqualTo("fi±∞…");
   }
 
+  @Test
+  public void branch_values() throws Exception {
+    ComponentDto project = db.components().insertMainBranch();
+    userSession.logIn().addProjectPermission(USER, project);
+    ComponentDto branch = db.components().insertProjectBranch(project);
+    definitions.addComponent(PropertyDefinition.builder("sonar.leak.period").onQualifiers(PROJECT).build());
+    propertyDb.insertProperties(newComponentPropertyDto(branch).setKey("sonar.leak.period").setValue("two"));
+
+    ValuesWsResponse result =  ws.newRequest()
+      .setParam("keys", "sonar.leak.period")
+      .setParam("component", branch.getKey())
+      .setParam("branch", branch.getBranch())
+      .executeProtobuf(ValuesWsResponse.class);
+
+    assertThat(result.getSettingsList()).hasSize(1);
+    assertSetting(result.getSettings(0), "sonar.leak.period", "two", false);
+  }
+
+  @Test
+  public void branch_values_inherit_from_project() throws Exception {
+    ComponentDto project = db.components().insertMainBranch();
+    userSession.logIn().addProjectPermission(USER, project);
+    ComponentDto branch = db.components().insertProjectBranch(project);
+    definitions.addComponent(PropertyDefinition.builder("sonar.leak.period").onQualifiers(PROJECT).build());
+    propertyDb.insertProperties(newComponentPropertyDto(project).setKey("sonar.leak.period").setValue("two"));
+
+    ValuesWsResponse result =  ws.newRequest()
+      .setParam("keys", "sonar.leak.period")
+      .setParam("component", branch.getKey())
+      .setParam("branch", branch.getBranch())
+      .executeProtobuf(ValuesWsResponse.class);
+
+    assertThat(result.getSettingsList()).hasSize(1);
+    assertSetting(result.getSettings(0), "sonar.leak.period", "two", true);
+  }
+
   @Test
   public void fail_when_user_has_not_project_browse_permission() throws Exception {
     userSession.logIn("project-admin").addProjectPermission(CODEVIEWER, project);
@@ -752,6 +788,34 @@ public class ValuesActionTest {
     executeRequestForGlobalProperties("foo", "deprecated");
   }
 
+  @Test
+  public void fail_when_component_not_found() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Component key 'unknown' not found");
+
+    ws.newRequest()
+      .setParam("keys", "foo")
+      .setParam("component", "unknown")
+      .execute();
+  }
+
+  @Test
+  public void fail_when_branch_not_found() {
+    ComponentDto project = db.components().insertMainBranch();
+    ComponentDto branch = db.components().insertProjectBranch(project);
+    String settingKey = "not_allowed_on_branch";
+    userSession.logIn().addProjectPermission(USER, project);
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", branch.getKey()));
+
+    ws.newRequest()
+      .setParam("keys", settingKey)
+      .setParam("component", branch.getKey())
+      .setParam("branch", "unknown")
+      .execute();
+  }
+
   @Test
   public void test_example_json_response() {
     logIn();
@@ -804,7 +868,7 @@ public class ValuesActionTest {
     assertThat(action.isInternal()).isFalse();
     assertThat(action.isPost()).isFalse();
     assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.params()).hasSize(2);
+    assertThat(action.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("keys", "component", "branch");
   }
 
   private ValuesWsResponse executeRequestForComponentProperties(ComponentDto componentDto, String... keys) {
index 230dbd992a528b1df1a8ce95a3d97f3d27bc9b41..3348fdb48c53d096de1a512a727ea0d375e33300 100644 (file)
@@ -53,7 +53,8 @@ public class SettingsService extends BaseService {
   public ValuesWsResponse values(ValuesRequest request) {
     GetRequest getRequest = new GetRequest(path(ACTION_VALUES))
       .setParam(PARAM_KEYS, inlineMultipleParamValue(request.getKeys()))
-      .setParam(PARAM_COMPONENT, request.getComponent());
+      .setParam(PARAM_COMPONENT, request.getComponent())
+      .setParam(PARAM_BRANCH, request.getBranch());
     return call(getRequest, ValuesWsResponse.parser());
   }
 
@@ -64,16 +65,14 @@ public class SettingsService extends BaseService {
       .setParam(PARAM_VALUES, request.getValues())
       .setParam(PARAM_FIELD_VALUES, request.getFieldValues())
       .setParam(PARAM_COMPONENT, request.getComponent())
-      .setParam(PARAM_BRANCH, request.getBranch())
-    );
+      .setParam(PARAM_BRANCH, request.getBranch()));
   }
 
   public void reset(ResetRequest request) {
     call(new PostRequest(path(ACTION_RESET))
       .setParam(PARAM_KEYS, inlineMultipleParamValue(request.getKeys()))
       .setParam(PARAM_COMPONENT, request.getComponent())
-      .setParam(PARAM_BRANCH, request.getBranch())
-    );
+      .setParam(PARAM_BRANCH, request.getBranch()));
   }
 
 }
index 6352e845fe88c9e29a967274ce5f3161916b1407..f45d8d015d62b747d6cc488b8423dd42b9a1557d 100644 (file)
@@ -29,12 +29,18 @@ import static java.util.Objects.requireNonNull;
 
 public class ValuesRequest {
 
-  private final String component;
   private final List<String> keys;
+  private final String component;
+  private final String branch;
 
   private ValuesRequest(Builder builder) {
-    this.component = builder.component;
     this.keys = builder.keys;
+    this.component = builder.component;
+    this.branch = builder.branch;
+  }
+
+  public List<String> getKeys() {
+    return keys;
   }
 
   @CheckForNull
@@ -42,8 +48,9 @@ public class ValuesRequest {
     return component;
   }
 
-  public List<String> getKeys() {
-    return keys;
+  @CheckForNull
+  public String getBranch() {
+    return branch;
   }
 
   public static Builder builder() {
@@ -51,18 +58,14 @@ public class ValuesRequest {
   }
 
   public static class Builder {
-    private String component;
     private List<String> keys = new ArrayList<>();
+    private String component;
+    private String branch;
 
     private Builder() {
       // enforce factory method use
     }
 
-    public Builder setComponent(@Nullable String component) {
-      this.component = component;
-      return this;
-    }
-
     public Builder setKeys(List<String> keys) {
       this.keys = requireNonNull(keys);
       return this;
@@ -72,6 +75,16 @@ public class ValuesRequest {
       return setKeys(asList(keys));
     }
 
+    public Builder setComponent(@Nullable String component) {
+      this.component = component;
+      return this;
+    }
+
+    public Builder setBranch(@Nullable String branch) {
+      this.branch = branch;
+      return this;
+    }
+
     public ValuesRequest build() {
       return new ValuesRequest(this);
     }
index c3c1f9c051e40b90a9cde655d972abfb807f878e..247acd0247f5808b9878cee31ef0c2fab5971986 100644 (file)
@@ -63,6 +63,7 @@ public class SettingsServiceTest {
     underTest.values(ValuesRequest.builder()
       .setKeys("sonar.debt,sonar.issue")
       .setComponent("KEY")
+      .setBranch("BRANCH")
       .build());
     GetRequest getRequest = serviceTester.getGetRequest();
 
@@ -70,6 +71,7 @@ public class SettingsServiceTest {
     serviceTester.assertThat(getRequest)
       .hasParam(PARAM_KEYS, "sonar.debt,sonar.issue")
       .hasParam(PARAM_COMPONENT, "KEY")
+      .hasParam(PARAM_BRANCH, "BRANCH")
       .andNoOtherParam();
   }
 
index fc0537d201415a531c6739a2bf036bad393297c9..fa6bdf940741ed456c1e624ed4dbbeffa22d40fd 100644 (file)
@@ -36,24 +36,36 @@ public class ValuesRequestTest {
   public void create_request_with_no_component() {
     ValuesRequest result = underTest.setKeys("sonar.debt").build();
 
-    assertThat(result.getComponent()).isNull();
     assertThat(result.getKeys()).containsOnly("sonar.debt");
+    assertThat(result.getComponent()).isNull();
+    assertThat(result.getBranch()).isNull();
   }
 
   @Test
   public void create_request_with_no_keys() {
     ValuesRequest result = underTest.build();
 
-    assertThat(result.getComponent()).isNull();
     assertThat(result.getKeys()).isEmpty();
+    assertThat(result.getComponent()).isNull();
+    assertThat(result.getBranch()).isNull();
   }
 
   @Test
   public void create_request_with_component() {
     ValuesRequest result = underTest.setKeys("sonar.debt").setComponent("projectKey").build();
 
+    assertThat(result.getKeys()).containsOnly("sonar.debt");
     assertThat(result.getComponent()).isEqualTo("projectKey");
+    assertThat(result.getBranch()).isNull();
+  }
+
+  @Test
+  public void create_request_with_component_and_branch() {
+    ValuesRequest result = underTest.setKeys("sonar.debt").setComponent("projectKey").setBranch("branch").build();
+
     assertThat(result.getKeys()).containsOnly("sonar.debt");
+    assertThat(result.getComponent()).isEqualTo("projectKey");
+    assertThat(result.getBranch()).isEqualTo("branch");
   }
 
 }