ソースを参照

SONAR-16050 Scanner fails with NPE if user doesn't have permission to analyze project

tags/9.4.0.54424
Duarte Meneses 2年前
コミット
1c1d85d052

sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesSupplier.java → sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositoriesProvider.java ファイルの表示

*/ */
package org.sonar.scanner.repository; package org.sonar.scanner.repository;


import java.util.function.Supplier;
import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler; import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.ScannerProperties; import org.sonar.scanner.bootstrap.ScannerProperties;
import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.springframework.context.annotation.Bean;


public class ProjectRepositoriesSupplier implements Supplier<ProjectRepositories> {
private static final Logger LOG = Loggers.get(ProjectRepositoriesSupplier.class);
public class ProjectRepositoriesProvider {
private static final Logger LOG = Loggers.get(ProjectRepositoriesProvider.class);
private static final String LOG_MSG = "Load project repositories"; private static final String LOG_MSG = "Load project repositories";
private final ProjectRepositoriesLoader loader; private final ProjectRepositoriesLoader loader;
private final ScannerProperties scannerProperties; private final ScannerProperties scannerProperties;
private final BranchConfiguration branchConfig; private final BranchConfiguration branchConfig;


private ProjectRepositories project = null;

public ProjectRepositoriesSupplier(ProjectRepositoriesLoader loader, ScannerProperties scannerProperties, BranchConfiguration branchConfig) {
public ProjectRepositoriesProvider(ProjectRepositoriesLoader loader, ScannerProperties scannerProperties, BranchConfiguration branchConfig) {
this.loader = loader; this.loader = loader;
this.scannerProperties = scannerProperties; this.scannerProperties = scannerProperties;
this.branchConfig = branchConfig; this.branchConfig = branchConfig;
} }


public ProjectRepositories get() {
if (project == null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
project = loader.load(scannerProperties.getProjectKey(), branchConfig.referenceBranchName());
profiler.stopInfo();
}

@Bean
public ProjectRepositories projectRepositories() {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
ProjectRepositories project = loader.load(scannerProperties.getProjectKey(), branchConfig.referenceBranchName());
profiler.stopInfo();
return project; return project;
} }
} }

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java ファイルの表示

import org.sonar.scanner.repository.ContextPropertiesCache; import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader; import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader;
import org.sonar.scanner.repository.DefaultQualityProfileLoader; import org.sonar.scanner.repository.DefaultQualityProfileLoader;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.ProjectRepositoriesProvider;
import org.sonar.scanner.repository.QualityProfilesProvider; import org.sonar.scanner.repository.QualityProfilesProvider;
import org.sonar.scanner.repository.ReferenceBranchSupplier; import org.sonar.scanner.repository.ReferenceBranchSupplier;
import org.sonar.scanner.repository.language.DefaultLanguagesRepository; import org.sonar.scanner.repository.language.DefaultLanguagesRepository;
new BranchConfigurationProvider(), new BranchConfigurationProvider(),
new ProjectBranchesProvider(), new ProjectBranchesProvider(),
new ProjectPullRequestsProvider(), new ProjectPullRequestsProvider(),
ProjectRepositoriesSupplier.class,
ProjectRepositoriesProvider.class,
new ProjectServerSettingsProvider(), new ProjectServerSettingsProvider(),
AnalysisCacheEnabled.class, AnalysisCacheEnabled.class,



+ 5
- 5
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java ファイルの表示

import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.FileData;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.ProjectRepositories;
import org.sonar.scanner.scm.ScmChangedFiles; import org.sonar.scanner.scm.ScmChangedFiles;


import static org.sonar.api.batch.fs.InputFile.Status.ADDED; import static org.sonar.api.batch.fs.InputFile.Status.ADDED;


@Immutable @Immutable
public class StatusDetection { public class StatusDetection {
private final ProjectRepositoriesSupplier projectSettingsSupplier;
private final ProjectRepositories projectRepositories;
private final ScmChangedFiles scmChangedFiles; private final ScmChangedFiles scmChangedFiles;


public StatusDetection(ProjectRepositoriesSupplier projectSettingsSupplier, ScmChangedFiles scmChangedFiles) {
this.projectSettingsSupplier = projectSettingsSupplier;
public StatusDetection(ProjectRepositories projectRepositories, ScmChangedFiles scmChangedFiles) {
this.projectRepositories = projectRepositories;
this.scmChangedFiles = scmChangedFiles; this.scmChangedFiles = scmChangedFiles;
} }


} }


