From 50b12df3787d87958fcef7fbf8c00598b141f1ee Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Fri, 30 Sep 2022 12:23:26 -0500 Subject: [PATCH] SONAR-17352 Refactor component keys to not include branch suffix --- .../analysis/ProjectConfigurationFactory.java | 13 +- .../component/ComponentUuidFactoryImpl.java | 14 + .../ComponentUuidFactoryWithMigration.java | 25 +- .../ConfigurationRepositoryImpl.java | 6 +- .../ReferenceBranchComponentUuids.java | 6 +- .../SiblingComponentsWithOpenIssues.java | 2 - .../issue/ProjectTrackerBaseLazyInput.java | 6 +- .../issue/SiblingsIssuesLoader.java | 4 +- .../issue/SourceBranchComponentUuids.java | 7 +- .../issue/TargetBranchComponentUuids.java | 2 - .../NewCodeReferenceBranchComponentUuids.java | 7 +- .../step/BuildComponentTreeStep.java | 3 +- .../step/PersistComponentsStep.java | 2 +- .../step/ValidateProjectStep.java | 12 +- .../ProjectConfigurationFactoryTest.java | 10 +- ...ComponentUuidFactoryWithMigrationTest.java | 30 ++- .../ConfigurationRepositoryTest.java | 55 ++-- .../issue/SiblingsIssueMergerTest.java | 6 +- .../step/PersistComponentsStepTest.java | 2 +- .../step/ReportPersistComponentsStepTest.java | 4 +- .../step/ValidateProjectStepTest.java | 6 +- ...sFailureNotificationExecutionListener.java | 26 +- ...lureNotificationExecutionListenerTest.java | 44 ++-- .../org/sonar/db/component/ComponentDao.java | 244 +++++++++--------- .../org/sonar/db/component/ComponentDto.java | 2 - .../db/component/ComponentKeyUpdaterDao.java | 34 +-- .../component/ComponentKeyUpdaterMapper.java | 4 +- .../sonar/db/component/ComponentMapper.java | 21 +- .../org/sonar/db/property/PropertiesDao.java | 13 +- .../org/sonar/db/purge/PurgeCommands.java | 2 +- .../java/org/sonar/db/purge/PurgeMapper.java | 2 +- .../component/ComponentKeyUpdaterMapper.xml | 4 +- .../sonar/db/component/ComponentMapper.xml | 108 +++++--- .../org/sonar/db/purge/PurgeMapper.xml | 2 +- .../sonar/db/component/ComponentDaoTest.java | 160 +++++++++--- .../component/ComponentKeyUpdaterDaoTest.java | 59 +---- .../sonar/db/property/PropertiesDaoTest.java | 39 +-- .../sonar/db/component/ComponentDbTester.java | 5 + .../sonar/db/property/PropertyDbTester.java | 28 +- .../setting/ProjectConfigurationLoader.java | 15 +- .../ProjectConfigurationLoaderImpl.java | 47 ++-- .../ProjectConfigurationLoaderImplTest.java | 176 ++++--------- .../server/issue/index/IssueQueryFactory.java | 21 +- .../org/sonar/server/batch/IssuesAction.java | 5 +- .../server/component/ComponentFinder.java | 32 ++- .../sonar/server/component/ws/ShowAction.java | 8 + .../component/ws/SuggestionsAction.java | 2 +- .../sonar/server/component/ws/TreeAction.java | 31 ++- .../developers/ws/SearchEventsAction.java | 48 ++-- .../duplication/ws/DuplicationsParser.java | 15 +- .../duplication/ws/ShowResponseBuilder.java | 5 +- .../sonar/server/hotspot/ws/SearchAction.java | 27 +- .../server/issue/ws/SearchResponseData.java | 6 +- .../server/issue/ws/SearchResponseFormat.java | 13 +- .../server/issue/ws/SearchResponseLoader.java | 7 +- .../server/measure/ws/ComponentAction.java | 5 +- .../measure/ws/ComponentTreeAction.java | 31 ++- .../server/measure/ws/ComponentTreeData.java | 12 + .../sonar/server/setting/ws/ValuesAction.java | 18 +- .../sonar/server/ui/ws/ComponentAction.java | 19 +- .../server/component/ComponentFinderTest.java | 31 ++- .../component/ComponentUpdaterTest.java | 2 +- .../server/component/ws/TreeActionTest.java | 15 +- .../ws/DuplicationsParserTest.java | 3 +- .../server/duplication/ws/ShowActionTest.java | 3 +- .../server/favorite/ws/RemoveActionTest.java | 12 - .../server/hotspot/ws/SearchActionTest.java | 41 +-- .../issue/ws/SearchActionComponentsTest.java | 14 +- .../server/issue/ws/SearchActionTest.java | 35 ++- ...archResponseFormatFormatOperationTest.java | 82 +++--- .../measure/ws/ComponentTreeActionTest.java | 2 +- .../TestProjectConfigurationLoader.java | 11 +- .../server/setting/ws/SetActionTest.java | 2 +- .../server/setting/ws/ValuesActionTest.java | 181 ++++++------- 74 files changed, 994 insertions(+), 1002 deletions(-) diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactory.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactory.java index 4d65f853965..abb3952be3a 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactory.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactory.java @@ -37,17 +37,18 @@ public class ProjectConfigurationFactory { this.dbClient = dbClient; } - public Configuration newProjectConfiguration(String projectKey, Branch branch) { + public Configuration newProjectConfiguration(String projectUuid, String branchUuid) { Settings projectSettings = new ChildSettings(globalSettings); - addSettings(projectSettings, projectKey); - // TODO branch / PR - addSettings(projectSettings, projectKey); + addSettings(projectSettings, projectUuid); + if (!projectUuid.equals(branchUuid)) { + addSettings(projectSettings, branchUuid); + } return new ConfigurationBridge(projectSettings); } - private void addSettings(Settings settings, String componentDbKey) { + private void addSettings(Settings settings, String componentUuid) { dbClient.propertiesDao() - .selectProjectProperties(componentDbKey) + .selectComponentProperties(componentUuid) .forEach(property -> settings.setProperty(property.getKey(), property.getValue())); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryImpl.java index 31b044c65e4..26e3fd4feb0 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryImpl.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryImpl.java @@ -22,9 +22,11 @@ package org.sonar.ce.task.projectanalysis.component; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.component.BranchType; import org.sonar.db.component.KeyWithUuidDto; public class ComponentUuidFactoryImpl implements ComponentUuidFactory { @@ -35,6 +37,18 @@ public class ComponentUuidFactoryImpl implements ComponentUuidFactory { keys.forEach(dto -> uuidsByKey.put(dto.key(), dto.uuid())); } + public ComponentUuidFactoryImpl(DbClient dbClient, DbSession dbSession, String rootKey, Branch branch) { + List keys; + if (branch.isMain()) { + keys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey); + } else if (branch.getType() == BranchType.PULL_REQUEST) { + keys = dbClient.componentDao().selectUuidsByKeyFromProjectKeyAndPullRequest(dbSession, rootKey, branch.getPullRequestKey()); + } else { + keys = dbClient.componentDao().selectUuidsByKeyFromProjectKeyAndBranch(dbSession, rootKey, branch.getName()); + } + keys.forEach(dto -> uuidsByKey.put(dto.key(), dto.uuid())); + } + /** * Get UUID from database if it exists, otherwise generate a new one. */ diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigration.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigration.java index 894853ba7c6..c8b963690d7 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigration.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigration.java @@ -30,9 +30,11 @@ import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; +import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentWithModuleUuidDto; import org.sonar.db.component.KeyWithUuidDto; @@ -41,13 +43,22 @@ public class ComponentUuidFactoryWithMigration implements ComponentUuidFactory { private final Map uuidsByDbKey = new HashMap<>(); private final Map uuidsByMigratedKey = new HashMap<>(); - public ComponentUuidFactoryWithMigration(DbClient dbClient, DbSession dbSession, String rootKey, Function pathToKey, Map reportModulesPath) { + public ComponentUuidFactoryWithMigration(DbClient dbClient, DbSession dbSession, String rootKey, Branch branch, + Function pathToKey, Map reportModulesPath) { Map modulePathsByUuid; - List keys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey); + List keys; + if (branch.isMain()) { + keys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey); + } else if (branch.getType() == BranchType.PULL_REQUEST) { + keys = dbClient.componentDao().selectUuidsByKeyFromProjectKeyAndPullRequest(dbSession, rootKey, branch.getPullRequestKey()); + } else { + keys = dbClient.componentDao().selectUuidsByKeyFromProjectKeyAndBranch(dbSession, rootKey, branch.getName()); + } + keys.forEach(dto -> uuidsByDbKey.put(dto.key(), dto.uuid())); if (!reportModulesPath.isEmpty()) { - modulePathsByUuid = loadModulePathsByUuid(dbClient, dbSession, rootKey, reportModulesPath); + modulePathsByUuid = loadModulePathsByUuid(dbClient, dbSession, rootKey, branch, reportModulesPath); if (!modulePathsByUuid.isEmpty()) { doMigration(dbClient, dbSession, rootKey, pathToKey, modulePathsByUuid); @@ -96,9 +107,13 @@ public class ComponentUuidFactoryWithMigration implements ComponentUuidFactory { return dbClient.componentDao().selectEnabledComponentsWithModuleUuidFromProjectKey(dbSession, rootKey); } - private static Map loadModulePathsByUuid(DbClient dbClient, DbSession dbSession, String rootKey, Map pathByModuleKey) { + private static Map loadModulePathsByUuid(DbClient dbClient, DbSession dbSession, String rootKey, + Branch branch, Map pathByModuleKey) { + String branchKey = branch.getType() == BranchType.BRANCH ? branch.getName() : null; + String prKey = branch.getType() == BranchType.PULL_REQUEST ? branch.getPullRequestKey() : null; + List moduleDtos = dbClient.componentDao() - .selectProjectAndModulesFromProjectKey(dbSession, rootKey, true).stream() + .selectProjectAndModulesFromProjectKey(dbSession, rootKey, true, branchKey, prKey).stream() .filter(c -> Qualifiers.MODULE.equals(c.qualifier())) .collect(Collectors.toList()); diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryImpl.java index 04970136a94..02aba3d59fe 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryImpl.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryImpl.java @@ -32,8 +32,10 @@ public class ConfigurationRepositoryImpl implements ConfigurationRepository { private final Supplier configuration; - public ConfigurationRepositoryImpl(AnalysisMetadataHolder analysisMetadataHolder, ProjectConfigurationFactory f) { - this.configuration = Suppliers.memoize(() -> f.newProjectConfiguration(analysisMetadataHolder.getProject().getKey(), analysisMetadataHolder.getBranch())); + public ConfigurationRepositoryImpl(TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder, ProjectConfigurationFactory f) { + String branchUuid = treeRootHolder.getRoot().getUuid(); + String projectUuid = analysisMetadataHolder.getProject().getUuid(); + this.configuration = Suppliers.memoize(() -> f.newProjectConfiguration(projectUuid, branchUuid)); } @Override diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ReferenceBranchComponentUuids.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ReferenceBranchComponentUuids.java index f77a898e369..099fbcd4e19 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ReferenceBranchComponentUuids.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ReferenceBranchComponentUuids.java @@ -31,7 +31,6 @@ import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import static com.google.common.base.Preconditions.checkState; -import static org.sonar.db.component.ComponentDto.removeBranchAndPullRequestFromKey; /** * Cache a map between component keys and uuids in the reference branch @@ -87,9 +86,8 @@ public class ReferenceBranchComponentUuids { } @CheckForNull - public String getComponentUuid(String dbKey) { + public String getComponentUuid(String key) { lazyInit(); - String cleanComponentKey = removeBranchAndPullRequestFromKey(dbKey); - return referenceBranchComponentsUuidsByKey.get(cleanComponentKey); + return referenceBranchComponentsUuidsByKey.get(key); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java index ffa537805b2..1bd2e4499a1 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java @@ -30,8 +30,6 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.KeyWithUuidDto; -import static org.sonar.db.component.ComponentDto.removeBranchAndPullRequestFromKey; - /** * Cache a map of component key -> set<uuid> in: * - sibling PRs that have open issues diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ProjectTrackerBaseLazyInput.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ProjectTrackerBaseLazyInput.java index ea027852f83..06c825707e9 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ProjectTrackerBaseLazyInput.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ProjectTrackerBaseLazyInput.java @@ -72,7 +72,11 @@ class ProjectTrackerBaseLazyInput extends BaseInputFactory.BaseLazyInput { if (!dirOrModulesUuidsWithIssues.isEmpty()) { Map pathByModuleKey = reportModulesPath.get(); // Migrate issues that were previously on modules or directories to the root project - Map modulesByUuid = dbClient.componentDao().selectProjectAndModulesFromProjectKey(dbSession, component.getKey(), true) + String branchKey = analysisMetadataHolder.isBranch() ? analysisMetadataHolder.getBranch().getName() : null; + String prKey = analysisMetadataHolder.isPullRequest() ? analysisMetadataHolder.getBranch().getPullRequestKey() : null; + + Map modulesByUuid = dbClient.componentDao() + .selectProjectAndModulesFromProjectKey(dbSession, component.getKey(), true, branchKey, prKey) .stream().collect(Collectors.toMap(ComponentDto::uuid, Function.identity())); List dirOrModulesWithIssues = dbClient.componentDao().selectByUuids(dbSession, dirOrModulesUuidsWithIssues); dirOrModulesWithIssues.forEach(c -> { diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssuesLoader.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssuesLoader.java index 60c94d1f999..661820926b3 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssuesLoader.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssuesLoader.java @@ -30,7 +30,6 @@ import org.sonar.ce.task.projectanalysis.component.SiblingComponentsWithOpenIssu import org.sonar.core.issue.DefaultIssue; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDto; import org.sonar.db.issue.IssueDto; import org.sonar.db.issue.PrIssueDto; @@ -52,8 +51,7 @@ public class SiblingsIssuesLoader { } public Collection loadCandidateSiblingIssuesForMerging(Component component) { - String componentKey = ComponentDto.removeBranchAndPullRequestFromKey(component.getKey()); - Set uuids = siblingComponentsWithOpenIssues.getUuids(componentKey); + Set uuids = siblingComponentsWithOpenIssues.getUuids(component.getKey()); if (uuids.isEmpty()) { return Collections.emptyList(); } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SourceBranchComponentUuids.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SourceBranchComponentUuids.java index 409c8204d48..bca0a4af370 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SourceBranchComponentUuids.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/SourceBranchComponentUuids.java @@ -30,8 +30,6 @@ import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; -import static org.sonar.db.component.ComponentDto.removeBranchAndPullRequestFromKey; - /** * Cache a map between component keys and uuids in the source branch of a pull request */ @@ -79,9 +77,8 @@ public class SourceBranchComponentUuids { } @CheckForNull - public String getSourceBranchComponentUuid(String dbKey) { + public String getSourceBranchComponentUuid(String key) { lazyInit(); - String cleanComponentKey = removeBranchAndPullRequestFromKey(dbKey); - return sourceBranchComponentsUuidsByKey.get(cleanComponentKey); + return sourceBranchComponentsUuidsByKey.get(key); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TargetBranchComponentUuids.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TargetBranchComponentUuids.java index 725cf52f6da..40ffea79fe2 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TargetBranchComponentUuids.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TargetBranchComponentUuids.java @@ -30,8 +30,6 @@ import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; -import static org.sonar.db.component.ComponentDto.removeBranchAndPullRequestFromKey; - /** * Cache a map between component keys and uuids in the merge branch and optionally the target branch (for PR and SLB, and only if this target branch is analyzed) */ diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/NewCodeReferenceBranchComponentUuids.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/NewCodeReferenceBranchComponentUuids.java index c45a933d1d3..5833d847ea2 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/NewCodeReferenceBranchComponentUuids.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/NewCodeReferenceBranchComponentUuids.java @@ -32,8 +32,6 @@ import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.newcodeperiod.NewCodePeriodType; -import static org.sonar.db.component.ComponentDto.removeBranchAndPullRequestFromKey; - /** * Cache a map between component keys and uuids in the reference branch */ @@ -76,9 +74,8 @@ public class NewCodeReferenceBranchComponentUuids { } @CheckForNull - public String getComponentUuid(String dbKey) { + public String getComponentUuid(String key) { lazyInit(); - String cleanComponentKey = removeBranchAndPullRequestFromKey(dbKey); - return referenceBranchComponentsUuidsByKey.get(cleanComponentKey); + return referenceBranchComponentsUuidsByKey.get(key); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/BuildComponentTreeStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/BuildComponentTreeStep.java index 6607b973a75..e27cb71510d 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/BuildComponentTreeStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/BuildComponentTreeStep.java @@ -79,7 +79,8 @@ public class BuildComponentTreeStep implements ComputationStep { String rootKey = keyGenerator.generateKey(reportProject.getKey(), null); Function pathToKey = path -> keyGenerator.generateKey(reportProject.getKey(), path); // loads the UUIDs from database. If they don't exist, then generate new ones - ComponentUuidFactoryWithMigration componentUuidFactoryWithMigration = new ComponentUuidFactoryWithMigration(dbClient, dbSession, rootKey, pathToKey, reportModulesPath.get()); + ComponentUuidFactoryWithMigration componentUuidFactoryWithMigration = + new ComponentUuidFactoryWithMigration(dbClient, dbSession, rootKey, analysisMetadataHolder.getBranch(), pathToKey, reportModulesPath.get()); String rootUuid = componentUuidFactoryWithMigration.getOrCreateForKey(rootKey); Optional baseAnalysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, rootUuid); diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStep.java index 16adb079fbd..28ff34d9775 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStep.java @@ -149,7 +149,7 @@ public class PersistComponentsStep implements ComputationStep { * disabled components. */ private Map indexExistingDtosByUuids(DbSession session) { - return dbClient.componentDao().selectAllComponentsFromProjectKey(session, treeRootHolder.getRoot().getKey()) + return dbClient.componentDao().selectByBranchUuid(treeRootHolder.getRoot().getUuid(), session) .stream() .collect(Collectors.toMap(ComponentDto::uuid, Function.identity())); } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java index 52716dd4e90..ac1a139afc5 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java @@ -67,7 +67,9 @@ public class ValidateProjectStep implements ComputationStep { validateTargetBranch(dbSession); Component root = treeRootHolder.getRoot(); // FIXME if module have really be dropped, no more need to load them - List baseModules = dbClient.componentDao().selectEnabledModulesFromProjectKey(dbSession, root.getKey()); + String branchKey = analysisMetadataHolder.isBranch() ? analysisMetadataHolder.getBranch().getName() : null; + String prKey = analysisMetadataHolder.isPullRequest() ? analysisMetadataHolder.getBranch().getPullRequestKey() : null; + List baseModules = dbClient.componentDao().selectEnabledModulesFromProjectKey(dbSession, root.getKey(), branchKey, prKey); Map baseModulesByKey = baseModules.stream().collect(Collectors.toMap(ComponentDto::getKey, x -> x)); ValidateProjectsVisitor visitor = new ValidateProjectsVisitor(dbSession, dbClient.componentDao(), baseModulesByKey); new DepthTraversalTypeAwareCrawler(visitor).visit(root); @@ -134,7 +136,7 @@ public class ValidateProjectStep implements ComputationStep { Long lastAnalysisDate = snapshotDto.map(SnapshotDto::getCreatedAt).orElse(null); if (lastAnalysisDate != null && currentAnalysisDate <= lastAnalysisDate) { validationMessages.add(format("Date of analysis cannot be older than the date of the last known analysis on this project. Value: \"%s\". " + - "Latest analysis: \"%s\". It's only possible to rebuild the past in a chronological order.", + "Latest analysis: \"%s\". It's only possible to rebuild the past in a chronological order.", formatDateTime(new Date(currentAnalysisDate)), formatDateTime(new Date(lastAnalysisDate)))); } } @@ -143,7 +145,11 @@ public class ValidateProjectStep implements ComputationStep { ComponentDto baseComponent = baseModulesByKey.get(rawComponentKey); if (baseComponent == null) { // Load component from key to be able to detect issue (try to analyze a module, etc.) - return componentDao.selectByKey(session, rawComponentKey); + if (analysisMetadataHolder.isBranch()) { + return componentDao.selectByKeyAndBranch(session, rawComponentKey, analysisMetadataHolder.getBranch().getName()); + } else { + return componentDao.selectByKeyAndPullRequest(session, rawComponentKey, analysisMetadataHolder.getBranch().getPullRequestKey()); + } } return Optional.of(baseComponent); } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactoryTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactoryTest.java index f6c512561db..69011ec0095 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactoryTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactoryTest.java @@ -31,20 +31,16 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; public class ProjectConfigurationFactoryTest { - - private static final String PROJECT_KEY = "PROJECT_KEY"; - @Rule public DbTester db = DbTester.create(); private MapSettings settings = new MapSettings(); - private ProjectConfigurationFactory underTest = new ProjectConfigurationFactory(settings, db.getDbClient()); @Test public void return_global_settings() { settings.setProperty("key", "value"); - Configuration config = underTest.newProjectConfiguration(PROJECT_KEY, new DefaultBranchImpl()); + Configuration config = underTest.newProjectConfiguration("unknown", "unknown"); assertThat(config.get("key")).hasValue("value"); } @@ -57,7 +53,7 @@ public class ProjectConfigurationFactoryTest { newComponentPropertyDto(project).setKey("2").setValue("val2"), newComponentPropertyDto(project).setKey("3").setValue("val3")); - Configuration config = underTest.newProjectConfiguration(project.getKey(), new DefaultBranchImpl()); + Configuration config = underTest.newProjectConfiguration(project.uuid(), project.uuid()); assertThat(config.get("1")).hasValue("val1"); assertThat(config.get("2")).hasValue("val2"); @@ -71,7 +67,7 @@ public class ProjectConfigurationFactoryTest { db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), newComponentPropertyDto(project).setKey("key").setValue("value2")); - Configuration projectConfig = underTest.newProjectConfiguration(project.getKey(), new DefaultBranchImpl()); + Configuration projectConfig = underTest.newProjectConfiguration(project.uuid(), project.uuid()); assertThat(projectConfig.get("key")).hasValue("value2"); } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigrationTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigrationTest.java index 230d04ee3d3..7f3839bab0f 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigrationTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryWithMigrationTest.java @@ -26,6 +26,7 @@ import java.util.function.Function; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.System2; +import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; @@ -33,7 +34,7 @@ import org.sonar.db.component.ComponentTesting; import static org.assertj.core.api.Assertions.assertThat; public class ComponentUuidFactoryWithMigrationTest { - + private final Branch mainBranch = new DefaultBranchImpl(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); private Function pathToKey = path -> path != null ? "project:" + path : "project"; @@ -45,7 +46,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map reportModulesPath = Collections.singletonMap(module.getKey(), "module1_path"); pathToKey = path -> path != null ? project.getKey() + ":" + path : project.getKey(); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, reportModulesPath); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, reportModulesPath); assertThat(underTest.getOrCreateForKey(project.getKey())).isEqualTo(project.uuid()); assertThat(underTest.getOrCreateForKey(module.getKey())).isEqualTo(module.uuid()); @@ -69,7 +71,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map modulesRelativePaths = new HashMap<>(); modulesRelativePaths.put("project:module1", "module1_path"); modulesRelativePaths.put("project:module1:module2", "module1_path/module2_path"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // migrated files assertThat(underTest.getOrCreateForKey("project:file1_path")).isEqualTo(file1.uuid()); @@ -94,7 +97,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map modulesRelativePaths = new HashMap<>(); modulesRelativePaths.put("project:module1", "module1_path"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // migrated files assertThat(underTest.getOrCreateForKey("project:file1")).isEqualTo(file1.uuid()); @@ -118,7 +122,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map modulesRelativePaths = new HashMap<>(); modulesRelativePaths.put("project:module1", "module1_path"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // migrated files assertThat(underTest.getOrCreateForKey("project:file1")).isEqualTo(file1.uuid()); @@ -142,7 +147,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map modulesRelativePaths = new HashMap<>(); modulesRelativePaths.put("project:module1", "module1_path"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // in theory we should migrate file1. But since disabledFileSameKey already have the expected migrated key, let's reuse it. assertThat(underTest.getOrCreateForKey("project:module1/file1")).isEqualTo(disabledFileSameKey.uuid()); @@ -170,7 +176,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map modulesRelativePaths = new HashMap<>(); modulesRelativePaths.put("project:module1", "module1_path"); modulesRelativePaths.put("project:module1:module2", "module1_path/module2_path"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // migrated files assertThat(underTest.getOrCreateForKey("project:file1_path")).isEqualTo(file1.uuid()); @@ -189,7 +196,8 @@ public class ComponentUuidFactoryWithMigrationTest { .setKey("project:module1:/")); Map modulesRelativePaths = Collections.singletonMap("project:module1", "module1_path"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // project remains the same assertThat(underTest.getOrCreateForKey(project.getKey())).isEqualTo(project.uuid()); @@ -210,7 +218,8 @@ public class ComponentUuidFactoryWithMigrationTest { Map modulesRelativePaths = new HashMap<>(); modulesRelativePaths.put("project", ""); modulesRelativePaths.put("project:module2", "module2"); - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), pathToKey, modulesRelativePaths); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), project.getKey(), mainBranch, pathToKey, modulesRelativePaths); // check root project. assertThat(underTest.getOrCreateForKey("project")).isEqualTo(project.uuid()); @@ -218,7 +227,8 @@ public class ComponentUuidFactoryWithMigrationTest { @Test public void generate_uuid_if_it_does_not_exist_in_db() { - ComponentUuidFactoryWithMigration underTest = new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), "theProjectKey", pathToKey, Collections.emptyMap()); + ComponentUuidFactoryWithMigration underTest = + new ComponentUuidFactoryWithMigration(db.getDbClient(), db.getSession(), "theProjectKey", mainBranch, pathToKey, Collections.emptyMap()); String generatedKey = underTest.getOrCreateForKey("foo"); assertThat(generatedKey).isNotEmpty(); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryTest.java index 072eec8a5ba..a7e43c2b813 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryTest.java @@ -41,28 +41,30 @@ import static org.mockito.Mockito.when; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; public class ConfigurationRepositoryTest { - - private static Project PROJECT = Project.from(newPrivateProjectDto()); - @Rule public final DbTester db = DbTester.create(System2.INSTANCE); + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); - private DbClient dbClient = db.getDbClient(); - private MapSettings globalSettings = new MapSettings(); - private Branch branch = mock(Branch.class); - private AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); + private final DbClient dbClient = db.getDbClient(); + private final MapSettings globalSettings = new MapSettings(); + private final Project project = Project.from(newPrivateProjectDto()); + private final Component root = mock(Component.class); private ConfigurationRepository underTest; + @Before public void setUp() { - when(branch.getName()).thenReturn("branchName"); - analysisMetadataHolder.setBranch(branch); - underTest = new ConfigurationRepositoryImpl(analysisMetadataHolder, new ProjectConfigurationFactory(globalSettings, dbClient)); + analysisMetadataHolder.setProject(project); + when(root.getUuid()).thenReturn(project.getUuid()); + treeRootHolder.setRoot(root); + underTest = new ConfigurationRepositoryImpl(treeRootHolder, analysisMetadataHolder, new ProjectConfigurationFactory(globalSettings, dbClient)); } @Test public void get_project_settings_from_global_settings() { - analysisMetadataHolder.setProject(PROJECT); globalSettings.setProperty("key", "value"); Configuration config = underTest.getConfiguration(); @@ -72,9 +74,7 @@ public class ConfigurationRepositoryTest { @Test public void get_project_settings_from_db() { - ComponentDto project = db.components().insertPrivateProject(); - analysisMetadataHolder.setProject(Project.from(project)); - insertProjectProperty(project, "key", "value"); + insertComponentProperty(project.getUuid(), "key", "value"); Configuration config = underTest.getConfiguration(); @@ -83,7 +83,6 @@ public class ConfigurationRepositoryTest { @Test public void call_twice_get_project_settings() { - analysisMetadataHolder.setProject(PROJECT); globalSettings.setProperty("key", "value"); Configuration config = underTest.getConfiguration(); @@ -96,9 +95,7 @@ public class ConfigurationRepositoryTest { @Test public void project_settings_override_global_settings() { globalSettings.setProperty("key", "value1"); - ComponentDto project = db.components().insertPrivateProject(); - insertProjectProperty(project, "key", "value2"); - analysisMetadataHolder.setProject(Project.from(project)); + insertComponentProperty(project.getUuid(), "key", "value2"); Configuration config = underTest.getConfiguration(); assertThat(config.get("key")).hasValue("value2"); @@ -106,9 +103,7 @@ public class ConfigurationRepositoryTest { @Test public void project_settings_are_cached_to_avoid_db_access() { - ComponentDto project = db.components().insertPrivateProject(); - insertProjectProperty(project, "key", "value"); - analysisMetadataHolder.setProject(Project.from(project)); + insertComponentProperty(project.getUuid(), "key", "value"); Configuration config = underTest.getConfiguration(); assertThat(config.get("key")).hasValue("value"); @@ -121,17 +116,9 @@ public class ConfigurationRepositoryTest { @Test public void branch_settings() { - ComponentDto project = db.components().insertPublicProject(); - String branchName = randomAlphanumeric(248); - ComponentDto branchDto = db.components().insertProjectBranch(project, b -> b.setKey(branchName)); - Branch branch = mock(Branch.class); - when(branch.getName()).thenReturn(branchName); - analysisMetadataHolder - .setProject(Project.from(project)) - .setBranch(branch); globalSettings.setProperty("global", "global value"); - insertProjectProperty(project, "project", "project value"); - insertProjectProperty(branchDto, "branch", "branch value"); + insertComponentProperty(project.getUuid(), "project", "project value"); + insertComponentProperty(root.getUuid(), "branch", "branch value"); Configuration config = underTest.getConfiguration(); @@ -140,8 +127,8 @@ public class ConfigurationRepositoryTest { assertThat(config.get("branch")).hasValue("branch value"); } - private void insertProjectProperty(ComponentDto project, String propertyKey, String propertyValue) { - db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(), - new PropertyDto().setKey(propertyKey).setValue(propertyValue).setComponentUuid(project.uuid())); + private void insertComponentProperty(String componentUuid, String propertyKey, String propertyValue) { + db.properties().insertProperties(null, null, null, null, + new PropertyDto().setKey(propertyKey).setValue(propertyValue).setComponentUuid(componentUuid)); } } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java index ebd2a0573cf..05ebd80be50 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java @@ -115,9 +115,9 @@ public class SiblingsIssueMergerTest { branch3Dto = db.components().insertProjectBranch(projectDto, b -> b.setKey("myBranch3") .setBranchType(BranchType.PULL_REQUEST) .setMergeBranchUuid(projectDto.uuid())); - fileOnBranch1Dto = db.components().insertComponent(newFileDto(branch1Dto).setKey(FILE_1_KEY + ":PULL_REQUEST:myBranch1")); - fileOnBranch2Dto = db.components().insertComponent(newFileDto(branch2Dto).setKey(FILE_1_KEY + ":PULL_REQUEST:myBranch2")); - fileOnBranch3Dto = db.components().insertComponent(newFileDto(branch3Dto).setKey(FILE_1_KEY + ":PULL_REQUEST:myBranch3")); + fileOnBranch1Dto = db.components().insertComponent(newFileDto(branch1Dto).setKey(FILE_1_KEY)); + fileOnBranch2Dto = db.components().insertComponent(newFileDto(branch2Dto).setKey(FILE_1_KEY)); + fileOnBranch3Dto = db.components().insertComponent(newFileDto(branch3Dto).setKey(FILE_1_KEY)); rule = db.rules().insert(); when(branch.getReferenceBranchUuid()).thenReturn(projectDto.uuid()); metadataHolder.setBranch(branch); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStepTest.java index b20ca1a6088..fbce8cc4f18 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStepTest.java @@ -53,7 +53,7 @@ public class PersistComponentsStepTest { doReturn(component).when(treeRootHolder).getRoot(); doReturn(projectKey).when(component).getKey(); doReturn(componentDao).when(dbClient).componentDao(); - doReturn(emptyList()).when(componentDao).selectAllComponentsFromProjectKey(any(DbSession.class), eq(projectKey)); + doReturn(emptyList()).when(componentDao).selectByBranchUuid(eq(projectKey), any(DbSession.class)); assertThatThrownBy(() -> { new PersistComponentsStep( diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java index 0f8bf052a3d..ec94c781441 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java @@ -184,7 +184,7 @@ public class ReportPersistComponentsStepTest extends BaseStepTest { assertThat(directoryDto.getUuidPath()).isEqualTo(UUID_PATH_SEPARATOR + branch.uuid() + UUID_PATH_SEPARATOR); assertThat(directoryDto.moduleUuid()).isEqualTo(branch.uuid()); assertThat(directoryDto.moduleUuidPath()).isEqualTo(branch.moduleUuidPath()); - assertThat(directoryDto.getMainBranchProjectUuid()).isEqualTo(branch.uuid()); + assertThat(directoryDto.getMainBranchProjectUuid()).isEqualTo(analysisMetadataHolder.getProject().getUuid()); assertThat(directoryDto.branchUuid()).isEqualTo(branch.uuid()); assertThat(directoryDto.qualifier()).isEqualTo("DIR"); assertThat(directoryDto.scope()).isEqualTo("DIR"); @@ -201,7 +201,7 @@ public class ReportPersistComponentsStepTest extends BaseStepTest { assertThat(fileDto.getUuidPath()).isEqualTo(directoryDto.getUuidPath() + directoryDto.uuid() + UUID_PATH_SEPARATOR); assertThat(fileDto.moduleUuid()).isEqualTo(branch.uuid()); assertThat(fileDto.moduleUuidPath()).isEqualTo(branch.moduleUuidPath()); - assertThat(fileDto.getMainBranchProjectUuid()).isEqualTo(branch.uuid()); + assertThat(fileDto.getMainBranchProjectUuid()).isEqualTo(analysisMetadataHolder.getProject().getUuid()); assertThat(fileDto.branchUuid()).isEqualTo(branch.uuid()); assertThat(fileDto.qualifier()).isEqualTo("FIL"); assertThat(fileDto.scope()).isEqualTo("FIL"); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java index 0e36782973a..fdc355dfe2a 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java @@ -80,8 +80,7 @@ public class ValidateProjectStepTest { @Test public void not_fail_if_analysis_date_is_after_last_analysis() { - ComponentDto project = ComponentTesting.newPrivateProjectDto("ABCD").setKey(PROJECT_KEY); - db.components().insertComponent(project); + ComponentDto project = db.components().insertPrivateProject("ABCD", c -> c.setKey(PROJECT_KEY)); dbClient.snapshotDao().insert(db.getSession(), SnapshotTesting.newAnalysis(project).setCreatedAt(PAST_ANALYSIS_TIME)); db.getSession().commit(); @@ -112,8 +111,7 @@ public class ValidateProjectStepTest { public void fail_if_analysis_date_is_before_last_analysis() { analysisMetadataHolder.setAnalysisDate(DateUtils.parseDate("2015-01-01")); - ComponentDto project = ComponentTesting.newPrivateProjectDto("ABCD").setKey(PROJECT_KEY); - db.components().insertComponent(project); + ComponentDto project = db.components().insertPrivateProject("ABCD", c -> c.setKey(PROJECT_KEY)); dbClient.snapshotDao().insert(db.getSession(), SnapshotTesting.newAnalysis(project).setCreatedAt(1433131200000L)); // 2015-06-01 db.getSession().commit(); diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java b/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java index 942135a776c..aa62c8cf56e 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java @@ -22,7 +22,6 @@ package org.sonar.ce.notification; import java.time.Duration; import javax.annotation.Nullable; import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; import org.sonar.api.utils.System2; import org.sonar.ce.task.CeTask; import org.sonar.ce.task.CeTaskResult; @@ -37,6 +36,7 @@ import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.server.notification.NotificationService; import static com.google.common.base.Preconditions.checkArgument; @@ -74,10 +74,11 @@ public class ReportAnalysisFailureNotificationExecutionListener implements CeWor if (notificationService.hasProjectSubscribersForTypes(projectUuid, singleton(ReportAnalysisFailureNotification.class))) { try (DbSession dbSession = dbClient.openSession(false)) { - ComponentDto projectDto = dbClient.componentDao().selectOrFailByUuid(dbSession, projectUuid); - BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, projectDto.branchUuid()) - .orElseThrow(() -> new IllegalStateException("Could not find a branch for component uuid " + projectDto.uuid())); - checkScopeAndQualifier(projectDto); + ProjectDto projectDto = dbClient.projectDao().selectByUuid(dbSession, projectUuid) + .orElseThrow(() -> new IllegalStateException("Could not find project uuid " + projectUuid)); + BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, projectDto.getUuid()) + .orElseThrow(() -> new IllegalStateException("Could not find a branch for project uuid " + projectDto.getUuid())); + checkQualifier(projectDto); CeActivityDto ceActivityDto = dbClient.ceActivityDao().selectByUuid(dbSession, ceTask.getUuid()) .orElseThrow(() -> new RowNotFoundException(format("CeActivity with uuid '%s' not found", ceTask.getUuid()))); ReportAnalysisFailureNotificationBuilder taskFailureNotification = buildNotification(ceActivityDto, projectDto, branchDto, error); @@ -93,23 +94,20 @@ public class ReportAnalysisFailureNotificationExecutionListener implements CeWor /** * @throws IllegalArgumentException if specified {@link ComponentDto} is not a project. */ - private static void checkScopeAndQualifier(ComponentDto projectDto) { - String scope = projectDto.scope(); - String qualifier = projectDto.qualifier(); - checkArgument( - scope.equals(Scopes.PROJECT) && qualifier.equals(Qualifiers.PROJECT), - "Component %s must be a project (scope=%s, qualifier=%s)", projectDto.uuid(), scope, qualifier); + private static void checkQualifier(ProjectDto projectDto) { + String qualifier = projectDto.getQualifier(); + checkArgument(qualifier.equals(Qualifiers.PROJECT), "Component %s must be a project (qualifier=%s)", projectDto.getUuid(), qualifier); } - private ReportAnalysisFailureNotificationBuilder buildNotification(CeActivityDto ceActivityDto, ComponentDto projectDto, BranchDto branchDto, + private ReportAnalysisFailureNotificationBuilder buildNotification(CeActivityDto ceActivityDto, ProjectDto projectDto, BranchDto branchDto, @Nullable Throwable error) { String projectBranch = branchDto.isMain() ? null : branchDto.getBranchKey(); Long executedAt = ceActivityDto.getExecutedAt(); return new ReportAnalysisFailureNotificationBuilder( new ReportAnalysisFailureNotificationBuilder.Project( - projectDto.uuid(), + projectDto.getUuid(), projectDto.getKey(), - projectDto.name(), + projectDto.getName(), projectBranch), new ReportAnalysisFailureNotificationBuilder.Task( ceActivityDto.getUuid(), diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java index c91133baf29..da0c7e7cb7a 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java @@ -25,11 +25,11 @@ import java.util.Arrays; import java.util.Optional; import java.util.Random; import javax.annotation.Nullable; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.sonar.api.notifications.Notification; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.ce.task.CeTask; import org.sonar.ce.task.CeTaskResult; @@ -44,6 +44,7 @@ import org.sonar.db.ce.CeQueueDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; +import org.sonar.db.project.ProjectDto; import org.sonar.server.notification.NotificationService; import static java.util.Collections.singleton; @@ -57,7 +58,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME; import static org.sonar.db.component.ComponentTesting.newDirectory; import static org.sonar.db.component.ComponentTesting.newModuleDto; @@ -79,11 +79,6 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { private final ReportAnalysisFailureNotificationExecutionListener underTest = new ReportAnalysisFailureNotificationExecutionListener( notificationService, dbClient, serializer, system2); - @Before - public void setUp() { - - } - @Test public void onStart_has_no_effect() { CeTask mockedCeTask = mock(CeTask.class); @@ -132,7 +127,7 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { } @Test - public void onEnd_fails_with_RowNotFoundException_if_component_does_not_exist_in_DB() { + public void onEnd_fails_with_ISE_if_project_does_not_exist_in_DB() { String componentUuid = randomAlphanumeric(6); when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT); when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(componentUuid, null, null))); @@ -140,8 +135,24 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { .thenReturn(true); assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock)) - .isInstanceOf(RowNotFoundException.class) - .hasMessage("Component with uuid '" + componentUuid + "' not found"); + .isInstanceOf(IllegalStateException.class) + .hasMessage("Could not find project uuid " + componentUuid); + } + + @Test + public void onEnd_fails_with_ISE_if_branch_does_not_exist_in_DB() { + String componentUuid = randomAlphanumeric(6); + ProjectDto project = new ProjectDto().setUuid(componentUuid).setKey(randomAlphanumeric(5)).setQualifier(Qualifiers.PROJECT); + dbTester.getDbClient().projectDao().insert(dbTester.getSession(), project); + dbTester.getSession().commit(); + when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT); + when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(componentUuid, null, null))); + when(notificationService.hasProjectSubscribersForTypes(componentUuid, singleton(ReportAnalysisFailureNotification.class))) + .thenReturn(true); + + assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Could not find a branch for project uuid " + componentUuid); } @Test @@ -167,8 +178,9 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { fail("An IllegalArgumentException should have been thrown for component " + component); } catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo(String.format( - "Component %s must be a project (scope=%s, qualifier=%s)", component.uuid(), component.scope(), component.qualifier())); + assertThat(e.getMessage()).isEqualTo(String.format("Component %s must be a project (qualifier=%s)", component.uuid(), component.qualifier())); + } catch (IllegalStateException e) { + assertThat(e.getMessage()).isEqualTo("Could not find project uuid " + component.uuid()); } }); } @@ -184,7 +196,7 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { .thenReturn(true); dbTester.components().insertPrivateProject(s -> s.setUuid(componentUuid)); - assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock)) + assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock)) .isInstanceOf(RowNotFoundException.class) .hasMessage("CeActivity with uuid '" + taskUuid + "' not found"); } @@ -208,7 +220,7 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { assertThat(notificationProject.getName()).isEqualTo(project.name()); assertThat(notificationProject.getKey()).isEqualTo(project.getKey()); assertThat(notificationProject.getUuid()).isEqualTo(project.uuid()); - assertThat(notificationProject.getBranchName()).isEqualTo(DEFAULT_MAIN_BRANCH_NAME); + assertThat(notificationProject.getBranchName()).isNull(); ReportAnalysisFailureNotificationBuilder.Task notificationTask = reportAnalysisFailureNotificationBuilder.getTask(); assertThat(notificationTask.getUuid()).isEqualTo(taskUuid); assertThat(notificationTask.getCreatedAt()).isEqualTo(createdAt); @@ -305,8 +317,8 @@ public class ReportAnalysisFailureNotificationExecutionListenerTest { .setTaskType(CeTaskTypes.REPORT) .setComponentUuid(project.uuid()) .setCreatedAt(createdAt)) - .setExecutedAt(executedAt) - .setStatus(CeActivityDto.Status.FAILED)); + .setExecutedAt(executedAt) + .setStatus(CeActivityDto.Status.FAILED)); dbTester.getSession().commit(); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java index 56f6bae2fd1..687d4e574aa 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java @@ -23,17 +23,14 @@ import com.google.common.collect.Ordering; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nullable; -import org.apache.commons.lang.StringUtils; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.sonar.api.resources.Qualifiers; @@ -45,6 +42,7 @@ import org.sonar.db.audit.AuditPersister; import org.sonar.db.audit.model.ComponentNewValue; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; import static java.util.Collections.emptyList; import static org.sonar.db.DatabaseUtils.checkThatNotTooManyConditions; import static org.sonar.db.DatabaseUtils.executeLargeInputs; @@ -58,26 +56,9 @@ public class ComponentDao implements Dao { this.auditPersister = auditPersister; } - private static List selectByQueryImpl(DbSession session, ComponentQuery query, int offset, int limit) { - if (query.hasEmptySetOfComponents()) { - return emptyList(); - } - checkThatNotTooManyComponents(query); - return mapper(session).selectByQuery(query, new RowBounds(offset, limit)); - } - - private static int countByQueryImpl(DbSession session, ComponentQuery query) { - if (query.hasEmptySetOfComponents()) { - return 0; - } - checkThatNotTooManyComponents(query); - return mapper(session).countByQuery(query); - } - - private static ComponentMapper mapper(DbSession session) { - return session.getMapper(ComponentMapper.class); - } - + /* + * SELECT BY UUID + */ public Optional selectByUuid(DbSession session, String uuid) { return Optional.ofNullable(mapper(session).selectByUuid(uuid)); } @@ -86,22 +67,12 @@ public class ComponentDao implements Dao { return selectByUuid(session, uuid).orElseThrow(() -> new RowNotFoundException(String.format("Component with uuid '%s' not found", uuid))); } - /** - * @throws IllegalArgumentException if parameter query#getComponentIds() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values - * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values - * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values - */ - public List selectByQuery(DbSession dbSession, ComponentQuery query, int offset, int limit) { - return selectByQueryImpl(dbSession, query, offset, limit); + public List selectByUuids(DbSession session, Collection uuids) { + return executeLargeInputs(uuids, mapper(session)::selectByUuids); } - /** - * @throws IllegalArgumentException if parameter query#getComponentIds() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values - * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values - * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values - */ - public int countByQuery(DbSession session, ComponentQuery query) { - return countByQueryImpl(session, query); + public List selectExistingUuids(DbSession session, Collection uuids) { + return executeLargeInputs(uuids, mapper(session)::selectExistingUuids); } public List selectSubProjectsByComponentUuids(DbSession session, Collection uuids) { @@ -127,81 +98,100 @@ public class ComponentDao implements Dao { return mapper(session).selectEnabledFilesFromProject(rootComponentUuid); } - public List selectByUuids(DbSession session, Collection uuids) { - return executeLargeInputs(uuids, mapper(session)::selectByUuids); + /** + * Retrieves all components with a specific branch UUID, no other filtering is done by this method. + */ + public List selectByBranchUuid(String branchUuid, DbSession dbSession) { + return mapper(dbSession).selectByBranchUuid(branchUuid); } - public List selectExistingUuids(DbSession session, Collection uuids) { - return executeLargeInputs(uuids, mapper(session)::selectExistingUuids); + public int countEnabledModulesByBranchUuid(DbSession session, String branchUuid) { + return mapper(session).countEnabledModulesByBranchUuid(branchUuid); } + /* + SELECT BY QUERY + */ + /** - * Return all components of a project (including disable ones) + * @throws IllegalArgumentException if parameter query#getComponentIds() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values + * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values + * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values */ - public List selectAllComponentsFromProjectKey(DbSession session, String projectKey) { - return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, null, false); + public List selectByQuery(DbSession dbSession, ComponentQuery query, int offset, int limit) { + return selectByQueryImpl(dbSession, query, offset, limit); } - public List selectUuidsByKeyFromProjectKey(DbSession session, String projectKey) { - return mapper(session).selectUuidsByKeyFromProjectKey(projectKey); + /** + * @throws IllegalArgumentException if parameter query#getComponentIds() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values + * @throws IllegalArgumentException if parameter query#getComponentKeys() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values + * @throws IllegalArgumentException if parameter query#getMainComponentUuids() has more than {@link org.sonar.db.DatabaseUtils#PARTITION_SIZE_FOR_ORACLE} values + */ + public int countByQuery(DbSession session, ComponentQuery query) { + return countByQueryImpl(session, query); } - public List selectProjectAndModulesFromProjectKey(DbSession session, String projectKey, boolean excludeDisabled) { - return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, Scopes.PROJECT, excludeDisabled); + private static List selectByQueryImpl(DbSession session, ComponentQuery query, int offset, int limit) { + if (query.hasEmptySetOfComponents()) { + return emptyList(); + } + checkThatNotTooManyComponents(query); + return mapper(session).selectByQuery(query, new RowBounds(offset, limit)); } - public int countEnabledModulesByBranchUuid(DbSession session, String branchUuid) { - return mapper(session).countEnabledModulesByBranchUuid(branchUuid); + private static int countByQueryImpl(DbSession session, ComponentQuery query) { + if (query.hasEmptySetOfComponents()) { + return 0; + } + checkThatNotTooManyComponents(query); + return mapper(session).countByQuery(query); } - public List selectEnabledModulesFromProjectKey(DbSession session, String projectKey) { - return selectProjectAndModulesFromProjectKey(session, projectKey, true); - } + /* + SELECT BY KEY + */ - public List selectByKeys(DbSession session, Collection keys) { - return executeLargeInputs(keys, mapper(session)::selectByKeys); + /** + * Return all components of a project (including disable ones) + */ + public List selectUuidsByKeyFromProjectKey(DbSession session, String projectKey) { + return mapper(session).selectUuidsByKeyFromProjectKeyAndBranchOrPr(projectKey, null, null); } - public List selectByKeysAndBranch(DbSession session, Collection keys, String branch) { - return executeLargeInputs(keys, subKeys -> mapper(session).selectByKeysAndBranch(subKeys, branch)); + public List selectUuidsByKeyFromProjectKeyAndBranch(DbSession session, String projectKey, String branch) { + return mapper(session).selectUuidsByKeyFromProjectKeyAndBranchOrPr(projectKey, branch, null); } - public List selectByKeysAndPullRequest(DbSession session, Collection keys, String pullRequestId) { - return executeLargeInputs(keys, subKeys -> mapper(session).selectByKeysAndBranch(subKeys, pullRequestId)); + public List selectUuidsByKeyFromProjectKeyAndPullRequest(DbSession session, String projectKey, String pullrequest) { + return mapper(session).selectUuidsByKeyFromProjectKeyAndBranchOrPr(projectKey, null, pullrequest); } - public List selectByDbKeys(DbSession session, Collection dbKeys) { - Map> keyByBranchKey = new HashMap<>(); - Map> keyByPrKey = new HashMap<>(); - List mainBranchKeys = new LinkedList<>(); - - for (String dbKey : dbKeys) { - String branchKey = StringUtils.substringAfterLast(dbKey, ComponentDto.BRANCH_KEY_SEPARATOR); - if (!StringUtils.isEmpty(branchKey)) { - keyByBranchKey.computeIfAbsent(branchKey, b -> new LinkedList<>()) - .add(StringUtils.substringBeforeLast(dbKey, ComponentDto.BRANCH_KEY_SEPARATOR)); - continue; - } + /** + * If no branch or pull request is provided, returns components in the main branch + */ + public List selectProjectAndModulesFromProjectKey(DbSession session, String projectKey, boolean excludeDisabled, + @Nullable String branch, @Nullable String pullRequest) { + checkState(branch == null || pullRequest == null, "Can't set both branch and pull request"); + return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, Scopes.PROJECT, excludeDisabled, branch, pullRequest); + } - String prKey = StringUtils.substringAfterLast(dbKey, ComponentDto.PULL_REQUEST_SEPARATOR); - if (!StringUtils.isEmpty(prKey)) { - keyByPrKey.computeIfAbsent(prKey, b -> new LinkedList<>()) - .add(StringUtils.substringBeforeLast(dbKey, ComponentDto.PULL_REQUEST_SEPARATOR)); - continue; - } + /** + * If no branch or pull request is provided, returns components in the main branch + */ + public List selectEnabledModulesFromProjectKey(DbSession session, String projectKey, @Nullable String branch, @Nullable String pullRequest) { + return selectProjectAndModulesFromProjectKey(session, projectKey, true, branch, pullRequest); + } - mainBranchKeys.add(dbKey); - } + public List selectByKeys(DbSession session, Collection keys) { + return selectByKeys(session, keys, null, null); + } - List components = new LinkedList<>(); - for (Map.Entry> e : keyByBranchKey.entrySet()) { - components.addAll(selectByKeysAndBranch(session, e.getValue(), e.getKey())); - } - for (Map.Entry> e : keyByPrKey.entrySet()) { - components.addAll(selectByKeysAndPullRequest(session, e.getValue(), e.getKey())); - } - components.addAll(selectByKeys(session, mainBranchKeys)); - return components; + /** + * If no branch or pull request is provided, returns components in the main branch + */ + public List selectByKeys(DbSession session, Collection keys, @Nullable String branch, @Nullable String pullRequest) { + checkState(branch == null || pullRequest == null, "Can't set both branch and pull request"); + return executeLargeInputs(keys, subKeys -> mapper(session).selectByKeysAndBranchOrPr(subKeys, branch, pullRequest)); } /** @@ -258,10 +248,25 @@ public class ComponentDao implements Dao { return Optional.ofNullable(mapper(session).selectByKeyAndPrKey(key, pullRequestId)); } + /* + SELECT ALL + */ public List selectAllViewsAndSubViews(DbSession session) { return mapper(session).selectUuidsForQualifiers(Qualifiers.APP, Qualifiers.VIEW, Qualifiers.SUBVIEW); } + /** + * Returns all projects (Scope {@link Scopes#PROJECT} and qualifier + * {@link Qualifiers#PROJECT}) which are enabled. + *

+ * Branches are not returned. + *

+ * Used by Views. + */ + public List selectProjects(DbSession session) { + return mapper(session).selectProjects(); + } + /** * Used by Governance */ @@ -276,18 +281,6 @@ public class ComponentDao implements Dao { return mapper(session).selectProjectsFromView("%." + escapedViewUuid + ".%", projectViewUuid); } - /** - * Returns all projects (Scope {@link Scopes#PROJECT} and qualifier - * {@link Qualifiers#PROJECT}) which are enabled. - *

- * Branches are not returned. - *

- * Used by Views. - */ - public List selectProjects(DbSession session) { - return mapper(session).selectProjects(); - } - /** * Selects all components that are relevant for indexing. The result is not returned (since it is usually too big), but handed over to the handler * @@ -299,15 +292,6 @@ public class ComponentDao implements Dao { mapper(session).scrollForIndexing(projectUuid, handler); } - /** - * Retrieves all components with a specific branch UUID, no other filtering is done by this method. - *

- * Used by Views plugin - */ - public List selectByBranchUuid(String branchUuid, DbSession dbSession) { - return mapper(dbSession).selectByBranchUuid(branchUuid); - } - /** * Retrieve enabled components keys with given qualifiers *

@@ -349,6 +333,25 @@ public class ComponentDao implements Dao { mapper(session).scrollAllFilesForFileMove(branchUuid, handler); } + public List selectPrivateProjectsWithNcloc(DbSession dbSession) { + return mapper(dbSession).selectPrivateProjectsWithNcloc(); + } + + public boolean existAnyOfComponentsWithQualifiers(DbSession session, Collection componentKeys, Set qualifiers) { + if (!componentKeys.isEmpty()) { + List result = new LinkedList<>(); + return executeLargeInputs(componentKeys, input -> { + boolean groupNeedIssueSync = mapper(session).checkIfAnyOfComponentsWithQualifiers(input, qualifiers) > 0; + result.add(groupNeedIssueSync); + return result; + }).stream().anyMatch(b -> b); + } + return false; + } + + /* + INSERT / UPDATE + */ public void insert(DbSession session, ComponentDto item) { mapper(session).insert(item); if (!isBranchOrPullRequest(item)) { @@ -396,27 +399,18 @@ public class ComponentDao implements Dao { mapper(session).setPrivateForRootComponentUuid(branchUuid, isPrivate); } + /* + UTIL + */ + private static ComponentMapper mapper(DbSession session) { + return session.getMapper(ComponentMapper.class); + } + private static void checkThatNotTooManyComponents(ComponentQuery query) { checkThatNotTooManyConditions(query.getComponentKeys(), "Too many component keys in query"); checkThatNotTooManyConditions(query.getComponentUuids(), "Too many component UUIDs in query"); } - public List selectPrivateProjectsWithNcloc(DbSession dbSession) { - return mapper(dbSession).selectPrivateProjectsWithNcloc(); - } - - public boolean existAnyOfComponentsWithQualifiers(DbSession session, Collection componentKeys, Set qualifiers) { - if (!componentKeys.isEmpty()) { - List result = new LinkedList<>(); - return executeLargeInputs(componentKeys, input -> { - boolean groupNeedIssueSync = mapper(session).checkIfAnyOfComponentsWithQualifiers(input, qualifiers) > 0; - result.add(groupNeedIssueSync); - return result; - }).stream().anyMatch(b -> b); - } - return false; - } - private static boolean isBranchOrPullRequest(ComponentDto item) { return item.getMainBranchProjectUuid() != null; } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java index d3303761465..ba308ad3ec2 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java @@ -46,8 +46,6 @@ public class ComponentDto { public static final String BRANCH_KEY_SEPARATOR = ":BRANCH:"; public static final String PULL_REQUEST_SEPARATOR = ":PULL_REQUEST:"; - private static final Splitter BRANCH_KEY_SPLITTER = Splitter.on(BRANCH_KEY_SEPARATOR); - public static final String UUID_PATH_SEPARATOR = "."; public static final String UUID_PATH_OF_ROOT = UUID_PATH_SEPARATOR; private static final Splitter UUID_PATH_SPLITTER = Splitter.on(UUID_PATH_SEPARATOR).omitEmptyStrings(); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterDao.java index ec86e389fe3..5e247061a92 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterDao.java @@ -32,9 +32,6 @@ import org.sonar.db.DbSession; import org.sonar.db.audit.AuditPersister; import org.sonar.db.audit.model.ComponentKeyNewValue; -import static org.sonar.db.component.ComponentDto.BRANCH_KEY_SEPARATOR; -import static org.sonar.db.component.ComponentDto.generateBranchKey; - /** * Class used to rename the key of a project and its resources. * @@ -52,17 +49,17 @@ public class ComponentKeyUpdaterDao implements Dao { checkExistentKey(mapper, newKey); // must SELECT first everything - ResourceDto project = mapper.selectProjectByUuid(projectUuid); + ResourceDto project = mapper.selectComponentByUuid(projectUuid); String projectOldKey = project.getKey(); - List resources = mapper.selectProjectResources(projectUuid); + List resources = mapper.selectBranchResources(projectUuid); resources.add(project); // add branch components dbSession.getMapper(BranchMapper.class).selectByProjectUuid(projectUuid).stream() .filter(branch -> !projectUuid.equals(branch.getUuid())) .forEach(branch -> { - resources.addAll(mapper.selectProjectResources(branch.getUuid())); - resources.add(mapper.selectProjectByUuid(branch.getUuid())); + resources.addAll(mapper.selectBranchResources(branch.getUuid())); + resources.add(mapper.selectComponentByUuid(branch.getUuid())); }); // and then proceed with the batch UPDATE at once @@ -70,29 +67,6 @@ public class ComponentKeyUpdaterDao implements Dao { }, dbSession); } - public void updateApplicationBranchKey(DbSession dbSession, String appBranchUuid, String appKey, String newBranchName) { - // TODO review - ComponentKeyUpdaterMapper mapper = dbSession.getMapper(ComponentKeyUpdaterMapper.class); - - String newAppBranchKey = generateBranchKey(appKey, newBranchName); - checkExistentKey(mapper, newAppBranchKey); - - ResourceDto appBranch = mapper.selectProjectByUuid(appBranchUuid); - String appBranchOldKey = appBranch.getKey(); - appBranch.setKey(newAppBranchKey); - mapper.updateComponent(appBranch); - - auditPersister.componentKeyBranchUpdate(dbSession, new ComponentKeyNewValue(appBranchUuid, appBranchOldKey, newAppBranchKey), Qualifiers.APP); - - String oldAppBranchFragment = appBranchOldKey.replace(BRANCH_KEY_SEPARATOR, ""); - String newAppBranchFragment = appKey + newBranchName; - for (ResourceDto appBranchResource : mapper.selectProjectResources(appBranchUuid)) { - String newKey = computeNewKey(appBranchResource.getKey(), oldAppBranchFragment, newAppBranchFragment); - appBranchResource.setKey(newKey); - mapper.updateComponent(appBranchResource); - } - } - @VisibleForTesting static String computeNewKey(String key, String stringToReplace, String replacementString) { return key.replace(stringToReplace, replacementString); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterMapper.java index 6a67af03dc2..f4c38fdf60c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterMapper.java @@ -26,9 +26,9 @@ public interface ComponentKeyUpdaterMapper { int countComponentsByKey(String key); - ResourceDto selectProjectByUuid(@Param("uuid") String uuid); + ResourceDto selectComponentByUuid(@Param("uuid") String uuid); - List selectProjectResources(@Param("rootUuid") String rootUuid); + List selectBranchResources(@Param("rootUuid") String rootUuid); void updateComponent(ResourceDto resource); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java index 98297278093..f669ff574df 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java @@ -29,18 +29,11 @@ import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; public interface ComponentMapper { - - @CheckForNull - ComponentDto selectByKey(@Param("key") String key); - @CheckForNull ComponentDto selectByKeyCaseInsensitive(@Param("key") String key); @CheckForNull - ComponentDto selectByKeyAndBranchKey(@Param("key") String key, @Param("branch") String branch); - - @CheckForNull - ComponentDto selectByKeyAndPrKey(@Param("key") String key, @Param("pr") String pr); + ComponentDto selectByKeyAndBranchOrPr(@Param("key") String key, @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest") String pullRequest); @CheckForNull ComponentDto selectByUuid(@Param("uuid") String uuid); @@ -50,9 +43,8 @@ public interface ComponentMapper { */ List selectSubProjectsByComponentUuids(@Param("uuids") Collection uuids); - List selectByKeys(@Param("keys") Collection keys); - - List selectByKeysAndBranch(@Param("keys") Collection keys, @Param("branch") String branch); + List selectByKeysAndBranchOrPr(@Param("keys") Collection keys, + @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest") String pullRequest); List selectByUuids(@Param("uuids") Collection uuids); @@ -109,12 +101,13 @@ public interface ComponentMapper { * @param scope scope of components to return. If null, all components are returned */ List selectComponentsFromProjectKeyAndScope(@Param("projectKey") String projectKey, @Nullable @Param("scope") String scope, - @Param(value = "excludeDisabled") boolean excludeDisabled); + @Param(value = "excludeDisabled") boolean excludeDisabled, @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest") String pullRequest); /** * Return keys and UUIDs of all components belonging to a project */ - List selectUuidsByKeyFromProjectKey(@Param("projectKey") String projectKey); + List selectUuidsByKeyFromProjectKeyAndBranchOrPr(@Param("projectKey") String projectKey, + @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest") String pullRequest); Set selectViewKeysWithEnabledCopyOfProject(@Param("projectUuids") Collection projectUuids); @@ -142,7 +135,7 @@ public interface ComponentMapper { void delete(String componentUuid); List selectComponentsFromPullRequestsTargetingCurrentBranchThatHaveOpenIssues(@Param("referenceBranchUuid") String referenceBranchUuid, - @Param("currentBranchUuid") String currentBranchUuid); + @Param("currentBranchUuid") String currentBranchUuid); List selectComponentsFromBranchesThatHaveOpenIssues(@Param("branchUuids") List branchUuids); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java index ecf0f8520b8..ae54ec9fd17 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java @@ -42,6 +42,8 @@ import org.sonar.db.audit.AuditPersister; import org.sonar.db.audit.model.PropertyNewValue; import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; import static org.apache.commons.lang.StringUtils.repeat; import static org.sonar.db.DatabaseUtils.executeLargeInputs; import static org.sonar.db.DatabaseUtils.executeLargeInputsIntoSet; @@ -67,7 +69,6 @@ public class PropertiesDao implements Dao { /** * Returns the logins of users who have subscribed to the given notification dispatcher with the given notification channel. * If a resource ID is passed, the search is made on users who have specifically subscribed for the given resource. - * * Note that {@link UserRole#USER} permission is not checked here, filter the results with * {@link org.sonar.db.permission.AuthorizationDao#keepAuthorizedLoginsOnProject} * @@ -151,14 +152,13 @@ public class PropertiesDao implements Dao { } } - // TODO distinguish branch from project - public List selectProjectProperties(DbSession session, String projectKey) { - return getMapper(session).selectProjectProperties(projectKey); + public List selectComponentProperties(DbSession session, String uuid) { + return getMapper(session).selectByComponentUuids(singletonList(uuid)); } - public List selectProjectProperties(String resourceKey) { + public List selectComponentProperties(String uuid) { try (DbSession session = mybatis.openSession(false)) { - return selectProjectProperties(session, resourceKey); + return selectComponentProperties(session, uuid); } } @@ -261,7 +261,6 @@ public class PropertiesDao implements Dao { * Delete either global, user, component or component per user properties. *

Behaves in exactly the same way as {@link #selectByQuery(PropertyQuery, DbSession)} but deletes rather than * selects

- * * Used by Governance. */ public int deleteByQuery(DbSession dbSession, PropertyQuery query) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java index 2b4255ef3e0..e5975bd3458 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java @@ -262,7 +262,7 @@ class PurgeCommands { void deleteComponents(String rootUuid) { profiler.start("deleteComponents (projects)"); - purgeMapper.deleteComponentsByProjectUuid(rootUuid); + purgeMapper.deleteComponentsByBranchUuid(rootUuid); session.commit(); profiler.stop(); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java index 1e8687178d4..c6139a76461 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java @@ -66,7 +66,7 @@ public interface PurgeMapper { void deletePropertiesByComponentUuids(@Param("componentUuids") List componentUuids); - void deleteComponentsByProjectUuid(@Param("rootUuid") String rootUuid); + void deleteComponentsByBranchUuid(@Param("rootUuid") String rootUuid); void deleteComponentsByMainBranchProjectUuid(@Param("uuid") String uuid); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentKeyUpdaterMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentKeyUpdaterMapper.xml index 8112fb214dd..e004a66d79a 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentKeyUpdaterMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentKeyUpdaterMapper.xml @@ -18,12 +18,12 @@ WHERE kee = #{key,jdbcType=VARCHAR} - select * from components where uuid = #{uuid,jdbcType=VARCHAR} - select * from components where root_uuid = #{rootUuid,jdbcType=VARCHAR} diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml index c25cc05c20b..5f67411da9d 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml @@ -52,15 +52,28 @@ and pb.branch_type='BRANCH' - select from components p - inner join project_branches pb on pb.uuid = p.branch_uuid + + inner join project_branches pb on pb.uuid = p.branch_uuid + where p.kee=#{key,jdbcType=VARCHAR} - and pb.kee=#{pr,jdbcType=VARCHAR} - and pb.branch_type='PULL_REQUEST' + + + AND pb.kee=#{branch,jdbcType=VARCHAR} + AND pb.branch_type = 'BRANCH' + + + AND pb.kee=#{pullRequest,jdbcType=VARCHAR} + AND pb.branch_type = 'PULL_REQUEST' + + + AND p.main_branch_project_uuid is NULL + + - - - - - SELECT FROM components p - INNER JOIN project_branches pb on pb.uuid = p.branch_uuid - + + INNER JOIN project_branches pb on pb.uuid = p.branch_uuid + + WHERE p.enabled=${_true} AND p.kee IN #{key,jdbcType=VARCHAR} - AND pb.kee=#{branch,jdbcType=VARCHAR} - + + + AND pb.kee=#{branch,jdbcType=VARCHAR} + AND pb.branch_type = 'BRANCH' + + + AND pb.kee=#{pullRequest,jdbcType=VARCHAR} + AND pb.branch_type = 'PULL_REQUEST' + + + AND p.main_branch_project_uuid IS NULL + + + + - SELECT p.kee, p.uuid FROM components p INNER JOIN components root ON root.uuid=p.branch_uuid AND root.kee=#{projectKey,jdbcType=VARCHAR} + + INNER JOIN project_branches pb ON pb.uuid = root.uuid + + + + + AND pb.kee = #{branch,jdbcType=VARCHAR} + AND pb.branch_type = 'BRANCH' + + + AND pb.kee=#{pullRequest,jdbcType=VARCHAR} + AND pb.branch_type = 'PULL_REQUEST' + + + AND root.main_branch_project_uuid is NULL + + +