aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-12-15 15:01:22 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-12-18 09:26:36 +0100
commitec804c4ee14131a5cf4aa0113546a46737b86409 (patch)
treeb1c2111b2fd7df144851de745b38d65761fe4c20
parent99c250bebeb529e77e6472750b47caee98c0edd3 (diff)
downloadsonarqube-ec804c4ee14131a5cf4aa0113546a46737b86409.tar.gz
sonarqube-ec804c4ee14131a5cf4aa0113546a46737b86409.zip
SONAR-10126 add scmPath to ReportAttributes
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java42
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ReportAttributes.java22
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilderTest.java124
4 files changed, 173 insertions, 18 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java
index 0581d636b86..219919562ba 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java
@@ -78,19 +78,21 @@ public class ComponentTreeBuilder {
this.baseAnalysis = baseAnalysis;
}
- public Component buildProject(ScannerReport.Component project) {
- return buildComponent(project, project);
+ public Component buildProject(ScannerReport.Component project, String scmBasePath) {
+ return buildComponent(project, project, trimToNull(scmBasePath));
}
- private List<Component> buildChildren(ScannerReport.Component component, ScannerReport.Component parentModule) {
+ private List<Component> buildChildren(ScannerReport.Component component, ScannerReport.Component parentModule,
+ String projectScmPath) {
return component.getChildRefList()
.stream()
.map(scannerComponentSupplier::apply)
- .map(c -> buildComponent(c, parentModule))
+ .map(c -> buildComponent(c, parentModule, projectScmPath))
.collect(Collectors.toList());
}
- private ComponentImpl buildComponent(ScannerReport.Component component, ScannerReport.Component closestModule) {
+ private ComponentImpl buildComponent(ScannerReport.Component component, ScannerReport.Component closestModule,
+ @Nullable String scmBasePath) {
switch (component.getType()) {
case PROJECT:
String projectKey = keyGenerator.generateKey(component, null);
@@ -103,10 +105,10 @@ public class ComponentTreeBuilder {
.setName(nameOfProject(component))
.setStatus(convertStatus(component.getStatus()))
.setDescription(trimToNull(component.getDescription()))
- .setReportAttributes(createAttributesBuilder(component)
+ .setReportAttributes(createAttributesBuilder(component, scmBasePath)
.setVersion(createProjectVersion(component))
.build())
- .addChildren(buildChildren(component, component))
+ .addChildren(buildChildren(component, component, scmBasePath))
.build();
case MODULE:
@@ -119,8 +121,8 @@ public class ComponentTreeBuilder {
.setName(nameOfOthers(component, modulePublicKey))
.setStatus(convertStatus(component.getStatus()))
.setDescription(trimToNull(component.getDescription()))
- .setReportAttributes(createAttributesBuilder(component).build())
- .addChildren(buildChildren(component, component))
+ .setReportAttributes(createAttributesBuilder(component, scmBasePath).build())
+ .addChildren(buildChildren(component, component, scmBasePath))
.build();
case DIRECTORY:
@@ -134,9 +136,9 @@ public class ComponentTreeBuilder {
.setName(nameOfOthers(component, publicKey))
.setStatus(convertStatus(component.getStatus()))
.setDescription(trimToNull(component.getDescription()))
- .setReportAttributes(createAttributesBuilder(component).build())
+ .setReportAttributes(createAttributesBuilder(component, scmBasePath).build())
.setFileAttributes(createFileAttributes(component))
- .addChildren(buildChildren(component, closestModule))
+ .addChildren(buildChildren(component, closestModule, scmBasePath))
.build();
default:
@@ -145,7 +147,7 @@ public class ComponentTreeBuilder {
}
private static Component.Status convertStatus(FileStatus status) {
- switch(status) {
+ switch (status) {
case ADDED:
return Component.Status.ADDED;
case SAME:
@@ -184,10 +186,22 @@ public class ComponentTreeBuilder {
return DEFAULT_PROJECT_VERSION;
}
- private static ReportAttributes.Builder createAttributesBuilder(ScannerReport.Component component) {
+ private static ReportAttributes.Builder createAttributesBuilder(ScannerReport.Component component, @Nullable String scmBasePath) {
return ReportAttributes.newBuilder(component.getRef())
.setVersion(trimToNull(component.getVersion()))
- .setPath(trimToNull(component.getPath()));
+ .setPath(trimToNull(component.getPath()))
+ .setScmPath(computeScmPath(scmBasePath, component.getProjectRelativePath()));
+ }
+
+ @CheckForNull
+ private static String computeScmPath(@Nullable String scmBasePath, String scmRelativePath) {
+ if (scmRelativePath.isEmpty()) {
+ return null;
+ }
+ if (scmBasePath == null) {
+ return scmRelativePath;
+ }
+ return scmBasePath + '/' + scmRelativePath;
}
@CheckForNull
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ReportAttributes.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ReportAttributes.java
index 0c7e5db435c..f560d6852be 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ReportAttributes.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ReportAttributes.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.computation.task.projectanalysis.component;
+import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -33,11 +34,14 @@ public class ReportAttributes {
private final String version;
@CheckForNull
private final String path;
+ @CheckForNull
+ private final String scmPath;
private ReportAttributes(Builder builder) {
this.ref = builder.ref;
this.version = builder.version;
this.path = builder.path;
+ this.scmPath = builder.scmPath;
}
public static Builder newBuilder(int ref) {
@@ -50,6 +54,8 @@ public class ReportAttributes {
private String version;
@CheckForNull
private String path;
+ @CheckForNull
+ private String scmPath;
private Builder(int ref) {
this.ref = ref;
@@ -65,6 +71,11 @@ public class ReportAttributes {
return this;
}
+ public Builder setScmPath(@Nullable String scmPath) {
+ this.scmPath = scmPath;
+ return this;
+ }
+
public ReportAttributes build() {
return new ReportAttributes(this);
}
@@ -93,12 +104,23 @@ public class ReportAttributes {
return path;
}
+ /**
+ * The path of the component relative the SCM root the project is part of.
+ * <p>
+ * Can be {@link Optional#empty() empty} if project is not version controlled,
+ * otherwise should be non {@link Optional#isPresent() non empty} for all components.
+ */
+ public Optional<String> getScmPath() {
+ return Optional.ofNullable(scmPath);
+ }
+
@Override
public String toString() {
return "ReportAttributes{" +
"ref=" + ref +
", version='" + version + '\'' +
", path='" + path + '\'' +
+ ", scmPath='" + scmPath + '\'' +
'}';
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java
index fffb6cb5db0..4af8a4019e1 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java
@@ -82,7 +82,8 @@ public class BuildComponentTreeStep implements ComputationStep {
reportReader::readComponent,
analysisMetadataHolder.getProject(),
baseAnalysis);
- Component project = builder.buildProject(reportProject);
+ String relativePathFromScmRoot = reportReader.readMetadata().getRelativePathFromScmRoot();
+ Component project = builder.buildProject(reportProject, relativePathFromScmRoot);
treeRootHolder.setRoot(project);
analysisMetadataHolder.setBaseAnalysis(toAnalysis(baseAnalysis));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilderTest.java
index 663125a229e..baddf91b3af 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilderTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilderTest.java
@@ -36,6 +36,7 @@ import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.server.computation.task.projectanalysis.analysis.Project;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.newBuilder;
@@ -54,6 +55,7 @@ public class ComponentTreeBuilderTest {
+ ComponentKeys.createEffectiveKey(module.getKey(), component != null ? component.getPath() : null);
private static final Function<String, String> UUID_SUPPLIER = (componentKey) -> componentKey + "_uuid";
private static final EnumSet<ScannerReport.Component.ComponentType> REPORT_TYPES = EnumSet.of(PROJECT, MODULE, DIRECTORY, FILE);
+ private static final String NO_SCM_BASE_PATH = "";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -81,7 +83,7 @@ public class ComponentTreeBuilderTest {
}
@Test
- public void by_default_project_is_loaded_from_report() {
+ public void by_default_project_fields_are_loaded_from_report() {
String nameInReport = "the name";
String descriptionInReport = "the desc";
Component root = call(newBuilder()
@@ -154,6 +156,114 @@ public class ComponentTreeBuilderTest {
}
@Test
+ public void project_scmPath_is_empty_if_scmBasePath_is_empty() {
+ Component root = call(newBuilder()
+ .setType(PROJECT)
+ .build(), NO_SCM_BASE_PATH);
+
+ assertThat(root.getReportAttributes().getScmPath()).isEmpty();
+ }
+
+ @Test
+ public void any_component_with_projectRelativePath_has_this_value_as_scmPath_if_scmBasePath_is_empty() {
+ String[] projectRelativePaths = {
+ randomAlphabetic(4),
+ randomAlphabetic(5),
+ randomAlphabetic(6),
+ randomAlphabetic(7)
+ };
+ ScannerReport.Component project = newBuilder()
+ .setType(PROJECT)
+ .setKey(projectInDb.getKey())
+ .setRef(1)
+ .addChildRef(2)
+ .setProjectRelativePath(projectRelativePaths[0])
+ .build();
+ scannerComponentProvider.add(newBuilder()
+ .setRef(2)
+ .setType(MODULE)
+ .setKey("M")
+ .setProjectRelativePath(projectRelativePaths[1])
+ .addChildRef(3));
+ scannerComponentProvider.add(newBuilder()
+ .setRef(3)
+ .setType(DIRECTORY)
+ .setPath("src/js")
+ .setProjectRelativePath(projectRelativePaths[2])
+ .addChildRef(4));
+ scannerComponentProvider.add(newBuilder()
+ .setRef(4)
+ .setType(FILE)
+ .setPath("src/js/Foo.js")
+ .setProjectRelativePath(projectRelativePaths[3])
+ .setLines(1));
+
+ Component root = call(project, NO_SCM_BASE_PATH);
+
+ assertThat(root.getReportAttributes().getScmPath())
+ .contains(projectRelativePaths[0]);
+ Component module = root.getChildren().iterator().next();
+ assertThat(module.getReportAttributes().getScmPath())
+ .contains(projectRelativePaths[1]);
+ Component directory = module.getChildren().iterator().next();
+ assertThat(directory.getReportAttributes().getScmPath())
+ .contains(projectRelativePaths[2]);
+ Component file = directory.getChildren().iterator().next();
+ assertThat(file.getReportAttributes().getScmPath())
+ .contains(projectRelativePaths[3]);
+ }
+
+ @Test
+ public void any_component_with_projectRelativePath_has_this_value_appended_to_scmBasePath_and_a_slash_as_scmPath_if_scmBasePath_is_not_empty() {
+ String[] projectRelativePaths = {
+ randomAlphabetic(4),
+ randomAlphabetic(5),
+ randomAlphabetic(6),
+ randomAlphabetic(7)
+ };
+ ScannerReport.Component project = newBuilder()
+ .setType(PROJECT)
+ .setKey(projectInDb.getKey())
+ .setRef(1)
+ .addChildRef(2)
+ .setProjectRelativePath(projectRelativePaths[0])
+ .build();
+ scannerComponentProvider.add(newBuilder()
+ .setRef(2)
+ .setType(MODULE)
+ .setKey("M")
+ .setProjectRelativePath(projectRelativePaths[1])
+ .addChildRef(3));
+ scannerComponentProvider.add(newBuilder()
+ .setRef(3)
+ .setType(DIRECTORY)
+ .setPath("src/js")
+ .setProjectRelativePath(projectRelativePaths[2])
+ .addChildRef(4));
+ scannerComponentProvider.add(newBuilder()
+ .setRef(4)
+ .setType(FILE)
+ .setPath("src/js/Foo.js")
+ .setProjectRelativePath(projectRelativePaths[3])
+ .setLines(1));
+ String scmBasePath = randomAlphabetic(10);
+
+ Component root = call(project, scmBasePath);
+
+ assertThat(root.getReportAttributes().getScmPath())
+ .contains(scmBasePath + "/" + projectRelativePaths[0]);
+ Component module = root.getChildren().iterator().next();
+ assertThat(module.getReportAttributes().getScmPath())
+ .contains(scmBasePath + "/" + projectRelativePaths[1]);
+ Component directory = module.getChildren().iterator().next();
+ assertThat(directory.getReportAttributes().getScmPath())
+ .contains(scmBasePath + "/" + projectRelativePaths[2]);
+ Component file = directory.getChildren().iterator().next();
+ assertThat(file.getReportAttributes().getScmPath())
+ .contains(scmBasePath + "/" + projectRelativePaths[3]);
+ }
+
+ @Test
public void keys_of_module_directory_and_file_are_generated() {
ScannerReport.Component project = newBuilder()
.setType(PROJECT)
@@ -732,11 +842,19 @@ public class ComponentTreeBuilderTest {
}
private Component call(ScannerReport.Component project) {
- return newUnderTest(null).buildProject(project);
+ return call(project, NO_SCM_BASE_PATH);
+ }
+
+ private Component call(ScannerReport.Component project, String scmBasePath) {
+ return newUnderTest(null).buildProject(project, scmBasePath);
}
private Component call(ScannerReport.Component project, @Nullable SnapshotDto baseAnalysis) {
- return newUnderTest(baseAnalysis).buildProject(project);
+ return call(project, baseAnalysis, NO_SCM_BASE_PATH);
+ }
+
+ private Component call(ScannerReport.Component project, @Nullable SnapshotDto baseAnalysis, String scmBasePath) {
+ return newUnderTest(baseAnalysis).buildProject(project, scmBasePath);
}
private ComponentTreeBuilder newUnderTest(@Nullable SnapshotDto baseAnalysis) {