From 49c7ed8d6a92fd697c8c9e0522300b13b52074c6 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 20 Mar 2015 14:15:38 +0100 Subject: [PATCH] SONAR-6012 Issues on files on removed modules should contain the module key --- .../org/sonar/server/batch/IssuesAction.java | 2 +- .../server/batch/ProjectRepositoryLoader.java | 6 +-- .../server/component/db/ComponentDao.java | 12 ++++-- .../sonar/server/view/index/ViewIndexer.java | 2 +- .../sonar/server/batch/IssuesActionTest.java | 31 +++++++++++++- .../server/component/db/ComponentDaoTest.java | 40 +++++++++++++------ .../db/ComponentDaoTest/multi-modules.xml | 20 ++++++++++ .../core/component/db/ComponentMapper.java | 10 +++-- .../sonar/core/properties/PropertiesDao.java | 4 +- .../core/properties/PropertiesMapper.java | 3 +- .../core/component/db/ComponentMapper.xml | 10 +++-- .../core/properties/PropertiesMapper.xml | 2 +- .../core/properties/PropertiesDaoTest.java | 8 ++-- 13 files changed, 112 insertions(+), 38 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/IssuesAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/IssuesAction.java index 147d7d899f2..c19c985787e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/IssuesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/IssuesAction.java @@ -135,7 +135,7 @@ public class IssuesAction implements RequestHandler { private Map keysByUUid(DbSession session, ComponentDto component) { Map keysByUUid = newHashMap(); if (Scopes.PROJECT.equals(component.scope())) { - List modulesTree = dbClient.componentDao().selectModulesTree(session, component.uuid()); + List modulesTree = dbClient.componentDao().selectDescendantModules(session, component.uuid()); for (ComponentDto componentDto : modulesTree) { keysByUUid.put(componentDto.uuid(), componentDto.key()); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java index 50576f75bf4..0ebebdac72a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java @@ -102,11 +102,11 @@ public class ProjectRepositoryLoader implements ServerComponent { projectKey = project.key(); } - List modulesTree = dbClient.componentDao().selectModulesTree(session, module.uuid()); + List modulesTree = dbClient.componentDao().selectEnabledDescendantModules(session, module.uuid()); Map moduleUuidsByKey = moduleUuidsByKey(module, modulesTree); Map moduleIdsByKey = moduleIdsByKey(module, modulesTree); - List modulesTreeSettings = dbClient.propertiesDao().selectModulePropertiesTree(module.uuid(), session); + List modulesTreeSettings = dbClient.propertiesDao().selectEnabledDescendantModuleProperties(module.uuid(), session); TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings, module); addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.newHashMap(), treeModuleSettings, hasScanPerm, session); @@ -288,7 +288,7 @@ public class ProjectRepositoryLoader implements ServerComponent { moduleKeysByUuid.put(module.uuid(), module.key()); } - for (FilePathWithHashDto file : dbClient.componentDao().selectModuleFilesTree(session, moduleKey)) { + for (FilePathWithHashDto file : dbClient.componentDao().selectEnabledDescendantFiles(session, moduleKey)) { FileData fileData = new FileData(file.getSrcHash(), false, null, null, null); ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData); } 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 27cd270de81..652e34631b9 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 @@ -95,12 +95,16 @@ public class ComponentDao extends BaseDao return mapper(session).findSubProjectsByComponentUuids(keys); } - public List selectModulesTree(DbSession session, String rootComponentUuid) { - return mapper(session).selectModulesTree(rootComponentUuid, Scopes.PROJECT); + public List selectDescendantModules(DbSession session, String rootComponentUuid) { + return mapper(session).selectDescendantModules(rootComponentUuid, Scopes.PROJECT, false); } - public List selectModuleFilesTree(DbSession session, String rootComponentUuid) { - return mapper(session).selectModuleFilesTree(rootComponentUuid, Scopes.FILE); + public List selectEnabledDescendantModules(DbSession session, String rootComponentUuid) { + return mapper(session).selectDescendantModules(rootComponentUuid, Scopes.PROJECT, true); + } + + public List selectEnabledDescendantFiles(DbSession session, String rootComponentUuid) { + return mapper(session).selectDescendantFiles(rootComponentUuid, Scopes.FILE, true); } public List getByIds(final DbSession session, Collection ids) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java index bc6f501be0b..1b8a12356b3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java @@ -82,7 +82,7 @@ public class ViewIndexer extends BaseIndexer { DbSession dbSession = dbClient.openSession(false); try { Map viewAndProjectViewUuidMap = newHashMap(); - for (ComponentDto viewOrSubView : dbClient.componentDao().selectModulesTree(dbSession, rootViewUuid)) { + for (ComponentDto viewOrSubView : dbClient.componentDao().selectEnabledDescendantModules(dbSession, rootViewUuid)) { viewAndProjectViewUuidMap.put(viewOrSubView.uuid(), viewOrSubView.projectUuid()); } index(dbSession, viewAndProjectViewUuidMap, true); diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java index ed1efae697c..9186253b320 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java @@ -298,11 +298,40 @@ public class IssuesActionTest { assertThat(previousIssue.getAssigneeLogin()).isEqualTo("john"); } + @Test + public void project_issues_attached_file_on_removed_module() throws Exception { + ComponentDto project = ComponentTesting.newProjectDto("ABCD").setKey(PROJECT_KEY); + // File and module are removed + ComponentDto module = ComponentTesting.newModuleDto("BCDE", project).setKey(MODULE_KEY).setEnabled(false); + ComponentDto file = ComponentTesting.newFileDto(module, "CDEF").setKey(FILE_KEY).setPath("src/org/struts/Action.java").setEnabled(false); + componentDao.insert(session, project, module, file); + session.commit(); + + indexIssues(IssueTesting.newDoc("EFGH", file) + .setRuleKey("squid:AvoidCycle") + .setSeverity("BLOCKER") + .setStatus("RESOLVED") + .setResolution("FALSE-POSITIVE") + .setManualSeverity(false) + .setMessage("Do not use this method") + .setLine(200) + .setChecksum("123456") + .setAssignee("john")); + + MockUserSession.set().setLogin("henry").setGlobalPermissions(GlobalPermissions.PREVIEW_EXECUTION); + + WsTester.TestRequest request = tester.newGetRequest("batch", "issues").setParam("key", PROJECT_KEY); + ServerIssue serverIssue = ServerIssue.parseDelimitedFrom(new ByteArrayInputStream(request.execute().output())); + assertThat(serverIssue.getKey()).isEqualTo("EFGH"); + // Module key of removed file should be returned + assertThat(serverIssue.getModuleKey()).isEqualTo(MODULE_KEY); + } + @Test(expected = ForbiddenException.class) public void fail_without_preview_permission() throws Exception { MockUserSession.set().setLogin("henry").setGlobalPermissions(GlobalPermissions.PROVISIONING); - WsTester.TestRequest request = tester.newGetRequest("batch", "issues").setParam("key", MODULE_KEY); + WsTester.TestRequest request = tester.newGetRequest("batch", "issues").setParam("key", PROJECT_KEY); request.execute(); } 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 1c62b09058e..8c55ee6ce1d 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 @@ -346,55 +346,71 @@ public class ComponentDaoTest extends AbstractDaoTestCase { } @Test - public void select_modules_tree() throws Exception { + public void select_enabled_modules_tree() throws Exception { setupData("multi-modules"); // From root project - List modules = dao.selectModulesTree(session, "ABCD"); + List modules = dao.selectEnabledDescendantModules(session, "ABCD"); assertThat(modules).extracting("uuid").containsOnly("ABCD", "EFGH", "FGHI"); // From module - modules = dao.selectModulesTree(session, "EFGH"); + modules = dao.selectEnabledDescendantModules(session, "EFGH"); assertThat(modules).extracting("uuid").containsOnly("EFGH", "FGHI"); // From sub module - modules = dao.selectModulesTree(session, "FGHI"); + modules = dao.selectEnabledDescendantModules(session, "FGHI"); assertThat(modules).extracting("uuid").containsOnly("FGHI"); // Folder - assertThat(dao.selectModulesTree(session, "GHIJ")).isEmpty(); - assertThat(dao.selectModulesTree(session, "unknown")).isEmpty(); + assertThat(dao.selectEnabledDescendantModules(session, "GHIJ")).isEmpty(); + assertThat(dao.selectEnabledDescendantModules(session, "unknown")).isEmpty(); } @Test - public void select_module_files_tree() throws Exception { + public void select_all_modules_tree() throws Exception { + setupData("multi-modules"); + + // From root project, disabled sub module is returned + List modules = dao.selectDescendantModules(session, "ABCD"); + assertThat(modules).extracting("uuid").containsOnly("ABCD", "EFGH", "FGHI", "IHGF"); + + // From module, disabled sub module is returned + modules = dao.selectDescendantModules(session, "EFGH"); + assertThat(modules).extracting("uuid").containsOnly("EFGH", "FGHI", "IHGF"); + + // From removed sub module -> should not be returned + assertThat(dao.selectDescendantModules(session, "IHGF")).isEmpty(); + } + + @Test + public void select_enabled_module_files_tree() throws Exception { setupData("select_module_files_tree"); // From root project - List files = dao.selectModuleFilesTree(session, "ABCD"); + List files = dao.selectEnabledDescendantFiles(session, "ABCD"); assertThat(files).extracting("uuid").containsOnly("EFGHI", "HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); // From module - files = dao.selectModuleFilesTree(session, "EFGH"); + files = dao.selectEnabledDescendantFiles(session, "EFGH"); assertThat(files).extracting("uuid").containsOnly("EFGHI", "HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); // From sub module - files = dao.selectModuleFilesTree(session, "FGHI"); + files = dao.selectEnabledDescendantFiles(session, "FGHI"); assertThat(files).extracting("uuid").containsOnly("HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/RequestContext.java"); // From directory - assertThat(dao.selectModuleFilesTree(session, "GHIJ")).isEmpty(); + assertThat(dao.selectEnabledDescendantFiles(session, "GHIJ")).isEmpty(); - assertThat(dao.selectModuleFilesTree(session, "unknown")).isEmpty(); + assertThat(dao.selectEnabledDescendantFiles(session, "unknown")).isEmpty(); } @Test diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml index 6f68d6d45cd..76ac0b9862f 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml @@ -87,4 +87,24 @@ depth="[null]" scope="FIL" qualifier="CLA" created_at="1228222680000" build_date="1228222680000" version="[null]" path="1.2.3.4."/> + + + + + + + + + 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 1f057c62dc8..648f2a7cf9d 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 @@ -68,14 +68,16 @@ public interface ComponentMapper { List findProjectUuids(); /** - * Return all modules tree (child, grand child, etc. including itself) from a module uuid + * Return all descendant modules (including itself) from a given component uuid and scope */ - List selectModulesTree(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope); + List selectDescendantModules(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, + @Param(value = "excludeDisabled") boolean excludeDisabled); /** - * Return all files children from a module uuid + * Return all descendant files from a given component uuid and scope */ - List selectModuleFilesTree(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope); + List selectDescendantFiles(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, + @Param(value = "excludeDisabled") boolean excludeDisabled); /** * Return uuids and project uuids from list of qualifiers diff --git a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java index 3f080f74beb..e32589f1b0c 100644 --- a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java +++ b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java @@ -157,8 +157,8 @@ public class PropertiesDao implements BatchComponent, ServerComponent, DaoCompon } } - public List selectModulePropertiesTree(String moduleUuid, SqlSession session) { - return session.getMapper(PropertiesMapper.class).selectModulePropertiesTree(moduleUuid, Scopes.PROJECT); + public List selectEnabledDescendantModuleProperties(String moduleUuid, SqlSession session) { + return session.getMapper(PropertiesMapper.class).selectDescendantModuleProperties(moduleUuid, Scopes.PROJECT, true); } public PropertyDto selectProjectProperty(long resourceId, String propertyKey) { diff --git a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java index 4124d23e46d..b2368e69f98 100644 --- a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesMapper.java @@ -44,7 +44,8 @@ public interface PropertiesMapper { List selectByQuery(@Param("query") PropertyQuery query); - List selectModulePropertiesTree(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope); + List selectDescendantModuleProperties(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, + @Param(value = "excludeDisabled") boolean excludeDisabled); void update(PropertyDto property); 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 547092e5076..91a3bc460a6 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 @@ -136,7 +136,7 @@ - SELECT FROM projects p @@ -144,9 +144,11 @@ INNER JOIN projects root_project ON root_project.uuid = p.project_uuid AND root_project.enabled = ${_true} - INNER JOIN projects module ON module.project_uuid = root_project.uuid AND module.enabled = ${_true} AND module.uuid = #{moduleUuid} AND module.scope='PRJ' + INNER JOIN projects module ON module.project_uuid = root_project.uuid AND module.uuid = #{moduleUuid} AND module.scope='PRJ' AND module.enabled = ${_true} - p.enabled = ${_true} + + p.enabled = ${_true} + AND p.scope = #{scope} AND @@ -163,7 +165,7 @@ - SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash FROM projects p INNER JOIN file_sources fs ON fs.file_uuid=p.uuid diff --git a/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml b/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml index 40b7eb2a38a..fb4e703d33e 100644 --- a/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/properties/PropertiesMapper.xml @@ -45,7 +45,7 @@ where p.resource_id=#{resourceId} and p.user_id is null - SELECT prop.id as id, prop.prop_key as "key", prop.text_value as value, prop.resource_id as resourceId, prop.user_id as userId FROM properties prop INNER JOIN (SELECT p.id FROM projects p) modules on modules.id=prop.resource_id diff --git a/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java b/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java index c92c655006a..3b20680b2dc 100644 --- a/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/properties/PropertiesDaoTest.java @@ -178,20 +178,20 @@ public class PropertiesDaoTest extends AbstractDaoTestCase { public void select_module_properties_tree() throws Exception { setupData("select_module_properties_tree"); - List properties = dao.selectModulePropertiesTree("ABCD", session); + List properties = dao.selectEnabledDescendantModuleProperties("ABCD", session); assertThat(properties.size(), is(4)); assertThat(properties).extracting("key").containsOnly("struts.one", "core.one", "core.two", "data.one"); assertThat(properties).extracting("value").containsOnly("one", "two"); - properties = dao.selectModulePropertiesTree("EFGH", session); + properties = dao.selectEnabledDescendantModuleProperties("EFGH", session); assertThat(properties.size(), is(3)); assertThat(properties).extracting("key").containsOnly("core.one", "core.two", "data.one"); - properties = dao.selectModulePropertiesTree("FGHI", session); + properties = dao.selectEnabledDescendantModuleProperties("FGHI", session); assertThat(properties.size(), is(1)); assertThat(properties).extracting("key").containsOnly("data.one"); - assertThat(dao.selectModulePropertiesTree("unknown", session).size(), is(0)); + assertThat(dao.selectEnabledDescendantModuleProperties("unknown", session).size(), is(0)); } @Test -- 2.39.5