*/
package org.sonar.ce.task.projectanalysis.component;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.resources.Qualifiers;
public class ComponentUuidFactory {
private final Map<String, String> uuidsByKey = new HashMap<>();
- public ComponentUuidFactory(DbClient dbClient, DbSession dbSession, String rootKey) {
- Map<String, String> modulePathsByUuid = loadModulePathsByUuid(dbClient, dbSession, rootKey);
+ public ComponentUuidFactory(DbClient dbClient, DbSession dbSession, String rootKey, Supplier<Map<String, String>> reportModulesPath) {
+ Map<String, String> modulePathsByUuid = loadModulePathsByUuid(dbClient, dbSession, rootKey, reportModulesPath);
if (modulePathsByUuid.isEmpty()) {
- // only contains root project
+ // only contains root project or we don't have relative paths for other modules anyway
List<KeyWithUuidDto> keys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey);
keys.forEach(dto -> uuidsByKey.put(dto.key(), dto.uuid()));
} else {
return dbClient.componentDao().selectComponentsWithModuleUuidFromProjectKey(dbSession, rootKey);
}
- private static Map<String, String> loadModulePathsByUuid(DbClient dbClient, DbSession dbSession, String rootKey) {
+ private static Map<String, String> loadModulePathsByUuid(DbClient dbClient, DbSession dbSession, String rootKey, Supplier<Map<String, String>> reportModulesPath) {
List<ComponentDto> moduleDtos = dbClient.componentDao()
.selectEnabledModulesFromProjectKey(dbSession, rootKey, false).stream()
.filter(c -> Qualifiers.MODULE.equals(c.qualifier()))
.collect(Collectors.toList());
- Map<String, ComponentDto> dtoByUuid = moduleDtos.stream()
- .collect(Collectors.toMap(ComponentDto::uuid, dto -> dto));
+ if (moduleDtos.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map<String, String> pathByModuleKey = reportModulesPath.get();
Map<String, String> modulePathByUuid = new HashMap<>();
-
for (ComponentDto dto : moduleDtos) {
- String modulePath = null;
- ComponentDto currentDto = dto;
- while (currentDto != null && currentDto.moduleUuid() != null) {
- String path = currentDto.path();
- if (modulePath == null) {
- modulePath = path;
- } else {
- modulePath = path + "/" + modulePath;
- }
- currentDto = dtoByUuid.get(currentDto.moduleUuid());
+ String relativePath = pathByModuleKey.get(dto.getKey());
+ if (relativePath != null) {
+ modulePathByUuid.put(dto.uuid(), relativePath);
}
-
- modulePathByUuid.put(dto.uuid(), modulePath);
}
-
return modulePathByUuid;
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.task.projectanalysis.component;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
+import org.sonar.scanner.protocol.output.ScannerReport;
+
+public class ReportModulesPath implements Supplier<Map<String, String>> {
+ private final BatchReportReader reader;
+
+ public ReportModulesPath(BatchReportReader reader) {
+ this.reader = reader;
+ }
+
+ public Map<String, String> get() {
+ ScannerReport.Metadata metadata = reader.readMetadata();
+ Map<String, String> modulesProjectRelativePathByKey = metadata.getModulesProjectRelativePathByKeyMap();
+ if (modulesProjectRelativePathByKey.isEmpty()) {
+ return collectModulesPathFromHierarchy(metadata);
+ }
+ return modulesProjectRelativePathByKey;
+ }
+
+ /**
+ * This should only be needed if we receive a report of the previous version without the path per module explicitly set
+ * (due to blue/green deployment)
+ * Can be removed in any future version
+ */
+ private Map<String, String> collectModulesPathFromHierarchy(ScannerReport.Metadata metadata) {
+ ScannerReport.Component root = reader.readComponent(metadata.getRootComponentRef());
+ Map<String, String> modulesPathByKey = new LinkedHashMap<>();
+ LinkedList<Integer> queue = new LinkedList<>();
+ queue.addAll(root.getChildRefList());
+
+ while (!queue.isEmpty()) {
+ ScannerReport.Component component = reader.readComponent(queue.removeFirst());
+ if (component.getType() == ScannerReport.Component.ComponentType.MODULE) {
+ queue.addAll(component.getChildRefList());
+ modulesPathByKey.put(component.getKey(), component.getProjectRelativePath());
+ }
+ }
+
+ return modulesPathByKey;
+ }
+
+}
import org.sonar.ce.task.projectanalysis.component.DbIdsRepositoryImpl;
import org.sonar.ce.task.projectanalysis.component.DisabledComponentsHolderImpl;
import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids;
+import org.sonar.ce.task.projectanalysis.component.ReportModulesPath;
import org.sonar.ce.task.projectanalysis.component.ShortBranchComponentsWithIssues;
import org.sonar.ce.task.projectanalysis.component.TreeRootHolderImpl;
import org.sonar.ce.task.projectanalysis.dbmigration.DbMigrationModule;
new ComputationTempFolderProvider(),
DbMigrationModule.class,
-
+ ReportModulesPath.class,
MetricModule.class,
// holders
import org.sonar.ce.task.projectanalysis.component.ComponentUuidFactory;
import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.ce.task.projectanalysis.component.MutableTreeRootHolder;
+import org.sonar.ce.task.projectanalysis.component.ReportModulesPath;
import org.sonar.ce.task.projectanalysis.issue.IssueRelocationToRoot;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.db.DbClient;
private final MutableTreeRootHolder treeRootHolder;
private final MutableAnalysisMetadataHolder analysisMetadataHolder;
private final IssueRelocationToRoot issueRelocationToRoot;
+ private final ReportModulesPath reportModulesPath;
- public BuildComponentTreeStep(DbClient dbClient, BatchReportReader reportReader,
- MutableTreeRootHolder treeRootHolder, MutableAnalysisMetadataHolder analysisMetadataHolder, IssueRelocationToRoot issueRelocationToRoot) {
+ public BuildComponentTreeStep(DbClient dbClient, BatchReportReader reportReader, MutableTreeRootHolder treeRootHolder,
+ MutableAnalysisMetadataHolder analysisMetadataHolder, IssueRelocationToRoot issueRelocationToRoot, ReportModulesPath reportModulesPath) {
this.dbClient = dbClient;
this.reportReader = reportReader;
this.treeRootHolder = treeRootHolder;
this.analysisMetadataHolder = analysisMetadataHolder;
this.issueRelocationToRoot = issueRelocationToRoot;
+ this.reportModulesPath = reportModulesPath;
}
@Override
ScannerReport.Component reportProject = reportReader.readComponent(analysisMetadataHolder.getRootComponentRef());
ComponentKeyGenerator keyGenerator = loadKeyGenerator();
ComponentKeyGenerator publicKeyGenerator = loadPublicKeyGenerator();
+ ScannerReport.Metadata metadata = reportReader.readMetadata();
// root key of branch, not necessarily of project
String rootKey = keyGenerator.generateKey(reportProject, null);
// loads the UUIDs from database. If they don't exist, then generate new ones
- ComponentUuidFactory componentUuidFactory = new ComponentUuidFactory(dbClient, dbSession, rootKey);
+ ComponentUuidFactory componentUuidFactory = new ComponentUuidFactory(dbClient, dbSession, rootKey, reportModulesPath);
String rootUuid = componentUuidFactory.getOrCreateForKey(rootKey);
SnapshotDto baseAnalysis = loadBaseAnalysis(dbSession, rootUuid);
analysisMetadataHolder.getProject(),
analysisMetadataHolder.getBranch(),
baseAnalysis, issueRelocationToRoot);
- String relativePathFromScmRoot = reportReader.readMetadata().getRelativePathFromScmRoot();
+ String relativePathFromScmRoot = metadata.getRelativePathFromScmRoot();
Component reportTreeRoot = builder.buildProject(reportProject, relativePathFromScmRoot);
scannerComponentProvider.add(newBuilder()
.setRef(2)
.setType(DIRECTORY)
- .setPath("/")
+ .setProjectRelativePath("/")
.addChildRef(3));
scannerComponentProvider.add(newBuilder()
.setRef(3)
*/
package org.sonar.ce.task.projectanalysis.component;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.component.ComponentTesting;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ComponentUuidFactoryTest {
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
+ private ReportModulesPath reportModulesPath = mock(ReportModulesPath.class);
+
@Test
public void load_uuids_from_existing_components_in_db() {
ComponentDto project = db.components().insertPrivateProject();
ComponentDto module = db.components().insertComponent(ComponentTesting
- .newModuleDto(project).setPath("module1"));
-
- ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey());
+ .newModuleDto(project));
+ when(reportModulesPath.get()).thenReturn(Collections.singletonMap(module.getKey(), "module1_path"));
+ ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey(), reportModulesPath);
assertThat(underTest.getOrCreateForKey(project.getDbKey())).isEqualTo(project.uuid());
assertThat(underTest.getOrCreateForKey(module.getDbKey())).isNotEqualTo(module.uuid());
public void migrate_project_with_modules() {
ComponentDto project = db.components().insertPrivateProject(dto -> dto.setDbKey("project"));
ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project)
- .setDbKey("project:module1")
- .setPath("module1_path"));
+ .setDbKey("project:module1"));
ComponentDto module2 = db.components().insertComponent(ComponentTesting.newModuleDto(module1)
- .setDbKey("project:module1:module2")
- .setPath("module2_path"));
+ .setDbKey("project:module1:module2"));
ComponentDto file1 = db.components().insertComponent(ComponentTesting.newFileDto(project)
.setDbKey("project:file1")
.setPath("file1_path"));
.setPath("file2_path"));
assertThat(file2.moduleUuidPath()).isEqualTo("." + project.uuid() + "." + module1.uuid() + "." + module2.uuid() + ".");
-
- ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey());
+ Map<String, String> modulesRelativePaths = new HashMap<>();
+ modulesRelativePaths.put("project:module1", "module1_path");
+ modulesRelativePaths.put("project:module1:module2", "module1_path/module2_path");
+ when(reportModulesPath.get()).thenReturn(modulesRelativePaths);
+ ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey(), reportModulesPath);
// migrated files
assertThat(underTest.getOrCreateForKey("project:file1_path")).isEqualTo(file1.uuid());
ComponentDto project = db.components().insertPrivateProject(dto -> dto.setDbKey("project"));
ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project)
.setDbKey("project:module1")
- .setEnabled(false)
- .setPath("module1_path"));
+ .setEnabled(false));
ComponentDto file1 = db.components().insertComponent(ComponentTesting.newFileDto(module1)
.setDbKey("project:file1")
.setEnabled(false)
.setPath("file1_path"));
+ when(reportModulesPath.get()).thenReturn(Collections.singletonMap("project:module1", "module1_path"));
- ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey());
+ ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey(), reportModulesPath);
// migrated files
assertThat(underTest.getOrCreateForKey("project:module1_path/file1_path")).isEqualTo(file1.uuid());
}
- @Test
- public void migrate_project_having_modules_without_paths() {
- ComponentDto project = db.components().insertPrivateProject(dto -> dto.setDbKey("project"));
- ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project)
- .setDbKey("project:module")
- .setPath(null));
- ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(module)
- .setDbKey("project:module:file")
- .setPath("file_path"));
-
- assertThat(file.moduleUuidPath()).isEqualTo("." + project.uuid() + "." + module.uuid() + ".");
-
- ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), project.getDbKey());
-
- // file will have this key since the module has a null path
- assertThat(underTest.getOrCreateForKey("project:file_path")).isEqualTo(file.uuid());
-
- // migrated module
- // TODO!!
- //assertThat(underTest.getOrCreateForKey("project:module")).isEqualTo(module.uuid());
-
- // project remains the same
- //assertThat(underTest.getOrCreateForKey(project.getDbKey())).isEqualTo(project.uuid());
-
- // old keys with modules don't exist
- assertThat(underTest.getOrCreateForKey(module.getDbKey())).isNotEqualTo(module.uuid());
- assertThat(underTest.getOrCreateForKey(file.getDbKey())).isNotEqualTo(file.uuid());
- }
-
@Test
public void generate_uuid_if_it_does_not_exist_in_db() {
- ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), "theProjectKey");
+ when(reportModulesPath.get()).thenReturn(Collections.emptyMap());
+ ComponentUuidFactory underTest = new ComponentUuidFactory(db.getDbClient(), db.getSession(), "theProjectKey", reportModulesPath);
String generatedKey = underTest.getOrCreateForKey("foo");
assertThat(generatedKey).isNotEmpty();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.task.projectanalysis.component;
+
+import java.util.Arrays;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Test;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
+import org.sonar.scanner.protocol.output.ScannerReport;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class ReportModulesPathTest {
+ private BatchReportReader reader = mock(BatchReportReader.class);
+ private ReportModulesPath reportModulesPath = new ReportModulesPath(reader);
+ private ScannerReport.Component root = addComponent(1, "project", ScannerReport.Component.ComponentType.PROJECT, null, 2);
+
+ @Test
+ public void should_not_read_hierarchy_if_metadata_available() {
+ when(reader.readMetadata()).thenReturn(ScannerReport.Metadata.newBuilder()
+ .putModulesProjectRelativePathByKey("module1", "path1")
+ .setRootComponentRef(1)
+ .build());
+ Map<String, String> pathByModuleKey = reportModulesPath.get();
+
+ assertThat(pathByModuleKey).containsExactly(entry("module1", "path1"));
+ verify(reader).readMetadata();
+ verifyNoMoreInteractions(reader);
+ }
+
+ @Test
+ public void should_read_hierarchy_if_metadata_not_available() {
+ when(reader.readMetadata()).thenReturn(ScannerReport.Metadata.newBuilder().setRootComponentRef(1).build());
+ addComponent(2, "project:module1", ScannerReport.Component.ComponentType.MODULE, "path1", 3);
+ addComponent(3, "project:module1:module2", ScannerReport.Component.ComponentType.MODULE, "path1/path2", 4);
+ addComponent(4, "project:module1:module2:dir", ScannerReport.Component.ComponentType.DIRECTORY, "path1/path2/dir");
+
+ Map<String, String> pathByModuleKey = reportModulesPath.get();
+
+ assertThat(pathByModuleKey).containsOnly(
+ entry("project:module1", "path1"),
+ entry("project:module1:module2", "path1/path2"));
+ verify(reader).readMetadata();
+ verify(reader).readComponent(1);
+ verify(reader).readComponent(2);
+ verify(reader).readComponent(3);
+ verify(reader).readComponent(4);
+
+ verifyNoMoreInteractions(reader);
+ }
+
+ private ScannerReport.Component addComponent(int ref, String key, ScannerReport.Component.ComponentType type, @Nullable String path, Integer... children) {
+ ScannerReport.Component.Builder builder = ScannerReport.Component.newBuilder()
+ .setRef(ref)
+ .setKey(key)
+ .addAllChildRef(Arrays.asList(children))
+ .setType(type);
+
+ if (path != null) {
+ builder.setProjectRelativePath(path);
+ }
+ ScannerReport.Component component = builder.build();
+ when(reader.readComponent(ref)).thenReturn(component);
+ return component;
+ }
+}
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.ce.task.projectanalysis.component.MutableTreeRootHolderRule;
+import org.sonar.ce.task.projectanalysis.component.ReportModulesPath;
import org.sonar.ce.task.projectanalysis.issue.IssueRelocationToRoot;
import org.sonar.ce.task.step.TestComputationStepContext;
import org.sonar.db.DbClient;
public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
@Rule
public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
-
+ private ReportModulesPath reportModulesPath = new ReportModulesPath(reportReader);
private IssueRelocationToRoot issueRelocationToRoot = mock(IssueRelocationToRoot.class);
private DbClient dbClient = dbTester.getDbClient();
- private BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ private BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
@Test(expected = NullPointerException.class)
public void fails_if_root_component_does_not_exist_in_reportReader() {
reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, "module/" + REPORT_DIR_PATH_1, FILE_1_REF));
reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, "module/" + REPORT_FILE_PATH_1));
-
+ reportReader.setMetadata(ScannerReport.Metadata.newBuilder().putModulesProjectRelativePathByKey(REPORT_MODULE_KEY,
+ "module").build());
underTest.execute(new TestComputationStepContext());
verifyComponentByRef(ROOT_REF, REPORT_PROJECT_KEY, "ABCD");
.setAnalysisDate(ANALYSIS_DATE)
.setProject(Project.from(newPrivateProjectDto(newOrganizationDto()).setDbKey(REPORT_PROJECT_KEY)))
.setBranch(branch);
- BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
reportReader.putComponent(component(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_PATH_1, FILE_1_REF));
.setAnalysisDate(ANALYSIS_DATE)
.setProject(Project.from(newPrivateProjectDto(newOrganizationDto()).setDbKey(REPORT_PROJECT_KEY)))
.setBranch(branch);
- BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF, LEAFLESS_MODULE_REF));
reportReader.putComponent(component(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_PATH_1, FILE_1_REF));
.setAnalysisDate(ANALYSIS_DATE)
.setProject(Project.from(newPrivateProjectDto(newOrganizationDto()).setDbKey(REPORT_PROJECT_KEY)))
.setBranch(branch);
- BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF, LEAFLESS_MODULE_REF));
reportReader.putComponent(component(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_PATH_1, FILE_1_REF));
.setAnalysisDate(ANALYSIS_DATE)
.setProject(Project.from(projectDto))
.setBranch(branch);
- BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
reportReader.putComponent(component(ROOT_REF, PROJECT, branchDto.getKey()));
underTest.execute(new TestComputationStepContext());
.setAnalysisDate(ANALYSIS_DATE)
.setProject(Project.from(newPrivateProjectDto(newOrganizationDto()).setDbKey(REPORT_PROJECT_KEY)))
.setBranch(branch);
- BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
reportReader.putComponent(component(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_PATH_1, FILE_1_REF));
.setAnalysisDate(ANALYSIS_DATE)
.setProject(Project.from(newPrivateProjectDto(newOrganizationDto()).setDbKey(REPORT_PROJECT_KEY)))
.setBranch(new DefaultBranchImpl("origin/feature"));
- BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, issueRelocationToRoot);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder,
+ issueRelocationToRoot, reportModulesPath);
reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
reportReader.putComponent(component(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_PATH_1, FILE_1_REF));
import java.io.File;
import java.nio.file.Path;
+import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.utils.log.Logger;
private final ScmConfiguration scmConfiguration;
public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties,
- QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration,
- @Nullable ScmConfiguration scmConfiguration) {
+ QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration,
+ @Nullable ScmConfiguration scmConfiguration) {
this.projectAnalysisInfo = projectAnalysisInfo;
this.moduleHierarchy = moduleHierarchy;
this.properties = properties;
}
public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties,
- QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration) {
+ QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration) {
this(projectAnalysisInfo, moduleHierarchy, properties, qProfiles, cpdSettings, pluginRepository, branchConfiguration, null);
}
}
for (QProfile qp : qProfiles.findAll()) {
- builder.getMutableQprofilesPerLanguage().put(qp.getLanguage(), ScannerReport.Metadata.QProfile.newBuilder()
+ builder.putQprofilesPerLanguage(qp.getLanguage(), ScannerReport.Metadata.QProfile.newBuilder()
.setKey(qp.getKey())
.setLanguage(qp.getLanguage())
.setName(qp.getName())
.setRulesUpdatedAt(qp.getRulesUpdatedAt().getTime()).build());
}
for (Entry<String, ScannerPlugin> pluginEntry : pluginRepository.getPluginsByKey().entrySet()) {
- builder.getMutablePluginsByKey().put(pluginEntry.getKey(), ScannerReport.Metadata.Plugin.newBuilder()
+ builder.putPluginsByKey(pluginEntry.getKey(), ScannerReport.Metadata.Plugin.newBuilder()
.setKey(pluginEntry.getKey())
.setUpdatedAt(pluginEntry.getValue().getUpdatedAt()).build());
}
+
+ addModulesRelativePaths(builder);
+
writer.writeMetadata(builder.build());
}
+ private void addModulesRelativePaths(ScannerReport.Metadata.Builder builder) {
+ LinkedList<DefaultInputModule> queue = new LinkedList<>();
+ queue.add(moduleHierarchy.root());
+
+ while (!queue.isEmpty()) {
+ DefaultInputModule module = queue.removeFirst();
+ queue.addAll(moduleHierarchy.children(module));
+ String relativePath = moduleHierarchy.relativePath(module);
+ if (relativePath != null) {
+ builder.putModulesProjectRelativePathByKey(module.key(), relativePath);
+ }
+ }
+ }
+
private void addScmInformation(ScannerReport.Metadata.Builder builder) {
ScmProvider scmProvider = scmConfiguration.provider();
if (scmProvider != null) {
public String relativePath(DefaultInputModule module) {
AbstractProjectOrModule parent = parent(module);
if (parent == null) {
- return null;
+ return "";
}
- DefaultInputModule inputModule = (DefaultInputModule) module;
Path parentBaseDir = parent.getBaseDir();
- Path moduleBaseDir = inputModule.getBaseDir();
+ Path moduleBaseDir = module.getBaseDir();
return PathResolver.relativize(parentBaseDir, moduleBaseDir).orElse(null);
}
import com.google.common.collect.ImmutableMap;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
import java.util.Date;
import java.util.Optional;
import org.junit.Before;
when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(Paths.get("dummy/path"));
when(scmProvider.revisionId(any(Path.class))).thenReturn("dummy-sha1");
- createPublisher(ProjectDefinition.create().setKey("foo"));
+ createPublisher(ProjectDefinition.create());
when(pluginRepository.getPluginsByKey()).thenReturn(emptyMap());
}
private void createPublisher(ProjectDefinition def) throws IOException {
- rootModule = new DefaultInputModule(def.setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()), TestInputFileBuilder.nextBatchId());
+ Path rootBaseDir = temp.newFolder().toPath();
+ Path moduleBaseDir = rootBaseDir.resolve("moduleDir");
+ Files.createDirectory(moduleBaseDir);
+ rootModule = new DefaultInputModule(def
+ .setBaseDir(rootBaseDir.toFile())
+ .setKey("root")
+ .setWorkDir(temp.newFolder()), TestInputFileBuilder.nextBatchId());
inputModuleHierarchy = mock(InputModuleHierarchy.class);
when(inputModuleHierarchy.root()).thenReturn(rootModule);
+ DefaultInputModule child = new DefaultInputModule(ProjectDefinition.create()
+ .setKey("module")
+ .setBaseDir(moduleBaseDir.toFile())
+ .setWorkDir(temp.newFolder()), TestInputFileBuilder.nextBatchId());
+ when(inputModuleHierarchy.children(rootModule)).thenReturn(Collections.singletonList(child));
+ when(inputModuleHierarchy.relativePath(child)).thenReturn("modulePath");
+ when(inputModuleHierarchy.relativePath(rootModule)).thenReturn("");
branches = mock(BranchConfiguration.class);
scmConfiguration = mock(ScmConfiguration.class);
when(scmConfiguration.provider()).thenReturn(scmProvider);
ScannerReportReader reader = new ScannerReportReader(outputDir);
ScannerReport.Metadata metadata = reader.readMetadata();
assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
- assertThat(metadata.getProjectKey()).isEqualTo("foo");
- assertThat(metadata.getProjectKey()).isEqualTo("foo");
- assertThat(metadata.getQprofilesPerLanguage()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile.newBuilder()
+ assertThat(metadata.getProjectKey()).isEqualTo("root");
+ assertThat(metadata.getModulesProjectRelativePathByKeyMap()).containsOnly(entry("module", "modulePath"), entry("root", ""));
+ assertThat(metadata.getQprofilesPerLanguageMap()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile.newBuilder()
.setKey("q1")
.setName("Q1")
.setLanguage("java")
.setRulesUpdatedAt(date.getTime())
.build()));
assertThat(metadata.getPluginsByKey()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder()
- .setKey("java")
- .setUpdatedAt(12345)
- .build()),
+ .setKey("java")
+ .setUpdatedAt(12345)
+ .build()),
entry("php", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder()
.setKey("php")
.setUpdatedAt(45678)
ScannerReportReader reader = new ScannerReportReader(outputDir);
ScannerReport.Metadata metadata = reader.readMetadata();
assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
- assertThat(metadata.getProjectKey()).isEqualTo("foo");
+ assertThat(metadata.getProjectKey()).isEqualTo("root");
assertThat(metadata.getDeprecatedBranch()).isEqualTo("myBranch");
assertThat(metadata.getCrossProjectDuplicationActivated()).isFalse();
}
ScannerReportReader reader = new ScannerReportReader(outputDir);
ScannerReport.Metadata metadata = reader.readMetadata();
- assertThat(properties.organizationKey()).isEqualTo(Optional.of("SonarSource"));
+ assertThat(metadata.getOrganizationKey()).isEqualTo("SonarSource");
}
@Test
return component.getName();
case DIRECTORY:
case FILE:
- return component.getPath();
+ return component.getProjectRelativePath();
default:
throw new IllegalArgumentException("Unknow component type: " + component.getType());
}
string scm_revision_id = 13;
string pull_request_key = 14;
+ map<string, string> modules_project_relative_path_by_key = 15;
message QProfile {
string key = 1;
message Component {
int32 ref = 1;
- // Path relative to module base directory
- string path = 2 [deprecated=true];
string name = 3;
ComponentType type = 4;
bool is_test = 5;
ScannerReportWriter writer = new ScannerReportWriter(dir);
ScannerReport.Component.Builder component = ScannerReport.Component.newBuilder()
.setRef(1)
- .setPath("src/main/java/Foo.java");
+ .setProjectRelativePath("src/main/java/Foo.java");
writer.writeComponent(component.build());
- assertThat(underTest.readComponent(1).getPath()).isEqualTo("src/main/java/Foo.java");
+ assertThat(underTest.readComponent(1).getProjectRelativePath()).isEqualTo("src/main/java/Foo.java");
}
@Test(expected = IllegalStateException.class)
ScannerReport.Component.Builder component = ScannerReport.Component.newBuilder()
.setRef(1)
.setLanguage("java")
- .setPath("src/Foo.java")
+ .setProjectRelativePath("src/Foo.java")
.setType(ComponentType.FILE)
.setIsTest(false)
.addChildRef(5)
// write data
ScannerReport.AdHocRule rule = ScannerReport.AdHocRule.newBuilder()
- .setEngineId("eslint")
- .setRuleId("123")
- .setName("Foo")
- .setDescription("Description")
- .setSeverity(Constants.Severity.BLOCKER)
- .setType(ScannerReport.IssueType.BUG)
- .build();
+ .setEngineId("eslint")
+ .setRuleId("123")
+ .setName("Foo")
+ .setDescription("Description")
+ .setSeverity(Constants.Severity.BLOCKER)
+ .setType(ScannerReport.IssueType.BUG)
+ .build();
underTest.appendAdHocRule(rule);
File file = underTest.getFileStructure().adHocRules();