From bec219de08fb555f4472865f7041746de612f5f5 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 1 Apr 2019 17:58:07 +0200 Subject: [PATCH] SONAR-11859, SONAR-11879 Track issues with the target branch --- .../MergeAndTargetBranchComponentUuids.java | 136 ++++++++++++++++ .../component/MergeBranchComponentUuids.java | 88 ----------- ...ProjectAnalysisTaskContainerPopulator.java | 8 +- .../issue/IntegrateIssuesVisitor.java | 10 +- .../issue/MergeBranchTrackerExecution.java | 6 +- ...rtBranchOrPullRequestTrackerExecution.java | 41 +++-- ...ackerMergeOrTargetBranchInputFactory.java} | 52 ++++--- .../projectanalysis/scm/ScmInfoDbLoader.java | 8 +- .../PostProjectAnalysisTasksExecutorTest.java | 3 +- ...ergeAndTargetBranchComponentUuidsTest.java | 146 ++++++++++++++++++ .../MergeBranchComponentUuidsTest.java | 79 ---------- .../issue/IntegrateIssuesVisitorTest.java | 14 +- .../MergeBranchTrackerExecutionTest.java | 4 +- ...anchOrPullRequestTrackerExecutionTest.java | 48 +++++- .../scm/ScmInfoDbLoaderTest.java | 8 +- .../scanner/scan/ProjectScanContainer.java | 3 +- 16 files changed, 423 insertions(+), 231 deletions(-) create mode 100644 server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuids.java delete mode 100644 server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuids.java rename server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/{TrackerMergeBranchInputFactory.java => TrackerMergeOrTargetBranchInputFactory.java} (50%) create mode 100644 server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuidsTest.java delete mode 100644 server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuidsTest.java diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuids.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuids.java new file mode 100644 index 00000000000..a126933cc3c --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuids.java @@ -0,0 +1,136 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import javax.annotation.CheckForNull; +import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +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 merge branch and optionally the target branch (for PR and SLB, and only if this target branch is analyzed) + */ +public class MergeAndTargetBranchComponentUuids { + private final AnalysisMetadataHolder analysisMetadataHolder; + private final DbClient dbClient; + private Map mergeBranchComponentsUuidsByKey; + private Map targetBranchComponentsUuidsByKey; + private String mergeBranchName; + private boolean hasMergeBranchAnalysis; + private boolean hasTargetBranchAnalysis; + @CheckForNull + private String targetBranchUuid; + + public MergeAndTargetBranchComponentUuids(AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient) { + this.analysisMetadataHolder = analysisMetadataHolder; + this.dbClient = dbClient; + } + + private void lazyInit() { + if (mergeBranchComponentsUuidsByKey == null) { + String mergeBranchUuid = analysisMetadataHolder.getBranch().getMergeBranchUuid(); + + mergeBranchComponentsUuidsByKey = new HashMap<>(); + targetBranchComponentsUuidsByKey = new HashMap<>(); + + try (DbSession dbSession = dbClient.openSession(false)) { + + Optional opt = dbClient.branchDao().selectByUuid(dbSession, mergeBranchUuid); + checkState(opt.isPresent(), "Merge branch '%s' does not exist", mergeBranchUuid); + mergeBranchName = opt.get().getKey(); + + initForMergeBranch(mergeBranchUuid, dbSession); + + if (analysisMetadataHolder.isSLBorPR()) { + initForTargetBranch(mergeBranchUuid, dbSession); + } else { + hasTargetBranchAnalysis = false; + } + } + } + } + + private void initForTargetBranch(String mergeBranchUuid, DbSession dbSession) { + Optional branchDtoOpt = dbClient.branchDao().selectByBranchKey(dbSession, analysisMetadataHolder.getProject().getUuid(), + analysisMetadataHolder.getBranch().getTargetBranchName()); + targetBranchUuid = branchDtoOpt.map(BranchDto::getUuid).orElse(null); + hasTargetBranchAnalysis = targetBranchUuid != null && dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, targetBranchUuid).isPresent(); + if (hasTargetBranchAnalysis && !targetBranchUuid.equals(mergeBranchUuid)) { + List targetComponents = dbClient.componentDao().selectByProjectUuid(targetBranchUuid, dbSession); + for (ComponentDto dto : targetComponents) { + targetBranchComponentsUuidsByKey.put(dto.getKey(), dto.uuid()); + } + } + } + + private void initForMergeBranch(String mergeBranchUuid, DbSession dbSession) { + hasMergeBranchAnalysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, mergeBranchUuid).isPresent(); + + if (hasMergeBranchAnalysis) { + List components = dbClient.componentDao().selectByProjectUuid(mergeBranchUuid, dbSession); + for (ComponentDto dto : components) { + mergeBranchComponentsUuidsByKey.put(dto.getKey(), dto.uuid()); + } + } + } + + public boolean hasMergeBranchAnalysis() { + lazyInit(); + return hasMergeBranchAnalysis; + } + + public boolean hasTargetBranchAnalysis() { + lazyInit(); + return hasTargetBranchAnalysis; + } + + public String getMergeBranchName() { + lazyInit(); + return mergeBranchName; + } + + public boolean areTargetAndMergeBranchesDifferent() { + lazyInit(); + return targetBranchUuid == null || !analysisMetadataHolder.getBranch().getMergeBranchUuid().equals(targetBranchUuid); + } + + @CheckForNull + public String getMergeBranchComponentUuid(String dbKey) { + lazyInit(); + String cleanComponentKey = removeBranchAndPullRequestFromKey(dbKey); + return mergeBranchComponentsUuidsByKey.get(cleanComponentKey); + } + + @CheckForNull + public String getTargetBranchComponentUuid(String dbKey) { + lazyInit(); + String cleanComponentKey = removeBranchAndPullRequestFromKey(dbKey); + return targetBranchComponentsUuidsByKey.get(cleanComponentKey); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuids.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuids.java deleted file mode 100644 index 888e0c181b1..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuids.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import javax.annotation.CheckForNull; -import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -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 merge branch - */ -public class MergeBranchComponentUuids { - private final AnalysisMetadataHolder analysisMetadataHolder; - private final DbClient dbClient; - private Map uuidsByKey; - private String mergeBranchName; - private boolean hasMergeBranchAnalysis; - - public MergeBranchComponentUuids(AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient) { - this.analysisMetadataHolder = analysisMetadataHolder; - this.dbClient = dbClient; - } - - private void lazyInit() { - if (uuidsByKey == null) { - String mergeBranchUuid = analysisMetadataHolder.getBranch().getMergeBranchUuid(); - - uuidsByKey = new HashMap<>(); - try (DbSession dbSession = dbClient.openSession(false)) { - - List components = dbClient.componentDao().selectByProjectUuid(mergeBranchUuid, dbSession); - for (ComponentDto dto : components) { - uuidsByKey.put(dto.getKey(), dto.uuid()); - } - - Optional opt = dbClient.branchDao().selectByUuid(dbSession, mergeBranchUuid); - checkState(opt.isPresent(), "Merge branch '%s' does not exist", mergeBranchUuid); - mergeBranchName = opt.get().getKey(); - - hasMergeBranchAnalysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, mergeBranchUuid).isPresent(); - } - } - } - - public boolean hasMergeBranchAnalysis() { - lazyInit(); - return hasMergeBranchAnalysis; - } - - public String getMergeBranchName() { - lazyInit(); - return mergeBranchName; - } - - @CheckForNull - public String getUuid(String dbKey) { - lazyInit(); - String cleanComponentKey = removeBranchAndPullRequestFromKey(dbKey); - return uuidsByKey.get(cleanComponentKey); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java index 776e9d63b9a..99358168cc2 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java @@ -34,7 +34,7 @@ import org.sonar.ce.task.projectanalysis.component.BranchPersisterImpl; import org.sonar.ce.task.projectanalysis.component.ConfigurationRepositoryImpl; import org.sonar.ce.task.projectanalysis.component.DbIdsRepositoryImpl; import org.sonar.ce.task.projectanalysis.component.DisabledComponentsHolderImpl; -import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; +import org.sonar.ce.task.projectanalysis.component.MergeAndTargetBranchComponentUuids; import org.sonar.ce.task.projectanalysis.component.ReportModulesPath; import org.sonar.ce.task.projectanalysis.component.SiblingComponentsWithOpenIssues; import org.sonar.ce.task.projectanalysis.component.TreeRootHolderImpl; @@ -82,7 +82,7 @@ import org.sonar.ce.task.projectanalysis.issue.SiblingsIssuesLoader; import org.sonar.ce.task.projectanalysis.issue.ShortBranchOrPullRequestTrackerExecution; import org.sonar.ce.task.projectanalysis.issue.TrackerBaseInputFactory; import org.sonar.ce.task.projectanalysis.issue.TrackerExecution; -import org.sonar.ce.task.projectanalysis.issue.TrackerMergeBranchInputFactory; +import org.sonar.ce.task.projectanalysis.issue.TrackerMergeOrTargetBranchInputFactory; import org.sonar.ce.task.projectanalysis.issue.TrackerRawInputFactory; import org.sonar.ce.task.projectanalysis.issue.UpdateConflictResolver; import org.sonar.ce.task.projectanalysis.issue.commonrule.BranchCoverageRule; @@ -196,7 +196,7 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop MeasureComputersHolderImpl.class, MutableTaskResultHolderImpl.class, BatchReportReaderImpl.class, - MergeBranchComponentUuids.class, + MergeAndTargetBranchComponentUuids.class, SiblingComponentsWithOpenIssues.class, // repositories @@ -271,7 +271,7 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop UpdateConflictResolver.class, TrackerBaseInputFactory.class, TrackerRawInputFactory.class, - TrackerMergeBranchInputFactory.class, + TrackerMergeOrTargetBranchInputFactory.class, ClosedIssuesInputFactory.class, Tracker.class, TrackerExecution.class, diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java index b048a138b9f..2c51dff13ef 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java @@ -27,7 +27,7 @@ import org.sonar.api.rules.RuleType; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.component.Component; import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit; -import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; +import org.sonar.ce.task.projectanalysis.component.MergeAndTargetBranchComponentUuids; import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter; import org.sonar.ce.task.projectanalysis.util.cache.DiskCache; import org.sonar.core.issue.DefaultIssue; @@ -42,11 +42,11 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter { private final IssueTrackingDelegator issueTracking; private final SiblingsIssueMerger issueStatusCopier; private final AnalysisMetadataHolder analysisMetadataHolder; - private final MergeBranchComponentUuids mergeBranchComponentUuids; + private final MergeAndTargetBranchComponentUuids mergeAndTargetBranchComponentUuids; public IntegrateIssuesVisitor(IssueCache issueCache, IssueLifecycle issueLifecycle, IssueVisitors issueVisitors, AnalysisMetadataHolder analysisMetadataHolder, IssueTrackingDelegator issueTracking, SiblingsIssueMerger issueStatusCopier, - MergeBranchComponentUuids mergeBranchComponentUuids) { + MergeAndTargetBranchComponentUuids mergeAndTargetBranchComponentUuids) { super(CrawlerDepthLimit.FILE, POST_ORDER); this.issueCache = issueCache; this.issueLifecycle = issueLifecycle; @@ -54,7 +54,7 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter { this.analysisMetadataHolder = analysisMetadataHolder; this.issueTracking = issueTracking; this.issueStatusCopier = issueStatusCopier; - this.mergeBranchComponentUuids = mergeBranchComponentUuids; + this.mergeAndTargetBranchComponentUuids = mergeAndTargetBranchComponentUuids; } @Override @@ -97,7 +97,7 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter { for (Map.Entry entry : matched.entrySet()) { DefaultIssue raw = entry.getKey(); DefaultIssue base = entry.getValue(); - issueLifecycle.copyExistingOpenIssueFromLongLivingBranch(raw, base, mergeBranchComponentUuids.getMergeBranchName()); + issueLifecycle.copyExistingOpenIssueFromLongLivingBranch(raw, base, mergeAndTargetBranchComponentUuids.getMergeBranchName()); process(component, raw, cacheAppender); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecution.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecution.java index 80daf00697a..26ff4b6f268 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecution.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecution.java @@ -26,10 +26,10 @@ import org.sonar.core.issue.tracking.Tracking; public class MergeBranchTrackerExecution { private final TrackerRawInputFactory rawInputFactory; - private final TrackerMergeBranchInputFactory mergeInputFactory; + private final TrackerMergeOrTargetBranchInputFactory mergeInputFactory; private final Tracker tracker; - public MergeBranchTrackerExecution(TrackerRawInputFactory rawInputFactory, TrackerMergeBranchInputFactory mergeInputFactory, + public MergeBranchTrackerExecution(TrackerRawInputFactory rawInputFactory, TrackerMergeOrTargetBranchInputFactory mergeInputFactory, Tracker tracker) { this.rawInputFactory = rawInputFactory; this.mergeInputFactory = mergeInputFactory; @@ -37,6 +37,6 @@ public class MergeBranchTrackerExecution { } public Tracking track(Component component) { - return tracker.trackNonClosed(rawInputFactory.create(component), mergeInputFactory.create(component)); + return tracker.trackNonClosed(rawInputFactory.create(component), mergeInputFactory.createForMergeBranch(component)); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecution.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecution.java index 3bc412a5c5c..f5ef7f30671 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecution.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecution.java @@ -36,13 +36,12 @@ import org.sonar.core.util.stream.MoreCollectors; public class ShortBranchOrPullRequestTrackerExecution { private final TrackerBaseInputFactory baseInputFactory; private final TrackerRawInputFactory rawInputFactory; - private final TrackerMergeBranchInputFactory mergeInputFactory; + private final TrackerMergeOrTargetBranchInputFactory mergeInputFactory; private final Tracker tracker; private final NewLinesRepository newLinesRepository; public ShortBranchOrPullRequestTrackerExecution(TrackerBaseInputFactory baseInputFactory, TrackerRawInputFactory rawInputFactory, - TrackerMergeBranchInputFactory mergeInputFactory, - Tracker tracker, NewLinesRepository newLinesRepository) { + TrackerMergeOrTargetBranchInputFactory mergeInputFactory, Tracker tracker, NewLinesRepository newLinesRepository) { this.baseInputFactory = baseInputFactory; this.rawInputFactory = rawInputFactory; this.mergeInputFactory = mergeInputFactory; @@ -52,21 +51,41 @@ public class ShortBranchOrPullRequestTrackerExecution { public Tracking track(Component component) { Input rawInput = rawInputFactory.create(component); - Input baseInput = baseInputFactory.create(component); + Input previousAnalysisInput = baseInputFactory.create(component); - Input unmatchedRawInput; + // Step 1: track issues with merge branch (= long living) + Input unmatchedRawsAfterMergeBranchTracking; if (mergeInputFactory.hasMergeBranchAnalysis()) { - Input mergeInput = mergeInputFactory.create(component); + Input mergeInput = mergeInputFactory.createForMergeBranch(component); Tracking mergeTracking = tracker.trackNonClosed(rawInput, mergeInput); List unmatchedRaws = mergeTracking.getUnmatchedRaws().collect(MoreCollectors.toList()); - unmatchedRawInput = new DefaultTrackingInput(unmatchedRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); + unmatchedRawsAfterMergeBranchTracking = new DefaultTrackingInput(unmatchedRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); } else { - List filteredRaws = keepIssuesHavingAtLeastOneLocationOnChangedLines(component, rawInput.getIssues()); - unmatchedRawInput = new DefaultTrackingInput(filteredRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); + unmatchedRawsAfterMergeBranchTracking = rawInput; } - // do second tracking with base branch using raws issues that are still unmatched - return tracker.trackNonClosed(unmatchedRawInput, baseInput); + // Step 2: track remaining unmatched issues with target branch + Input unmatchedRawsAfterTargetBranchTracking; + if (mergeInputFactory.hasTargetBranchAnalysis() && mergeInputFactory.areTargetAndMergeBranchesDifferent()) { + Input targetInput = mergeInputFactory.createForTargetBranch(component); + Tracking mergeTracking = tracker.trackNonClosed(unmatchedRawsAfterMergeBranchTracking, targetInput); + List unmatchedRaws = mergeTracking.getUnmatchedRaws().collect(MoreCollectors.toList()); + unmatchedRawsAfterTargetBranchTracking = new DefaultTrackingInput(unmatchedRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); + } else { + unmatchedRawsAfterTargetBranchTracking = unmatchedRawsAfterMergeBranchTracking; + } + + // Step 3: if there is no analysis or merge or target branch, keep only issues on changed lines + Input unmatchedRawsAfterChangedLineFiltering; + if (!mergeInputFactory.hasTargetBranchAnalysis() || !mergeInputFactory.hasMergeBranchAnalysis()) { + List filteredRaws = keepIssuesHavingAtLeastOneLocationOnChangedLines(component, unmatchedRawsAfterTargetBranchTracking.getIssues()); + unmatchedRawsAfterChangedLineFiltering = new DefaultTrackingInput(filteredRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); + } else { + unmatchedRawsAfterChangedLineFiltering = unmatchedRawsAfterTargetBranchTracking; + } + + // Step 4: track issues of previous analysis of the current branch/PR + return tracker.trackNonClosed(unmatchedRawsAfterChangedLineFiltering, previousAnalysisInput); } private List keepIssuesHavingAtLeastOneLocationOnChangedLines(Component component, Collection issues) { diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TrackerMergeOrTargetBranchInputFactory.java similarity index 50% rename from server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java rename to server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TrackerMergeOrTargetBranchInputFactory.java index 8690f1bd8dd..94322468791 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TrackerMergeOrTargetBranchInputFactory.java @@ -23,7 +23,7 @@ import java.util.Collections; import java.util.List; import javax.annotation.Nullable; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; +import org.sonar.ce.task.projectanalysis.component.MergeAndTargetBranchComponentUuids; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.tracking.Input; import org.sonar.core.issue.tracking.LazyInput; @@ -31,46 +31,60 @@ import org.sonar.core.issue.tracking.LineHashSequence; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -public class TrackerMergeBranchInputFactory { +public class TrackerMergeOrTargetBranchInputFactory { private static final LineHashSequence EMPTY_LINE_HASH_SEQUENCE = new LineHashSequence(Collections.emptyList()); - private final ComponentIssuesLoader mergeIssuesLoader; + private final ComponentIssuesLoader componentIssuesLoader; private final DbClient dbClient; - private final MergeBranchComponentUuids mergeBranchComponentUuids; + private final MergeAndTargetBranchComponentUuids mergeAndTargetBranchComponentUuids; - public TrackerMergeBranchInputFactory(ComponentIssuesLoader mergeIssuesLoader, MergeBranchComponentUuids mergeBranchComponentUuids, DbClient dbClient) { - this.mergeIssuesLoader = mergeIssuesLoader; - this.mergeBranchComponentUuids = mergeBranchComponentUuids; + public TrackerMergeOrTargetBranchInputFactory(ComponentIssuesLoader componentIssuesLoader, MergeAndTargetBranchComponentUuids mergeAndTargetBranchComponentUuids, + DbClient dbClient) { + this.componentIssuesLoader = componentIssuesLoader; + this.mergeAndTargetBranchComponentUuids = mergeAndTargetBranchComponentUuids; this.dbClient = dbClient; // TODO detect file moves? } public boolean hasMergeBranchAnalysis() { - return mergeBranchComponentUuids.hasMergeBranchAnalysis(); + return mergeAndTargetBranchComponentUuids.hasMergeBranchAnalysis(); } - public Input create(Component component) { - String mergeBranchComponentUuid = mergeBranchComponentUuids.getUuid(component.getDbKey()); - return new MergeLazyInput(component.getType(), mergeBranchComponentUuid); + public boolean hasTargetBranchAnalysis() { + return mergeAndTargetBranchComponentUuids.hasTargetBranchAnalysis(); } - private class MergeLazyInput extends LazyInput { + public boolean areTargetAndMergeBranchesDifferent() { + return mergeAndTargetBranchComponentUuids.areTargetAndMergeBranchesDifferent(); + } + + public Input createForMergeBranch(Component component) { + String mergeBranchComponentUuid = mergeAndTargetBranchComponentUuids.getMergeBranchComponentUuid(component.getDbKey()); + return new MergeOrTargetLazyInput(component.getType(), mergeBranchComponentUuid); + } + + public Input createForTargetBranch(Component component) { + String targetBranchComponentUuid = mergeAndTargetBranchComponentUuids.getTargetBranchComponentUuid(component.getDbKey()); + return new MergeOrTargetLazyInput(component.getType(), targetBranchComponentUuid); + } + + private class MergeOrTargetLazyInput extends LazyInput { private final Component.Type type; - private final String mergeBranchComponentUuid; + private final String mergeOrTargetBranchComponentUuid; - private MergeLazyInput(Component.Type type, @Nullable String mergeBranchComponentUuid) { + private MergeOrTargetLazyInput(Component.Type type, @Nullable String mergeOrTargetBranchComponentUuid) { this.type = type; - this.mergeBranchComponentUuid = mergeBranchComponentUuid; + this.mergeOrTargetBranchComponentUuid = mergeOrTargetBranchComponentUuid; } @Override protected LineHashSequence loadLineHashSequence() { - if (mergeBranchComponentUuid == null || type != Component.Type.FILE) { + if (mergeOrTargetBranchComponentUuid == null || type != Component.Type.FILE) { return EMPTY_LINE_HASH_SEQUENCE; } try (DbSession session = dbClient.openSession(false)) { - List hashes = dbClient.fileSourceDao().selectLineHashes(session, mergeBranchComponentUuid); + List hashes = dbClient.fileSourceDao().selectLineHashes(session, mergeOrTargetBranchComponentUuid); if (hashes == null || hashes.isEmpty()) { return EMPTY_LINE_HASH_SEQUENCE; } @@ -80,10 +94,10 @@ public class TrackerMergeBranchInputFactory { @Override protected List loadIssues() { - if (mergeBranchComponentUuid == null) { + if (mergeOrTargetBranchComponentUuid == null) { return Collections.emptyList(); } - return mergeIssuesLoader.loadOpenIssuesWithChanges(mergeBranchComponentUuid); + return componentIssuesLoader.loadOpenIssuesWithChanges(mergeOrTargetBranchComponentUuid); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoader.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoader.java index e553e40f8a6..ba8a81f75bd 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoader.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoader.java @@ -25,7 +25,7 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; +import org.sonar.ce.task.projectanalysis.component.MergeAndTargetBranchComponentUuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.source.FileSourceDto; @@ -35,9 +35,9 @@ public class ScmInfoDbLoader { private final AnalysisMetadataHolder analysisMetadataHolder; private final DbClient dbClient; - private final MergeBranchComponentUuids mergeBranchComponentUuid; + private final MergeAndTargetBranchComponentUuids mergeBranchComponentUuid; - public ScmInfoDbLoader(AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient, MergeBranchComponentUuids mergeBranchComponentUuid) { + public ScmInfoDbLoader(AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient, MergeAndTargetBranchComponentUuids mergeBranchComponentUuid) { this.analysisMetadataHolder = analysisMetadataHolder; this.dbClient = dbClient; this.mergeBranchComponentUuid = mergeBranchComponentUuid; @@ -67,7 +67,7 @@ public class ScmInfoDbLoader { // at this point, it's the first analysis but had copyFromPrevious flag true Branch branch = analysisMetadataHolder.getBranch(); if (!branch.isMain()) { - return Optional.ofNullable(mergeBranchComponentUuid.getUuid(file.getDbKey())); + return Optional.ofNullable(mergeBranchComponentUuid.getMergeBranchComponentUuid(file.getDbKey())); } return Optional.empty(); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java index adc120665a2..954d14b1b3e 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java @@ -307,7 +307,8 @@ public class PostProjectAnalysisTasksExecutorTest { throw new UnsupportedOperationException(); } - @Override public String getTargetBranchName() { + @Override + public String getTargetBranchName() { throw new UnsupportedOperationException(); } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuidsTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuidsTest.java new file mode 100644 index 00000000000..02a4f40dabf --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeAndTargetBranchComponentUuidsTest.java @@ -0,0 +1,146 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule; +import org.sonar.ce.task.projectanalysis.analysis.Branch; +import org.sonar.db.DbTester; +import org.sonar.db.component.BranchType; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentTesting; +import org.sonar.server.project.Project; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.db.component.SnapshotTesting.newAnalysis; + +public class MergeAndTargetBranchComponentUuidsTest { + @Rule + public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); + + @Rule + public DbTester db = DbTester.create(); + + private MergeAndTargetBranchComponentUuids underTest; + private Branch branch = mock(Branch.class); + + private ComponentDto longBranch1; + private ComponentDto longBranch1File; + private ComponentDto shortBranch1File; + private ComponentDto shortBranch2File; + private Project project; + private ComponentDto shortBranch1; + private ComponentDto shortBranch2; + private ComponentDto longBranch2; + private ComponentDto longBranch2File; + + @Before + public void setUp() { + underTest = new MergeAndTargetBranchComponentUuids(analysisMetadataHolder, db.getDbClient()); + project = mock(Project.class); + analysisMetadataHolder.setProject(project); + analysisMetadataHolder.setBranch(branch); + + ComponentDto projectDto = db.components().insertMainBranch(); + when(project.getUuid()).thenReturn(projectDto.uuid()); + longBranch1 = db.components().insertProjectBranch(projectDto, b -> b.setKey("longBranch1")); + longBranch2 = db.components().insertProjectBranch(projectDto, b -> b.setKey("longBranch2")); + shortBranch1 = db.components().insertProjectBranch(projectDto, b -> b.setKey("shortBranch1").setBranchType(BranchType.SHORT).setMergeBranchUuid(longBranch1.uuid())); + shortBranch2 = db.components().insertProjectBranch(projectDto, b -> b.setKey("shortBranch2").setBranchType(BranchType.SHORT).setMergeBranchUuid(longBranch1.uuid())); + longBranch1File = ComponentTesting.newFileDto(longBranch1, null, "file").setUuid("long1File"); + longBranch2File = ComponentTesting.newFileDto(longBranch2, null, "file").setUuid("long2File"); + shortBranch1File = ComponentTesting.newFileDto(shortBranch1, null, "file").setUuid("file1"); + shortBranch2File = ComponentTesting.newFileDto(shortBranch2, null, "file").setUuid("file2"); + db.components().insertComponents(longBranch1File, shortBranch1File, shortBranch2File, longBranch2File); + } + + @Test + public void should_support_db_key_when_looking_for_merge_component() { + when(branch.getMergeBranchUuid()).thenReturn(longBranch1.uuid()); + when(branch.getType()).thenReturn(BranchType.SHORT); + when(branch.getTargetBranchName()).thenReturn("notAnalyzedBranch"); + db.components().insertSnapshot(newAnalysis(longBranch1)); + assertThat(underTest.getMergeBranchComponentUuid(shortBranch1File.getDbKey())).isEqualTo(longBranch1File.uuid()); + assertThat(underTest.getTargetBranchComponentUuid(shortBranch1File.getDbKey())).isNull(); + assertThat(underTest.hasMergeBranchAnalysis()).isTrue(); + assertThat(underTest.hasTargetBranchAnalysis()).isFalse(); + assertThat(underTest.areTargetAndMergeBranchesDifferent()).isTrue(); + assertThat(underTest.getMergeBranchName()).isEqualTo("longBranch1"); + } + + @Test + public void should_support_db_key_when_looking_for_target_component() { + when(branch.getMergeBranchUuid()).thenReturn(longBranch1.uuid()); + when(branch.getTargetBranchName()).thenReturn("shortBranch2"); + when(branch.getType()).thenReturn(BranchType.SHORT); + db.components().insertSnapshot(newAnalysis(longBranch1)); + db.components().insertSnapshot(newAnalysis(shortBranch2)); + assertThat(underTest.getMergeBranchComponentUuid(shortBranch1File.getDbKey())).isEqualTo(longBranch1File.uuid()); + assertThat(underTest.getTargetBranchComponentUuid(shortBranch1File.getDbKey())).isEqualTo(shortBranch2File.uuid()); + assertThat(underTest.hasMergeBranchAnalysis()).isTrue(); + assertThat(underTest.hasTargetBranchAnalysis()).isTrue(); + assertThat(underTest.areTargetAndMergeBranchesDifferent()).isTrue(); + } + + @Test + public void should_support_key_when_looking_for_merge_component() { + when(branch.getMergeBranchUuid()).thenReturn(longBranch1.uuid()); + when(branch.getType()).thenReturn(BranchType.SHORT); + when(branch.getTargetBranchName()).thenReturn("notAnalyzedBranch"); + db.components().insertSnapshot(newAnalysis(longBranch1)); + assertThat(underTest.getMergeBranchComponentUuid(shortBranch1File.getKey())).isEqualTo(longBranch1File.uuid()); + } + + @Test + public void return_null_if_file_doesnt_exist() { + when(branch.getMergeBranchUuid()).thenReturn(longBranch1.uuid()); + when(branch.getType()).thenReturn(BranchType.SHORT); + when(branch.getTargetBranchName()).thenReturn("notAnalyzedBranch"); + db.components().insertSnapshot(newAnalysis(longBranch1)); + assertThat(underTest.getMergeBranchComponentUuid("doesnt exist")).isNull(); + } + + @Test + public void skip_init_if_no_merge_branch_analysis() { + when(branch.getMergeBranchUuid()).thenReturn(longBranch1.uuid()); + when(branch.getType()).thenReturn(BranchType.SHORT); + when(branch.getTargetBranchName()).thenReturn("notAnalyzedBranch"); + assertThat(underTest.getMergeBranchComponentUuid(shortBranch1File.getDbKey())).isNull(); + } + + @Test + public void should_skip_target_components_init_on_long_branches() { + when(branch.getMergeBranchUuid()).thenReturn(longBranch1.uuid()); + when(branch.getType()).thenReturn(BranchType.LONG); + when(branch.getTargetBranchName()).thenThrow(new IllegalStateException("Unsupported on long branches")); + db.components().insertSnapshot(newAnalysis(longBranch1)); + + assertThat(underTest.getMergeBranchComponentUuid(longBranch2File.getDbKey())).isEqualTo(longBranch1File.uuid()); + assertThat(underTest.getTargetBranchComponentUuid(longBranch2File.getDbKey())).isNull(); + assertThat(underTest.hasMergeBranchAnalysis()).isTrue(); + assertThat(underTest.hasTargetBranchAnalysis()).isFalse(); + assertThat(underTest.areTargetAndMergeBranchesDifferent()).isTrue(); + assertThat(underTest.getMergeBranchName()).isEqualTo("longBranch1"); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuidsTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuidsTest.java deleted file mode 100644 index a0409c6a56e..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuidsTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule; -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; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class MergeBranchComponentUuidsTest { - @Rule - public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); - - @Rule - public DbTester db = DbTester.create(); - - private MergeBranchComponentUuids underTest; - private Branch branch = mock(Branch.class); - - private ComponentDto mergeBranch; - private ComponentDto mergeBranchFile; - private ComponentDto branchFile; - - @Before - public void setUp() { - underTest = new MergeBranchComponentUuids(analysisMetadataHolder, db.getDbClient()); - analysisMetadataHolder.setBranch(branch); - - ComponentDto project = db.components().insertMainBranch(); - mergeBranch = db.components().insertProjectBranch(project, b -> b.setKey("mergeBranch")); - ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("branch1")); - mergeBranchFile = ComponentTesting.newFileDto(mergeBranch, null, "file").setUuid("mergeFile"); - branchFile = ComponentTesting.newFileDto(branch, null, "file").setUuid("file1"); - db.components().insertComponents(mergeBranchFile, branchFile); - } - - @Test - public void should_support_db_key() { - when(branch.getMergeBranchUuid()).thenReturn(mergeBranch.uuid()); - assertThat(underTest.getUuid(branchFile.getDbKey())).isEqualTo(mergeBranchFile.uuid()); - } - - @Test - public void should_support_key() { - when(branch.getMergeBranchUuid()).thenReturn(mergeBranch.uuid()); - assertThat(underTest.getUuid(branchFile.getKey())).isEqualTo(mergeBranchFile.uuid()); - } - - @Test - public void return_null_if_file_doesnt_exist() { - when(branch.getMergeBranchUuid()).thenReturn(mergeBranch.uuid()); - assertThat(underTest.getUuid("doesnt exist")).isNull(); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java index 55e56244c62..90853ca12bc 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java @@ -36,7 +36,7 @@ import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; +import org.sonar.ce.task.projectanalysis.component.MergeAndTargetBranchComponentUuids; import org.sonar.ce.task.projectanalysis.component.ReportComponent; import org.sonar.ce.task.projectanalysis.component.ReportModulesPath; import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; @@ -116,9 +116,9 @@ public class IntegrateIssuesVisitorTest { private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class); private IssueLifecycle issueLifecycle = mock(IssueLifecycle.class); private IssueVisitor issueVisitor = mock(IssueVisitor.class); - private MergeBranchComponentUuids mergeBranchComponentsUuids = mock(MergeBranchComponentUuids.class); + private MergeAndTargetBranchComponentUuids mergeBranchComponentsUuids = mock(MergeAndTargetBranchComponentUuids.class); private SiblingsIssueMerger issueStatusCopier = mock(SiblingsIssueMerger.class); - private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class); + private MergeAndTargetBranchComponentUuids mergeAndTargetBranchComponentUuids = mock(MergeAndTargetBranchComponentUuids.class); private SourceLinesHashRepository sourceLinesHash = mock(SourceLinesHashRepository.class); private NewLinesRepository newLinesRepository = mock(NewLinesRepository.class); @@ -145,7 +145,7 @@ public class IntegrateIssuesVisitorTest { TrackerRawInputFactory rawInputFactory = new TrackerRawInputFactory(treeRootHolder, reportReader, sourceLinesHash, new CommonRuleEngineImpl(), issueFilter, ruleRepositoryRule, activeRulesHolder); TrackerBaseInputFactory baseInputFactory = new TrackerBaseInputFactory(issuesLoader, dbClient, movedFilesRepository, mock(ReportModulesPath.class), analysisMetadataHolder, new IssueFieldsSetter(), mock(ComponentsWithUnprocessedIssues.class)); - TrackerMergeBranchInputFactory mergeInputFactory = new TrackerMergeBranchInputFactory(issuesLoader, mergeBranchComponentsUuids, dbClient); + TrackerMergeOrTargetBranchInputFactory mergeInputFactory = new TrackerMergeOrTargetBranchInputFactory(issuesLoader, mergeBranchComponentsUuids, dbClient); ClosedIssuesInputFactory closedIssuesInputFactory = new ClosedIssuesInputFactory(issuesLoader, dbClient, movedFilesRepository); tracker = new TrackerExecution(baseInputFactory, rawInputFactory, closedIssuesInputFactory, new Tracker<>(), issuesLoader, analysisMetadataHolder); shortBranchTracker = new ShortBranchOrPullRequestTrackerExecution(baseInputFactory, rawInputFactory, mergeInputFactory, new Tracker<>(), newLinesRepository); @@ -155,7 +155,7 @@ public class IntegrateIssuesVisitorTest { treeRootHolder.setRoot(PROJECT); issueCache = new IssueCache(temp.newFile(), System2.INSTANCE); when(issueFilter.accept(any(DefaultIssue.class), eq(FILE))).thenReturn(true); - underTest = new IntegrateIssuesVisitor(issueCache, issueLifecycle, issueVisitors, analysisMetadataHolder, trackingDelegator, issueStatusCopier, mergeBranchComponentUuids); + underTest = new IntegrateIssuesVisitor(issueCache, issueLifecycle, issueVisitors, analysisMetadataHolder, trackingDelegator, issueStatusCopier, mergeAndTargetBranchComponentUuids); } @Test @@ -262,8 +262,8 @@ public class IntegrateIssuesVisitorTest { @Test public void copy_issues_when_creating_new_long_living_branch() { - when(mergeBranchComponentsUuids.getUuid(FILE_KEY)).thenReturn(FILE_UUID_ON_BRANCH); - when(mergeBranchComponentUuids.getMergeBranchName()).thenReturn("master"); + when(mergeBranchComponentsUuids.getMergeBranchComponentUuid(FILE_KEY)).thenReturn(FILE_UUID_ON_BRANCH); + when(mergeAndTargetBranchComponentUuids.getMergeBranchName()).thenReturn("master"); when(analysisMetadataHolder.isLongLivingBranch()).thenReturn(true); when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecutionTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecutionTest.java index ab510b11471..6613d954249 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecutionTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/MergeBranchTrackerExecutionTest.java @@ -37,7 +37,7 @@ public class MergeBranchTrackerExecutionTest { @Mock private TrackerRawInputFactory rawInputFactory; @Mock - private TrackerMergeBranchInputFactory mergeInputFactory; + private TrackerMergeOrTargetBranchInputFactory mergeInputFactory; @Mock private Tracker tracker; @Mock @@ -57,7 +57,7 @@ public class MergeBranchTrackerExecutionTest { Input mergeInput = mock(Input.class); NonClosedTracking result = mock(NonClosedTracking.class); when(rawInputFactory.create(component)).thenReturn(rawInput); - when(mergeInputFactory.create(component)).thenReturn(mergeInput); + when(mergeInputFactory.createForMergeBranch(component)).thenReturn(mergeInput); when(tracker.trackNonClosed(rawInput, mergeInput)).thenReturn(result); assertThat(underTest.track(component)).isEqualTo(result); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecutionTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecutionTest.java index 94fc7b5334b..3e651ba26eb 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecutionTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/ShortBranchOrPullRequestTrackerExecutionTest.java @@ -62,7 +62,7 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { @Mock private TrackerBaseInputFactory baseFactory; @Mock - private TrackerMergeBranchInputFactory mergeFactory; + private TrackerMergeOrTargetBranchInputFactory mergeFactory; @Mock private NewLinesRepository newLinesRepository; @@ -71,6 +71,7 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { private List rawIssues = new ArrayList<>(); private List baseIssues = new ArrayList<>(); private List mergeBranchIssues = new ArrayList<>(); + private List targetBranchIssues = new ArrayList<>(); @Before public void setUp() throws Exception { @@ -78,7 +79,8 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { when(rawFactory.create(FILE)).thenReturn(createInput(rawIssues)); when(baseFactory.create(FILE)).thenReturn(createInput(baseIssues)); - when(mergeFactory.create(FILE)).thenReturn(createInput(mergeBranchIssues)); + when(mergeFactory.createForMergeBranch(FILE)).thenReturn(createInput(mergeBranchIssues)); + when(mergeFactory.createForTargetBranch(FILE)).thenReturn(createInput(targetBranchIssues)); Tracker tracker = new Tracker<>(); underTest = new ShortBranchOrPullRequestTrackerExecution(baseFactory, rawFactory, mergeFactory, tracker, newLinesRepository); @@ -95,6 +97,7 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { rawIssues.add(issue2); when(mergeFactory.hasMergeBranchAnalysis()).thenReturn(false); + when(mergeFactory.hasTargetBranchAnalysis()).thenReturn(true); when(newLinesRepository.getNewLines(FILE)).thenReturn(Optional.of(new HashSet<>(Arrays.asList(1, 3)))); Tracking tracking = underTest.track(FILE); @@ -132,6 +135,7 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { rawIssues.add(issueWithALocationOnADifferentFile); when(mergeFactory.hasMergeBranchAnalysis()).thenReturn(false); + when(mergeFactory.hasTargetBranchAnalysis()).thenReturn(false); when(newLinesRepository.getNewLines(FILE)).thenReturn(Optional.of(new HashSet<>(Arrays.asList(7, 10)))); Tracking tracking = underTest.track(FILE); @@ -142,12 +146,14 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { } @Test - public void tracking_with_all_results() { + public void track_and_ignore_issues_from_merge_branch() { rawIssues.add(createIssue(1, RuleTesting.XOO_X1)); rawIssues.add(createIssue(2, RuleTesting.XOO_X2)); rawIssues.add(createIssue(3, RuleTesting.XOO_X3)); when(mergeFactory.hasMergeBranchAnalysis()).thenReturn(true); + when(mergeFactory.hasTargetBranchAnalysis()).thenReturn(true); + when(mergeFactory.areTargetAndMergeBranchesDifferent()).thenReturn(true); mergeBranchIssues.add(rawIssues.get(0)); baseIssues.add(rawIssues.get(0)); @@ -158,6 +164,42 @@ public class ShortBranchOrPullRequestTrackerExecutionTest { assertThat(tracking.getUnmatchedRaws()).containsOnly(rawIssues.get(2)); } + @Test + public void track_and_ignore_issues_from_target_branch() { + rawIssues.add(createIssue(1, RuleTesting.XOO_X1)); + rawIssues.add(createIssue(2, RuleTesting.XOO_X2)); + rawIssues.add(createIssue(3, RuleTesting.XOO_X3)); + + when(mergeFactory.hasMergeBranchAnalysis()).thenReturn(true); + when(mergeFactory.hasTargetBranchAnalysis()).thenReturn(true); + when(mergeFactory.areTargetAndMergeBranchesDifferent()).thenReturn(true); + targetBranchIssues.add(rawIssues.get(0)); + + baseIssues.add(rawIssues.get(0)); + baseIssues.add(rawIssues.get(1)); + + Tracking tracking = underTest.track(FILE); + assertThat(tracking.getMatchedRaws()).isEqualTo(Collections.singletonMap(rawIssues.get(1), rawIssues.get(1))); + assertThat(tracking.getUnmatchedRaws()).containsOnly(rawIssues.get(2)); + } + + @Test + public void track_and_ignore_issues_from_merge_and_target_branch() { + rawIssues.add(createIssue(1, RuleTesting.XOO_X1)); + rawIssues.add(createIssue(2, RuleTesting.XOO_X2)); + rawIssues.add(createIssue(3, RuleTesting.XOO_X3)); + + when(mergeFactory.hasMergeBranchAnalysis()).thenReturn(true); + when(mergeFactory.hasTargetBranchAnalysis()).thenReturn(true); + when(mergeFactory.areTargetAndMergeBranchesDifferent()).thenReturn(true); + mergeBranchIssues.add(rawIssues.get(0)); + targetBranchIssues.add(rawIssues.get(1)); + + Tracking tracking = underTest.track(FILE); + assertThat(tracking.getMatchedRaws()).isEmpty(); + assertThat(tracking.getUnmatchedRaws()).containsOnly(rawIssues.get(2)); + } + private DefaultIssue createIssue(int line, RuleKey ruleKey) { DefaultIssue issue = new DefaultIssue() .setRuleKey(ruleKey) diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoaderTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoaderTest.java index 159f82d34bf..e560a364301 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoaderTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoaderTest.java @@ -33,7 +33,7 @@ import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule; import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; +import org.sonar.ce.task.projectanalysis.component.MergeAndTargetBranchComponentUuids; import org.sonar.core.hash.SourceHashComputer; import org.sonar.db.DbTester; import org.sonar.db.protobuf.DbFileSources; @@ -67,9 +67,9 @@ public class ScmInfoDbLoaderTest { public BatchReportReaderRule reportReader = new BatchReportReaderRule(); private Branch branch = mock(Branch.class); - private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class); + private MergeAndTargetBranchComponentUuids mergeAndTargetBranchComponentUuids = mock(MergeAndTargetBranchComponentUuids.class); - private ScmInfoDbLoader underTest = new ScmInfoDbLoader(analysisMetadataHolder, dbTester.getDbClient(), mergeBranchComponentUuids); + private ScmInfoDbLoader underTest = new ScmInfoDbLoader(analysisMetadataHolder, dbTester.getDbClient(), mergeAndTargetBranchComponentUuids); @Test public void returns_ScmInfo_from_DB() { @@ -95,7 +95,7 @@ public class ScmInfoDbLoaderTest { String hash = computeSourceHash(1); when(branch.getMergeBranchUuid()).thenReturn("mergeBranchUuid"); - when(mergeBranchComponentUuids.getUuid(FILE.getDbKey())).thenReturn(mergeFileUuid); + when(mergeAndTargetBranchComponentUuids.getMergeBranchComponentUuid(FILE.getDbKey())).thenReturn(mergeFileUuid); addFileSourceInDb("henry", DATE_1, "rev-1", hash, mergeFileUuid); DbScmInfo scmInfo = underTest.getScmInfo(FILE).get(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java index 548a477c7d0..d31dfe56c1b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java @@ -304,7 +304,8 @@ public class ProjectScanContainer extends ComponentContainer { BranchConfiguration branchConfig = getComponentByType(BranchConfiguration.class); if (branchConfig.branchType() == BranchType.PULL_REQUEST) { - LOG.info("Pull request {} for merge into {} from {}", branchConfig.pullRequestKey(), pullRequestBaseToDisplayName(branchConfig.targetBranchName()), branchConfig.branchName()); + LOG.info("Pull request {} for merge into {} from {}", branchConfig.pullRequestKey(), pullRequestBaseToDisplayName(branchConfig.targetBranchName()), + branchConfig.branchName()); } else if (branchConfig.branchName() != null) { LOG.info("Branch name: {}, type: {}", branchConfig.branchName(), branchTypeToDisplayName(branchConfig.branchType())); } -- 2.39.5