aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2019-04-01 11:28:19 +0200
committerSonarTech <sonartech@sonarsource.com>2019-04-23 20:21:07 +0200
commit81638702d68033ca95ddd406aa655fb2bfdab036 (patch)
tree517407d64df2d9cb95ed27a32aab3c82b8f58092
parentafe312e4cbf9ac88676d526ff6da0b641aef4ae8 (diff)
downloadsonarqube-81638702d68033ca95ddd406aa655fb2bfdab036.tar.gz
sonarqube-81638702d68033ca95ddd406aa655fb2bfdab036.zip
SONAR-11856 Store the "true" target branch in the scanner report to display it properly
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java17
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java8
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/DefaultBranchImpl.java10
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuids.java2
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java13
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoader.java2
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java2
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java13
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java11
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MergeBranchComponentUuidsTest.java7
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssuesTest.java41
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java14
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoaderTest.java3
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java8
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java9
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java4
-rw-r--r--server/sonar-db-dao/src/main/protobuf/db-project-branches.proto2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/branch/pr/ws/ListAction.java8
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/branch/pr/ws/list-example.json3
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java4
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ChangedLinesPublisher.java6
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java4
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java15
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesSupplier.java (renamed from sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesProvider.java)18
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfileLoader.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java12
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java6
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfiguration.java15
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/DefaultBranchConfiguration.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java29
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFiles.java14
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java24
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java17
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java8
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java4
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java9
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java22
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesSupplierTest.java (renamed from sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java)28
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java43
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java2
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java20
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java10
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java15
-rw-r--r--sonar-scanner-protocol/src/main/protobuf/scanner_report.proto3
-rw-r--r--sonar-ws/src/main/protobuf/ws-projectpullrequests.proto1
46 files changed, 287 insertions, 227 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java
index e9eb4c21914..22c0702dd15 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/Branch.java
@@ -19,7 +19,6 @@
*/
package org.sonar.ce.task.projectanalysis.analysis;
-import java.util.Optional;
import javax.annotation.concurrent.Immutable;
import org.sonar.ce.task.projectanalysis.component.ComponentKeyGenerator;
import org.sonar.db.component.BranchType;
@@ -43,10 +42,11 @@ public interface Branch extends ComponentKeyGenerator {
String getName();
/**
- * Indicates the branch from which it was forked.
- * It will be empty for main branches or legacy branches.
+ * Indicates the first LLB branch from which it was forked.
+ *
+ * @throws IllegalStateException for main branches or legacy branches.
*/
- Optional<String> getMergeBranchUuid();
+ String getMergeBranchUuid();
/**
* Whether the cross-project duplication tracker must be enabled
@@ -58,4 +58,13 @@ public interface Branch extends ComponentKeyGenerator {
* @throws IllegalStateException if this branch configuration is not a pull request.
*/
String getPullRequestKey();
+
+ /**
+ * The target/base branch name of a SLB or PR.
+ * Correspond to <pre>sonar.pullrequest.base</pre> or <pre>sonar.branch.target</pre>
+ * It's not guaranteed to exist.
+ *
+ * @throws IllegalStateException if this branch configuration is not a pull request or SLB.
+ */
+ String getTargetBranchName();
}
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java
index cde9d00d1c6..a8bfb52aab2 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java
@@ -20,6 +20,7 @@
package org.sonar.ce.task.projectanalysis.component;
import javax.annotation.Nullable;
+import org.sonar.api.resources.Qualifiers;
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.ce.task.projectanalysis.analysis.Branch;
import org.sonar.db.DbClient;
@@ -62,8 +63,10 @@ public class BranchPersisterImpl implements BranchPersister {
dto.setProjectUuid(firstNonNull(componentDto.getMainBranchProjectUuid(), componentDto.projectUuid()));
dto.setBranchType(branch.getType());
- // merge branch is only present if it's a short living branch
- dto.setMergeBranchUuid(branch.getMergeBranchUuid().orElse(null));
+ // merge branch is only present if it's not a main branch and not an application
+ if (!branch.isMain() && !Qualifiers.APP.equals(componentDto.qualifier())) {
+ dto.setMergeBranchUuid(branch.getMergeBranchUuid());
+ }
if (branch.getType() == BranchType.PULL_REQUEST) {
dto.setKey(analysisMetadataHolder.getPullRequestKey());
@@ -71,6 +74,7 @@ public class BranchPersisterImpl implements BranchPersister {
DbProjectBranches.PullRequestData pullRequestData = DbProjectBranches.PullRequestData.newBuilder()
.setBranch(branch.getName())
.setTitle(branch.getName())
+ .setTarget(branch.getTargetBranchName())
.build();
dto.setPullRequestData(pullRequestData);
} else {
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/DefaultBranchImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/DefaultBranchImpl.java
index ae137aa4743..1a15ad8e243 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/DefaultBranchImpl.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/DefaultBranchImpl.java
@@ -19,7 +19,6 @@
*/
package org.sonar.ce.task.projectanalysis.component;
-import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.utils.MessageException;
import org.sonar.ce.task.projectanalysis.analysis.Branch;
@@ -64,8 +63,8 @@ public class DefaultBranchImpl implements Branch {
}
@Override
- public Optional<String> getMergeBranchUuid() {
- return Optional.empty();
+ public String getMergeBranchUuid() {
+ throw new IllegalStateException("Not valid for the main branch");
}
@Override
@@ -90,6 +89,11 @@ public class DefaultBranchImpl implements Branch {
}
@Override
+ public String getTargetBranchName() {
+ throw new IllegalStateException("Only on a short lived branch or pull request");
+ }
+
+ @Override
public String generateKey(String projectKey, @Nullable String fileOrDirPath) {
if (isLegacyBranch) {
projectKey = ComponentKeys.createKey(projectKey, branchName);
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
index 84d5d066f0f..888e0c181b1 100644
--- 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
@@ -50,7 +50,7 @@ public class MergeBranchComponentUuids {
private void lazyInit() {
if (uuidsByKey == null) {
- String mergeBranchUuid = analysisMetadataHolder.getBranch().getMergeBranchUuid().get();
+ String mergeBranchUuid = analysisMetadataHolder.getBranch().getMergeBranchUuid();
uuidsByKey = new HashMap<>();
try (DbSession dbSession = dbClient.openSession(false)) {
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java
index cce1c2d09dc..6d7defeccb6 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssues.java
@@ -34,7 +34,6 @@ import static org.sonar.db.component.ComponentDto.removeBranchAndPullRequestFrom
/**
* Cache a map of component key -> set&lt;uuid&gt; in sibling branches/PR that have open issues
- *
*/
public class SiblingComponentsWithOpenIssues {
private final DbClient dbClient;
@@ -50,11 +49,19 @@ public class SiblingComponentsWithOpenIssues {
}
private void loadUuidsByKey() {
- uuidsByKey = new HashMap<>();
String currentBranchUuid = treeRootHolder.getRoot().getUuid();
+ String longLivingReferenceBranchUuid;
+
+ if (metadataHolder.isSLBorPR()) {
+ longLivingReferenceBranchUuid = metadataHolder.getBranch().getMergeBranchUuid();
+ } else {
+ longLivingReferenceBranchUuid = currentBranchUuid;
+ }
+
+ uuidsByKey = new HashMap<>();
try (DbSession dbSession = dbClient.openSession(false)) {
List<KeyWithUuidDto> components = dbClient.componentDao().selectAllSiblingComponentKeysHavingOpenIssues(dbSession,
- metadataHolder.getBranch().getMergeBranchUuid().orElse(currentBranchUuid), currentBranchUuid);
+ longLivingReferenceBranchUuid, currentBranchUuid);
for (KeyWithUuidDto dto : components) {
uuidsByKey.computeIfAbsent(removeBranchAndPullRequestFromKey(dto.key()), s -> new HashSet<>()).add(dto.uuid());
}
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 6f9b8b5442b..e553e40f8a6 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
@@ -66,7 +66,7 @@ public class ScmInfoDbLoader {
// at this point, it's the first analysis but had copyFromPrevious flag true
Branch branch = analysisMetadataHolder.getBranch();
- if (branch.getMergeBranchUuid().isPresent()) {
+ if (!branch.isMain()) {
return Optional.ofNullable(mergeBranchComponentUuid.getUuid(file.getDbKey()));
}
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java
index fab944e408d..441e9eefbb8 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStep.java
@@ -91,7 +91,7 @@ public class ValidateProjectStep implements ComputationStep {
if (!analysisMetadataHolder.isSLBorPR()) {
return;
}
- String mergeBranchUuid = analysisMetadataHolder.getBranch().getMergeBranchUuid().get();
+ String mergeBranchUuid = analysisMetadataHolder.getBranch().getMergeBranchUuid();
int moduleCount = dbClient.componentDao().countEnabledModulesByProjectUuid(session, mergeBranchUuid);
if (moduleCount > 0) {
Optional<BranchDto> opt = dbClient.branchDao().selectByUuid(session, mergeBranchUuid);
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 e275c6dffac..adc120665a2 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
@@ -25,7 +25,6 @@ import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.Date;
import java.util.List;
-import java.util.Optional;
import java.util.Random;
import javax.annotation.Nullable;
import org.apache.commons.lang.RandomStringUtils;
@@ -135,7 +134,7 @@ public class PostProjectAnalysisTasksExecutorTest {
new PostProjectAnalysisTasksExecutor(
ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
system2, new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2})
- .finished(allStepsExecuted);
+ .finished(allStepsExecuted);
inOrder.verify(postProjectAnalysisTask1).finished(projectAnalysisArgumentCaptor.capture());
inOrder.verify(postProjectAnalysisTask2).finished(projectAnalysisArgumentCaptor.capture());
@@ -289,8 +288,8 @@ public class PostProjectAnalysisTasksExecutorTest {
}
@Override
- public Optional<String> getMergeBranchUuid() {
- return Optional.empty();
+ public String getMergeBranchUuid() {
+ throw new UnsupportedOperationException();
}
@Override
@@ -308,6 +307,10 @@ public class PostProjectAnalysisTasksExecutorTest {
throw new UnsupportedOperationException();
}
+ @Override public String getTargetBranchName() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String generateKey(String projectKey, @Nullable String fileOrDirPath) {
throw new UnsupportedOperationException();
@@ -372,7 +375,7 @@ public class PostProjectAnalysisTasksExecutorTest {
new PostProjectAnalysisTasksExecutor(
ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
system2, new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2, postProjectAnalysisTask3})
- .finished(allStepsExecuted);
+ .finished(allStepsExecuted);
inOrder.verify(postProjectAnalysisTask1).finished(projectAnalysisArgumentCaptor.capture());
inOrder.verify(postProjectAnalysisTask2).finished(projectAnalysisArgumentCaptor.capture());
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java
index 8b98135f33d..cb4764c1b7b 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java
@@ -142,8 +142,7 @@ public class BranchPersisterImplTest {
}
@Test
- @UseDataProvider("nullOrNotNullString")
- public void persist_creates_row_in_PROJECTS_BRANCHES_for_pull_request(@Nullable String mergeBranchUuid) {
+ public void persist_creates_row_in_PROJECTS_BRANCHES_for_pull_request() {
String pullRequestId = "pr-123";
// add project and branch in table PROJECTS
@@ -153,7 +152,7 @@ public class BranchPersisterImplTest {
dbTester.commit();
// set project in metadata
treeRootHolder.setRoot(BRANCH);
- analysisMetadataHolder.setBranch(createBranch(PULL_REQUEST, false, pullRequestId, mergeBranchUuid));
+ analysisMetadataHolder.setBranch(createBranch(PULL_REQUEST, false, pullRequestId, "mergeBanchUuid"));
analysisMetadataHolder.setProject(Project.from(mainComponent));
analysisMetadataHolder.setPullRequestKey(pullRequestId);
@@ -166,10 +165,11 @@ public class BranchPersisterImplTest {
assertThat(branchDto).isPresent();
assertThat(branchDto.get().getBranchType()).isEqualTo(PULL_REQUEST);
assertThat(branchDto.get().getKey()).isEqualTo(pullRequestId);
- assertThat(branchDto.get().getMergeBranchUuid()).isEqualTo(mergeBranchUuid);
+ assertThat(branchDto.get().getMergeBranchUuid()).isEqualTo("mergeBanchUuid");
assertThat(branchDto.get().getProjectUuid()).isEqualTo(MAIN.getUuid());
assertThat(branchDto.get().getPullRequestData()).isEqualTo(DbProjectBranches.PullRequestData.newBuilder()
.setBranch(pullRequestId)
+ .setTarget("mergeBanchUuid")
.setTitle(pullRequestId)
.build());
}
@@ -183,7 +183,8 @@ public class BranchPersisterImplTest {
when(branch.getType()).thenReturn(type);
when(branch.getName()).thenReturn(name);
when(branch.isMain()).thenReturn(isMain);
- when(branch.getMergeBranchUuid()).thenReturn(Optional.ofNullable(mergeBranchUuid));
+ when(branch.getMergeBranchUuid()).thenReturn(mergeBranchUuid);
+ when(branch.getTargetBranchName()).thenReturn(mergeBranchUuid);
return branch;
}
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
index 5fe2b5e950b..a0409c6a56e 100644
--- 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
@@ -19,7 +19,6 @@
*/
package org.sonar.ce.task.projectanalysis.component;
-import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -62,19 +61,19 @@ public class MergeBranchComponentUuidsTest {
@Test
public void should_support_db_key() {
- when(branch.getMergeBranchUuid()).thenReturn(Optional.of(mergeBranch.uuid()));
+ when(branch.getMergeBranchUuid()).thenReturn(mergeBranch.uuid());
assertThat(underTest.getUuid(branchFile.getDbKey())).isEqualTo(mergeBranchFile.uuid());
}
@Test
public void should_support_key() {
- when(branch.getMergeBranchUuid()).thenReturn(Optional.of(mergeBranch.uuid()));
+ 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(Optional.of(mergeBranch.uuid()));
+ 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/component/SiblingComponentsWithOpenIssuesTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssuesTest.java
index dc73d0cb075..acb41e57fe4 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssuesTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/SiblingComponentsWithOpenIssuesTest.java
@@ -19,7 +19,6 @@
*/
package org.sonar.ce.task.projectanalysis.component;
-import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Rule;
@@ -110,14 +109,14 @@ public class SiblingComponentsWithOpenIssuesTest {
fileWithOneResolvedIssueOnLong2Short1 = db.components().insertComponent(ComponentTesting.newFileDto(long2short1, null));
db.issues().insertIssue(IssueTesting.newIssue(rule, long2short1, fileWithOneResolvedIssueOnLong2Short1).setStatus("RESOLVED"));
- setCurrentBranchUuid(long1.uuid());
+ setRoot(long1);
underTest = new SiblingComponentsWithOpenIssues(treeRootHolder, metadataHolder, db.getDbClient());
}
@Test
public void should_find_sibling_components_with_open_issues_for_long1() {
- setCurrentBranchUuid(long1.uuid());
- setReferenceBranchUuid(null);
+ setRoot(long1);
+ setBranch(BranchType.LONG);
assertThat(underTest.getUuids(fileWithNoIssuesOnLong1.getKey())).isEmpty();
assertThat(underTest.getUuids(fileWithOneOpenIssueOnLong1Short1.getKey())).containsOnly(fileWithOneOpenIssueOnLong1Short1.uuid());
@@ -132,8 +131,8 @@ public class SiblingComponentsWithOpenIssuesTest {
@Test
public void should_find_sibling_components_with_open_issues_for_short1() {
- setCurrentBranchUuid(long1short1.uuid());
- setReferenceBranchUuid(long1.uuid());
+ setRoot(long1short1);
+ setBranch(BranchType.SHORT, long1.uuid());
assertThat(underTest.getUuids(fileWithNoIssuesOnLong1.getKey())).isEmpty();
assertThat(underTest.getUuids(fileWithOneOpenIssueOnLong1Short1.getKey())).isEmpty();
@@ -146,8 +145,9 @@ public class SiblingComponentsWithOpenIssuesTest {
@Test
public void should_find_sibling_components_with_open_issues_for_long2() {
- setCurrentBranchUuid(long2.uuid());
- setReferenceBranchUuid(null);
+ setRoot(long2);
+ setBranch(BranchType.LONG);
+
underTest = new SiblingComponentsWithOpenIssues(treeRootHolder, metadataHolder, db.getDbClient());
assertThat(underTest.getUuids(fileWithOneResolvedIssueOnLong1Short1.getKey())).isEmpty();
@@ -158,8 +158,8 @@ public class SiblingComponentsWithOpenIssuesTest {
@Test
public void should_find_sibling_components_with_open_issues_from_short() {
ComponentDto project = db.components().insertMainBranch();
- setCurrentBranchUuid(project.uuid());
- setReferenceBranchUuid(null);
+ setRoot(project);
+ setBranch(BranchType.LONG);
ComponentDto branch = db.components().insertProjectBranch(project,
b -> b.setBranchType(BranchType.SHORT),
@@ -178,8 +178,8 @@ public class SiblingComponentsWithOpenIssuesTest {
@Test
public void should_find_sibling_components_with_open_issues_from_pullrequest() {
ComponentDto project = db.components().insertMainBranch();
- setCurrentBranchUuid(project.uuid());
- setReferenceBranchUuid(null);
+ setRoot(project);
+ setBranch(BranchType.LONG);
ComponentDto pullRequest = db.components().insertProjectBranch(project,
b -> b.setBranchType(BranchType.PULL_REQUEST),
@@ -198,8 +198,8 @@ public class SiblingComponentsWithOpenIssuesTest {
@Test
public void should_not_find_sibling_components_on_derived_long() {
ComponentDto project = db.components().insertMainBranch();
- setCurrentBranchUuid(project.uuid());
- setReferenceBranchUuid(null);
+ setRoot(project);
+ setBranch(BranchType.LONG);
ComponentDto derivedLongBranch = db.components().insertProjectBranch(project,
b -> b.setBranchType(BranchType.LONG),
@@ -215,15 +215,20 @@ public class SiblingComponentsWithOpenIssuesTest {
assertThat(underTest.getUuids(fileWithResolvedIssueOnDerivedLongBranch.getKey())).isEmpty();
}
- private void setCurrentBranchUuid(String uuid) {
+ private void setRoot(ComponentDto componentDto) {
Component root = mock(Component.class);
- when(root.getUuid()).thenReturn(uuid);
+ when(root.getUuid()).thenReturn(componentDto.uuid());
treeRootHolder.setRoot(root);
}
- private void setReferenceBranchUuid(@Nullable String uuid) {
+ private void setBranch(BranchType currentBranchType) {
+ setBranch(currentBranchType, null);
+ }
+
+ private void setBranch(BranchType currentBranchType, @Nullable String mergeBranchUuid) {
Branch branch = mock(Branch.class);
- when(branch.getMergeBranchUuid()).thenReturn(Optional.ofNullable(uuid));
+ when(branch.getType()).thenReturn(currentBranchType);
+ when(branch.getMergeBranchUuid()).thenReturn(mergeBranchUuid);
metadataHolder.setBranch(branch);
}
}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java
index e595aa04b69..4272c9f6981 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java
@@ -23,7 +23,6 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Date;
-import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Rule;
@@ -87,9 +86,9 @@ public class SiblingsIssueMergerTest {
private static final org.sonar.ce.task.projectanalysis.component.Component FILE_1 = builder(
org.sonar.ce.task.projectanalysis.component.Component.Type.FILE, FILE_1_REF)
- .setKey(FILE_1_KEY)
- .setUuid(FILE_1_UUID)
- .build();
+ .setKey(FILE_1_KEY)
+ .setUuid(FILE_1_UUID)
+ .build();
private SimpleTracker<DefaultIssue, SiblingIssue> tracker = new SimpleTracker<>();
private SiblingsIssueMerger copier;
@@ -105,11 +104,10 @@ public class SiblingsIssueMergerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(branch.getMergeBranchUuid()).thenReturn(Optional.empty());
- metadataHolder.setBranch(branch);
DbClient dbClient = db.getDbClient();
ComponentIssuesLoader componentIssuesLoader = new ComponentIssuesLoader(dbClient, null, null, new MapSettings().asConfig(), System2.INSTANCE);
- copier = new SiblingsIssueMerger(new SiblingsIssuesLoader(new SiblingComponentsWithOpenIssues(treeRootHolder, metadataHolder, dbClient), dbClient, componentIssuesLoader), tracker,
+ copier = new SiblingsIssueMerger(new SiblingsIssuesLoader(new SiblingComponentsWithOpenIssues(treeRootHolder, metadataHolder, dbClient), dbClient, componentIssuesLoader),
+ tracker,
issueLifecycle);
projectDto = db.components().insertMainBranch(p -> p.setDbKey(PROJECT_KEY).setUuid(PROJECT_UUID));
branch1Dto = db.components().insertProjectBranch(projectDto, b -> b.setKey("myBranch1")
@@ -125,6 +123,8 @@ public class SiblingsIssueMergerTest {
fileOnBranch2Dto = db.components().insertComponent(newFileDto(branch2Dto).setDbKey(FILE_1_KEY + ":BRANCH:myBranch2"));
fileOnBranch3Dto = db.components().insertComponent(newFileDto(branch3Dto).setDbKey(FILE_1_KEY + ":BRANCH:myBranch3"));
rule = db.rules().insert();
+ when(branch.getMergeBranchUuid()).thenReturn(projectDto.uuid());
+ metadataHolder.setBranch(branch);
}
@Test
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 0e9d474ecb6..159f82d34bf 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
@@ -93,7 +93,7 @@ public class ScmInfoDbLoaderTest {
String mergeFileUuid = "mergeFileUuid";
String hash = computeSourceHash(1);
- when(branch.getMergeBranchUuid()).thenReturn(Optional.of("mergeBranchUuid"));
+ when(branch.getMergeBranchUuid()).thenReturn("mergeBranchUuid");
when(mergeBranchComponentUuids.getUuid(FILE.getDbKey())).thenReturn(mergeFileUuid);
addFileSourceInDb("henry", DATE_1, "rev-1", hash, mergeFileUuid);
@@ -118,7 +118,6 @@ public class ScmInfoDbLoaderTest {
@Test
public void do_not_read_from_db_on_first_analysis_and_no_merge_branch() {
Branch branch = mock(Branch.class);
- when(branch.getMergeBranchUuid()).thenReturn(Optional.empty());
analysisMetadataHolder.setBaseAnalysis(null);
analysisMetadataHolder.setBranch(branch);
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java
index a1ad8c75e3d..2d219d0825c 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java
@@ -25,7 +25,6 @@ import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
-import java.util.Optional;
import java.util.Random;
import java.util.stream.Stream;
import javax.annotation.Nullable;
@@ -447,7 +446,7 @@ public class LoadPeriodsStepTest extends BaseStepTest {
}
@Override
- public Optional<String> getMergeBranchUuid() {
+ public String getMergeBranchUuid() {
throw new UnsupportedOperationException("getMergeBranchUuid not implemented");
}
@@ -462,6 +461,11 @@ public class LoadPeriodsStepTest extends BaseStepTest {
}
@Override
+ public String getTargetBranchName() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public String generateKey(String projectKey, @Nullable String fileOrDirPath) {
throw new UnsupportedOperationException("generateKey not implemented");
}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java
index 605a3005bd6..d19eb51ad14 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistComponentsStepTest.java
@@ -671,8 +671,8 @@ public class ReportPersistComponentsStepTest extends BaseStepTest {
}
@Override
- public java.util.Optional<String> getMergeBranchUuid() {
- return java.util.Optional.empty();
+ public String getMergeBranchUuid() {
+ throw new UnsupportedOperationException();
}
@Override
@@ -696,6 +696,11 @@ public class ReportPersistComponentsStepTest extends BaseStepTest {
}
@Override
+ public String getTargetBranchName() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public String generateKey(String projectKey, @Nullable String fileOrDirPath) {
if (isEmpty(fileOrDirPath)) {
return projectKey;
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java
index ccfc54e6708..05e3136e39f 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ValidateProjectStepTest.java
@@ -20,7 +20,6 @@
package org.sonar.ce.task.projectanalysis.step;
import java.util.Date;
-import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
@@ -129,11 +128,10 @@ public class ValidateProjectStepTest {
underTest.execute(new TestComputationStepContext());
}
-
private void setBranch(BranchType type, @Nullable String mergeBranchUuid) {
Branch branch = mock(Branch.class);
when(branch.getType()).thenReturn(type);
- when(branch.getMergeBranchUuid()).thenReturn(Optional.ofNullable(mergeBranchUuid));
+ when(branch.getMergeBranchUuid()).thenReturn(mergeBranchUuid);
analysisMetadataHolder.setBranch(branch);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
index d065136abab..7914cec53e6 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
@@ -364,6 +364,10 @@ public class ComponentDao implements Dao {
return mapper(dbSession).selectProjectsByNameQuery(nameQueryForSql, includeModules);
}
+ /**
+ * Returns components with open issues from branches that use a certain long living branch as reference (merge branch).
+ * Excludes components from the current branch.
+ */
public List<KeyWithUuidDto> selectAllSiblingComponentKeysHavingOpenIssues(DbSession dbSession, String referenceBranchUuid, String currentBranchUuid) {
return mapper(dbSession).selectAllSiblingComponentKeysHavingOpenIssues(referenceBranchUuid, currentBranchUuid);
}
diff --git a/server/sonar-db-dao/src/main/protobuf/db-project-branches.proto b/server/sonar-db-dao/src/main/protobuf/db-project-branches.proto
index ac6f5047f4a..f3d5fcd49f0 100644
--- a/server/sonar-db-dao/src/main/protobuf/db-project-branches.proto
+++ b/server/sonar-db-dao/src/main/protobuf/db-project-branches.proto
@@ -35,4 +35,6 @@ message PullRequestData {
string url = 3;
map<string, string> attributes = 4;
+
+ string target = 5;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/branch/pr/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/branch/pr/ws/ListAction.java
index 281ba36202d..4ee21954cdb 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/branch/pr/ws/ListAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/branch/pr/ws/ListAction.java
@@ -25,6 +25,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
@@ -150,6 +151,13 @@ public class ListAction implements PullRequestWsAction {
} else {
builder.setIsOrphan(true);
}
+
+ if (StringUtils.isNotEmpty(pullRequestData.getTarget())) {
+ builder.setTarget(pullRequestData.getTarget());
+ } else if (mergeBranch.isPresent()) {
+ builder.setTarget(mergeBranch.get().getKey());
+ }
+
ofNullable(analysisDate).ifPresent(builder::setAnalysisDate);
setQualityGate(builder, qualityGateMeasure, branchStatistics);
response.addPullRequests(builder);
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/branch/pr/ws/list-example.json b/server/sonar-server/src/main/resources/org/sonar/server/branch/pr/ws/list-example.json
index 4fef887dc82..877d25c17ef 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/branch/pr/ws/list-example.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/branch/pr/ws/list-example.json
@@ -12,7 +12,8 @@
"codeSmells": 0
},
"analysisDate": "2017-04-01T02:15:42+0200",
- "url": "https://github.com/SonarSource/sonar-core-plugins/pull/32"
+ "url": "https://github.com/SonarSource/sonar-core-plugins/pull/32",
+ "target": "feature/foo"
}
]
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java
index 6317707f6f8..d6c17571fac 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/StatusPredicate.java
@@ -22,6 +22,10 @@ package org.sonar.api.batch.fs.internal;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputFile;
+@Deprecated
+/**
+ * @deprecated since 7.8
+ */
public class StatusPredicate extends AbstractFilePredicate {
private final InputFile.Status status;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ChangedLinesPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ChangedLinesPublisher.java
index 8bc978109b6..ff393c42773 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ChangedLinesPublisher.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ChangedLinesPublisher.java
@@ -57,8 +57,8 @@ public class ChangedLinesPublisher implements ReportPublisherStep {
@Override
public void publish(ScannerReportWriter writer) {
- String targetScmBranch = branchConfiguration.targetScmBranch();
- if (scmConfiguration.isDisabled() || !branchConfiguration.isShortOrPullRequest() || targetScmBranch == null) {
+ String targetBranchName = branchConfiguration.targetBranchName();
+ if (scmConfiguration.isDisabled() || !branchConfiguration.isShortOrPullRequest() || targetBranchName == null) {
return;
}
@@ -68,7 +68,7 @@ public class ChangedLinesPublisher implements ReportPublisherStep {
}
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
- int count = writeChangedLines(provider, writer, targetScmBranch);
+ int count = writeChangedLines(provider, writer, targetBranchName);
LOG.debug("SCM reported changed lines for {} {} in the branch", count, ScannerUtils.pluralize("file", count));
profiler.stopInfo();
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
index 69891747295..9bf40f4a94e 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
@@ -160,6 +160,10 @@ public class MetadataPublisher implements ReportPublisherStep {
if (referenceBranch != null) {
builder.setMergeBranchName(referenceBranch);
}
+ String targetBranchName = branchConfiguration.targetBranchName();
+ if (targetBranchName != null) {
+ builder.setTargetBranchName(targetBranchName);
+ }
if (branchType == BranchType.PULL_REQUEST) {
builder.setPullRequestKey(branchConfiguration.pullRequestKey());
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java
index 6c3c2f93da2..361eeab3e6d 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java
@@ -50,24 +50,27 @@ public class DefaultQualityProfileLoader implements QualityProfileLoader {
this.wsClient = wsClient;
}
- @Override
- public List<QualityProfile> loadDefault() {
+ private List<QualityProfile> loadDefault() {
StringBuilder url = new StringBuilder(WS_URL + "?defaults=true");
- return handleErrors(url, () -> "Failed to load the default quality profiles");
+ return handleErrors(url, () -> "Failed to load the default quality profiles", false);
}
@Override
public List<QualityProfile> load(String projectKey) {
StringBuilder url = new StringBuilder(WS_URL + "?projectKey=").append(encodeForUrl(projectKey));
- return handleErrors(url, () -> String.format("Failed to load the quality profiles of project '%s'", projectKey));
+ return handleErrors(url, () -> String.format("Failed to load the quality profiles of project '%s'", projectKey), true);
}
- private List<QualityProfile> handleErrors(StringBuilder url, Supplier<String> errorMsg) {
+ private List<QualityProfile> handleErrors(StringBuilder url, Supplier<String> errorMsg, boolean tryLoadDefault) {
try {
return doLoad(url);
} catch (HttpException e) {
if (e.code() == 404) {
- throw MessageException.of(errorMsg.get() + ": " + ScannerWsClient.createErrorMessage(e));
+ if (tryLoadDefault) {
+ return loadDefault();
+ } else {
+ throw MessageException.of(errorMsg.get() + ": " + ScannerWsClient.createErrorMessage(e));
+ }
}
throw new IllegalStateException(errorMsg.get() + ": " + ScannerWsClient.createErrorMessage(e));
} catch (MessageException e) {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesSupplier.java
index d2f7bfeb1af..f0fda872182 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesProvider.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesSupplier.java
@@ -19,19 +19,29 @@
*/
package org.sonar.scanner.repository;
-import org.picocontainer.injectors.ProviderAdapter;
+import java.util.function.Supplier;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
import org.sonar.scanner.scan.branch.BranchConfiguration;
-public class ProjectRepositoriesProvider extends ProviderAdapter {
- private static final Logger LOG = Loggers.get(ProjectRepositoriesProvider.class);
+public class ProjectRepositoriesSupplier implements Supplier<ProjectRepositories> {
+ private static final Logger LOG = Loggers.get(ProjectRepositoriesSupplier.class);
private static final String LOG_MSG = "Load project repositories";
+ private final ProjectRepositoriesLoader loader;
+ private final ProcessedScannerProperties scannerProperties;
+ private final BranchConfiguration branchConfig;
+
private ProjectRepositories project = null;
- public ProjectRepositories provide(ProjectRepositoriesLoader loader, ProcessedScannerProperties scannerProperties, BranchConfiguration branchConfig) {
+ public ProjectRepositoriesSupplier(ProjectRepositoriesLoader loader, ProcessedScannerProperties scannerProperties, BranchConfiguration branchConfig) {
+ this.loader = loader;
+ this.scannerProperties = scannerProperties;
+ this.branchConfig = branchConfig;
+ }
+
+ public ProjectRepositories get() {
if (project == null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
project = loader.load(scannerProperties.getKeyWithBranch(), branchConfig.longLivingSonarReferenceBranch());
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfileLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfileLoader.java
index 202cc6389e1..df17a1f2247 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfileLoader.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfileLoader.java
@@ -24,6 +24,4 @@ import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
public interface QualityProfileLoader {
List<QualityProfile> load(String projectKey);
-
- List<QualityProfile> loadDefault();
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java
index 267d0c01729..e78e4d7457f 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java
@@ -19,31 +19,23 @@
*/
package org.sonar.scanner.repository;
-import java.util.List;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
import org.sonar.scanner.rule.QualityProfiles;
-import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
public class QualityProfilesProvider extends ProviderAdapter {
private static final Logger LOG = Loggers.get(QualityProfilesProvider.class);
private static final String LOG_MSG = "Load quality profiles";
private QualityProfiles profiles = null;
- public QualityProfiles provide(QualityProfileLoader loader, ProjectRepositories projectRepositories, ProcessedScannerProperties props) {
+ public QualityProfiles provide(QualityProfileLoader loader, ProcessedScannerProperties props) {
if (this.profiles == null) {
- List<QualityProfile> profileList;
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
- if (!projectRepositories.exists()) {
- profileList = loader.loadDefault();
- } else {
- profileList = loader.load(props.getKeyWithBranch());
- }
+ profiles = new QualityProfiles(loader.load(props.getKeyWithBranch()));
profiler.stopInfo();
- profiles = new QualityProfiles(profileList);
}
return profiles;
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 dc242a2b4bd..548a477c7d0 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
@@ -77,7 +77,7 @@ import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader;
import org.sonar.scanner.repository.DefaultQualityProfileLoader;
import org.sonar.scanner.repository.ProjectRepositoriesLoader;
-import org.sonar.scanner.repository.ProjectRepositoriesProvider;
+import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.QualityProfileLoader;
import org.sonar.scanner.repository.QualityProfilesProvider;
import org.sonar.scanner.repository.language.DefaultLanguagesRepository;
@@ -157,7 +157,7 @@ public class ProjectScanContainer extends ComponentContainer {
new ProjectBranchesProvider(),
new ProjectPullRequestsProvider(),
DefaultAnalysisMode.class,
- new ProjectRepositoriesProvider(),
+ ProjectRepositoriesSupplier.class,
new ProjectServerSettingsProvider(),
// temp
@@ -304,7 +304,7 @@ 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.targetScmBranch()), 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()));
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfiguration.java
index 87dedb54d11..d3f51049c0d 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfiguration.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfiguration.java
@@ -27,7 +27,6 @@ public interface BranchConfiguration {
/**
* The type of the branch we're on, determined by:
- *
* - If the specified branch exists on the server, then its type
* - If the branch name matches the pattern of long-lived branches, then it's long-lived
* - Otherwise it's short-lived
@@ -43,7 +42,8 @@ public interface BranchConfiguration {
/**
* For long/short living branches, this is the value of sonar.branch.name, and fallback on the default branch name configured in SQ
* For PR: the name of the branch containing PR changes (sonar.pullrequest.branch)
- * Only @null if the branch feature is not available.
+ *
+ * @return null if the branch feature is not available or no branch was specified.
*/
@CheckForNull
String branchName();
@@ -56,17 +56,20 @@ public interface BranchConfiguration {
* transitively use its own target.
* For PR, we look at sonar.pullrequest.base (default to default branch). If it exists but is a short living branch or PR, we will
* transitively use its own target. If base is not analyzed, we will use default branch.
- * Only @null if the branch feature is not available.
+ *
+ * @return null if the branch feature is not available or no branch was specified.
*/
@CheckForNull
String longLivingSonarReferenceBranch();
/**
- * Raw value of sonar.branch.target or sonar.pullrequest.base (fallback to the default branch), will be used by the SCM to compute changed files and changed lines.
- * @null for long living branches and if the branch feature is not available
+ * Raw value of sonar.branch.target or sonar.pullrequest.base (fallback to the default branch).
+ * In the scanner side, it will be used by the SCM to compute changed files and changed lines.
+ *
+ * @return null if the branch feature is not available, the branch being analyzed is the main branch or no branch was specified.
*/
@CheckForNull
- String targetScmBranch();
+ String targetBranchName();
/**
* The key of the pull request.
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/DefaultBranchConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/DefaultBranchConfiguration.java
index 436afec909e..7314597a828 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/DefaultBranchConfiguration.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/DefaultBranchConfiguration.java
@@ -37,7 +37,7 @@ public class DefaultBranchConfiguration implements BranchConfiguration {
@CheckForNull
@Override
- public String targetScmBranch() {
+ public String targetBranchName() {
return null;
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java
index 8f33e02ea2c..09561999935 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java
@@ -24,7 +24,7 @@ import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.scanner.repository.FileData;
-import org.sonar.scanner.repository.ProjectRepositories;
+import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.scm.ScmChangedFiles;
import static org.sonar.api.batch.fs.InputFile.Status.ADDED;
@@ -33,33 +33,40 @@ import static org.sonar.api.batch.fs.InputFile.Status.SAME;
@Immutable
public class StatusDetection {
- private final ProjectRepositories projectRepositories;
+ private final ProjectRepositoriesSupplier projectSettingsSupplier;
private final ScmChangedFiles scmChangedFiles;
- public StatusDetection(ProjectRepositories projectSettings, ScmChangedFiles scmChangedFiles) {
- this.projectRepositories = projectSettings;
+ public StatusDetection(ProjectRepositoriesSupplier projectSettingsSupplier, ScmChangedFiles scmChangedFiles) {
+ this.projectSettingsSupplier = projectSettingsSupplier;
this.scmChangedFiles = scmChangedFiles;
}
InputFile.Status status(String moduleKeyWithBranch, DefaultInputFile inputFile, String hash) {
- FileData fileDataPerPath = projectRepositories.fileData(moduleKeyWithBranch, inputFile);
+ if (scmChangedFiles.isValid()) {
+ return checkChangedWithScm(inputFile);
+ }
+ return checkChangedWithProjectRepositories(moduleKeyWithBranch, inputFile, hash);
+ }
+
+ private InputFile.Status checkChangedWithProjectRepositories(String moduleKeyWithBranch, DefaultInputFile inputFile, String hash) {
+ FileData fileDataPerPath = projectSettingsSupplier.get().fileData(moduleKeyWithBranch, inputFile);
if (fileDataPerPath == null) {
- return checkChanged(ADDED, inputFile);
+ return ADDED;
}
String previousHash = fileDataPerPath.hash();
if (StringUtils.equals(hash, previousHash)) {
return SAME;
}
if (StringUtils.isEmpty(previousHash)) {
- return checkChanged(ADDED, inputFile);
+ return ADDED;
}
- return checkChanged(CHANGED, inputFile);
+ return CHANGED;
}
- private InputFile.Status checkChanged(InputFile.Status status, DefaultInputFile inputFile) {
- if (!scmChangedFiles.verifyChanged(inputFile.path())) {
+ private InputFile.Status checkChangedWithScm(DefaultInputFile inputFile) {
+ if (!scmChangedFiles.isChanged(inputFile.path())) {
return SAME;
}
- return status;
+ return CHANGED;
}
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFiles.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFiles.java
index dfb078ecccb..380c65c32a2 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFiles.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFiles.java
@@ -21,6 +21,7 @@ package org.sonar.scanner.scm;
import java.nio.file.Path;
import java.util.Collection;
+import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -33,10 +34,19 @@ public class ScmChangedFiles {
this.fileCollection = changedFiles;
}
- public boolean verifyChanged(Path file) {
- return fileCollection == null || fileCollection.contains(file);
+ public boolean isChanged(Path file) {
+ if (!isValid()) {
+ throw new IllegalStateException("Scm didn't provide valid data");
+ }
+
+ return fileCollection.contains(file);
+ }
+
+ public boolean isValid() {
+ return fileCollection != null;
}
+ @CheckForNull
Collection<Path> get() {
return fileCollection;
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java
index 63f30c85f2c..b7fd4c8bf76 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java
@@ -22,7 +22,6 @@ package org.sonar.scanner.scm;
import java.nio.file.Path;
import java.util.Collection;
import javax.annotation.CheckForNull;
-import org.picocontainer.annotations.Nullable;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.scm.ScmProvider;
@@ -38,19 +37,12 @@ public class ScmChangedFilesProvider extends ProviderAdapter {
private ScmChangedFiles scmBranchChangedFiles;
- /*
- * ScmConfiguration is not available in issues mode
- */
- public ScmChangedFiles provide(@Nullable ScmConfiguration scmConfiguration, BranchConfiguration branchConfiguration, DefaultInputProject project) {
+ public ScmChangedFiles provide(ScmConfiguration scmConfiguration, BranchConfiguration branchConfiguration, DefaultInputProject project) {
if (scmBranchChangedFiles == null) {
- if (scmConfiguration == null) {
- scmBranchChangedFiles = new ScmChangedFiles(null);
- } else {
- Path rootBaseDir = project.getBaseDir();
- Collection<Path> changedFiles = loadChangedFilesIfNeeded(scmConfiguration, branchConfiguration, rootBaseDir);
- validatePaths(changedFiles);
- scmBranchChangedFiles = new ScmChangedFiles(changedFiles);
- }
+ Path rootBaseDir = project.getBaseDir();
+ Collection<Path> changedFiles = loadChangedFilesIfNeeded(scmConfiguration, branchConfiguration, rootBaseDir);
+ validatePaths(changedFiles);
+ scmBranchChangedFiles = new ScmChangedFiles(changedFiles);
}
return scmBranchChangedFiles;
}
@@ -63,12 +55,12 @@ public class ScmChangedFilesProvider extends ProviderAdapter {
@CheckForNull
private static Collection<Path> loadChangedFilesIfNeeded(ScmConfiguration scmConfiguration, BranchConfiguration branchConfiguration, Path rootBaseDir) {
- String targetScmBranch = branchConfiguration.targetScmBranch();
- if (branchConfiguration.isShortOrPullRequest() && targetScmBranch != null) {
+ final String targetBranchName = branchConfiguration.targetBranchName();
+ if (branchConfiguration.isShortOrPullRequest() && targetBranchName != null) {
ScmProvider scmProvider = scmConfiguration.provider();
if (scmProvider != null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
- Collection<Path> changedFiles = scmProvider.branchChangedFiles(targetScmBranch, rootBaseDir);
+ Collection<Path> changedFiles = scmProvider.branchChangedFiles(targetBranchName, rootBaseDir);
profiler.stopInfo();
if (changedFiles != null) {
LOG.debug("SCM reported {} {} changed in the branch", changedFiles.size(), ScannerUtils.pluralize("file", changedFiles.size()));
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java
index 4abb86427d5..819abc8adce 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java
@@ -35,7 +35,7 @@ import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.report.ReportPublisher;
import org.sonar.scanner.repository.FileData;
-import org.sonar.scanner.repository.ProjectRepositories;
+import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.InputComponentStore;
@@ -44,16 +44,16 @@ public final class ScmPublisher {
private static final Logger LOG = Loggers.get(ScmPublisher.class);
private final ScmConfiguration configuration;
- private final ProjectRepositories projectRepositories;
+ private final ProjectRepositoriesSupplier projectRepositoriesSupplier;
private final InputComponentStore componentStore;
private final FileSystem fs;
private final ScannerReportWriter writer;
private final BranchConfiguration branchConfiguration;
- public ScmPublisher(ScmConfiguration configuration, ProjectRepositories projectRepositories,
- InputComponentStore componentStore, FileSystem fs, ReportPublisher reportPublisher, BranchConfiguration branchConfiguration) {
+ public ScmPublisher(ScmConfiguration configuration, ProjectRepositoriesSupplier projectRepositoriesSupplier,
+ InputComponentStore componentStore, FileSystem fs, ReportPublisher reportPublisher, BranchConfiguration branchConfiguration) {
this.configuration = configuration;
- this.projectRepositories = projectRepositories;
+ this.projectRepositoriesSupplier = projectRepositoriesSupplier;
this.componentStore = componentStore;
this.fs = fs;
this.branchConfiguration = branchConfiguration;
@@ -96,12 +96,11 @@ public final class ScmPublisher {
if (configuration.forceReloadAll() || f.status() != Status.SAME) {
addIfNotEmpty(filesToBlame, f);
} else if (!branchConfiguration.isShortOrPullRequest()) {
- // File status is SAME so that mean fileData exists
- FileData fileData = projectRepositories.fileData(componentStore.findModule(f).getKeyWithBranch(), f);
- if (StringUtils.isEmpty(fileData.revision())) {
+ FileData fileData = projectRepositoriesSupplier.get().fileData(componentStore.findModule(f).getKeyWithBranch(), f);
+ if (fileData == null || StringUtils.isEmpty(fileData.revision())) {
addIfNotEmpty(filesToBlame, f);
} else {
- askToCopyDataFromPreviousAnalysis((DefaultInputFile) f, writer);
+ askToCopyDataFromPreviousAnalysis(f, writer);
}
}
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java
index 49df2785567..28cb9ba3ed8 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java
@@ -74,7 +74,6 @@ import org.sonarqube.ws.Rules.ListResponse.Rule;
/**
* Main utility class for writing scanner medium tests.
- *
*/
public class ScannerMediumTester extends ExternalResource {
@@ -389,7 +388,7 @@ public class ScannerMediumTester extends ExternalResource {
@CheckForNull
@Override
- public String targetScmBranch() {
+ public String targetBranchName() {
return branchTarget;
}
@@ -449,11 +448,6 @@ public class ScannerMediumTester extends ExternalResource {
public List<QualityProfile> load(String projectKey) {
return qualityProfiles;
}
-
- @Override
- public List<QualityProfile> loadDefault() {
- return qualityProfiles;
- }
}
private static class FakeGlobalSettingsLoader implements GlobalSettingsLoader {
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java
index b45964ecad6..2d155cea756 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java
@@ -69,7 +69,7 @@ public class ChangedLinesPublisherTest {
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
when(scmConfiguration.isDisabled()).thenReturn(false);
when(scmConfiguration.provider()).thenReturn(provider);
- when(branchConfiguration.targetScmBranch()).thenReturn(TARGET_BRANCH);
+ when(branchConfiguration.targetBranchName()).thenReturn(TARGET_BRANCH);
when(project.getBaseDir()).thenReturn(BASE_DIR);
}
@@ -91,7 +91,7 @@ public class ChangedLinesPublisherTest {
@Test
public void skip_if_target_branch_is_null() {
- when(branchConfiguration.targetScmBranch()).thenReturn(null);
+ when(branchConfiguration.targetBranchName()).thenReturn(null);
publisher.publish(writer);
verifyZeroInteractions(inputComponentStore, inputModuleHierarchy, provider);
assertNotPublished();
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
index f7df36536d9..2c90a1a8eed 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
@@ -260,9 +260,11 @@ public class MetadataPublisherTest {
@Test
public void write_short_lived_branch_info() throws Exception {
String branchName = "feature";
- String branchTarget = "short-lived";
+ String targetBranchName = "short-lived";
+ String longLivingSonarReferenceBranch = "long-lived";
when(branches.branchName()).thenReturn(branchName);
- when(branches.longLivingSonarReferenceBranch()).thenReturn(branchTarget);
+ when(branches.targetBranchName()).thenReturn(targetBranchName);
+ when(branches.longLivingSonarReferenceBranch()).thenReturn(longLivingSonarReferenceBranch);
File outputDir = temp.newFolder();
underTest.publish(new ScannerReportWriter(outputDir));
@@ -271,7 +273,8 @@ public class MetadataPublisherTest {
ScannerReport.Metadata metadata = reader.readMetadata();
assertThat(metadata.getBranchName()).isEqualTo(branchName);
assertThat(metadata.getBranchType()).isEqualTo(ScannerReport.Metadata.BranchType.SHORT);
- assertThat(metadata.getMergeBranchName()).isEqualTo(branchTarget);
+ assertThat(metadata.getMergeBranchName()).isEqualTo(longLivingSonarReferenceBranch);
+ assertThat(metadata.getTargetBranchName()).isEqualTo(targetBranchName);
}
@Test
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java
index 757bd52ab3a..95e38e4520e 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java
@@ -70,17 +70,27 @@ public class DefaultQualityProfileLoaderTest {
}
@Test
- public void loadDefault_gets_all_default_profiles() throws IOException {
- prepareCallWithResults();
- underTest.loadDefault();
+ public void load_tries_default_if_no_profiles_found_for_project() throws IOException {
+ HttpException e = new HttpException("", 404, "{\"errors\":[{\"msg\":\"No project found with key 'foo'\"}]}");
+ WsTestUtil.mockException(wsClient, "/api/qualityprofiles/search.protobuf?projectKey=foo", e);
+ WsTestUtil.mockStream(wsClient, "/api/qualityprofiles/search.protobuf?defaults=true", createStreamOfProfiles("qp"));
+
+ underTest.load("foo");
+
+ verifyCalledPath("/api/qualityprofiles/search.protobuf?projectKey=foo");
verifyCalledPath("/api/qualityprofiles/search.protobuf?defaults=true");
}
@Test
public void loadDefault_sets_organization_parameter_if_defined_in_settings() throws IOException {
when(properties.organizationKey()).thenReturn(Optional.of("my-org"));
+
+ HttpException e = new HttpException("", 404, "{\"errors\":[{\"msg\":\"No organization with key 'myorg'\"}]}");
+ WsTestUtil.mockException(wsClient, "/api/qualityprofiles/search.protobuf?projectKey=foo&organization=my-org", e);
WsTestUtil.mockStream(wsClient, "/api/qualityprofiles/search.protobuf?defaults=true&organization=my-org", createStreamOfProfiles("qp"));
- underTest.loadDefault();
+
+ underTest.load("foo");
+
verifyCalledPath("/api/qualityprofiles/search.protobuf?defaults=true&organization=my-org");
}
@@ -96,12 +106,12 @@ public class DefaultQualityProfileLoaderTest {
}
@Test
- public void load_throws_MessageException_if_organization_is_not_found() throws IOException {
+ public void load_throws_MessageException_if_organization_is_not_found_after_trying_default() throws IOException {
HttpException e = new HttpException("", 404, "{\"errors\":[{\"msg\":\"No organization with key 'myorg'\"}]}");
WsTestUtil.mockException(wsClient, e);
exception.expect(MessageException.class);
- exception.expectMessage("Failed to load the quality profiles of project 'project': No organization with key 'myorg'");
+ exception.expectMessage("Failed to load the default quality profiles: No organization with key 'myorg'");
underTest.load("project");
verifyNoMoreInteractions(wsClient);
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesSupplierTest.java
index 2fb5056e0c9..72c58dca71d 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesSupplierTest.java
@@ -23,53 +23,43 @@ import com.google.common.collect.Maps;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-public class ProjectRepositoriesProviderTest {
- private ProjectRepositoriesProvider provider;
+public class ProjectRepositoriesSupplierTest {
+ private ProjectRepositoriesSupplier underTest;
private ProjectRepositories project;
- @Mock
- private ProjectRepositoriesLoader loader;
- @Mock
- private ProcessedScannerProperties props;
- @Mock
- private BranchConfiguration branchConfiguration;
+ private ProjectRepositoriesLoader loader = mock(ProjectRepositoriesLoader.class);
+ private ProcessedScannerProperties props = mock(ProcessedScannerProperties.class);
+ private BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
-
+ underTest = new ProjectRepositoriesSupplier(loader, props, branchConfiguration);
Map<String, FileData> fileMap = Maps.newHashMap();
-
project = new SingleProjectRepository(fileMap);
- provider = new ProjectRepositoriesProvider();
-
when(props.getKeyWithBranch()).thenReturn("key");
}
@Test
public void testValidation() {
when(loader.load(eq("key"), any())).thenReturn(project);
-
- provider.provide(loader, props, branchConfiguration);
+ underTest.get();
}
@Test
public void testAssociated() {
when(loader.load(eq("key"), any())).thenReturn(project);
-
- ProjectRepositories repo = provider.provide(loader, props, branchConfiguration);
+ ProjectRepositories repo = underTest.get();
assertThat(repo.exists()).isEqualTo(true);
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java
index a318a6e9b59..94bc1b6f10c 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java
@@ -19,25 +19,21 @@
*/
package org.sonar.scanner.repository;
-import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
import org.sonar.scanner.rule.QualityProfiles;
import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -49,22 +45,16 @@ public class QualityProfileProviderTest {
private QualityProfilesProvider qualityProfileProvider;
- @Mock
- private QualityProfileLoader loader;
- @Mock
- private ProcessedScannerProperties props;
- @Mock
- private ProjectRepositories projectRepo;
+ private QualityProfileLoader loader = mock(QualityProfileLoader.class);
+ private ProcessedScannerProperties props = mock(ProcessedScannerProperties.class);
private List<QualityProfile> response;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
qualityProfileProvider = new QualityProfilesProvider();
when(props.getKeyWithBranch()).thenReturn("project");
- when(projectRepo.exists()).thenReturn(true);
response = new ArrayList<>(1);
response.add(QualityProfile.newBuilder().setKey("profile").setName("profile").setLanguage("lang").setRulesUpdatedAt(DateUtils.formatDateTime(new Date())).build());
@@ -73,7 +63,7 @@ public class QualityProfileProviderTest {
@Test
public void testProvide() {
when(loader.load("project")).thenReturn(response);
- QualityProfiles qps = qualityProfileProvider.provide(loader, projectRepo, props);
+ QualityProfiles qps = qualityProfileProvider.provide(loader, props);
assertResponse(qps);
verify(loader).load("project");
@@ -81,39 +71,16 @@ public class QualityProfileProviderTest {
}
@Test
- public void testProjectDoesntExist() {
- when(projectRepo.exists()).thenReturn(false);
- when(loader.loadDefault()).thenReturn(response);
- QualityProfiles qps = qualityProfileProvider.provide(loader, projectRepo, props);
- assertResponse(qps);
-
- verify(loader).loadDefault();
- verifyNoMoreInteractions(loader);
- }
-
- @Test
public void testProfileProp() {
when(loader.load(eq("project"))).thenReturn(response);
- QualityProfiles qps = qualityProfileProvider.provide(loader, projectRepo, props);
+ QualityProfiles qps = qualityProfileProvider.provide(loader, props);
assertResponse(qps);
verify(loader).load(eq("project"));
verifyNoMoreInteractions(loader);
}
- @Test
- public void testProfilePropDefault() {
- when(projectRepo.exists()).thenReturn(false);
- when(loader.loadDefault()).thenReturn(response);
-
- QualityProfiles qps = qualityProfileProvider.provide(loader, projectRepo, props);
- assertResponse(qps);
-
- verify(loader).loadDefault();
- verifyNoMoreInteractions(loader);
- }
-
private void assertResponse(QualityProfiles qps) {
assertThat(qps.findAll()).extracting("key").containsExactly("profile");
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java
index 8863e9c1a35..6b79b11276e 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java
@@ -96,7 +96,7 @@ public class BranchConfigurationProviderTest {
public void should_return_default_if_no_loader() {
BranchConfiguration result = provider.provide(null, globalConfiguration, reactor, globalServerSettings, projectServerSettings, branches, pullRequests);
- assertThat(result.targetScmBranch()).isNull();
+ assertThat(result.targetBranchName()).isNull();
assertThat(result.branchType()).isEqualTo(BranchType.LONG);
}
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java
index b5ed22c270f..857f12e9f69 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java
@@ -23,22 +23,32 @@ import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.scanner.repository.FileData;
+import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.SingleProjectRepository;
import org.sonar.scanner.scm.ScmChangedFiles;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class StatusDetectionTest {
+ private ProjectRepositoriesSupplier projectRepositoriesSupplier = mock(ProjectRepositoriesSupplier.class);
+
+ @Before
+ public void setUp() {
+ when(projectRepositoriesSupplier.get()).thenReturn(new SingleProjectRepository(createFileDataPerPathMap()));
+ }
+
@Test
public void detect_status() {
- SingleProjectRepository ref = new SingleProjectRepository(createFileDataPerPathMap());
ScmChangedFiles changedFiles = new ScmChangedFiles(null);
- StatusDetection statusDetection = new StatusDetection(ref, changedFiles);
+ StatusDetection statusDetection = new StatusDetection(projectRepositoriesSupplier, changedFiles);
assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "ABCDE")).isEqualTo(InputFile.Status.SAME);
assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.CHANGED);
@@ -47,9 +57,8 @@ public class StatusDetectionTest {
@Test
public void detect_status_branches_exclude() {
- SingleProjectRepository ref = new SingleProjectRepository(createFileDataPerPathMap());
ScmChangedFiles changedFiles = new ScmChangedFiles(Collections.emptyList());
- StatusDetection statusDetection = new StatusDetection(ref, changedFiles);
+ StatusDetection statusDetection = new StatusDetection(projectRepositoriesSupplier, changedFiles);
// normally changed
assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.SAME);
@@ -60,9 +69,8 @@ public class StatusDetectionTest {
@Test
public void detect_status_branches_confirm() {
- SingleProjectRepository ref = new SingleProjectRepository(createFileDataPerPathMap());
ScmChangedFiles changedFiles = new ScmChangedFiles(Collections.singletonList(Paths.get("module", "src", "Foo.java")));
- StatusDetection statusDetection = new StatusDetection(ref, changedFiles);
+ StatusDetection statusDetection = new StatusDetection(projectRepositoriesSupplier, changedFiles);
assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.CHANGED);
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java
index 7d0795eb2de..4b81bb45f5e 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java
@@ -66,7 +66,7 @@ public class ScmChangedFilesProviderTest {
@Test
public void testNoScmProvider() {
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
- when(branchConfiguration.targetScmBranch()).thenReturn("target");
+ when(branchConfiguration.targetBranchName()).thenReturn("target");
ScmChangedFiles scmChangedFiles = provider.provide(scmConfiguration, branchConfiguration, project);
@@ -76,7 +76,7 @@ public class ScmChangedFilesProviderTest {
@Test
public void testFailIfRelativePath() {
- when(branchConfiguration.targetScmBranch()).thenReturn("target");
+ when(branchConfiguration.targetBranchName()).thenReturn("target");
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
when(scmConfiguration.provider()).thenReturn(scmProvider);
when(scmProvider.branchChangedFiles("target", rootBaseDir)).thenReturn(Collections.singleton(Paths.get("changedFile")));
@@ -88,7 +88,7 @@ public class ScmChangedFilesProviderTest {
@Test
public void testProviderDoesntSupport() {
- when(branchConfiguration.targetScmBranch()).thenReturn("target");
+ when(branchConfiguration.targetBranchName()).thenReturn("target");
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
when(scmConfiguration.provider()).thenReturn(scmProvider);
when(scmProvider.branchChangedFiles("target", rootBaseDir)).thenReturn(null);
@@ -118,7 +118,7 @@ public class ScmChangedFilesProviderTest {
when(scmConfiguration.provider()).thenReturn(legacy);
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
- when(branchConfiguration.targetScmBranch()).thenReturn("target");
+ when(branchConfiguration.targetBranchName()).thenReturn("target");
ScmChangedFiles scmChangedFiles = provider.provide(scmConfiguration, branchConfiguration, project);
@@ -128,7 +128,7 @@ public class ScmChangedFilesProviderTest {
@Test
public void testReturnChangedFiles() {
- when(branchConfiguration.targetScmBranch()).thenReturn("target");
+ when(branchConfiguration.targetBranchName()).thenReturn("target");
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
when(scmConfiguration.provider()).thenReturn(scmProvider);
when(scmProvider.branchChangedFiles("target", rootBaseDir)).thenReturn(Collections.singleton(Paths.get("changedFile").toAbsolutePath()));
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java
index bd0e0d21d1a..2e2f493302b 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java
@@ -23,13 +23,18 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import static org.assertj.core.api.Assertions.assertThat;
public class ScmChangedFilesTest {
private ScmChangedFiles scmChangedFiles;
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
@Test
public void testGetter() {
Collection<Path> files = Collections.singletonList(Paths.get("files"));
@@ -40,15 +45,19 @@ public class ScmChangedFilesTest {
@Test
public void testNullable() {
scmChangedFiles = new ScmChangedFiles(null);
+ assertThat(scmChangedFiles.isValid()).isFalse();
assertThat(scmChangedFiles.get()).isNull();
- assertThat(scmChangedFiles.verifyChanged(Paths.get("files2"))).isTrue();
+
+ exception.expect(IllegalStateException.class);
+ assertThat(scmChangedFiles.isChanged(Paths.get("files2"))).isTrue();
}
@Test
public void testConfirm() {
Collection<Path> files = Collections.singletonList(Paths.get("files"));
scmChangedFiles = new ScmChangedFiles(files);
- assertThat(scmChangedFiles.verifyChanged(Paths.get("files"))).isTrue();
- assertThat(scmChangedFiles.verifyChanged(Paths.get("files2"))).isFalse();
+ assertThat(scmChangedFiles.isValid()).isTrue();
+ assertThat(scmChangedFiles.isChanged(Paths.get("files"))).isTrue();
+ assertThat(scmChangedFiles.isChanged(Paths.get("files2"))).isFalse();
}
}
diff --git a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
index 2d63cc866dd..381824cc9ea 100644
--- a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
+++ b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
@@ -39,6 +39,7 @@ message Metadata {
bool cross_project_duplication_activated = 6;
map<string, QProfile> qprofiles_per_language = 7;
map<string, Plugin> plugins_by_key = 8;
+
string branch_name = 9;
BranchType branch_type = 10;
string merge_branch_name = 11;
@@ -52,6 +53,8 @@ message Metadata {
string projectVersion = 16;
string buildString = 17;
+ string target_branch_name = 18;
+
message QProfile {
string key = 1;
string name = 2;
diff --git a/sonar-ws/src/main/protobuf/ws-projectpullrequests.proto b/sonar-ws/src/main/protobuf/ws-projectpullrequests.proto
index 24203121496..cad1acf8e58 100644
--- a/sonar-ws/src/main/protobuf/ws-projectpullrequests.proto
+++ b/sonar-ws/src/main/protobuf/ws-projectpullrequests.proto
@@ -40,6 +40,7 @@ message PullRequest {
optional bool isOrphan = 6;
optional string analysisDate = 7;
optional string url = 8;
+ optional string target = 9;
}
message Status {