private InputFile.Status checkChangedWithProjectRepositories(String moduleKeyWithBranch, DefaultInputFile inputFile, String hash) { private InputFile.Status checkChangedWithProjectRepositories(String moduleKeyWithBranch, DefaultInputFile inputFile, String hash) {
FileData fileDataPerPath = projectSettingsSupplier.get().fileData(moduleKeyWithBranch, inputFile);
FileData fileDataPerPath = projectRepositories.fileData(moduleKeyWithBranch, inputFile);
if (fileDataPerPath == null) { if (fileDataPerPath == null) {
return ADDED; return ADDED;
} }

+ 5
- 5
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java ファイルの表示

import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.protocol.output.ScannerReportWriter;
import org.sonar.scanner.report.ReportPublisher; import org.sonar.scanner.report.ReportPublisher;
import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.FileData;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.ProjectRepositories;
import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.InputComponentStore; import org.sonar.scanner.scan.filesystem.InputComponentStore;


private static final Logger LOG = Loggers.get(ScmPublisher.class); private static final Logger LOG = Loggers.get(ScmPublisher.class);


private final ScmConfiguration configuration; private final ScmConfiguration configuration;
private final ProjectRepositoriesSupplier projectRepositoriesSupplier;
private final ProjectRepositories projectRepositories;
private final InputComponentStore componentStore; private final InputComponentStore componentStore;
private final FileSystem fs; private final FileSystem fs;
private final ScannerReportWriter writer; private final ScannerReportWriter writer;
private AnalysisWarnings analysisWarnings; private AnalysisWarnings analysisWarnings;
private final BranchConfiguration branchConfiguration; private final BranchConfiguration branchConfiguration;


public ScmPublisher(ScmConfiguration configuration, ProjectRepositoriesSupplier projectRepositoriesSupplier, InputComponentStore componentStore, FileSystem fs,
public ScmPublisher(ScmConfiguration configuration, ProjectRepositories projectRepositories, InputComponentStore componentStore, FileSystem fs,
ReportPublisher reportPublisher, BranchConfiguration branchConfiguration, AnalysisWarnings analysisWarnings) { ReportPublisher reportPublisher, BranchConfiguration branchConfiguration, AnalysisWarnings analysisWarnings) {
this.configuration = configuration; this.configuration = configuration;
this.projectRepositoriesSupplier = projectRepositoriesSupplier;
this.projectRepositories = projectRepositories;
this.componentStore = componentStore; this.componentStore = componentStore;
this.fs = fs; this.fs = fs;
this.branchConfiguration = branchConfiguration; this.branchConfiguration = branchConfiguration;
if (configuration.forceReloadAll() || f.status() != Status.SAME) { if (configuration.forceReloadAll() || f.status() != Status.SAME) {
addIfNotEmpty(filesToBlame, f); addIfNotEmpty(filesToBlame, f);
} else if (!branchConfiguration.isPullRequest()) { } else if (!branchConfiguration.isPullRequest()) {
FileData fileData = projectRepositoriesSupplier.get().fileData(componentStore.findModule(f).key(), f);
FileData fileData = projectRepositories.fileData(componentStore.findModule(f).key(), f);
if (fileData == null || StringUtils.isEmpty(fileData.revision())) { if (fileData == null || StringUtils.isEmpty(fileData.revision())) {
addIfNotEmpty(filesToBlame, f); addIfNotEmpty(filesToBlame, f);
} else { } else {

sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesSupplierTest.java → sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java ファイルの表示

import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;


public class ProjectRepositoriesSupplierTest {
private ProjectRepositoriesSupplier underTest;
public class ProjectRepositoriesProviderTest {
private ProjectRepositoriesProvider underTest;
private ProjectRepositories project; private ProjectRepositories project;


private ProjectRepositoriesLoader loader = mock(ProjectRepositoriesLoader.class);
private ScannerProperties props = mock(ScannerProperties.class);
private BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
private final ProjectRepositoriesLoader loader = mock(ProjectRepositoriesLoader.class);
private final ScannerProperties props = mock(ScannerProperties.class);
private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);


@Before @Before
public void setUp() { public void setUp() {
underTest = new ProjectRepositoriesSupplier(loader, props, branchConfiguration);
underTest = new ProjectRepositoriesProvider(loader, props, branchConfiguration);
Map<String, FileData> fileMap = emptyMap(); Map<String, FileData> fileMap = emptyMap();
project = new SingleProjectRepository(fileMap); project = new SingleProjectRepository(fileMap);
when(props.getProjectKey()).thenReturn("key"); when(props.getProjectKey()).thenReturn("key");
@Test @Test
public void testValidation() { public void testValidation() {
when(loader.load(eq("key"), any())).thenReturn(project); when(loader.load(eq("key"), any())).thenReturn(project);
underTest.get();
assertThat(underTest.projectRepositories()).isEqualTo(project);
} }


@Test @Test
public void testAssociated() { public void testAssociated() {
when(loader.load(eq("key"), any())).thenReturn(project); when(loader.load(eq("key"), any())).thenReturn(project);
ProjectRepositories repo = underTest.get();
ProjectRepositories repo = underTest.projectRepositories();


assertThat(repo.exists()).isTrue(); assertThat(repo.exists()).isTrue();


verify(props).getProjectKey(); verify(props).getProjectKey();
verify(loader).load(eq("key"), eq(null));
verify(loader).load("key", null);
verifyNoMoreInteractions(loader, props); verifyNoMoreInteractions(loader, props);
} }
} }

+ 5
- 13
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java ファイルの表示

import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.FileData;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.ProjectRepositories;
import org.sonar.scanner.repository.SingleProjectRepository; import org.sonar.scanner.repository.SingleProjectRepository;
import org.sonar.scanner.scm.ScmChangedFiles; import org.sonar.scanner.scm.ScmChangedFiles;


import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


public class StatusDetectionTest { public class StatusDetectionTest {
private ProjectRepositoriesSupplier projectRepositoriesSupplier = mock(ProjectRepositoriesSupplier.class);

@Before
public void setUp() {
when(projectRepositoriesSupplier.get()).thenReturn(new SingleProjectRepository(createFileDataPerPathMap()));
}
private final ProjectRepositories projectRepositories = new SingleProjectRepository(createFileDataPerPathMap());


@Test @Test
public void detect_status() { public void detect_status() {
ScmChangedFiles changedFiles = new ScmChangedFiles(null); ScmChangedFiles changedFiles = new ScmChangedFiles(null);
StatusDetection statusDetection = new StatusDetection(projectRepositoriesSupplier, changedFiles);
StatusDetection statusDetection = new StatusDetection(projectRepositories, changedFiles);


assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "ABCDE")).isEqualTo(InputFile.Status.SAME); 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); assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.CHANGED);
@Test @Test
public void detect_status_branches_exclude() { public void detect_status_branches_exclude() {
ScmChangedFiles changedFiles = new ScmChangedFiles(Collections.emptyList()); ScmChangedFiles changedFiles = new ScmChangedFiles(Collections.emptyList());
StatusDetection statusDetection = new StatusDetection(projectRepositoriesSupplier, changedFiles);
StatusDetection statusDetection = new StatusDetection(projectRepositories, changedFiles);


// normally changed // normally changed
assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.SAME); assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.SAME);
@Test @Test
public void detect_status_branches_confirm() { public void detect_status_branches_confirm() {
ScmChangedFiles changedFiles = new ScmChangedFiles(Collections.singletonList(Paths.get("module", "src", "Foo.java"))); ScmChangedFiles changedFiles = new ScmChangedFiles(Collections.singletonList(Paths.get("module", "src", "Foo.java")));
StatusDetection statusDetection = new StatusDetection(projectRepositoriesSupplier, changedFiles);
StatusDetection statusDetection = new StatusDetection(projectRepositories, changedFiles);


assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.CHANGED); assertThat(statusDetection.status("foo", createFile("src/Foo.java"), "XXXXX")).isEqualTo(InputFile.Status.CHANGED);
} }

読み込み中…
キャンセル
保存