From: Julien Lancelot Date: Fri, 29 May 2015 15:52:02 +0000 (+0200) Subject: Revert "Revert "SONAR-6259 Validate project and module keys"" X-Git-Tag: 5.2-RC1~1760 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e0819b36e967c7b5c6f192475bf78648c3906214;p=sonarqube.git Revert "Revert "SONAR-6259 Validate project and module keys"" This reverts commit b542009c4736bdf93ab45e989117a6b7e7fef8f2. --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java index fdebb5a6f69..52169547e35 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java @@ -22,6 +22,12 @@ package org.sonar.server.component.db; import com.google.common.base.Function; import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.apache.ibatis.session.RowBounds; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; @@ -36,14 +42,6 @@ import org.sonar.core.persistence.DbSession; import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.NotFoundException; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import static com.google.common.collect.Maps.newHashMapWithExpectedSize; /** @@ -82,10 +80,6 @@ public class ComponentDao implements DaoComponent { return mapper(session).countById(id) > 0; } - public List selectModulesByProject(String projectKey, DbSession session) { - return mapper(session).selectModulesByProject(projectKey); - } - public List selectSubProjectsByComponentUuids(DbSession session, Collection keys) { if (keys.isEmpty()) { return Collections.emptyList(); @@ -137,7 +131,11 @@ public class ComponentDao implements DaoComponent { } public List selectComponentsFromProjectKey(DbSession session, String projectKey) { - return mapper(session).selectComponentsFromProjectKey(projectKey); + return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, null); + } + + public List selectModulesFromProjectKey(DbSession session, String projectKey) { + return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, Scopes.PROJECT); } public List selectByKeys(DbSession session, Collection keys) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index 9f3368cff76..c1052d65fdf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -37,6 +37,7 @@ public class ComputationSteps { public static List> orderedStepClasses() { return Arrays.asList( PopulateComponentsUuidAndKeyStep.class, + ValidateProjectStep.class, // Read report ParseReportStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ValidateProjectStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ValidateProjectStep.java new file mode 100644 index 00000000000..120b507a6de --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ValidateProjectStep.java @@ -0,0 +1,183 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.step; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.Maps; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.component.ComponentKeys; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.component.db.ComponentDao; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; +import org.sonar.server.db.DbClient; + +/** + * Validate project and modules. It will fail in the following cases : + *
    + *
  1. property {@link org.sonar.api.CoreProperties#CORE_PREVENT_AUTOMATIC_PROJECT_CREATION} is set to true and project does not exists
  2. + *
  3. branch is not valid
  4. + *
  5. project or module key is not valid
  6. + *
  7. module key already exists in another project (same module key cannot exists in different projects)
  8. + *
  9. module key is already used as a project key
  10. + *
+ */ +public class ValidateProjectStep implements ComputationStep { + + private static final Joiner MESSAGES_JOINER = Joiner.on("\n o "); + + private final DbClient dbClient; + private final Settings settings; + + public ValidateProjectStep(DbClient dbClient, Settings settings) { + this.dbClient = dbClient; + this.settings = settings; + } + + @Override + public void execute(ComputationContext context) { + DbSession session = dbClient.openSession(false); + try { + List modules = dbClient.componentDao().selectModulesFromProjectKey(session, context.getRoot().getKey()); + Map modulesByKey = Maps.uniqueIndex(modules, new Function() { + @Override + public String apply(@Nonnull ComponentDto input) { + return input.key(); + } + }); + ValidateProjectsVisitor visitor = new ValidateProjectsVisitor(session, dbClient.componentDao(), context.getReportMetadata(), + settings.getBoolean(CoreProperties.CORE_PREVENT_AUTOMATIC_PROJECT_CREATION), modulesByKey); + visitor.visit(context.getRoot()); + + if (!visitor.validationMessages.isEmpty()) { + throw new IllegalArgumentException("Validation of project failed:\n o " + MESSAGES_JOINER.join(visitor.validationMessages)); + } + } finally { + session.close(); + } + } + + @Override + public String getDescription() { + return "Validate project and modules keys"; + } + + private static class ValidateProjectsVisitor extends DepthTraversalTypeAwareVisitor { + private final DbSession session; + private final ComponentDao componentDao; + private final BatchReport.Metadata reportMetadata; + private final boolean preventAutomaticProjectCreation; + private final Map modulesByKey; + private final List validationMessages = new ArrayList<>(); + + private Component root; + + public ValidateProjectsVisitor(DbSession session, ComponentDao componentDao, BatchReport.Metadata reportMetadata, boolean preventAutomaticProjectCreation, + Map modulesByKey) { + super(Component.Type.MODULE, Order.PRE_ORDER); + this.session = session; + this.componentDao = componentDao; + this.reportMetadata = reportMetadata; + this.preventAutomaticProjectCreation = preventAutomaticProjectCreation; + this.modulesByKey = modulesByKey; + } + + @Override + public void visitProject(Component project) { + this.root = project; + validateBranch(); + + String projectKey = project.getKey(); + ComponentDto projectDto = loadComponent(projectKey); + if (projectDto == null) { + if (preventAutomaticProjectCreation) { + validationMessages.add(String.format("Unable to scan non-existing project '%s'", projectKey)); + } + } else if (!projectDto.projectUuid().equals(projectDto.uuid())) { + // Project key is already used as a module of another project + ComponentDto anotherProject = componentDao.selectByUuid(session, projectDto.projectUuid()); + validationMessages.add(String.format("The project \"%s\" is already defined in SonarQube but as a module of project \"%s\". " + + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".", + projectKey, anotherProject.key(), anotherProject.key(), projectKey)); + } + validateKey(projectKey); + } + + @Override + public void visitModule(Component module) { + String moduleKey = module.getKey(); + String projectKey = root.getKey(); + validateKey(moduleKey); + + ComponentDto moduleDto = loadComponent(moduleKey); + if (moduleDto == null) { + return; + } + if (moduleDto.projectUuid().equals(moduleDto.uuid())) { + // module is actually a project + validationMessages.add(String.format("The project \"%s\" is already defined in SonarQube but not as a module of project \"%s\". " + + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".", + moduleKey, projectKey, moduleKey, projectKey)); + } else if (!moduleDto.projectUuid().equals(root.getUuid())) { + ComponentDto projectModule = componentDao.selectByUuid(session, moduleDto.projectUuid()); + validationMessages.add(String.format("Module \"%s\" is already part of project \"%s\"", moduleKey, projectModule.key())); + } + } + + private void validateKey(String moduleKey) { + if (!ComponentKeys.isValidModuleKey(moduleKey)) { + validationMessages.add(String.format("\"%s\" is not a valid project or module key. " + + "Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", moduleKey)); + } + } + + @CheckForNull + private void validateBranch() { + if (!reportMetadata.hasBranch()) { + return; + } + String branch = reportMetadata.getBranch(); + if (!ComponentKeys.isValidBranch(branch)) { + validationMessages.add(String.format("\"%s\" is not a valid branch name. " + + "Allowed characters are alphanumeric, '-', '_', '.' and '/'.", branch)); + } + } + + private ComponentDto loadComponent(String componentKey) { + ComponentDto componentDto = modulesByKey.get(componentKey); + if (componentDto == null) { + // Load component from key to be able to detect issue (try to analyze a module, etc.) + return componentDao.selectNullableByKey(session, componentKey); + } + return componentDto; + } + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java index d64ef797efa..396c5c8d33e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java @@ -20,6 +20,8 @@ package org.sonar.server.component.db; +import java.util.Collections; +import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -34,9 +36,6 @@ import org.sonar.core.persistence.DbTester; import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.NotFoundException; -import java.util.Collections; -import java.util.List; - import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; @@ -310,23 +309,6 @@ public class ComponentDaoTest { assertThat(sut.existsById(111L, session)).isFalse(); } - @Test - public void find_modules_by_project() { - db.prepareDbUnit(getClass(), "multi-modules.xml"); - - List results = sut.selectModulesByProject("org.struts:struts", session); - assertThat(results).hasSize(1); - assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-core"); - - results = sut.selectModulesByProject("org.struts:struts-core", session); - assertThat(results).hasSize(1); - assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data"); - - assertThat(sut.selectModulesByProject("org.struts:struts-data", session)).isEmpty(); - - assertThat(sut.selectModulesByProject("unknown", session)).isEmpty(); - } - @Test public void find_sub_projects_by_component_keys() { db.prepareDbUnit(getClass(), "multi-modules.xml"); @@ -463,6 +445,16 @@ public class ComponentDaoTest { assertThat(sut.selectComponentsFromProjectKey(session, "UNKNOWN")).isEmpty(); } + @Test + public void select_modules_from_project() { + db.prepareDbUnit(getClass(), "multi-modules.xml"); + + List components = sut.selectModulesFromProjectKey(session, "org.struts:struts"); + assertThat(components).hasSize(3); + + assertThat(sut.selectModulesFromProjectKey(session, "UNKNOWN")).isEmpty(); + } + @Test public void select_views_and_sub_views() { db.prepareDbUnit(getClass(), "shared_views.xml"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java index 7ed17968743..188773c5c41 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java @@ -52,12 +52,13 @@ public class ComputationStepsTest { mock(PopulateComponentsUuidAndKeyStep.class), mock(PersistComponentsStep.class), mock(IndexTestsStep.class), - mock(QualityProfileEventsStep.class) + mock(QualityProfileEventsStep.class), + mock(ValidateProjectStep.class) ); - assertThat(registry.orderedSteps()).hasSize(20); + assertThat(registry.orderedSteps()).hasSize(21); assertThat(registry.orderedSteps().get(0)).isInstanceOf(PopulateComponentsUuidAndKeyStep.class); - assertThat(registry.orderedSteps().get(19)).isInstanceOf(SendIssueNotificationsStep.class); + assertThat(registry.orderedSteps().get(20)).isInstanceOf(SendIssueNotificationsStep.class); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ValidateProjectStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ValidateProjectStepTest.java new file mode 100644 index 00000000000..434c3dfca86 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ValidateProjectStepTest.java @@ -0,0 +1,222 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.step; + +import java.io.File; +import java.io.IOException; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.DbTester; +import org.sonar.server.component.ComponentTesting; +import org.sonar.server.component.db.ComponentDao; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.ComponentTreeBuilders; +import org.sonar.server.computation.component.DumbComponent; +import org.sonar.server.db.DbClient; + +public class ValidateProjectStepTest { + + private static final String PROJECT_KEY = "PROJECT_KEY"; + private static final String MODULE_KEY = "MODULE_KEY"; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @ClassRule + public static DbTester dbTester = new DbTester(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + DbClient dbClient; + + DbSession dbSession; + + Settings settings; + + ValidateProjectStep sut; + + @Before + public void setUp() throws Exception { + dbTester.truncateTables(); + dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao()); + dbSession = dbClient.openSession(false); + settings = new Settings(); + + sut = new ValidateProjectStep(dbClient, settings); + } + + @After + public void tearDown() throws Exception { + dbSession.close(); + } + + @Test + public void not_fail_if_provisioning_enforced_and_project_exists() throws Exception { + settings.appendProperty(CoreProperties.CORE_PREVENT_AUTOMATIC_PROJECT_CREATION, "true"); + dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto("ABCD").setKey(PROJECT_KEY)); + dbSession.commit(); + + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, + ComponentTreeBuilders.from(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY)), null)); + } + + @Test + public void fail_if_provisioning_enforced_and_project_does_not_exists() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Unable to scan non-existing project '" + PROJECT_KEY + "'"); + + settings.appendProperty(CoreProperties.CORE_PREVENT_AUTOMATIC_PROJECT_CREATION, "true"); + + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, + ComponentTreeBuilders.from(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY)), null)); + } + + @Test + public void fail_if_provisioning_not_enforced_and_project_does_not_exists() throws Exception { + settings.appendProperty(CoreProperties.CORE_PREVENT_AUTOMATIC_PROJECT_CREATION, "false"); + + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, + ComponentTreeBuilders.from(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY)), null)); + } + + @Test + public void not_fail_on_valid_branch() throws Exception { + File reportDir = temp.newFolder(); + BatchReportWriter writer = new BatchReportWriter(reportDir); + writer.writeMetadata(BatchReport.Metadata.newBuilder() + .setBranch("origin/master") + .build()); + + sut.execute(new ComputationContext(new BatchReportReader(reportDir), null, null, null, + ComponentTreeBuilders.from(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY)), null)); + } + + @Test + public void fail_on_invalid_branch() throws Exception { + File reportDir = temp.newFolder(); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Validation of project failed:\n" + + " o \"bran#ch\" is not a valid branch name. Allowed characters are alphanumeric, '-', '_', '.' and '/'."); + + BatchReportWriter writer = new BatchReportWriter(reportDir); + writer.writeMetadata(BatchReport.Metadata.newBuilder() + .setBranch("bran#ch") + .build()); + + sut.execute(new ComputationContext(new BatchReportReader(reportDir), null, null, null, + ComponentTreeBuilders.from(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY)), null)); + } + + @Test + public void fail_on_invalid_key() throws Exception { + String invalidProjectKey = "Project\\Key"; + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Validation of project failed:\n" + + " o \"Project\\Key\" is not a valid project or module key. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.\n" + + " o \"Module$Key\" is not a valid project or module key. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit"); + + DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", invalidProjectKey, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", "Module$Key")); + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, ComponentTreeBuilders.from(root), null)); + } + + @Test + public void fail_if_module_key_is_already_used_as_project_key() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Validation of project failed:\n" + + " o The project \"" + MODULE_KEY + "\" is already defined in SonarQube but not as a module of project \"" + PROJECT_KEY + "\". " + + "If you really want to stop directly analysing project \"" + MODULE_KEY + "\", please first delete it from SonarQube and then relaunch the analysis of project \"" + + PROJECT_KEY + "\"."); + + ComponentDto project = ComponentTesting.newProjectDto("ABCD").setKey(MODULE_KEY); + dbClient.componentDao().insert(dbSession, project); + dbSession.commit(); + + DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", MODULE_KEY)); + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, + ComponentTreeBuilders.from(root), null)); + } + + @Test + public void fail_if_module_key_already_exists_in_another_project() throws Exception { + String anotherProjectKey = "ANOTHER_PROJECT_KEY"; + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Validation of project failed:\n" + + " o Module \"" + MODULE_KEY + "\" is already part of project \"" + anotherProjectKey + "\""); + + ComponentDto project = ComponentTesting.newProjectDto("ABCD").setKey(PROJECT_KEY); + ComponentDto anotherProject = ComponentTesting.newProjectDto().setKey(anotherProjectKey); + dbClient.componentDao().insert(dbSession, project, anotherProject); + ComponentDto module = ComponentTesting.newModuleDto("BCDE", anotherProject).setKey(MODULE_KEY); + dbClient.componentDao().insert(dbSession, module); + dbSession.commit(); + + DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", MODULE_KEY)); + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, + ComponentTreeBuilders.from(root), null)); + } + + @Test + public void fail_if_project_key_already_exists_as_module() throws Exception { + String anotherProjectKey = "ANOTHER_PROJECT_KEY"; + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Validation of project failed:\n" + + " o The project \"" + PROJECT_KEY + "\" is already defined in SonarQube but as a module of project \"" + anotherProjectKey + "\". " + + "If you really want to stop directly analysing project \"" + anotherProjectKey + "\", please first delete it from SonarQube and then relaunch the analysis of project \"" + + PROJECT_KEY + "\"."); + + ComponentDto anotherProject = ComponentTesting.newProjectDto().setKey(anotherProjectKey); + dbClient.componentDao().insert(dbSession, anotherProject); + ComponentDto module = ComponentTesting.newModuleDto("ABCD", anotherProject).setKey(PROJECT_KEY); + dbClient.componentDao().insert(dbSession, module); + dbSession.commit(); + + DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", MODULE_KEY)); + sut.execute(new ComputationContext(createBasicBatchReportReader(), null, null, null, + ComponentTreeBuilders.from(root), null)); + } + + private BatchReportReader createBasicBatchReportReader() throws IOException { + File reportDir = temp.newFolder(); + BatchReportWriter writer = new BatchReportWriter(reportDir); + writer.writeMetadata(BatchReport.Metadata.newBuilder() + .build()); + return new BatchReportReader(reportDir); + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java index 424b8a269bf..7eac6cd994c 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java @@ -20,18 +20,17 @@ package org.sonar.core.component.db; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.session.RowBounds; import org.sonar.core.component.ComponentDto; import org.sonar.core.component.FilePathWithHashDto; import org.sonar.core.component.UuidWithProjectUuidDto; -import javax.annotation.CheckForNull; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - /** * @since 4.3 */ @@ -46,11 +45,6 @@ public interface ComponentMapper { @CheckForNull ComponentDto selectByUuid(String uuid); - /** - * Return direct modules from a project/module - */ - List selectModulesByProject(@Param("projectKey") String projectKey); - /** * Return sub project of component keys */ @@ -96,7 +90,7 @@ public interface ComponentMapper { /** * Return all components of a project */ - List selectComponentsFromProjectKey(@Param("projectKey") String projectKey); + List selectComponentsFromProjectKeyAndScope(@Param("projectKey") String projectKey, @Nullable @Param("scope") String scope); /** * Return technical projects from a view or a sub-view diff --git a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml index ad195fe0815..8c58c026256 100644 --- a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml @@ -64,18 +64,6 @@ - - - SELECT FROM projects p INNER JOIN projects root ON root.uuid=p.project_uuid AND root.kee=#{projectKey} AND p.enabled=${_true} + + AND p.scope=#{scope} +