diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-08-04 12:02:40 +0200 |
---|---|---|
committer | Janos Gyerik <janos.gyerik@sonarsource.com> | 2017-09-12 10:55:10 +0200 |
commit | 5c9f6c0ddd90b00de33f37bd1ce40b10935eaa27 (patch) | |
tree | c757f599841f7342e0223e0a4ec2addd00be0e3d | |
parent | 4f500d461015eb6edc471677961c72e8e68b87bf (diff) | |
download | sonarqube-5c9f6c0ddd90b00de33f37bd1ce40b10935eaa27.tar.gz sonarqube-5c9f6c0ddd90b00de33f37bd1ce40b10935eaa27.zip |
SONAR-9616 Support branch in api/measures/component_tree
6 files changed, 91 insertions, 14 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java index b3e3c5b5ae6..8c894c4dae9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java @@ -54,6 +54,7 @@ import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createAddi import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters; import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetric; +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.WsParameterBuilder.createQualifiersParameter; import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; @@ -65,6 +66,7 @@ import static org.sonarqube.ws.client.measure.MeasuresWsParameters.ADDITIONAL_PE import static org.sonarqube.ws.client.measure.MeasuresWsParameters.DEPRECATED_PARAM_BASE_COMPONENT_ID; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.DEPRECATED_PARAM_BASE_COMPONENT_KEY; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_ADDITIONAL_FIELDS; +import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_BRANCH; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_DEVELOPER_ID; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_DEVELOPER_KEY; @@ -165,6 +167,12 @@ public class ComponentTreeAction implements MeasuresWsAction { .setExampleValue(KEY_PROJECT_EXAMPLE_001) .setDeprecatedKey(DEPRECATED_PARAM_BASE_COMPONENT_KEY, "6.6"); + action.createParam(PARAM_BRANCH) + .setDescription("Branch key") + .setExampleValue(KEY_BRANCH_EXAMPLE_001) + .setInternal(true) + .setSince("6.6"); + action.createParam(PARAM_METRIC_SORT) .setDescription( format("Metric key to sort by. The '%s' parameter must contain the '%s' or '%s' value. It must be part of the '%s' parameter", Param.SORT, METRIC_SORT, METRIC_PERIOD_SORT, @@ -283,6 +291,7 @@ public class ComponentTreeAction implements MeasuresWsAction { ComponentTreeWsRequest componentTreeWsRequest = new ComponentTreeWsRequest() .setBaseComponentId(request.param(DEPRECATED_PARAM_BASE_COMPONENT_ID)) .setComponent(request.param(PARAM_COMPONENT)) + .setBranch(request.param(PARAM_BRANCH)) .setMetricKeys(metricKeys) .setStrategy(request.mandatoryParam(PARAM_STRATEGY)) .setQualifiers(request.paramAsStrings(PARAM_QUALIFIERS)) diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java index b454bebd4fa..e599bb77803 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java @@ -74,6 +74,8 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.LEAVES_STRATEGY; import static org.sonar.server.measure.ws.ComponentTreeAction.STRATEGIES; import static org.sonar.server.measure.ws.ComponentTreeAction.WITH_MEASURES_ONLY_METRIC_SORT_FILTER; import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPeriods; +import static org.sonarqube.ws.client.measure.MeasuresWsParameters.DEPRECATED_PARAM_BASE_COMPONENT_ID; +import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_BRANCH; public class ComponentTreeDataLoader { private static final Set<String> QUALIFIERS_ELIGIBLE_FOR_BEST_VALUE = ImmutableSet.of(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE); @@ -93,7 +95,7 @@ public class ComponentTreeDataLoader { ComponentTreeData load(ComponentTreeWsRequest wsRequest) { try (DbSession dbSession = dbClient.openSession(false)) { - ComponentDto baseComponent = componentFinder.getByUuidOrKey(dbSession, wsRequest.getBaseComponentId(), wsRequest.getComponent(), BASE_COMPONENT_ID_AND_KEY); + ComponentDto baseComponent = loadComponent(dbSession, wsRequest); checkPermissions(baseComponent); Optional<SnapshotDto> baseSnapshot = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, baseComponent.projectUuid()); if (!baseSnapshot.isPresent()) { @@ -128,6 +130,16 @@ public class ComponentTreeDataLoader { } } + private ComponentDto loadComponent(DbSession dbSession, ComponentTreeWsRequest request) { + String componentKey = request.getComponent(); + String componentId = request.getBaseComponentId(); + String branch = request.getBranch(); + checkArgument(componentId == null || branch == null, "'%s' and '%s' parameters cannot be used at the same time", DEPRECATED_PARAM_BASE_COMPONENT_ID, PARAM_BRANCH); + return branch == null + ? componentFinder.getByUuidOrKey(dbSession, componentId, componentKey, BASE_COMPONENT_ID_AND_KEY) + : componentFinder.getByKeyAndBranch(dbSession, componentKey, branch); + } + @CheckForNull private Long searchDeveloperId(DbSession dbSession, ComponentTreeWsRequest wsRequest) { if (wsRequest.getDeveloperId() == null && wsRequest.getDeveloperKey() == null) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java index b9f233b5693..2c3e8e2cfd5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java @@ -22,7 +22,6 @@ package org.sonar.server.measure.ws; import com.google.common.base.Joiner; import java.util.List; import java.util.stream.IntStream; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -39,6 +38,7 @@ import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ResourceTypesRule; import org.sonar.db.component.SnapshotDto; +import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.MetricTesting; import org.sonar.server.component.ComponentFinder; @@ -52,6 +52,7 @@ import org.sonarqube.ws.Common; import org.sonarqube.ws.WsMeasures; import org.sonarqube.ws.WsMeasures.ComponentTreeWsResponse; +import static java.lang.Double.parseDouble; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; @@ -60,6 +61,11 @@ import static org.sonar.api.measures.Metric.ValueType.DISTRIB; import static org.sonar.api.measures.Metric.ValueType.FLOAT; import static org.sonar.api.measures.Metric.ValueType.INT; import static org.sonar.api.measures.Metric.ValueType.RATING; +import static org.sonar.api.resources.Qualifiers.DIRECTORY; +import static org.sonar.api.resources.Qualifiers.FILE; +import static org.sonar.api.resources.Qualifiers.MODULE; +import static org.sonar.api.resources.Qualifiers.PROJECT; +import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; import static org.sonar.api.server.ws.WebService.Param.SORT; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.api.web.UserRole.USER; @@ -78,6 +84,7 @@ import static org.sonar.test.JsonAssert.assertJson; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.ADDITIONAL_PERIODS; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.DEPRECATED_PARAM_BASE_COMPONENT_KEY; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_ADDITIONAL_FIELDS; +import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_BRANCH; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS; import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_PERIOD_SORT; @@ -88,14 +95,17 @@ import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_STRATEG public class ComponentTreeActionTest { @Rule - public UserSessionRule userSession = UserSessionRule.standalone(); + public UserSessionRule userSession = UserSessionRule.standalone().logIn().setRoot(); @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); private I18nRule i18n = new I18nRule(); - private ResourceTypesRule resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT); + private ResourceTypesRule resourceTypes = new ResourceTypesRule() + .setRootQualifiers(PROJECT) + .setChildrenQualifiers(MODULE, FILE, DIRECTORY) + .setLeavesQualifiers(FILE, UNIT_TEST_FILE); private ComponentDbTester componentDb = new ComponentDbTester(db); private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); @@ -105,13 +115,6 @@ public class ComponentTreeActionTest { new ComponentTreeDataLoader(dbClient, new ComponentFinder(dbClient, resourceTypes), userSession, resourceTypes), i18n, resourceTypes)); - @Before - public void setUp() { - userSession.logIn().setRoot(); - resourceTypes.setChildrenQualifiers(Qualifiers.MODULE, Qualifiers.FILE, Qualifiers.DIRECTORY); - resourceTypes.setLeavesQualifiers(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE); - } - @Test public void json_example() { ComponentDto project = db.components().insertPrivateProject(p -> p.setDbKey("MY_PROJECT") @@ -124,19 +127,19 @@ public class ComponentTreeActionTest { .setDbKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java") .setName("ElementImpl.java") .setLanguage("java") - .setQualifier(Qualifiers.FILE) + .setQualifier(FILE) .setPath("src/main/java/com/sonarsource/markdown/impl/ElementImpl.java")); ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null) .setUuid("AVIwDXE_bJbJqrw6wFwJ") .setDbKey("com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java") .setName("ElementImplTest.java") .setLanguage("java") - .setQualifier(Qualifiers.UNIT_TEST_FILE) + .setQualifier(UNIT_TEST_FILE) .setPath("src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java")); ComponentDto dir = componentDb.insertComponent(newDirectory(project, "src/main/java/com/sonarsource/markdown/impl") .setUuid("AVIwDXE-bJbJqrw6wFv8") .setDbKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl") - .setQualifier(Qualifiers.DIRECTORY)); + .setQualifier(DIRECTORY)); MetricDto complexity = insertComplexityMetric(); dbClient.measureDao().insert(dbSession, @@ -488,6 +491,28 @@ public class ComponentTreeActionTest { } @Test + public void branch() { + ComponentDto project = db.components().insertPrivateProject(); + ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("my_branch")); + SnapshotDto analysis = db.components().insertSnapshot(branch); + ComponentDto file = db.components().insertComponent(newFileDto(branch)); + MetricDto complexity = insertComplexityMetric(); + MeasureDto measure = db.measures().insertMeasure(file, analysis, complexity, m -> m.setValue(12.0d)); + + ComponentTreeWsResponse response = ws.newRequest() + .setParam(PARAM_COMPONENT, file.getKey()) + .setParam(PARAM_BRANCH, file.getBranch()) + .setParam(PARAM_METRIC_KEYS, complexity.getKey()) + .executeProtobuf(WsMeasures.ComponentTreeWsResponse.class); + + assertThat(response.getBaseComponent()).extracting(WsMeasures.Component::getKey, WsMeasures.Component::getBranch) + .containsExactlyInAnyOrder(file.getKey(), file.getBranch()); + assertThat(response.getBaseComponent().getMeasuresList()) + .extracting(WsMeasures.Measure::getMetric, m -> parseDouble(m.getValue())) + .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); + } + + @Test public void return_deprecated_id_in_the_response() { ComponentDto project = db.components().insertPrivateProject(); SnapshotDto analysis = db.components().insertSnapshot(project); @@ -796,6 +821,23 @@ public class ComponentTreeActionTest { .execute(); } + @Test + public void fail_if_branch_does_not_exist() { + ComponentDto project = db.components().insertPrivateProject(); + ComponentDto file = db.components().insertComponent(newFileDto(project)); + userSession.addProjectPermission(UserRole.USER, project); + db.components().insertProjectBranch(project, b -> b.setKey("my_branch")); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(String.format("Component '%s' on branch '%s' not found", file.getKey(), "another_branch")); + + ws.newRequest() + .setParam(PARAM_COMPONENT, file.getKey()) + .setParam(PARAM_BRANCH, "another_branch") + .setParam(PARAM_METRIC_KEYS, "ncloc") + .execute(); + } + private static MetricDto newMetricDto() { return MetricTesting.newMetricDto() .setWorstValue(null) diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/ComponentTreeWsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/ComponentTreeWsRequest.java index d6c550eae92..0a89515828a 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/ComponentTreeWsRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/ComponentTreeWsRequest.java @@ -28,6 +28,7 @@ public class ComponentTreeWsRequest { private String baseComponentId; private String baseComponentKey; private String component; + private String branch; private String strategy; private List<String> qualifiers; private List<String> additionalFields; @@ -90,6 +91,16 @@ public class ComponentTreeWsRequest { } @CheckForNull + public String getBranch() { + return branch; + } + + public ComponentTreeWsRequest setBranch(@Nullable String branch) { + this.branch = branch; + return this; + } + + @CheckForNull public String getStrategy() { return strategy; } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/MeasuresService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/MeasuresService.java index 9c94c285667..db8b7e4bde2 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/MeasuresService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/measure/MeasuresService.java @@ -61,6 +61,7 @@ public class MeasuresService extends BaseService { .setParam(DEPRECATED_PARAM_BASE_COMPONENT_ID, request.getBaseComponentId()) .setParam(DEPRECATED_PARAM_BASE_COMPONENT_KEY, request.getBaseComponentKey()) .setParam(PARAM_COMPONENT, request.getComponent()) + .setParam(PARAM_BRANCH, request.getBranch()) .setParam(PARAM_STRATEGY, request.getStrategy()) .setParam(PARAM_QUALIFIERS, inlineMultipleParamValue(request.getQualifiers())) .setParam(PARAM_METRIC_KEYS, inlineMultipleParamValue(request.getMetricKeys())) diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/measure/MeasuresServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/measure/MeasuresServiceTest.java index b42cc3e45ad..c8d4e66d339 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/measure/MeasuresServiceTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/measure/MeasuresServiceTest.java @@ -114,6 +114,7 @@ public class MeasuresServiceTest { .setBaseComponentId(VALUE_BASE_COMPONENT_ID) .setBaseComponentKey(VALUE_BASE_COMPONENT_KEY) .setComponent(VALUE_BASE_COMPONENT_KEY) + .setBranch("my_branch") .setMetricKeys(VALUE_METRIC_KEYS) .setStrategy(VALUE_STRATEGY) .setQualifiers(VALUE_QUALIFIERS) @@ -136,6 +137,7 @@ public class MeasuresServiceTest { .hasParam(DEPRECATED_PARAM_BASE_COMPONENT_ID, VALUE_BASE_COMPONENT_ID) .hasParam(DEPRECATED_PARAM_BASE_COMPONENT_KEY, VALUE_BASE_COMPONENT_KEY) .hasParam(PARAM_COMPONENT, VALUE_BASE_COMPONENT_KEY) + .hasParam(PARAM_BRANCH, "my_branch") .hasParam(PARAM_METRIC_KEYS, "ncloc,complexity") .hasParam(PARAM_STRATEGY, VALUE_STRATEGY) .hasParam(PARAM_QUALIFIERS, "FIL,PRJ") |