@@ -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<String, String> mergeBranchComponentsUuidsByKey; | |||
private Map<String, String> 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<BranchDto> 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<BranchDto> 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<ComponentDto> 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<ComponentDto> 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); | |||
} | |||
} |
@@ -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<String, String> 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<ComponentDto> components = dbClient.componentDao().selectByProjectUuid(mergeBranchUuid, dbSession); | |||
for (ComponentDto dto : components) { | |||
uuidsByKey.put(dto.getKey(), dto.uuid()); | |||
} | |||
Optional<BranchDto> 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); | |||
} | |||
} |
@@ -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, |
@@ -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<DefaultIssue, DefaultIssue> 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); | |||
} | |||
} |
@@ -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<DefaultIssue, DefaultIssue> tracker; | |||
public MergeBranchTrackerExecution(TrackerRawInputFactory rawInputFactory, TrackerMergeBranchInputFactory mergeInputFactory, | |||
public MergeBranchTrackerExecution(TrackerRawInputFactory rawInputFactory, TrackerMergeOrTargetBranchInputFactory mergeInputFactory, | |||
Tracker<DefaultIssue, DefaultIssue> tracker) { | |||
this.rawInputFactory = rawInputFactory; | |||
this.mergeInputFactory = mergeInputFactory; | |||
@@ -37,6 +37,6 @@ public class MergeBranchTrackerExecution { | |||
} | |||
public Tracking<DefaultIssue, DefaultIssue> track(Component component) { | |||
return tracker.trackNonClosed(rawInputFactory.create(component), mergeInputFactory.create(component)); | |||
return tracker.trackNonClosed(rawInputFactory.create(component), mergeInputFactory.createForMergeBranch(component)); | |||
} | |||
} |
@@ -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<DefaultIssue, DefaultIssue> tracker; | |||
private final NewLinesRepository newLinesRepository; | |||
public ShortBranchOrPullRequestTrackerExecution(TrackerBaseInputFactory baseInputFactory, TrackerRawInputFactory rawInputFactory, | |||
TrackerMergeBranchInputFactory mergeInputFactory, | |||
Tracker<DefaultIssue, DefaultIssue> tracker, NewLinesRepository newLinesRepository) { | |||
TrackerMergeOrTargetBranchInputFactory mergeInputFactory, Tracker<DefaultIssue, DefaultIssue> tracker, NewLinesRepository newLinesRepository) { | |||
this.baseInputFactory = baseInputFactory; | |||
this.rawInputFactory = rawInputFactory; | |||
this.mergeInputFactory = mergeInputFactory; | |||
@@ -52,21 +51,41 @@ public class ShortBranchOrPullRequestTrackerExecution { | |||
public Tracking<DefaultIssue, DefaultIssue> track(Component component) { | |||
Input<DefaultIssue> rawInput = rawInputFactory.create(component); | |||
Input<DefaultIssue> baseInput = baseInputFactory.create(component); | |||
Input<DefaultIssue> previousAnalysisInput = baseInputFactory.create(component); | |||
Input<DefaultIssue> unmatchedRawInput; | |||
// Step 1: track issues with merge branch (= long living) | |||
Input<DefaultIssue> unmatchedRawsAfterMergeBranchTracking; | |||
if (mergeInputFactory.hasMergeBranchAnalysis()) { | |||
Input<DefaultIssue> mergeInput = mergeInputFactory.create(component); | |||
Input<DefaultIssue> mergeInput = mergeInputFactory.createForMergeBranch(component); | |||
Tracking<DefaultIssue, DefaultIssue> mergeTracking = tracker.trackNonClosed(rawInput, mergeInput); | |||
List<DefaultIssue> unmatchedRaws = mergeTracking.getUnmatchedRaws().collect(MoreCollectors.toList()); | |||
unmatchedRawInput = new DefaultTrackingInput(unmatchedRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); | |||
unmatchedRawsAfterMergeBranchTracking = new DefaultTrackingInput(unmatchedRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence()); | |||
} else { | |||
List<DefaultIssue> 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<DefaultIssue> unmatchedRawsAfterTargetBranchTracking; | |||
if (mergeInputFactory.hasTargetBranchAnalysis() && mergeInputFactory.areTargetAndMergeBranchesDifferent()) { | |||
Input<DefaultIssue> targetInput = mergeInputFactory.createForTargetBranch(component); | |||
Tracking<DefaultIssue, DefaultIssue> mergeTracking = tracker.trackNonClosed(unmatchedRawsAfterMergeBranchTracking, targetInput); | |||
List<DefaultIssue> 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<DefaultIssue> unmatchedRawsAfterChangedLineFiltering; | |||
if (!mergeInputFactory.hasTargetBranchAnalysis() || !mergeInputFactory.hasMergeBranchAnalysis()) { | |||
List<DefaultIssue> 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<DefaultIssue> keepIssuesHavingAtLeastOneLocationOnChangedLines(Component component, Collection<DefaultIssue> issues) { |
@@ -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<DefaultIssue> 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<DefaultIssue> { | |||
public boolean areTargetAndMergeBranchesDifferent() { | |||
return mergeAndTargetBranchComponentUuids.areTargetAndMergeBranchesDifferent(); | |||
} | |||
public Input<DefaultIssue> createForMergeBranch(Component component) { | |||
String mergeBranchComponentUuid = mergeAndTargetBranchComponentUuids.getMergeBranchComponentUuid(component.getDbKey()); | |||
return new MergeOrTargetLazyInput(component.getType(), mergeBranchComponentUuid); | |||
} | |||
public Input<DefaultIssue> createForTargetBranch(Component component) { | |||
String targetBranchComponentUuid = mergeAndTargetBranchComponentUuids.getTargetBranchComponentUuid(component.getDbKey()); | |||
return new MergeOrTargetLazyInput(component.getType(), targetBranchComponentUuid); | |||
} | |||
private class MergeOrTargetLazyInput extends LazyInput<DefaultIssue> { | |||
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<String> hashes = dbClient.fileSourceDao().selectLineHashes(session, mergeBranchComponentUuid); | |||
List<String> 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<DefaultIssue> loadIssues() { | |||
if (mergeBranchComponentUuid == null) { | |||
if (mergeOrTargetBranchComponentUuid == null) { | |||
return Collections.emptyList(); | |||
} | |||
return mergeIssuesLoader.loadOpenIssuesWithChanges(mergeBranchComponentUuid); | |||
return componentIssuesLoader.loadOpenIssuesWithChanges(mergeOrTargetBranchComponentUuid); | |||
} | |||
} | |||
@@ -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(); |
@@ -307,7 +307,8 @@ public class PostProjectAnalysisTasksExecutorTest { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override public String getTargetBranchName() { | |||
@Override | |||
public String getTargetBranchName() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@@ -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"); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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); |
@@ -37,7 +37,7 @@ public class MergeBranchTrackerExecutionTest { | |||
@Mock | |||
private TrackerRawInputFactory rawInputFactory; | |||
@Mock | |||
private TrackerMergeBranchInputFactory mergeInputFactory; | |||
private TrackerMergeOrTargetBranchInputFactory mergeInputFactory; | |||
@Mock | |||
private Tracker<DefaultIssue, DefaultIssue> tracker; | |||
@Mock | |||
@@ -57,7 +57,7 @@ public class MergeBranchTrackerExecutionTest { | |||
Input<DefaultIssue> mergeInput = mock(Input.class); | |||
NonClosedTracking<DefaultIssue, DefaultIssue> 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); |
@@ -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<DefaultIssue> rawIssues = new ArrayList<>(); | |||
private List<DefaultIssue> baseIssues = new ArrayList<>(); | |||
private List<DefaultIssue> mergeBranchIssues = new ArrayList<>(); | |||
private List<DefaultIssue> 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<DefaultIssue, DefaultIssue> 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<DefaultIssue, DefaultIssue> 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<DefaultIssue, DefaultIssue> 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<DefaultIssue, DefaultIssue> 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<DefaultIssue, DefaultIssue> 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) |
@@ -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(); |
@@ -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())); | |||
} |