mirror of
https://github.com/SonarSource/sonarqube.git
synced 2024-08-08 14:11:17 +02:00
SONAR-6817 Issues mode should support analysis of projects not associated
This commit is contained in:
parent
84c39f50d5
commit
4be016e61f
@ -0,0 +1,5 @@
|
||||
#sonar.projectKey=sample
|
||||
sonar.projectName=Sample
|
||||
sonar.projectVersion=1.0-SNAPSHOT
|
||||
sonar.sources=src/main/xoo
|
||||
sonar.language=xoo
|
@ -0,0 +1,16 @@
|
||||
package sample;
|
||||
|
||||
public class Sample {
|
||||
|
||||
public Sample(int i) {
|
||||
int j = i++;
|
||||
}
|
||||
|
||||
private String myMethod() {
|
||||
if (foo == bar) {
|
||||
return "hello";
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
ncloc:13
|
||||
#Used by dashboard/widgets tests
|
||||
complexity:3
|
||||
complexity_in_classes:3
|
||||
classes:1
|
||||
comment_lines:3
|
||||
public_api:5
|
||||
public_undocumented_api:2
|
||||
duplicated_files:1
|
||||
duplicated_blocks:2
|
||||
duplicated_lines:3
|
@ -69,28 +69,45 @@ public class IssuesModeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issuesAnalysisOnNewProject() throws IOException {
|
||||
public void issues_analysis_on_new_project() throws IOException {
|
||||
restoreProfile("one-issue-per-line.xml");
|
||||
orchestrator.getServer().provisionProject("sample", "xoo-sample");
|
||||
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
|
||||
SonarRunner runner = configureRunnerIssues("shared/xoo-sample");
|
||||
orchestrator.executeBuild(runner);
|
||||
BuildResult result = orchestrator.executeBuild(runner);
|
||||
assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void invalidIncrementalMode() throws IOException {
|
||||
public void invalid_incremental_mode() throws IOException {
|
||||
restoreProfile("one-issue-per-line.xml");
|
||||
orchestrator.getServer().provisionProject("sample", "xoo-sample");
|
||||
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
|
||||
SonarRunner runner = configureRunner("shared/xoo-sample");
|
||||
runner.setProperty("sonar.analysis.mode", "incremental");
|
||||
|
||||
|
||||
thrown.expect(BuildFailureException.class);
|
||||
BuildResult res = orchestrator.executeBuild(runner);
|
||||
|
||||
|
||||
assertThat(res.getLogs()).contains("Invalid analysis mode: incremental. This mode was removed in SonarQube 5.2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void non_associated_mode() throws IOException {
|
||||
restoreProfile("one-issue-per-line.xml");
|
||||
setDefaultQualityProfile("xoo", "one-issue-per-line");
|
||||
SonarRunner runner = configureRunnerIssues("shared/xoo-sample-non-associated");
|
||||
BuildResult result = orchestrator.executeBuild(runner);
|
||||
|
||||
assertThat(result.getLogs()).contains("is not associated");
|
||||
assertThat(result.getLogs()).contains("Cache not found, synchronizing data");
|
||||
assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
|
||||
|
||||
result = orchestrator.executeBuild(runner);
|
||||
assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
|
||||
assertThat(result.getLogs()).contains("Found cache");
|
||||
}
|
||||
|
||||
// SONAR-5715
|
||||
@Test
|
||||
public void test_issues_mode_on_project_with_space_in_filename() throws IOException {
|
||||
@ -329,16 +346,16 @@ public class IssuesModeTest {
|
||||
boolean expectedError = false;
|
||||
for (Future<BuildResult> result : executorService.invokeAll(tasks)) {
|
||||
try {
|
||||
result.get();
|
||||
} catch(ExecutionException e) {
|
||||
if(e.getCause() instanceof BuildFailureException) {
|
||||
result.get();
|
||||
} catch (ExecutionException e) {
|
||||
if (e.getCause() instanceof BuildFailureException) {
|
||||
BuildFailureException bfe = (BuildFailureException) e.getCause();
|
||||
assertThat(bfe.getResult().getLogs()).contains("Another SonarQube analysis is already in progress for this project");
|
||||
expectedError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!expectedError) {
|
||||
if (!expectedError) {
|
||||
fail("At least one of the threads should have failed");
|
||||
}
|
||||
}
|
||||
@ -370,4 +387,10 @@ public class IssuesModeTest {
|
||||
return runner;
|
||||
}
|
||||
|
||||
private void setDefaultQualityProfile(String languageKey, String profileName) {
|
||||
orchestrator.getServer().adminWsClient().post("api/qualityprofiles/set_default",
|
||||
"language", languageKey,
|
||||
"profileName", profileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ public class ProjectRepositories {
|
||||
public Map<String, String> settings(String moduleKey) {
|
||||
return settingsByModule.containsKey(moduleKey) ? settingsByModule.get(moduleKey) : Collections.<String, String>emptyMap();
|
||||
}
|
||||
|
||||
public Map<String, Map<String, String>> settings() {
|
||||
return settingsByModule;
|
||||
}
|
||||
|
||||
public ProjectRepositories addSettings(String moduleKey, Map<String, String> settings) {
|
||||
Map<String, String> existingSettings = settingsByModule.get(moduleKey);
|
||||
|
@ -38,6 +38,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DefaultAnalysisMode.class);
|
||||
|
||||
private boolean mediumTestMode;
|
||||
private boolean notAssociated;
|
||||
|
||||
public DefaultAnalysisMode(GlobalProperties globalProps, AnalysisProperties props) {
|
||||
init(globalProps.properties(), props.properties());
|
||||
@ -47,6 +48,10 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
|
||||
return mediumTestMode;
|
||||
}
|
||||
|
||||
public boolean isNotAssociated() {
|
||||
return notAssociated;
|
||||
}
|
||||
|
||||
private void init(Map<String, String> globalProps, Map<String, String> analysisProps) {
|
||||
// make sure analysis is consistent with global properties
|
||||
boolean globalPreview = isIssues(globalProps);
|
||||
@ -64,6 +69,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
|
||||
validate(mode);
|
||||
issues = CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode) || CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode);
|
||||
mediumTestMode = "true".equals(getPropertyWithFallback(analysisProps, globalProps, FakePluginInstaller.MEDIUM_TEST_ENABLED));
|
||||
notAssociated = issues && rootProjectKeyMissing(analysisProps);
|
||||
}
|
||||
|
||||
public void printMode() {
|
||||
@ -77,6 +83,9 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
|
||||
if (mediumTestMode) {
|
||||
LOG.info("Medium test mode");
|
||||
}
|
||||
if (notAssociated) {
|
||||
LOG.info("Project is not associated with the server");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPropertyWithFallback(Map<String, String> props1, Map<String, String> props2, String key) {
|
||||
@ -93,4 +102,9 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
|
||||
return CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode);
|
||||
}
|
||||
|
||||
private static boolean rootProjectKeyMissing(Map<String, String> props) {
|
||||
// ProjectReactorBuilder depends on this class, so it will only create this property later
|
||||
return !props.containsKey(CoreProperties.PROJECT_KEY_PROPERTY);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -123,14 +123,22 @@ public class GlobalContainer extends ComponentContainer {
|
||||
public void executeAnalysis(Map<String, String> analysisProperties, Object... components) {
|
||||
AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
|
||||
if (isIssuesMode(props)) {
|
||||
new ProjectSyncContainer(this, props, false).execute();
|
||||
String projectKey = getProjectKeyWithBranch(props);
|
||||
new ProjectSyncContainer(this, projectKey, false).execute();
|
||||
}
|
||||
new ProjectScanContainer(this, props, components).execute();
|
||||
}
|
||||
|
||||
public void syncProject(Map<String, String> analysisProperties, boolean force) {
|
||||
AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
|
||||
new ProjectSyncContainer(this, props, force).execute();
|
||||
private static String getProjectKeyWithBranch(AnalysisProperties props) {
|
||||
String projectKey = props.property(CoreProperties.PROJECT_KEY_PROPERTY);
|
||||
if (projectKey != null && props.property(CoreProperties.PROJECT_BRANCH_PROPERTY) != null) {
|
||||
projectKey = projectKey + ":" + props.property(CoreProperties.PROJECT_BRANCH_PROPERTY);
|
||||
}
|
||||
return projectKey;
|
||||
}
|
||||
|
||||
public void syncProject(String projectKey, boolean force) {
|
||||
new ProjectSyncContainer(this, projectKey, force).execute();
|
||||
}
|
||||
|
||||
private boolean isIssuesMode(AnalysisProperties props) {
|
||||
|
@ -19,6 +19,9 @@
|
||||
*/
|
||||
package org.sonar.batch.bootstrap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
@ -27,10 +30,13 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
@ -55,8 +61,8 @@ import org.sonar.core.util.DefaultHttpDownloader;
|
||||
*/
|
||||
@BatchSide
|
||||
public class ServerClient {
|
||||
|
||||
private static final String GET = "GET";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ServerClient.class);
|
||||
private GlobalProperties props;
|
||||
private DefaultHttpDownloader.BaseHttpDownloader downloader;
|
||||
|
||||
@ -68,6 +74,20 @@ public class ServerClient {
|
||||
public String getURL() {
|
||||
return StringUtils.removeEnd(StringUtils.defaultIfBlank(props.property("sonar.host.url"), "http://localhost:9000"), "/");
|
||||
}
|
||||
|
||||
public String getServerVersion() {
|
||||
InputStream is = this.getClass().getClassLoader().getResourceAsStream("sq-version.txt");
|
||||
if (is == null) {
|
||||
LOG.warn("Failed to get SQ version");
|
||||
return null;
|
||||
}
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
return br.readLine();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Failed to get SQ version", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public URI getURI(String pathStartingWithSlash) {
|
||||
Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /: " + pathStartingWithSlash);
|
||||
|
@ -19,9 +19,6 @@
|
||||
*/
|
||||
package org.sonar.batch.bootstrapper;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.sonar.api.CoreProperties;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@ -134,8 +131,7 @@ public final class Batch {
|
||||
*/
|
||||
public Batch syncProject(String projectKey) {
|
||||
checkStarted();
|
||||
Map<String, String> props = ImmutableMap.of(CoreProperties.PROJECT_KEY_PROPERTY, projectKey);
|
||||
bootstrapContainer.syncProject(props, true);
|
||||
bootstrapContainer.syncProject(projectKey, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.sonar.batch.bootstrap.ServerClient;
|
||||
import org.sonar.home.cache.PersistentCache;
|
||||
|
||||
@ -40,7 +42,7 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(String projectKey) {
|
||||
public void save(@Nullable String projectKey) {
|
||||
Date now = new Date();
|
||||
|
||||
try {
|
||||
@ -55,7 +57,7 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String projectKey) {
|
||||
public void delete(@Nullable String projectKey) {
|
||||
try {
|
||||
cache.put(getKey(projectKey), new byte[0]);
|
||||
} catch (IOException e) {
|
||||
@ -64,7 +66,7 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getSyncStatus(String projectKey) {
|
||||
public Date getSyncStatus(@Nullable String projectKey) {
|
||||
try {
|
||||
byte[] status = cache.get(getKey(projectKey), null);
|
||||
if (status == null || status.length == 0) {
|
||||
@ -79,7 +81,11 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey(String projectKey) {
|
||||
return STATUS_PREFIX + client.getURL() + "-" + projectKey;
|
||||
private String getKey(@Nullable String projectKey) {
|
||||
if (projectKey != null) {
|
||||
return STATUS_PREFIX + client.getURL() + "-" + client.getServerVersion() + "-" + projectKey;
|
||||
} else {
|
||||
return STATUS_PREFIX + client.getURL() + "-" + client.getServerVersion();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
92
sonar-batch/src/main/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizer.java
vendored
Normal file
92
sonar-batch/src/main/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizer.java
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import org.sonar.batch.rule.ActiveRulesLoader;
|
||||
import org.sonar.batch.repository.QualityProfileLoader;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
import org.sonar.api.utils.log.Loggers;
|
||||
import org.sonar.api.utils.log.Profiler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class NonAssociatedCacheSynchronizer {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NonAssociatedCacheSynchronizer.class);
|
||||
|
||||
private ProjectCacheStatus cacheStatus;
|
||||
private QualityProfileLoader qualityProfileLoader;
|
||||
private ActiveRulesLoader activeRulesLoader;
|
||||
|
||||
public NonAssociatedCacheSynchronizer(QualityProfileLoader qualityProfileLoader, ActiveRulesLoader activeRulesLoader, ProjectCacheStatus cacheStatus) {
|
||||
this.qualityProfileLoader = qualityProfileLoader;
|
||||
this.activeRulesLoader = activeRulesLoader;
|
||||
this.cacheStatus = cacheStatus;
|
||||
}
|
||||
|
||||
public void execute(boolean force) {
|
||||
Date lastSync = cacheStatus.getSyncStatus(null);
|
||||
|
||||
if (lastSync != null) {
|
||||
if (!force) {
|
||||
LOG.info("Found cache [{}]", lastSync);
|
||||
return;
|
||||
} else {
|
||||
LOG.info("-- Found cache [{}], synchronizing data..", lastSync);
|
||||
}
|
||||
cacheStatus.delete(null);
|
||||
} else {
|
||||
LOG.info("-- Cache not found, synchronizing data..");
|
||||
}
|
||||
|
||||
loadData();
|
||||
saveStatus();
|
||||
}
|
||||
|
||||
private static Collection<String> getKeys(Collection<QProfile> qProfiles) {
|
||||
List<String> list = new ArrayList<>(qProfiles.size());
|
||||
for (QProfile qp : qProfiles) {
|
||||
list.add(qp.key());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void saveStatus() {
|
||||
cacheStatus.save(null);
|
||||
LOG.info("-- Succesfully synchronized cache");
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
Profiler profiler = Profiler.create(Loggers.get(ProjectCacheSynchronizer.class));
|
||||
|
||||
profiler.startInfo("Load default quality profiles");
|
||||
Collection<QProfile> qProfiles = qualityProfileLoader.load(null, null);
|
||||
profiler.stopInfo();
|
||||
|
||||
profiler.startInfo("Load default active rules");
|
||||
activeRulesLoader.load(getKeys(qProfiles), null);
|
||||
profiler.stopInfo();
|
||||
}
|
||||
}
|
@ -49,14 +49,14 @@ public class PersistentCacheProvider extends ProviderAdapter {
|
||||
builder.setSonarHome(Paths.get(home));
|
||||
}
|
||||
|
||||
builder.setVersion(getVersion());
|
||||
builder.setVersion(getServerVersion());
|
||||
cache = builder.build();
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
private String getServerVersion() {
|
||||
InputStream is = this.getClass().getClassLoader().getResourceAsStream("sq-version.txt");
|
||||
if (is == null) {
|
||||
LOG.warn("Failed to get SQ version");
|
||||
|
@ -19,12 +19,14 @@
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface ProjectCacheStatus {
|
||||
void save(String projectKey);
|
||||
void save(@Nullable String projectKey);
|
||||
|
||||
void delete(String projectKey);
|
||||
void delete(@Nullable String projectKey);
|
||||
|
||||
Date getSyncStatus(String projectKey);
|
||||
Date getSyncStatus(@Nullable String projectKey);
|
||||
}
|
||||
|
@ -19,100 +19,98 @@
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import com.google.common.base.Function;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.sonar.api.utils.log.Loggers;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonar.api.utils.log.Loggers;
|
||||
import org.sonar.api.utils.log.Profiler;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
|
||||
import com.google.common.base.Function;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
import org.sonar.batch.repository.ProjectSettingsLoader;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
import org.sonar.batch.repository.QualityProfileLoader;
|
||||
import org.sonar.batch.repository.ServerIssuesLoader;
|
||||
import org.sonar.batch.repository.user.UserRepositoryLoader;
|
||||
import org.sonar.batch.rule.ActiveRulesLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.batch.repository.user.UserRepositoryLoader;
|
||||
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
|
||||
import org.sonar.batch.repository.ServerIssuesLoader;
|
||||
import org.sonar.batch.repository.ProjectRepositoriesLoader;
|
||||
|
||||
public class ProjectCacheSynchronizer {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ProjectCacheSynchronizer.class);
|
||||
private static final int NUM_THREAD = 2;
|
||||
|
||||
private final ProjectDefinition project;
|
||||
private final AnalysisProperties properties;
|
||||
private final ProjectRepositoriesLoader projectRepositoryLoader;
|
||||
private final ServerIssuesLoader issuesLoader;
|
||||
private final ServerLineHashesLoader lineHashesLoader;
|
||||
private final UserRepositoryLoader userRepository;
|
||||
private final ProjectCacheStatus cacheStatus;
|
||||
private final QualityProfileLoader qualityProfileLoader;
|
||||
private final ProjectSettingsLoader projectSettingsLoader;
|
||||
private final ActiveRulesLoader activeRulesLoader;
|
||||
|
||||
public ProjectCacheSynchronizer(ProjectReactor project, ProjectRepositoriesLoader projectRepositoryLoader, AnalysisProperties properties,
|
||||
ServerIssuesLoader issuesLoader, ServerLineHashesLoader lineHashesLoader, UserRepositoryLoader userRepository, ProjectCacheStatus cacheStatus) {
|
||||
this.project = project.getRoot();
|
||||
this.projectRepositoryLoader = projectRepositoryLoader;
|
||||
this.properties = properties;
|
||||
public ProjectCacheSynchronizer(QualityProfileLoader qualityProfileLoader, ProjectSettingsLoader projectSettingsLoader,
|
||||
ActiveRulesLoader activeRulesLoader, ServerIssuesLoader issuesLoader,
|
||||
UserRepositoryLoader userRepository, ProjectCacheStatus cacheStatus) {
|
||||
this.qualityProfileLoader = qualityProfileLoader;
|
||||
this.projectSettingsLoader = projectSettingsLoader;
|
||||
this.activeRulesLoader = activeRulesLoader;
|
||||
this.issuesLoader = issuesLoader;
|
||||
this.lineHashesLoader = lineHashesLoader;
|
||||
this.userRepository = userRepository;
|
||||
this.cacheStatus = cacheStatus;
|
||||
}
|
||||
|
||||
public void load(boolean force) {
|
||||
Date lastSync = cacheStatus.getSyncStatus(project.getKeyWithBranch());
|
||||
public void load(String projectKey, boolean force) {
|
||||
Date lastSync = cacheStatus.getSyncStatus(projectKey);
|
||||
|
||||
if (lastSync != null) {
|
||||
if (!force) {
|
||||
LOG.info("Found project [{}] cache [{}]", project.getKeyWithBranch(), lastSync);
|
||||
LOG.info("Found project [{}] cache [{}]", projectKey, lastSync);
|
||||
return;
|
||||
} else {
|
||||
LOG.info("-- Found project [{}] cache [{}], synchronizing data..", project.getKeyWithBranch(), lastSync);
|
||||
LOG.info("-- Found project [{}] cache [{}], synchronizing data..", projectKey, lastSync);
|
||||
}
|
||||
cacheStatus.delete(project.getKeyWithBranch());
|
||||
cacheStatus.delete(projectKey);
|
||||
} else {
|
||||
LOG.info("-- Cache for project [{}] not found, synchronizing data..", project.getKeyWithBranch());
|
||||
LOG.info("-- Cache for project [{}] not found, synchronizing data..", projectKey);
|
||||
}
|
||||
|
||||
loadData();
|
||||
saveStatus();
|
||||
loadData(projectKey);
|
||||
saveStatus(projectKey);
|
||||
}
|
||||
|
||||
private void saveStatus() {
|
||||
cacheStatus.save(project.getKeyWithBranch());
|
||||
private void saveStatus(String projectKey) {
|
||||
cacheStatus.save(projectKey);
|
||||
LOG.info("-- Succesfully synchronized project cache");
|
||||
}
|
||||
|
||||
private static String getComponentKey(String moduleKey, String filePath) {
|
||||
return moduleKey + ":" + filePath;
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
private void loadData(String projectKey) {
|
||||
Profiler profiler = Profiler.create(Loggers.get(ProjectCacheSynchronizer.class));
|
||||
|
||||
profiler.startInfo("Load project repository");
|
||||
ProjectRepositories projectRepo = projectRepositoryLoader.load(project, properties, null);
|
||||
profiler.startInfo("Load project settings");
|
||||
ProjectSettingsRepo settings = projectSettingsLoader.load(projectKey, null);
|
||||
profiler.stopInfo();
|
||||
|
||||
if (projectRepo.lastAnalysisDate() == null) {
|
||||
if (settings.lastAnalysisDate() == null) {
|
||||
LOG.debug("No previous analysis found");
|
||||
return;
|
||||
}
|
||||
|
||||
profiler.startInfo("Load project quality profiles");
|
||||
Collection<QProfile> qProfiles = qualityProfileLoader.load(projectKey, null);
|
||||
profiler.stopInfo();
|
||||
|
||||
Collection<String> profileKeys = getKeys(qProfiles);
|
||||
|
||||
profiler.startInfo("Load project active rules");
|
||||
activeRulesLoader.load(profileKeys, projectKey);
|
||||
profiler.stopInfo();
|
||||
|
||||
profiler.startInfo("Load server issues");
|
||||
UserLoginAccumulator consumer = new UserLoginAccumulator();
|
||||
issuesLoader.load(project.getKeyWithBranch(), consumer);
|
||||
issuesLoader.load(projectKey, consumer);
|
||||
profiler.stopInfo();
|
||||
|
||||
profiler.startInfo("Load user information (" + consumer.loginSet.size() + " users)");
|
||||
@ -120,56 +118,15 @@ public class ProjectCacheSynchronizer {
|
||||
userRepository.load(login, null);
|
||||
}
|
||||
profiler.stopInfo("Load user information");
|
||||
|
||||
loadLineHashes(projectRepo.fileDataByModuleAndPath(), profiler);
|
||||
}
|
||||
|
||||
private void loadLineHashes(Map<String, Map<String, FileData>> fileDataByModuleAndPath, Profiler profiler) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(NUM_THREAD);
|
||||
int numFiles = 0;
|
||||
|
||||
for (Map<String, FileData> fileDataByPath : fileDataByModuleAndPath.values()) {
|
||||
numFiles += fileDataByPath.size();
|
||||
}
|
||||
profiler.startInfo("Load line file hashes (" + numFiles + " files)");
|
||||
|
||||
for (Entry<String, Map<String, FileData>> e1 : fileDataByModuleAndPath.entrySet()) {
|
||||
String moduleKey = e1.getKey();
|
||||
|
||||
for (Entry<String, FileData> e2 : e1.getValue().entrySet()) {
|
||||
String filePath = e2.getKey();
|
||||
executor.submit(new LineHashLoadWorker(getComponentKey(moduleKey, filePath)));
|
||||
}
|
||||
private static Collection<String> getKeys(Collection<QProfile> qProfiles) {
|
||||
List<String> list = new ArrayList<>(qProfiles.size());
|
||||
for (QProfile qp : qProfiles) {
|
||||
list.add(qp.key());
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
|
||||
try {
|
||||
boolean done = executor.awaitTermination(30, TimeUnit.MINUTES);
|
||||
if (!done) {
|
||||
executor.shutdownNow();
|
||||
throw new IllegalStateException("Timeout while fetching line hashes");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
throw new IllegalStateException("Interrupted while fetching line hashes", e);
|
||||
}
|
||||
|
||||
profiler.stopInfo("Load line file hashes (done)");
|
||||
}
|
||||
|
||||
private class LineHashLoadWorker implements Callable<Void> {
|
||||
private String fileKey;
|
||||
|
||||
LineHashLoadWorker(String fileKey) {
|
||||
this.fileKey = fileKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
lineHashesLoader.getLineHashes(fileKey, null);
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static class UserLoginAccumulator implements Function<ServerIssue, Void> {
|
||||
|
@ -19,59 +19,73 @@
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.batch.repository.ProjectRepositoriesFactoryProvider;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.cache.WSLoader.LoadStrategy;
|
||||
import org.sonar.api.CoreProperties;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.sonar.batch.bootstrap.GlobalProperties;
|
||||
import org.sonar.batch.repository.ProjectSettingsLoader;
|
||||
import org.sonar.batch.repository.DefaultProjectSettingsLoader;
|
||||
import org.sonar.batch.rule.ActiveRulesLoader;
|
||||
import org.sonar.batch.rule.DefaultActiveRulesLoader;
|
||||
import org.sonar.batch.repository.QualityProfileLoader;
|
||||
import org.sonar.batch.repository.DefaultQualityProfileLoader;
|
||||
import org.sonar.batch.cache.WSLoader.LoadStrategy;
|
||||
import org.sonar.batch.repository.user.UserRepositoryLoader;
|
||||
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
|
||||
import org.sonar.batch.repository.DefaultProjectRepositoriesLoader;
|
||||
import org.sonar.batch.repository.DefaultServerIssuesLoader;
|
||||
import org.sonar.batch.repository.ProjectRepositoriesLoader;
|
||||
import org.sonar.batch.repository.ServerIssuesLoader;
|
||||
import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader;
|
||||
import org.sonar.core.platform.ComponentContainer;
|
||||
|
||||
public class ProjectSyncContainer extends ComponentContainer {
|
||||
private final boolean force;
|
||||
private final AnalysisProperties properties;
|
||||
private final String projectKey;
|
||||
|
||||
public ProjectSyncContainer(ComponentContainer globalContainer, AnalysisProperties analysisProperties, boolean force) {
|
||||
public ProjectSyncContainer(ComponentContainer globalContainer, String projectKey, boolean force) {
|
||||
super(globalContainer);
|
||||
this.properties = analysisProperties;
|
||||
this.projectKey = projectKey;
|
||||
this.force = force;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBeforeStart() {
|
||||
ProjectReactor projectReactor = createProjectReactor();
|
||||
add(projectReactor);
|
||||
addComponents();
|
||||
}
|
||||
|
||||
private ProjectReactor createProjectReactor() {
|
||||
ProjectDefinition rootProjectDefinition = ProjectDefinition.create();
|
||||
rootProjectDefinition.setProperties(properties.properties());
|
||||
return new ProjectReactor(rootProjectDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterStart() {
|
||||
getComponentByType(ProjectCacheSynchronizer.class).load(force);
|
||||
if (projectKey != null) {
|
||||
getComponentByType(ProjectCacheSynchronizer.class).load(projectKey, force);
|
||||
} else {
|
||||
getComponentByType(NonAssociatedCacheSynchronizer.class).execute(force);
|
||||
}
|
||||
}
|
||||
|
||||
private static DefaultAnalysisMode createIssuesAnalisysMode() {
|
||||
Map<String, String> props = ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES);
|
||||
GlobalProperties globalProps = new GlobalProperties(props);
|
||||
AnalysisProperties analysisProps = new AnalysisProperties(props);
|
||||
return new DefaultAnalysisMode(globalProps, analysisProps);
|
||||
}
|
||||
|
||||
private void addComponents() {
|
||||
add(new StrategyWSLoaderProvider(LoadStrategy.SERVER_FIRST),
|
||||
properties,
|
||||
DefaultAnalysisMode.class,
|
||||
ProjectCacheSynchronizer.class,
|
||||
UserRepositoryLoader.class);
|
||||
add(new StrategyWSLoaderProvider(LoadStrategy.SERVER_ONLY),
|
||||
projectKey != null ? ProjectCacheSynchronizer.class : NonAssociatedCacheSynchronizer.class,
|
||||
UserRepositoryLoader.class,
|
||||
new ProjectRepositoriesFactoryProvider(projectKey),
|
||||
createIssuesAnalisysMode());
|
||||
|
||||
addIfMissing(DefaultProjectCacheStatus.class, ProjectCacheStatus.class);
|
||||
addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
|
||||
addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class);
|
||||
addIfMissing(DefaultServerLineHashesLoader.class, ServerLineHashesLoader.class);
|
||||
addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class);
|
||||
addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class);
|
||||
addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,13 +51,13 @@ public class WSLoader {
|
||||
SERVER_FIRST, CACHE_FIRST, SERVER_ONLY, CACHE_ONLY;
|
||||
}
|
||||
|
||||
private final LoadStrategy loadStrategy;
|
||||
private final LoadStrategy defautLoadStrategy;
|
||||
private ServerStatus serverStatus;
|
||||
private final ServerClient client;
|
||||
private final PersistentCache cache;
|
||||
|
||||
public WSLoader(LoadStrategy strategy, PersistentCache cache, ServerClient client) {
|
||||
this.loadStrategy = strategy;
|
||||
this.defautLoadStrategy = strategy;
|
||||
this.serverStatus = UNKNOWN;
|
||||
this.cache = cache;
|
||||
this.client = client;
|
||||
@ -65,19 +65,28 @@ public class WSLoader {
|
||||
|
||||
@Nonnull
|
||||
public WSLoaderResult<ByteSource> loadSource(String id) {
|
||||
WSLoaderResult<byte[]> byteResult = load(id);
|
||||
WSLoaderResult<byte[]> byteResult = load(id, defautLoadStrategy);
|
||||
return new WSLoaderResult<ByteSource>(ByteSource.wrap(byteResult.get()), byteResult.isFromCache());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public WSLoaderResult<String> loadString(String id) {
|
||||
WSLoaderResult<byte[]> byteResult = load(id);
|
||||
return loadString(id, defautLoadStrategy);
|
||||
}
|
||||
@Nonnull
|
||||
public WSLoaderResult<String> loadString(String id, WSLoader.LoadStrategy strategy) {
|
||||
WSLoaderResult<byte[]> byteResult = load(id, strategy);
|
||||
return new WSLoaderResult<String>(new String(byteResult.get(), StandardCharsets.UTF_8), byteResult.isFromCache());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public WSLoaderResult<byte[]> load(String id) {
|
||||
switch (loadStrategy) {
|
||||
return load(id, defautLoadStrategy);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public WSLoaderResult<byte[]> load(String id, WSLoader.LoadStrategy strategy) {
|
||||
switch (strategy) {
|
||||
case CACHE_FIRST:
|
||||
return loadFromCacheFirst(id, true);
|
||||
case CACHE_ONLY:
|
||||
@ -91,7 +100,7 @@ public class WSLoader {
|
||||
}
|
||||
|
||||
public LoadStrategy getStrategy() {
|
||||
return this.loadStrategy;
|
||||
return this.defautLoadStrategy;
|
||||
}
|
||||
|
||||
private void switchToOffline() {
|
||||
|
@ -19,8 +19,9 @@
|
||||
*/
|
||||
package org.sonar.batch.issue.tracking;
|
||||
|
||||
import org.sonar.batch.cache.WSLoaderResult;
|
||||
import org.sonar.batch.cache.WSLoader.LoadStrategy;
|
||||
|
||||
import org.sonar.batch.cache.WSLoaderResult;
|
||||
import org.sonar.batch.cache.WSLoader;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
|
||||
@ -50,7 +51,7 @@ public class DefaultServerLineHashesLoader implements ServerLineHashesLoader {
|
||||
Profiler profiler = Profiler.createIfDebug(Loggers.get(getClass()))
|
||||
.addContext("file", fileKey)
|
||||
.startDebug("Load line hashes");
|
||||
WSLoaderResult<String> result = wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey));
|
||||
WSLoaderResult<String> result = wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey), LoadStrategy.CACHE_FIRST);
|
||||
try {
|
||||
if (fromCache != null) {
|
||||
fromCache.setValue(result.isFromCache());
|
||||
|
@ -19,16 +19,22 @@
|
||||
*/
|
||||
package org.sonar.batch.issue.tracking;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
|
||||
import org.sonar.api.batch.BatchSide;
|
||||
import org.sonar.api.batch.fs.internal.DefaultInputFile;
|
||||
import org.sonar.api.batch.rule.ActiveRule;
|
||||
@ -41,7 +47,6 @@ import org.sonar.api.utils.KeyValueFormat;
|
||||
import org.sonar.batch.index.BatchComponent;
|
||||
import org.sonar.batch.index.BatchComponentCache;
|
||||
import org.sonar.batch.issue.IssueCache;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.protocol.output.BatchReport;
|
||||
import org.sonar.batch.protocol.output.BatchReportReader;
|
||||
import org.sonar.batch.report.ReportPublisher;
|
||||
@ -72,7 +77,7 @@ public class LocalIssueTracking {
|
||||
public LocalIssueTracking(BatchComponentCache resourceCache, IssueCache issueCache, IssueTracking tracking,
|
||||
ServerLineHashesLoader lastLineHashes, IssueWorkflow workflow, IssueUpdater updater,
|
||||
ActiveRules activeRules, ServerIssueRepository serverIssueRepository,
|
||||
ProjectRepositories projectRepositories, ReportPublisher reportPublisher) {
|
||||
ProjectSettingsRepo projectRepositories, ReportPublisher reportPublisher, DefaultAnalysisMode mode) {
|
||||
this.componentCache = resourceCache;
|
||||
this.issueCache = issueCache;
|
||||
this.tracking = tracking;
|
||||
@ -84,7 +89,7 @@ public class LocalIssueTracking {
|
||||
this.analysisDate = ((Project) resourceCache.getRoot().resource()).getAnalysisDate();
|
||||
this.changeContext = IssueChangeContext.createScan(analysisDate);
|
||||
this.activeRules = activeRules;
|
||||
this.hasServerAnalysis = projectRepositories.lastAnalysisDate() != null;
|
||||
this.hasServerAnalysis = !mode.isNotAssociated() && projectRepositories.lastAnalysisDate() != null;
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
|
@ -19,29 +19,42 @@
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.picocontainer.injectors.ProviderAdapter;
|
||||
import org.sonar.api.batch.AnalysisMode;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
|
||||
import org.sonar.batch.rule.ModuleQProfiles;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.api.utils.log.Logger;
|
||||
import org.sonar.api.utils.log.Loggers;
|
||||
import org.sonar.api.utils.log.Profiler;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public class ProjectRepositoriesProvider extends ProviderAdapter {
|
||||
|
||||
public class DefaultProjectRepositoriesFactory implements ProjectRepositoriesFactory {
|
||||
private static final String LOG_MSG = "Load project repositories";
|
||||
private static final Logger LOG = Loggers.get(ProjectRepositoriesProvider.class);
|
||||
private static final Logger LOG = Loggers.get(DefaultProjectRepositoriesFactory.class);
|
||||
private static final String NON_EXISTING = "non1-existing2-project3-key";
|
||||
|
||||
private final DefaultAnalysisMode analysisMode;
|
||||
private final ProjectRepositoriesLoader loader;
|
||||
private final AnalysisProperties props;
|
||||
private final ProjectReactor projectReactor;
|
||||
|
||||
private ProjectRepositories projectReferentials;
|
||||
|
||||
public ProjectRepositories provide(ProjectRepositoriesLoader loader, ProjectReactor reactor, AnalysisProperties taskProps, AnalysisMode analysisMode) {
|
||||
public DefaultProjectRepositoriesFactory(ProjectReactor projectReactor, DefaultAnalysisMode analysisMode, ProjectRepositoriesLoader loader, AnalysisProperties props) {
|
||||
this.projectReactor = projectReactor;
|
||||
this.analysisMode = analysisMode;
|
||||
this.loader = loader;
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectRepositories create() {
|
||||
if (projectReferentials == null) {
|
||||
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
|
||||
MutableBoolean fromCache = new MutableBoolean();
|
||||
projectReferentials = loader.load(reactor.getRoot(), taskProps, fromCache);
|
||||
projectReferentials = loader.load(getProjectKey(), getSonarProfile(), fromCache);
|
||||
profiler.stopInfo(fromCache.booleanValue());
|
||||
|
||||
if (analysisMode.isIssues() && projectReferentials.lastAnalysisDate() == null) {
|
||||
@ -50,4 +63,19 @@ public class ProjectRepositoriesProvider extends ProviderAdapter {
|
||||
}
|
||||
return projectReferentials;
|
||||
}
|
||||
|
||||
private String getProjectKey() {
|
||||
if (analysisMode.isNotAssociated()) {
|
||||
return NON_EXISTING;
|
||||
}
|
||||
return projectReactor.getRoot().getKeyWithBranch();
|
||||
}
|
||||
|
||||
private String getSonarProfile() {
|
||||
String profile = null;
|
||||
if (!analysisMode.isIssues()) {
|
||||
profile = props.property(ModuleQProfiles.SONAR_PROFILE_PROP);
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
}
|
@ -23,12 +23,10 @@ import org.sonar.batch.cache.WSLoaderResult;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.cache.WSLoader;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonar.api.utils.MessageException;
|
||||
@ -50,13 +48,12 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectRepositories load(ProjectDefinition projectDefinition, AnalysisProperties taskProperties, @Nullable MutableBoolean fromCache) {
|
||||
String projectKey = projectDefinition.getKeyWithBranch();
|
||||
String url = BATCH_PROJECT_URL + "?key=" + BatchUtils.encodeForUrl(projectKey);
|
||||
if (taskProperties.properties().containsKey(ModuleQProfiles.SONAR_PROFILE_PROP)) {
|
||||
public ProjectRepositories load(String projectKeyWithBranch, @Nullable String sonarProfile, @Nullable MutableBoolean fromCache) {
|
||||
String url = BATCH_PROJECT_URL + "?key=" + BatchUtils.encodeForUrl(projectKeyWithBranch);
|
||||
if (sonarProfile != null) {
|
||||
LOG.warn("Ability to set quality profile from command line using '" + ModuleQProfiles.SONAR_PROFILE_PROP
|
||||
+ "' is deprecated and will be dropped in a future SonarQube version. Please configure quality profile used by your project on SonarQube server.");
|
||||
url += "&profile=" + BatchUtils.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP));
|
||||
url += "&profile=" + BatchUtils.encodeForUrl(sonarProfile);
|
||||
}
|
||||
url += "&preview=" + analysisMode.isIssues();
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public class DefaultProjectSettingsLoader implements ProjectSettingsLoader {
|
||||
private ProjectRepositoriesFactory projectRepositoryFactory;
|
||||
|
||||
public DefaultProjectSettingsLoader(ProjectRepositoriesFactory projectRepositoryFactory) {
|
||||
this.projectRepositoryFactory = projectRepositoryFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectSettingsRepo load(String projectKey, @Nullable MutableBoolean fromCache) {
|
||||
ProjectRepositories pr = projectRepositoryFactory.create();
|
||||
return new ProjectSettingsRepo(toTable(pr.settings()), toTable(pr.fileDataByModuleAndPath()), pr.lastAnalysisDate());
|
||||
}
|
||||
|
||||
private static <T, U, V> Table<T, U, V> toTable(Map<T, Map<U, V>> map) {
|
||||
Table<T, U, V> table = HashBasedTable.create();
|
||||
|
||||
for (Map.Entry<T, Map<U, V>> e1 : map.entrySet()) {
|
||||
for (Map.Entry<U, V> e2 : e1.getValue().entrySet()) {
|
||||
table.put(e1.getKey(), e2.getKey(), e2.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class DefaultQualityProfileLoader implements QualityProfileLoader {
|
||||
|
||||
private ProjectRepositoriesFactory projectRepositoriesFactory;
|
||||
|
||||
public DefaultQualityProfileLoader(ProjectRepositoriesFactory projectRepositoriesFactory) {
|
||||
this.projectRepositoriesFactory = projectRepositoriesFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<QProfile> load(@Nullable String projectKey, @Nullable String sonarProfile) {
|
||||
ProjectRepositories pr = projectRepositoriesFactory.create();
|
||||
validate(pr.qProfiles());
|
||||
return pr.qProfiles();
|
||||
}
|
||||
|
||||
private static void validate(Collection<QProfile> profiles) {
|
||||
if (profiles == null || profiles.isEmpty()) {
|
||||
throw new IllegalStateException("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public interface ProjectRepositoriesFactory {
|
||||
|
||||
ProjectRepositories create();
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.picocontainer.injectors.ProviderAdapter;
|
||||
|
||||
public class ProjectRepositoriesFactoryProvider extends ProviderAdapter {
|
||||
|
||||
private final String projectKey;
|
||||
private SyncProjectRepositoriesFactory factory;
|
||||
|
||||
public ProjectRepositoriesFactoryProvider(String projectKey) {
|
||||
this.projectKey = projectKey;
|
||||
this.factory = null;
|
||||
}
|
||||
|
||||
public ProjectRepositoriesFactory provide(ProjectRepositoriesLoader loader) {
|
||||
if (factory == null) {
|
||||
factory = new SyncProjectRepositoriesFactory(projectKey, loader);
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
@ -19,16 +19,14 @@
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public interface ProjectRepositoriesLoader {
|
||||
|
||||
ProjectRepositories load(ProjectDefinition projectDefinition, AnalysisProperties taskProperties, @Nullable MutableBoolean fromCache);
|
||||
ProjectRepositories load(String projectKeyWithBranch, @Nullable String sonarProfile, @Nullable MutableBoolean fromCache);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ProjectSettingsLoader {
|
||||
ProjectSettingsRepo load(String projectKey, @Nullable MutableBoolean fromCache);
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.sonar.api.utils.log.Logger;
|
||||
import org.sonar.api.utils.log.Loggers;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.picocontainer.injectors.ProviderAdapter;
|
||||
|
||||
public class ProjectSettingsProvider extends ProviderAdapter {
|
||||
private static final Logger LOG = Loggers.get(ProjectSettingsProvider.class);
|
||||
private ProjectSettingsRepo settings = null;
|
||||
|
||||
public ProjectSettingsRepo provide(@Nullable ProjectSettingsLoader loader, ProjectReactor projectReactor, DefaultAnalysisMode mode) {
|
||||
if (settings == null) {
|
||||
if (mode.isNotAssociated()) {
|
||||
settings = createNonAssociatedProjectSettings();
|
||||
} else {
|
||||
MutableBoolean fromCache = new MutableBoolean();
|
||||
settings = loader.load(projectReactor.getRoot().getKeyWithBranch(), fromCache);
|
||||
checkProject(mode);
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
private void checkProject(DefaultAnalysisMode mode) {
|
||||
if (mode.isIssues() && settings.lastAnalysisDate() == null) {
|
||||
LOG.warn("No analysis has been found on the server for this project. All issues will be marked as 'new'.");
|
||||
}
|
||||
}
|
||||
|
||||
private static ProjectSettingsRepo createNonAssociatedProjectSettings() {
|
||||
Table<String, String, String> emptySettings = ImmutableTable.of();
|
||||
Table<String, String, FileData> emptyFileData = ImmutableTable.of();
|
||||
return new ProjectSettingsRepo(emptySettings, emptyFileData, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import com.google.common.collect.Table;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProjectSettingsRepo {
|
||||
private Table<String, String, String> settingsByModule = null;
|
||||
private Table<String, String, FileData> fileDataByModuleAndPath = null;
|
||||
private Date lastAnalysisDate;
|
||||
|
||||
public ProjectSettingsRepo(Table<String, String, String> settingsByModule, Table<String, String, FileData> fileDataByModuleAndPath,
|
||||
@Nullable Date lastAnalysisDate) {
|
||||
super();
|
||||
this.settingsByModule = settingsByModule;
|
||||
this.fileDataByModuleAndPath = fileDataByModuleAndPath;
|
||||
this.lastAnalysisDate = lastAnalysisDate;
|
||||
}
|
||||
|
||||
public Map<String, FileData> fileDataByPath(String moduleKey) {
|
||||
return fileDataByModuleAndPath.row(moduleKey);
|
||||
}
|
||||
|
||||
public Table<String, String, FileData> fileDataByModuleAndPath() {
|
||||
return fileDataByModuleAndPath;
|
||||
}
|
||||
|
||||
public Map<String, String> settings(String moduleKey) {
|
||||
return settingsByModule.row(moduleKey);
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public FileData fileData(String projectKey, String path) {
|
||||
return fileDataByModuleAndPath.get(projectKey, path);
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public Date lastAnalysisDate() {
|
||||
return lastAnalysisDate;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface QualityProfileLoader {
|
||||
Collection<QProfile> load(@Nullable String projectKey, @Nullable String sonarProfile);
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.sonar.api.batch.AnalysisMode;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.sonar.batch.rule.ModuleQProfiles;
|
||||
import org.picocontainer.injectors.ProviderAdapter;
|
||||
|
||||
public class QualityProfileProvider extends ProviderAdapter {
|
||||
private ModuleQProfiles profiles = null;
|
||||
|
||||
public ModuleQProfiles provide(ProjectReactor projectReactor, QualityProfileLoader loader, AnalysisProperties props, AnalysisMode mode) {
|
||||
if (this.profiles == null) {
|
||||
String profile = null;
|
||||
if (!mode.isIssues()) {
|
||||
profile = props.property(ModuleQProfiles.SONAR_PROFILE_PROP);
|
||||
}
|
||||
Collection<QProfile> qps = loader.load(projectReactor.getRoot().getKeyWithBranch(), profile);
|
||||
profiles = new ModuleQProfiles(qps);
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.api.utils.log.Logger;
|
||||
import org.sonar.api.utils.log.Loggers;
|
||||
import org.sonar.api.utils.log.Profiler;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public class SyncProjectRepositoriesFactory implements ProjectRepositoriesFactory {
|
||||
private static final String LOG_MSG = "Load project repositories";
|
||||
private static final Logger LOG = Loggers.get(SyncProjectRepositoriesFactory.class);
|
||||
private static final String NON_EXISTING = "non1-existing2-project3-key";
|
||||
|
||||
private final ProjectRepositoriesLoader loader;
|
||||
private final String projectKey;
|
||||
|
||||
private ProjectRepositories projectRepositories;
|
||||
|
||||
public SyncProjectRepositoriesFactory(@Nullable String projectKey, ProjectRepositoriesLoader loader) {
|
||||
this.projectKey = projectKey;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectRepositories create() {
|
||||
if (projectRepositories == null) {
|
||||
projectRepositories = newInstance();
|
||||
}
|
||||
|
||||
return projectRepositories;
|
||||
}
|
||||
|
||||
public ProjectRepositories newInstance() {
|
||||
if (projectRepositories == null) {
|
||||
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
|
||||
MutableBoolean fromCache = new MutableBoolean();
|
||||
projectRepositories = loader.load(getProjectKey(projectKey), null, fromCache);
|
||||
profiler.stopInfo(fromCache.booleanValue());
|
||||
|
||||
if (projectRepositories.lastAnalysisDate() == null) {
|
||||
LOG.warn("No analysis has been found on the server for this project. All issues will be marked as 'new'.");
|
||||
}
|
||||
}
|
||||
return projectRepositories;
|
||||
}
|
||||
|
||||
private static String getProjectKey(@Nullable String projectKey) {
|
||||
if (projectKey == null) {
|
||||
return NON_EXISTING;
|
||||
}
|
||||
return projectKey;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.rule;
|
||||
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ActiveRulesLoader {
|
||||
Collection<ActiveRule> load(Collection<String> qualityProfileKeys, String projectKey);
|
||||
}
|
@ -19,14 +19,17 @@
|
||||
*/
|
||||
package org.sonar.batch.rule;
|
||||
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.picocontainer.injectors.ProviderAdapter;
|
||||
import org.sonar.api.batch.rule.ActiveRules;
|
||||
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
|
||||
import org.sonar.api.batch.rule.internal.NewActiveRule;
|
||||
import org.sonar.api.rule.RuleKey;
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
@ -37,16 +40,16 @@ public class ActiveRulesProvider extends ProviderAdapter {
|
||||
|
||||
private ActiveRules singleton = null;
|
||||
|
||||
public ActiveRules provide(ProjectRepositories ref) {
|
||||
public ActiveRules provide(ActiveRulesLoader ref, ModuleQProfiles qProfiles, ProjectReactor projectReactor) {
|
||||
if (singleton == null) {
|
||||
singleton = load(ref);
|
||||
singleton = load(ref, qProfiles, projectReactor);
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
private static ActiveRules load(ProjectRepositories ref) {
|
||||
private static ActiveRules load(ActiveRulesLoader loader, ModuleQProfiles qProfiles, ProjectReactor projectReactor) {
|
||||
ActiveRulesBuilder builder = new ActiveRulesBuilder();
|
||||
for (ActiveRule activeRule : ref.activeRules()) {
|
||||
for (ActiveRule activeRule : loader.load(getKeys(qProfiles), projectReactor.getRoot().getKeyWithBranch())) {
|
||||
NewActiveRule newActiveRule = builder.create(RuleKey.of(activeRule.repositoryKey(), activeRule.ruleKey()));
|
||||
newActiveRule.setName(activeRule.name());
|
||||
newActiveRule.setSeverity(activeRule.severity());
|
||||
@ -63,4 +66,14 @@ public class ActiveRulesProvider extends ProviderAdapter {
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Collection<String> getKeys(ModuleQProfiles qProfiles) {
|
||||
List<String> keys = new ArrayList<>(qProfiles.findAll().size());
|
||||
|
||||
for (QProfile qp : qProfiles.findAll()) {
|
||||
keys.add(qp.getKey());
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.rule;
|
||||
|
||||
import org.sonar.batch.repository.ProjectRepositoriesFactory;
|
||||
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public class DefaultActiveRulesLoader implements ActiveRulesLoader {
|
||||
private final ProjectRepositoriesFactory projectRepositoriesFactory;
|
||||
|
||||
public DefaultActiveRulesLoader(ProjectRepositoriesFactory projectRepositoriesFactory) {
|
||||
this.projectRepositoriesFactory = projectRepositoriesFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ActiveRule> load(Collection<String> qualityProfileKeys, String projectKey) {
|
||||
ProjectRepositories pr = projectRepositoriesFactory.create();
|
||||
return pr.activeRules();
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,6 @@ package org.sonar.batch.rule;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.sonar.api.batch.BatchSide;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
|
||||
@ -37,10 +36,10 @@ public class ModuleQProfiles {
|
||||
public static final String SONAR_PROFILE_PROP = "sonar.profile";
|
||||
private final Map<String, QProfile> byLanguage;
|
||||
|
||||
public ModuleQProfiles(ProjectRepositories ref) {
|
||||
public ModuleQProfiles(Collection<org.sonar.batch.protocol.input.QProfile> profiles) {
|
||||
ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder();
|
||||
|
||||
for (org.sonar.batch.protocol.input.QProfile qProfile : ref.qProfiles()) {
|
||||
for (org.sonar.batch.protocol.input.QProfile qProfile : profiles) {
|
||||
builder.put(qProfile.language(),
|
||||
new QProfile().setKey(qProfile.key()).setName(qProfile.name()).setLanguage(qProfile.language()).setRulesUpdatedAt(qProfile.rulesUpdatedAt()));
|
||||
}
|
||||
|
@ -148,7 +148,6 @@ public class ModuleScanContainer extends ComponentContainer {
|
||||
CoverageExclusions.class,
|
||||
|
||||
// rules
|
||||
ModuleQProfiles.class,
|
||||
new RulesProfileProvider(),
|
||||
QProfileSensor.class,
|
||||
CheckFactory.class,
|
||||
|
@ -19,8 +19,9 @@
|
||||
*/
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
@ -30,20 +31,19 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.api.config.Settings;
|
||||
import org.sonar.api.utils.MessageException;
|
||||
import org.sonar.batch.bootstrap.GlobalSettings;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
/**
|
||||
* @since 2.12
|
||||
*/
|
||||
public class ModuleSettings extends Settings {
|
||||
|
||||
private final ProjectRepositories projectReferentials;
|
||||
private final ProjectSettingsRepo projectSettingsRepo;
|
||||
private DefaultAnalysisMode analysisMode;
|
||||
|
||||
public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition moduleDefinition, ProjectRepositories projectReferentials,
|
||||
public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition moduleDefinition, ProjectSettingsRepo projectSettingsRepo,
|
||||
DefaultAnalysisMode analysisMode) {
|
||||
super(batchSettings.getDefinitions());
|
||||
this.projectReferentials = projectReferentials;
|
||||
this.projectSettingsRepo = projectSettingsRepo;
|
||||
this.analysisMode = analysisMode;
|
||||
getEncryption().setPathToSecretKey(batchSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
|
||||
|
||||
@ -58,13 +58,13 @@ public class ModuleSettings extends Settings {
|
||||
|
||||
private void addProjectProperties(ProjectDefinition moduleDefinition, GlobalSettings batchSettings) {
|
||||
addProperties(batchSettings.getProperties());
|
||||
addProperties(projectReferentials.settings(moduleDefinition.getKeyWithBranch()));
|
||||
addProperties(projectSettingsRepo.settings(moduleDefinition.getKeyWithBranch()));
|
||||
}
|
||||
|
||||
private void addBuildProperties(ProjectDefinition project) {
|
||||
List<ProjectDefinition> orderedProjects = getTopDownParentProjects(project);
|
||||
for (ProjectDefinition p : orderedProjects) {
|
||||
addProperties(p.getProperties());
|
||||
addProperties(p.properties());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,6 @@ public class ProjectLock implements Startable {
|
||||
if (lockFile == null) {
|
||||
failAlreadyInProgress(null);
|
||||
}
|
||||
|
||||
} catch (OverlappingFileLockException e) {
|
||||
failAlreadyInProgress(e);
|
||||
} catch (IOException e) {
|
||||
|
@ -19,8 +19,9 @@
|
||||
*/
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.sonar.api.batch.AnalysisMode;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
@ -108,12 +109,16 @@ public class ProjectReactorBuilder {
|
||||
*/
|
||||
private static final List<String> NON_HERITED_PROPERTIES_FOR_CHILD = Lists.newArrayList(PROPERTY_PROJECT_BASEDIR, CoreProperties.WORKING_DIRECTORY, PROPERTY_MODULES,
|
||||
CoreProperties.PROJECT_DESCRIPTION_PROPERTY);
|
||||
|
||||
private static final String NON_ASSOCIATED_PROJECT_KEY = "project";
|
||||
|
||||
private AnalysisProperties taskProps;
|
||||
private final AnalysisProperties taskProps;
|
||||
private final AnalysisMode analysisMode;
|
||||
private File rootProjectWorkDir;
|
||||
|
||||
public ProjectReactorBuilder(AnalysisProperties props) {
|
||||
public ProjectReactorBuilder(AnalysisProperties props, AnalysisMode analysisMode) {
|
||||
this.taskProps = props;
|
||||
this.analysisMode = analysisMode;
|
||||
}
|
||||
|
||||
public ProjectReactor execute() {
|
||||
@ -160,8 +165,16 @@ public class ProjectReactorBuilder {
|
||||
extractPropertiesByModule(propertiesByModuleId, moduleId, currentModuleProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void prepareNonAssociatedProject(Map<String, String> props, AnalysisMode mode) {
|
||||
if(mode.isIssues() && !props.containsKey(CoreProperties.PROJECT_KEY_PROPERTY)) {
|
||||
props.put(CoreProperties.PROJECT_KEY_PROPERTY, NON_ASSOCIATED_PROJECT_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
protected ProjectDefinition defineRootProject(Map<String, String> rootProperties, @Nullable ProjectDefinition parent) {
|
||||
prepareNonAssociatedProject(rootProperties, analysisMode);
|
||||
|
||||
if (rootProperties.containsKey(PROPERTY_MODULES)) {
|
||||
checkMandatoryProperties(rootProperties, MANDATORY_PROPERTIES_FOR_MULTIMODULE_PROJECT);
|
||||
} else {
|
||||
|
@ -28,7 +28,6 @@ import org.sonar.api.CoreProperties;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.sonar.api.config.Settings;
|
||||
import org.sonar.api.utils.SonarException;
|
||||
import org.sonar.core.component.ComponentKeys;
|
||||
|
||||
/**
|
||||
@ -58,7 +57,7 @@ public class ProjectReactorValidator {
|
||||
validateBranch(validationMessages, branch);
|
||||
|
||||
if (!validationMessages.isEmpty()) {
|
||||
throw new SonarException("Validation of project reactor failed:\n o " + Joiner.on("\n o ").join(validationMessages));
|
||||
throw new IllegalStateException("Validation of project reactor failed:\n o " + Joiner.on("\n o ").join(validationMessages));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,16 @@
|
||||
*/
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.sonar.batch.repository.DefaultProjectRepositoriesFactory;
|
||||
|
||||
import org.sonar.batch.repository.QualityProfileProvider;
|
||||
import org.sonar.batch.repository.DefaultQualityProfileLoader;
|
||||
import org.sonar.batch.repository.QualityProfileLoader;
|
||||
import org.sonar.batch.repository.ProjectSettingsLoader;
|
||||
import org.sonar.batch.repository.DefaultProjectSettingsLoader;
|
||||
import org.sonar.batch.repository.ProjectSettingsProvider;
|
||||
import org.sonar.batch.rule.DefaultActiveRulesLoader;
|
||||
import org.sonar.batch.rule.ActiveRulesLoader;
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.analysis.AnalysisWSLoaderProvider;
|
||||
import org.sonar.batch.analysis.AnalysisTempFolderProvider;
|
||||
@ -69,7 +79,6 @@ import org.sonar.batch.report.MetadataPublisher;
|
||||
import org.sonar.batch.report.ReportPublisher;
|
||||
import org.sonar.batch.report.SourcePublisher;
|
||||
import org.sonar.batch.report.TestExecutionAndCoveragePublisher;
|
||||
import org.sonar.batch.repository.ProjectRepositoriesProvider;
|
||||
import org.sonar.batch.repository.language.DefaultLanguagesRepository;
|
||||
import org.sonar.batch.rule.ActiveRulesProvider;
|
||||
import org.sonar.batch.scan.filesystem.InputPathCache;
|
||||
@ -116,6 +125,7 @@ public class ProjectScanContainer extends ComponentContainer {
|
||||
props,
|
||||
DefaultAnalysisMode.class,
|
||||
ProjectReactorBuilder.class,
|
||||
DefaultProjectRepositoriesFactory.class,
|
||||
new MutableProjectReactorProvider(),
|
||||
new ImmutableProjectReactorProvider(),
|
||||
ProjectBuildersExecutor.class,
|
||||
@ -126,7 +136,6 @@ public class ProjectScanContainer extends ComponentContainer {
|
||||
DefaultProjectTree.class,
|
||||
ProjectExclusions.class,
|
||||
ProjectReactorValidator.class,
|
||||
new ProjectRepositoriesProvider(),
|
||||
new AnalysisWSLoaderProvider(),
|
||||
CodeColorizers.class,
|
||||
MetricProvider.class,
|
||||
@ -136,6 +145,7 @@ public class ProjectScanContainer extends ComponentContainer {
|
||||
Caches.class,
|
||||
BatchComponentCache.class,
|
||||
DefaultIssueCallback.class,
|
||||
new ProjectSettingsProvider(),
|
||||
|
||||
// temp
|
||||
new AnalysisTempFolderProvider(),
|
||||
@ -146,6 +156,7 @@ public class ProjectScanContainer extends ComponentContainer {
|
||||
|
||||
// rules
|
||||
new ActiveRulesProvider(),
|
||||
new QualityProfileProvider(),
|
||||
|
||||
// issues
|
||||
IssueUpdater.class,
|
||||
@ -153,8 +164,8 @@ public class ProjectScanContainer extends ComponentContainer {
|
||||
IssueWorkflow.class,
|
||||
IssueCache.class,
|
||||
DefaultProjectIssues.class,
|
||||
LocalIssueTracking.class,
|
||||
ServerIssueRepository.class,
|
||||
LocalIssueTracking.class,
|
||||
|
||||
// metrics
|
||||
DefaultMetricFinder.class,
|
||||
@ -190,9 +201,16 @@ public class ProjectScanContainer extends ComponentContainer {
|
||||
ScanTaskObservers.class,
|
||||
UserRepositoryLoader.class);
|
||||
|
||||
addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
|
||||
addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class);
|
||||
addIfMissing(DefaultServerLineHashesLoader.class, ServerLineHashesLoader.class);
|
||||
addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class);
|
||||
addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class);
|
||||
addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
|
||||
addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class);
|
||||
}
|
||||
|
||||
private boolean isProjectAssociated() {
|
||||
return !getComponentByType(DefaultAnalysisMode.class).isNotAssociated();
|
||||
}
|
||||
|
||||
private void addBatchExtensions() {
|
||||
|
@ -19,8 +19,9 @@
|
||||
*/
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
@ -32,7 +33,6 @@ import org.sonar.api.config.Settings;
|
||||
import org.sonar.api.utils.MessageException;
|
||||
import org.sonar.batch.bootstrap.DroppedPropertyChecker;
|
||||
import org.sonar.batch.bootstrap.GlobalSettings;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
public class ProjectSettings extends Settings {
|
||||
|
||||
@ -45,11 +45,11 @@ public class ProjectSettings extends Settings {
|
||||
);
|
||||
|
||||
private final GlobalSettings globalSettings;
|
||||
private final ProjectRepositories projectRepositories;
|
||||
private final ProjectSettingsRepo projectRepositories;
|
||||
private final DefaultAnalysisMode mode;
|
||||
|
||||
public ProjectSettings(ProjectReactor reactor, GlobalSettings globalSettings, PropertyDefinitions propertyDefinitions,
|
||||
ProjectRepositories projectRepositories, DefaultAnalysisMode mode) {
|
||||
ProjectSettingsRepo projectRepositories, DefaultAnalysisMode mode) {
|
||||
super(propertyDefinitions);
|
||||
this.mode = mode;
|
||||
getEncryption().setPathToSecretKey(globalSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
|
||||
|
@ -19,21 +19,22 @@
|
||||
*/
|
||||
package org.sonar.batch.scan.filesystem;
|
||||
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.sonar.api.batch.fs.InputFile;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
class StatusDetection {
|
||||
|
||||
private final ProjectRepositories projectReferentials;
|
||||
private final ProjectSettingsRepo projectSettings;
|
||||
|
||||
StatusDetection(ProjectRepositories projectReferentials) {
|
||||
this.projectReferentials = projectReferentials;
|
||||
StatusDetection(ProjectSettingsRepo projectSettings) {
|
||||
this.projectSettings = projectSettings;
|
||||
}
|
||||
|
||||
InputFile.Status status(String projectKey, String relativePath, String hash) {
|
||||
FileData fileDataPerPath = projectReferentials.fileData(projectKey, relativePath);
|
||||
FileData fileDataPerPath = projectSettings.fileData(projectKey, relativePath);
|
||||
if (fileDataPerPath == null) {
|
||||
return InputFile.Status.ADDED;
|
||||
}
|
||||
|
@ -19,15 +19,16 @@
|
||||
*/
|
||||
package org.sonar.batch.scan.filesystem;
|
||||
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import org.sonar.api.batch.BatchSide;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
@BatchSide
|
||||
public class StatusDetectionFactory {
|
||||
|
||||
private final ProjectRepositories projectReferentials;
|
||||
private final ProjectSettingsRepo projectReferentials;
|
||||
|
||||
public StatusDetectionFactory(ProjectRepositories projectReferentials) {
|
||||
public StatusDetectionFactory(ProjectSettingsRepo projectReferentials) {
|
||||
this.projectReferentials = projectReferentials;
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,11 @@
|
||||
*/
|
||||
package org.sonar.batch.scm;
|
||||
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonar.api.CoreProperties;
|
||||
@ -33,7 +36,6 @@ import org.sonar.api.batch.sensor.SensorContext;
|
||||
import org.sonar.api.batch.sensor.SensorDescriptor;
|
||||
import org.sonar.batch.index.BatchComponentCache;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.report.ReportPublisher;
|
||||
import org.sonar.batch.scan.filesystem.InputPathCache;
|
||||
|
||||
@ -44,16 +46,16 @@ public final class ScmSensor implements Sensor {
|
||||
private final ProjectDefinition projectDefinition;
|
||||
private final ScmConfiguration configuration;
|
||||
private final FileSystem fs;
|
||||
private final ProjectRepositories projectReferentials;
|
||||
private final ProjectSettingsRepo projectSettings;
|
||||
private final BatchComponentCache resourceCache;
|
||||
private final ReportPublisher publishReportJob;
|
||||
|
||||
public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration,
|
||||
ProjectRepositories projectReferentials, FileSystem fs, InputPathCache inputPathCache, BatchComponentCache resourceCache,
|
||||
ProjectSettingsRepo projectSettings, FileSystem fs, InputPathCache inputPathCache, BatchComponentCache resourceCache,
|
||||
ReportPublisher publishReportJob) {
|
||||
this.projectDefinition = projectDefinition;
|
||||
this.configuration = configuration;
|
||||
this.projectReferentials = projectReferentials;
|
||||
this.projectSettings = projectSettings;
|
||||
this.fs = fs;
|
||||
this.resourceCache = resourceCache;
|
||||
this.publishReportJob = publishReportJob;
|
||||
@ -95,7 +97,7 @@ public final class ScmSensor implements Sensor {
|
||||
if (configuration.forceReloadAll()) {
|
||||
addIfNotEmpty(filesToBlame, f);
|
||||
} else {
|
||||
FileData fileData = projectReferentials.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
|
||||
FileData fileData = projectSettings.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
|
||||
if (f.status() != Status.SAME || fileData == null || fileData.needBlame()) {
|
||||
addIfNotEmpty(filesToBlame, f);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.sonar.home.cache.PersistentCacheLoader;
|
||||
|
||||
import org.junit.internal.runners.statements.ExpectException;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -58,6 +57,7 @@ public class DefaultProjectCacheStatusTest {
|
||||
public void setUp() {
|
||||
cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, mock(Logger.class), null);
|
||||
client = mock(ServerClient.class);
|
||||
when(client.getServerVersion()).thenReturn("5.2");
|
||||
when(client.getURL()).thenReturn("localhost");
|
||||
cacheStatus = new DefaultProjectCacheStatus(cache, client);
|
||||
}
|
||||
@ -84,6 +84,17 @@ public class DefaultProjectCacheStatusTest {
|
||||
cacheStatus.save(PROJ_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useServerVersionAsKey() {
|
||||
cacheStatus.save(PROJ_KEY);
|
||||
assertThat(cacheStatus.getSyncStatus(PROJ_KEY)).isNotNull();
|
||||
assertThat(age(cacheStatus.getSyncStatus(PROJ_KEY))).isLessThan(2000);
|
||||
|
||||
when(client.getServerVersion()).thenReturn("5.1");
|
||||
|
||||
assertThat(cacheStatus.getSyncStatus(PROJ_KEY)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorStatus() throws IOException {
|
||||
cache = mock(PersistentCache.class);
|
||||
|
91
sonar-batch/src/test/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizerTest.java
vendored
Normal file
91
sonar-batch/src/test/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizerTest.java
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mock;
|
||||
import org.sonar.batch.rule.ActiveRulesLoader;
|
||||
import org.sonar.batch.repository.QualityProfileLoader;
|
||||
|
||||
public class NonAssociatedCacheSynchronizerTest {
|
||||
private NonAssociatedCacheSynchronizer synchronizer;
|
||||
|
||||
@Mock
|
||||
private QualityProfileLoader qualityProfileLoader;
|
||||
@Mock
|
||||
private ActiveRulesLoader activeRulesLoader;
|
||||
@Mock
|
||||
private ProjectCacheStatus cacheStatus;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
QProfile pf = new QProfile("profile", "profile", "lang", new Date(1000));
|
||||
ActiveRule ar = mock(ActiveRule.class);
|
||||
|
||||
when(qualityProfileLoader.load(null, null)).thenReturn(ImmutableList.of(pf));
|
||||
when(activeRulesLoader.load(ImmutableList.of("profile"), null)).thenReturn(ImmutableList.of(ar));
|
||||
|
||||
synchronizer = new NonAssociatedCacheSynchronizer(qualityProfileLoader, activeRulesLoader, cacheStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dont_sync_if_exists() {
|
||||
when(cacheStatus.getSyncStatus(null)).thenReturn(new Date());
|
||||
synchronizer.execute(false);
|
||||
verifyNoMoreInteractions(qualityProfileLoader, activeRulesLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void always_sync_if_force() {
|
||||
when(cacheStatus.getSyncStatus(null)).thenReturn(new Date());
|
||||
synchronizer.execute(true);
|
||||
checkSync();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sync_if_doesnt_exist() {
|
||||
synchronizer.execute(false);
|
||||
checkSync();
|
||||
}
|
||||
|
||||
private void checkSync() {
|
||||
verify(cacheStatus).getSyncStatus(null);
|
||||
verify(cacheStatus).save(null);
|
||||
verify(qualityProfileLoader).load(null, null);
|
||||
verify(activeRulesLoader).load(ImmutableList.of("profile"), null);
|
||||
|
||||
verifyNoMoreInteractions(qualityProfileLoader, activeRulesLoader);
|
||||
}
|
||||
}
|
@ -19,10 +19,12 @@
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.sonar.batch.bootstrap.GlobalProperties;
|
||||
import org.sonar.batch.cache.PersistentCacheProvider;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
@ -30,6 +32,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PersistentCacheProviderTest {
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
private PersistentCacheProvider provider = null;
|
||||
private GlobalProperties props = null;
|
||||
|
||||
@ -51,7 +56,8 @@ public class PersistentCacheProviderTest {
|
||||
|
||||
@Test
|
||||
public void test_home() {
|
||||
props.properties().put("sonar.userHome", "myhome");
|
||||
assertThat(provider.provide(props).getBaseDirectory()).isEqualTo(Paths.get("myhome/ws_cache"));
|
||||
File f = temp.getRoot();
|
||||
props.properties().put("sonar.userHome", f.getAbsolutePath());
|
||||
assertThat(provider.provide(props).getBaseDirectory()).isEqualTo(f.toPath().resolve("ws_cache"));
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +20,27 @@
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.sonar.batch.repository.ProjectRepositoriesFactory;
|
||||
|
||||
import org.sonar.batch.repository.DefaultProjectRepositoriesFactory;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.batch.repository.DefaultProjectSettingsLoader;
|
||||
import org.sonar.batch.rule.DefaultActiveRulesLoader;
|
||||
import org.sonar.batch.repository.DefaultQualityProfileLoader;
|
||||
import org.sonar.batch.repository.ProjectSettingsLoader;
|
||||
import org.sonar.batch.rule.ActiveRulesLoader;
|
||||
import org.sonar.batch.repository.QualityProfileLoader;
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader;
|
||||
import org.sonar.batch.repository.DefaultServerIssuesLoader;
|
||||
import org.sonar.batch.repository.DefaultProjectRepositoriesLoader;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
@ -36,6 +52,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
@ -47,7 +64,6 @@ import org.junit.Before;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Mock;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
|
||||
import org.sonar.batch.repository.ProjectRepositoriesLoader;
|
||||
import org.sonar.batch.repository.ServerIssuesLoader;
|
||||
import org.sonar.batch.repository.user.UserRepositoryLoader;
|
||||
@ -55,8 +71,10 @@ import org.sonar.batch.repository.user.UserRepositoryLoader;
|
||||
public class ProjectCacheSynchronizerTest {
|
||||
private static final String BATCH_PROJECT = "/batch/project?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin&preview=true";
|
||||
private static final String ISSUES = "/batch/issues?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin";
|
||||
private static final String LINE_HASHES1 = "/api/sources/hash?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin%3Asrc%2Ftest%2Fjava%2Forg%2Fsonar%2Fplugins%2Fscm%2Fgit%2FJGitBlameCommandTest.java";
|
||||
private static final String LINE_HASHES2 = "/api/sources/hash?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin%3Asrc%2Fmain%2Fjava%2Forg%2Fsonar%2Fplugins%2Fscm%2Fgit%2FGitScmProvider.java";
|
||||
private static final String PROJECT_KEY = "org.codehaus.sonar-plugins:sonar-scm-git-plugin";
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private ProjectDefinition project;
|
||||
@ -73,10 +91,10 @@ public class ProjectCacheSynchronizerTest {
|
||||
|
||||
private ProjectRepositoriesLoader projectRepositoryLoader;
|
||||
private ServerIssuesLoader issuesLoader;
|
||||
private ServerLineHashesLoader lineHashesLoader;
|
||||
private UserRepositoryLoader userRepositoryLoader;
|
||||
|
||||
private ProjectCacheSynchronizer sync;
|
||||
private QualityProfileLoader qualityProfileLoader;
|
||||
private ActiveRulesLoader activeRulesLoader;
|
||||
private ProjectSettingsLoader projectSettingsLoader;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
@ -84,62 +102,108 @@ public class ProjectCacheSynchronizerTest {
|
||||
|
||||
String batchProject = getResourceAsString("batch_project.json");
|
||||
ByteSource issues = getResourceAsByteSource("batch_issues.protobuf");
|
||||
String lineHashes2 = getResourceAsString("api_sources_hash_GitScmProvider.text");
|
||||
String lineHashes1 = getResourceAsString("api_sources_hash_JGitBlameCommand.text");
|
||||
|
||||
when(ws.loadString(BATCH_PROJECT)).thenReturn(new WSLoaderResult<>(batchProject, false));
|
||||
when(ws.loadSource(ISSUES)).thenReturn(new WSLoaderResult<>(issues, false));
|
||||
when(ws.loadString(LINE_HASHES1)).thenReturn(new WSLoaderResult<>(lineHashes1, false));
|
||||
when(ws.loadString(LINE_HASHES2)).thenReturn(new WSLoaderResult<>(lineHashes2, false));
|
||||
|
||||
when(analysisMode.isIssues()).thenReturn(true);
|
||||
when(project.getKeyWithBranch()).thenReturn("org.codehaus.sonar-plugins:sonar-scm-git-plugin");
|
||||
when(projectReactor.getRoot()).thenReturn(project);
|
||||
when(properties.properties()).thenReturn(new HashMap<String, String>());
|
||||
}
|
||||
|
||||
private ProjectCacheSynchronizer create(ProjectRepositories projectRepositories) {
|
||||
if (projectRepositories == null) {
|
||||
projectRepositoryLoader = new DefaultProjectRepositoriesLoader(ws, analysisMode);
|
||||
} else {
|
||||
projectRepositoryLoader = mock(ProjectRepositoriesLoader.class);
|
||||
when(projectRepositoryLoader.load(anyString(), anyString(), any(MutableBoolean.class))).thenReturn(projectRepositories);
|
||||
}
|
||||
|
||||
ProjectReactor reactor = mock(ProjectReactor.class);
|
||||
ProjectDefinition root = mock(ProjectDefinition.class);
|
||||
when(root.getKeyWithBranch()).thenReturn(PROJECT_KEY);
|
||||
when(reactor.getRoot()).thenReturn(root);
|
||||
|
||||
ProjectRepositoriesFactory projectRepositoriesFactory = new DefaultProjectRepositoriesFactory(reactor, analysisMode, projectRepositoryLoader, properties);
|
||||
|
||||
projectRepositoryLoader = new DefaultProjectRepositoriesLoader(ws, analysisMode);
|
||||
issuesLoader = new DefaultServerIssuesLoader(ws);
|
||||
lineHashesLoader = new DefaultServerLineHashesLoader(ws);
|
||||
userRepositoryLoader = new UserRepositoryLoader(ws);
|
||||
qualityProfileLoader = new DefaultQualityProfileLoader(projectRepositoriesFactory);
|
||||
activeRulesLoader = new DefaultActiveRulesLoader(projectRepositoriesFactory);
|
||||
projectSettingsLoader = new DefaultProjectSettingsLoader(projectRepositoriesFactory);
|
||||
|
||||
sync = new ProjectCacheSynchronizer(projectReactor, projectRepositoryLoader, properties, issuesLoader, lineHashesLoader, userRepositoryLoader,
|
||||
cacheStatus);
|
||||
return new ProjectCacheSynchronizer(qualityProfileLoader, projectSettingsLoader, activeRulesLoader, issuesLoader, userRepositoryLoader, cacheStatus);
|
||||
}
|
||||
|
||||
private ProjectCacheSynchronizer createMockedLoaders(Date lastAnalysisDate) {
|
||||
issuesLoader = mock(DefaultServerIssuesLoader.class);
|
||||
userRepositoryLoader = mock(UserRepositoryLoader.class);
|
||||
qualityProfileLoader = mock(DefaultQualityProfileLoader.class);
|
||||
activeRulesLoader = mock(DefaultActiveRulesLoader.class);
|
||||
projectSettingsLoader = mock(DefaultProjectSettingsLoader.class);
|
||||
|
||||
QProfile pf = new QProfile("profile", "profile", "lang", new Date(1000));
|
||||
ActiveRule ar = mock(ActiveRule.class);
|
||||
ProjectSettingsRepo repo = mock(ProjectSettingsRepo.class);
|
||||
|
||||
when(qualityProfileLoader.load(PROJECT_KEY, null)).thenReturn(ImmutableList.of(pf));
|
||||
when(activeRulesLoader.load(ImmutableList.of("profile"), PROJECT_KEY)).thenReturn(ImmutableList.of(ar));
|
||||
when(repo.lastAnalysisDate()).thenReturn(lastAnalysisDate);
|
||||
when(projectSettingsLoader.load(anyString(), any(MutableBoolean.class))).thenReturn(repo);
|
||||
|
||||
return new ProjectCacheSynchronizer(qualityProfileLoader, projectSettingsLoader, activeRulesLoader, issuesLoader, userRepositoryLoader, cacheStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSync() {
|
||||
sync.load(false);
|
||||
ProjectCacheSynchronizer sync = create(null);
|
||||
|
||||
sync.load(PROJECT_KEY, false);
|
||||
|
||||
verify(ws).loadString(BATCH_PROJECT);
|
||||
verify(ws).loadSource(ISSUES);
|
||||
verify(ws).loadString(LINE_HASHES1);
|
||||
verify(ws).loadString(LINE_HASHES2);
|
||||
verifyNoMoreInteractions(ws);
|
||||
|
||||
verify(cacheStatus).save(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadersUsage() {
|
||||
ProjectCacheSynchronizer synchronizer = createMockedLoaders(new Date());
|
||||
synchronizer.load(PROJECT_KEY, false);
|
||||
|
||||
verify(issuesLoader).load(eq(PROJECT_KEY), any(Function.class));
|
||||
verify(qualityProfileLoader).load(PROJECT_KEY, null);
|
||||
verify(activeRulesLoader).load(ImmutableList.of("profile"), PROJECT_KEY);
|
||||
verify(projectSettingsLoader).load(eq(PROJECT_KEY), any(MutableBoolean.class));
|
||||
|
||||
verifyNoMoreInteractions(issuesLoader, userRepositoryLoader, qualityProfileLoader, activeRulesLoader, projectSettingsLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadersUsage_NoLastAnalysis() {
|
||||
ProjectCacheSynchronizer synchronizer = createMockedLoaders(null);
|
||||
synchronizer.load(PROJECT_KEY, false);
|
||||
|
||||
verify(projectSettingsLoader).load(eq(PROJECT_KEY), any(MutableBoolean.class));
|
||||
|
||||
verifyNoMoreInteractions(issuesLoader, userRepositoryLoader, qualityProfileLoader, activeRulesLoader, projectSettingsLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncNoLastAnalysis() {
|
||||
projectRepositoryLoader = mock(DefaultProjectRepositoriesLoader.class);
|
||||
ProjectRepositories mockedProjectRepositories = mock(ProjectRepositories.class);
|
||||
when(mockedProjectRepositories.lastAnalysisDate()).thenReturn(null);
|
||||
when(projectRepositoryLoader.load(any(ProjectDefinition.class), any(AnalysisProperties.class), any(MutableBoolean.class))).thenReturn(mockedProjectRepositories);
|
||||
|
||||
sync = new ProjectCacheSynchronizer(projectReactor, projectRepositoryLoader, properties, issuesLoader, lineHashesLoader, userRepositoryLoader,
|
||||
cacheStatus);
|
||||
sync.load(true);
|
||||
|
||||
verify(cacheStatus).save("org.codehaus.sonar-plugins:sonar-scm-git-plugin");
|
||||
ProjectCacheSynchronizer sync = create(mockedProjectRepositories);
|
||||
sync.load(PROJECT_KEY, true);
|
||||
verify(cacheStatus).save(PROJECT_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDontSyncIfNotForce() {
|
||||
when(cacheStatus.getSyncStatus("org.codehaus.sonar-plugins:sonar-scm-git-plugin")).thenReturn(new Date());
|
||||
|
||||
ProjectCacheSynchronizer sync = new ProjectCacheSynchronizer(projectReactor, projectRepositoryLoader, properties, issuesLoader, lineHashesLoader, userRepositoryLoader,
|
||||
cacheStatus);
|
||||
sync.load(false);
|
||||
when(cacheStatus.getSyncStatus(PROJECT_KEY)).thenReturn(new Date());
|
||||
ProjectCacheSynchronizer sync = create(null);
|
||||
sync.load(PROJECT_KEY, false);
|
||||
|
||||
verifyNoMoreInteractions(ws);
|
||||
}
|
||||
|
@ -19,16 +19,13 @@
|
||||
*/
|
||||
package org.sonar.batch.cache;
|
||||
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
import org.sonar.batch.bootstrap.GlobalProperties;
|
||||
import org.sonar.batch.bootstrap.ServerClient;
|
||||
import org.sonar.home.cache.PersistentCache;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import org.sonar.core.platform.ComponentContainer;
|
||||
@ -47,24 +44,11 @@ public class ProjectSyncContainerTest {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public AnalysisProperties createProjectProperties() {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("sonar.branch", "branch");
|
||||
properties.put("sonar.projectKey", "my:project");
|
||||
properties.put("sonar.projectName", "My project");
|
||||
properties.put("sonar.projectVersion", "1.0");
|
||||
properties.put("sonar.sources", ".");
|
||||
properties.put("sonar.projectBaseDir", ".");
|
||||
return new AnalysisProperties(properties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProjectKeyWithBranch() {
|
||||
ProjectSyncContainer container = new ProjectSyncContainer(createParentContainer(), createProjectProperties(), true);
|
||||
public void testProjectRepository() {
|
||||
ProjectSyncContainer container = new ProjectSyncContainer(createParentContainer(), "my:project", true);
|
||||
container.doBeforeStart();
|
||||
container.getPicoContainer().start();
|
||||
|
||||
ProjectReactor projectReactor = container.getComponentByType(ProjectReactor.class);
|
||||
assertThat(projectReactor.getRoot().getKeyWithBranch()).isEqualTo("my:project:branch");
|
||||
container.getComponentByType(ProjectRepositories.class);
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@
|
||||
*/
|
||||
package org.sonar.batch.issue.tracking;
|
||||
|
||||
import org.sonar.batch.cache.WSLoader.LoadStrategy;
|
||||
import org.sonar.batch.cache.WSLoaderResult;
|
||||
|
||||
import org.sonar.batch.cache.WSLoader;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.junit.Before;
|
||||
@ -32,6 +32,8 @@ import org.sonar.api.utils.HttpDownloader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -50,19 +52,19 @@ public class DefaultServerLineHashesLoaderTest {
|
||||
@Test
|
||||
public void should_download_source_from_ws_if_preview_mode() {
|
||||
WSLoader wsLoader = mock(WSLoader.class);
|
||||
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
|
||||
when(wsLoader.loadString(anyString(), any(LoadStrategy.class))).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
|
||||
|
||||
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(wsLoader);
|
||||
|
||||
String[] hashes = lastSnapshots.getLineHashes("myproject:org/foo/Bar.c", null);
|
||||
assertThat(hashes).containsOnly("ae12", "", "43fb");
|
||||
verify(wsLoader).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FBar.c");
|
||||
verify(wsLoader).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FBar.c", LoadStrategy.CACHE_FIRST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_download_source_with_space_from_ws_if_preview_mode() {
|
||||
WSLoader server = mock(WSLoader.class);
|
||||
when(server.loadString(anyString())).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
|
||||
when(server.loadString(anyString(), any(LoadStrategy.class))).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
|
||||
|
||||
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
|
||||
|
||||
@ -70,13 +72,13 @@ public class DefaultServerLineHashesLoaderTest {
|
||||
String[] hashes = lastSnapshots.getLineHashes("myproject:org/foo/Foo Bar.c", fromCache);
|
||||
assertThat(fromCache.booleanValue()).isTrue();
|
||||
assertThat(hashes).containsOnly("ae12", "", "43fb");
|
||||
verify(server).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FFoo+Bar.c");
|
||||
verify(server).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FFoo+Bar.c", LoadStrategy.CACHE_FIRST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_to_download_source_from_ws() throws URISyntaxException {
|
||||
WSLoader server = mock(WSLoader.class);
|
||||
when(server.loadString(anyString())).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
|
||||
when(server.loadString(anyString(), any(LoadStrategy.class))).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
|
||||
|
||||
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
|
||||
|
||||
|
@ -19,27 +19,26 @@
|
||||
*/
|
||||
package org.sonar.batch.mediumtest;
|
||||
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.sonar.batch.cache.ProjectCacheStatus;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonarqube.ws.Rules.ListResponse.Rule;
|
||||
import org.sonar.batch.bootstrapper.IssueListener;
|
||||
import org.sonar.api.server.rule.RulesDefinition.Repository;
|
||||
import org.sonar.api.server.rule.RulesDefinition;
|
||||
import org.sonar.batch.rule.RulesLoader;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@ -75,12 +74,41 @@ public class BatchMediumTester {
|
||||
|
||||
public static final String MEDIUM_TEST_ENABLED = "sonar.mediumTest.enabled";
|
||||
private Batch batch;
|
||||
private static Path workingDir = null;
|
||||
private static Path globalWorkingDir = null;
|
||||
|
||||
private static void createWorkingDirs() throws IOException {
|
||||
destroyWorkingDirs();
|
||||
|
||||
workingDir = java.nio.file.Files.createTempDirectory("mediumtest-working-dir");
|
||||
globalWorkingDir = java.nio.file.Files.createTempDirectory("mediumtest-global-working-dir");
|
||||
}
|
||||
|
||||
private static void destroyWorkingDirs() throws IOException {
|
||||
if(workingDir != null) {
|
||||
FileUtils.deleteDirectory(workingDir.toFile());
|
||||
workingDir = null;
|
||||
}
|
||||
|
||||
if(globalWorkingDir != null) {
|
||||
FileUtils.deleteDirectory(globalWorkingDir.toFile());
|
||||
globalWorkingDir = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static BatchMediumTesterBuilder builder() {
|
||||
try {
|
||||
createWorkingDirs();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
BatchMediumTesterBuilder builder = new BatchMediumTesterBuilder().registerCoreMetrics();
|
||||
builder.bootstrapProperties.put(MEDIUM_TEST_ENABLED, "true");
|
||||
builder.bootstrapProperties.put(ReportPublisher.KEEP_REPORT_PROP_KEY, "true");
|
||||
builder.bootstrapProperties.put(CoreProperties.WORKING_DIRECTORY, Files.createTempDir().getAbsolutePath());
|
||||
builder.bootstrapProperties.put(CoreProperties.WORKING_DIRECTORY, workingDir.toString());
|
||||
builder.bootstrapProperties.put(CoreProperties.GLOBAL_WORKING_DIRECTORY, globalWorkingDir.toString());
|
||||
return builder;
|
||||
}
|
||||
|
||||
@ -93,12 +121,18 @@ public class BatchMediumTester {
|
||||
private final Map<String, String> bootstrapProperties = new HashMap<>();
|
||||
private final FakeRulesLoader rulesLoader = new FakeRulesLoader();
|
||||
private final FakeProjectCacheStatus projectCacheStatus = new FakeProjectCacheStatus();
|
||||
private boolean associated = true;
|
||||
private LogOutput logOutput = null;
|
||||
|
||||
public BatchMediumTester build() {
|
||||
return new BatchMediumTester(this);
|
||||
}
|
||||
|
||||
public BatchMediumTesterBuilder setAssociated(boolean associated) {
|
||||
this.associated = associated;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BatchMediumTesterBuilder setLogOutput(LogOutput logOutput) {
|
||||
this.logOutput = logOutput;
|
||||
return this;
|
||||
@ -210,6 +244,11 @@ public class BatchMediumTester {
|
||||
|
||||
public void stop() {
|
||||
batch.stop();
|
||||
try {
|
||||
destroyWorkingDirs();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void syncProject(String projectKey) {
|
||||
@ -217,21 +256,24 @@ public class BatchMediumTester {
|
||||
}
|
||||
|
||||
private BatchMediumTester(BatchMediumTesterBuilder builder) {
|
||||
batch = Batch.builder()
|
||||
Batch.Builder batchBuilder = Batch.builder()
|
||||
.setEnableLoggingConfiguration(true)
|
||||
.addComponents(
|
||||
new EnvironmentInformation("mediumTest", "1.0"),
|
||||
builder.pluginInstaller,
|
||||
builder.globalRefProvider,
|
||||
builder.projectRefProvider,
|
||||
builder.serverIssues,
|
||||
builder.serverLineHashes,
|
||||
builder.rulesLoader,
|
||||
builder.projectCacheStatus,
|
||||
builder.projectRefProvider,
|
||||
new DefaultDebtModel())
|
||||
.setBootstrapProperties(builder.bootstrapProperties)
|
||||
.setLogOutput(builder.logOutput)
|
||||
.build();
|
||||
.setLogOutput(builder.logOutput);
|
||||
|
||||
if (builder.associated) {
|
||||
batchBuilder.addComponents(
|
||||
builder.serverIssues);
|
||||
}
|
||||
batch = batchBuilder.build();
|
||||
}
|
||||
|
||||
public TaskBuilder newTask() {
|
||||
@ -343,7 +385,7 @@ public class BatchMediumTester {
|
||||
private ProjectRepositories ref = new ProjectRepositories();
|
||||
|
||||
@Override
|
||||
public ProjectRepositories load(ProjectDefinition projDefinition, AnalysisProperties taskProperties, @Nullable MutableBoolean fromCache) {
|
||||
public ProjectRepositories load(String projectKey, @Nullable String sonarProfile, @Nullable MutableBoolean fromCache) {
|
||||
return ref;
|
||||
}
|
||||
|
||||
@ -385,7 +427,6 @@ public class BatchMediumTester {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FakeProjectCacheStatus implements ProjectCacheStatus {
|
||||
|
@ -19,22 +19,25 @@
|
||||
*/
|
||||
package org.sonar.batch.mediumtest.cache;
|
||||
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
|
||||
import org.junit.Test;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.sonar.api.CoreProperties;
|
||||
import org.sonar.batch.mediumtest.BatchMediumTester;
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.sonar.xoo.XooPlugin;
|
||||
import org.sonar.xoo.rule.XooRulesDefinition;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class CacheSyncTest {
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
public BatchMediumTester tester;
|
||||
private BatchMediumTester tester;
|
||||
|
||||
@After
|
||||
public void stop() {
|
||||
@ -47,9 +50,42 @@ public class CacheSyncTest {
|
||||
@Test
|
||||
public void testSyncFirstTime() {
|
||||
FileData file1 = new FileData("hash", true);
|
||||
String[] hashes = new String[] {
|
||||
"line1", "line2"
|
||||
};
|
||||
|
||||
tester = BatchMediumTester.builder()
|
||||
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
|
||||
.registerPlugin("xoo", new XooPlugin())
|
||||
.addRules(new XooRulesDefinition())
|
||||
.addQProfile("lang", "name")
|
||||
.activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
|
||||
.setPreviousAnalysisDate(new Date())
|
||||
.addFileData("test-project", "file1", file1)
|
||||
.build();
|
||||
|
||||
tester.start();
|
||||
tester.syncProject("test-project");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonAssociated() {
|
||||
FileData file1 = new FileData("hash", true);
|
||||
|
||||
tester = BatchMediumTester.builder()
|
||||
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
|
||||
.registerPlugin("xoo", new XooPlugin())
|
||||
.addRules(new XooRulesDefinition())
|
||||
.addQProfile("lang", "name")
|
||||
.activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
|
||||
.setPreviousAnalysisDate(new Date())
|
||||
.addFileData("test-project", "file1", file1)
|
||||
.build();
|
||||
|
||||
tester.start();
|
||||
tester.syncProject(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoQProfile() {
|
||||
FileData file1 = new FileData("hash", true);
|
||||
|
||||
tester = BatchMediumTester.builder()
|
||||
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
|
||||
@ -58,12 +94,13 @@ public class CacheSyncTest {
|
||||
.activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
|
||||
.setPreviousAnalysisDate(new Date())
|
||||
.addFileData("test-project", "file1", file1)
|
||||
.mockLineHashes("test-project:file1", hashes)
|
||||
.build();
|
||||
|
||||
tester.start();
|
||||
tester.syncProject("test-project");
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectMessage("No quality");
|
||||
tester.syncProject("test-project");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.mediumtest.issuesmode;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.filefilter.FileFilterUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.sonar.api.CoreProperties;
|
||||
import org.sonar.api.utils.log.LogTester;
|
||||
import org.sonar.batch.mediumtest.BatchMediumTester;
|
||||
import org.sonar.batch.mediumtest.TaskResult;
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
import org.sonar.xoo.XooPlugin;
|
||||
import org.sonar.xoo.rule.XooRulesDefinition;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class NonAssociatedProject {
|
||||
@org.junit.Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
@org.junit.Rule
|
||||
public LogTester logTester = new LogTester();
|
||||
|
||||
public BatchMediumTester tester;
|
||||
|
||||
@Before
|
||||
public void prepare() throws IOException {
|
||||
tester = BatchMediumTester.builder()
|
||||
.bootstrapProperties(ImmutableMap.of(
|
||||
CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES,
|
||||
CoreProperties.GLOBAL_WORKING_DIRECTORY, temp.newFolder().getAbsolutePath()))
|
||||
.registerPlugin("xoo", new XooPlugin())
|
||||
.addQProfile("xoo", "Sonar Way")
|
||||
.addRules(new XooRulesDefinition())
|
||||
.addRule("manual:MyManualIssue", "manual", "MyManualIssue", "My manual issue")
|
||||
.addRule("manual:MyManualIssueDup", "manual", "MyManualIssue", "My manual issue")
|
||||
.activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo"))
|
||||
.activateRule(new ActiveRule("xoo", "OneIssueOnDirPerFile", null, "OneIssueOnDirPerFile", "MAJOR", null, "xoo"))
|
||||
.activateRule(new ActiveRule("xoo", "OneIssuePerModule", null, "OneIssuePerModule", "MAJOR", null, "xoo"))
|
||||
.activateRule(new ActiveRule("manual", "MyManualIssue", null, "My manual issue", "MAJOR", null, null))
|
||||
.setAssociated(false)
|
||||
.build();
|
||||
tester.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stop() {
|
||||
tester.stop();
|
||||
}
|
||||
|
||||
private File copyProject(String path) throws Exception {
|
||||
File projectDir = temp.newFolder();
|
||||
File originalProjectDir = new File(IssueModeAndReportsMediumTest.class.getResource(path).toURI());
|
||||
FileUtils.copyDirectory(originalProjectDir, projectDir, FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter(".sonar")));
|
||||
return projectDir;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonAssociated() throws Exception {
|
||||
File projectDir = copyProject("/mediumtest/xoo/multi-modules-sample-not-associated");
|
||||
|
||||
TaskResult result = tester
|
||||
.newScanTask(new File(projectDir, "sonar-project.properties"))
|
||||
.start();
|
||||
|
||||
}
|
||||
}
|
@ -23,10 +23,8 @@ import org.sonar.batch.cache.WSLoaderResult;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.cache.WSLoader;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
@ -40,7 +38,6 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.api.utils.MessageException;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
import org.sonar.batch.rule.ModuleQProfiles;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@ -56,7 +53,6 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
private WSLoader wsLoader;
|
||||
private DefaultAnalysisMode analysisMode;
|
||||
private ProjectDefinition project;
|
||||
private AnalysisProperties taskProperties;
|
||||
|
||||
@Before
|
||||
public void prepare() {
|
||||
@ -65,7 +61,6 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
loader = new DefaultProjectRepositoriesLoader(wsLoader, analysisMode);
|
||||
loader = spy(loader);
|
||||
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>("{}", true));
|
||||
taskProperties = new AnalysisProperties(Maps.<String, String>newHashMap(), "");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -73,11 +68,11 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
addQualityProfile();
|
||||
project = ProjectDefinition.create().setKey("foo");
|
||||
when(analysisMode.isIssues()).thenReturn(false);
|
||||
loader.load(project, taskProperties, null);
|
||||
loader.load(project.getKeyWithBranch(), null, null);
|
||||
verify(wsLoader).loadString("/batch/project?key=foo&preview=false");
|
||||
|
||||
when(analysisMode.isIssues()).thenReturn(true);
|
||||
loader.load(project, taskProperties, null);
|
||||
loader.load(project.getKeyWithBranch(), null, null);
|
||||
verify(wsLoader).loadString("/batch/project?key=foo&preview=true");
|
||||
}
|
||||
|
||||
@ -88,7 +83,7 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>(response, true));
|
||||
project = ProjectDefinition.create().setKey("foo");
|
||||
MutableBoolean fromCache = new MutableBoolean();
|
||||
ProjectRepositories projectRepo = loader.load(project, taskProperties, fromCache);
|
||||
ProjectRepositories projectRepo = loader.load(project.getKeyWithBranch(), null, fromCache);
|
||||
|
||||
assertThat(fromCache.booleanValue()).isTrue();
|
||||
assertThat(projectRepo.activeRules().size()).isEqualTo(221);
|
||||
@ -100,7 +95,7 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
public void passAndEncodeProjectKeyParameter() {
|
||||
addQualityProfile();
|
||||
project = ProjectDefinition.create().setKey("foo bàr");
|
||||
loader.load(project, taskProperties, null);
|
||||
loader.load(project.getKeyWithBranch(), null, null);
|
||||
verify(wsLoader).loadString("/batch/project?key=foo+b%C3%A0r&preview=false");
|
||||
}
|
||||
|
||||
@ -108,8 +103,7 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
public void passAndEncodeProfileParameter() {
|
||||
addQualityProfile();
|
||||
project = ProjectDefinition.create().setKey("foo");
|
||||
taskProperties.properties().put(ModuleQProfiles.SONAR_PROFILE_PROP, "my-profile#2");
|
||||
loader.load(project, taskProperties, null);
|
||||
loader.load(project.getKeyWithBranch(), "my-profile#2", null);
|
||||
verify(wsLoader).loadString("/batch/project?key=foo&profile=my-profile%232&preview=false");
|
||||
}
|
||||
|
||||
@ -121,7 +115,7 @@ public class DefaultProjectRepositoriesLoaderTest {
|
||||
project = ProjectDefinition.create().setKey("foo");
|
||||
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>(new ProjectRepositories().toJson(), true));
|
||||
|
||||
loader.load(project, taskProperties, null);
|
||||
loader.load(project.getKeyWithBranch(), null, null);
|
||||
}
|
||||
|
||||
private void addQualityProfile() {
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
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 DefaultProjectSettingsLoaderTest {
|
||||
private DefaultProjectSettingsLoader loader;
|
||||
private DefaultProjectRepositoriesFactory factory;
|
||||
private ProjectRepositories projectRepositories;
|
||||
|
||||
private FileData f1;
|
||||
private FileData f2;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
createProjectRepo();
|
||||
factory = mock(DefaultProjectRepositoriesFactory.class);
|
||||
when(factory.create()).thenReturn(projectRepositories);
|
||||
loader = new DefaultProjectSettingsLoader(factory);
|
||||
}
|
||||
|
||||
private void createProjectRepo() {
|
||||
projectRepositories = new ProjectRepositories();
|
||||
projectRepositories.setLastAnalysisDate(new Date(1000));
|
||||
|
||||
f1 = new FileData("hash1", true);
|
||||
f2 = new FileData("hash2", true);
|
||||
projectRepositories.addFileData("module1", "file1", f1);
|
||||
projectRepositories.addFileData("module1", "file2", f2);
|
||||
|
||||
projectRepositories.addSettings("module1", ImmutableMap.of("key", "value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ProjectSettingsRepo loaded = loader.load("project", null);
|
||||
|
||||
assertThat(loaded.fileData("module1", "file1")).isEqualTo(f1);
|
||||
assertThat(loaded.fileData("module1", "file2")).isEqualTo(f2);
|
||||
assertThat(loaded.settings("module1")).isEqualTo(ImmutableMap.of("key", "value"));
|
||||
assertThat(loaded.lastAnalysisDate()).isEqualTo(new Date(1000));
|
||||
|
||||
verify(factory).create();
|
||||
verifyNoMoreInteractions(factory);
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class DefaultQualityProfileLoaderTest {
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
private DefaultQualityProfileLoader qpLoader;
|
||||
private DefaultProjectRepositoriesFactory factory;
|
||||
private ProjectRepositories projectRepositories;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
projectRepositories = new ProjectRepositories();
|
||||
projectRepositories.addQProfile(new QProfile("profile", "name", "lang", new Date()));
|
||||
|
||||
factory = mock(DefaultProjectRepositoriesFactory.class);
|
||||
when(factory.create()).thenReturn(projectRepositories);
|
||||
qpLoader = new DefaultQualityProfileLoader(factory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Collection<QProfile> loaded = qpLoader.load("project", null);
|
||||
|
||||
assertThat(loaded).hasSize(1);
|
||||
assertThat(loaded.iterator().next().key()).isEqualTo("profile");
|
||||
verify(factory).create();
|
||||
verifyNoMoreInteractions(factory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoProfile() {
|
||||
projectRepositories = new ProjectRepositories();
|
||||
when(factory.create()).thenReturn(projectRepositories);
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectMessage("No quality profiles");
|
||||
|
||||
qpLoader.load("project", null);
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.repository;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.sonar.batch.protocol.input.QProfile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.sonar.batch.rule.ModuleQProfiles;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.junit.Test;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.sonar.api.batch.AnalysisMode;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.mockito.Mock;
|
||||
import org.junit.Before;
|
||||
|
||||
public class QualityProfileProviderTest {
|
||||
private QualityProfileProvider qualityProfileProvider;
|
||||
|
||||
@Mock
|
||||
private QualityProfileLoader loader;
|
||||
@Mock
|
||||
private ProjectReactor projectReactor;
|
||||
@Mock
|
||||
private AnalysisMode mode;
|
||||
@Mock
|
||||
private AnalysisProperties props;
|
||||
|
||||
private Collection<QProfile> response;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
qualityProfileProvider = new QualityProfileProvider();
|
||||
|
||||
ProjectDefinition root = mock(ProjectDefinition.class);
|
||||
when(root.getKeyWithBranch()).thenReturn("project");
|
||||
when(projectReactor.getRoot()).thenReturn(root);
|
||||
|
||||
response = new ArrayList<QProfile>(1);
|
||||
response.add(new QProfile("profile", "name", "lang", new Date()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProvide() {
|
||||
when(loader.load("project", null)).thenReturn(response);
|
||||
ModuleQProfiles qps = qualityProfileProvider.provide(projectReactor, loader, props, mode);
|
||||
assertResponse(qps);
|
||||
|
||||
verify(loader).load("project", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProfileProp() {
|
||||
when(loader.load("project", "custom")).thenReturn(response);
|
||||
when(props.property(ModuleQProfiles.SONAR_PROFILE_PROP)).thenReturn("custom");
|
||||
|
||||
ModuleQProfiles qps = qualityProfileProvider.provide(projectReactor, loader, props, mode);
|
||||
assertResponse(qps);
|
||||
|
||||
verify(loader).load("project", "custom");
|
||||
}
|
||||
|
||||
private void assertResponse(ModuleQProfiles qps) {
|
||||
assertThat(qps.findAll()).hasSize(1);
|
||||
assertThat(qps.findAll()).extracting("key").containsExactly("profile");
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SonarQube, open source software quality management tool.
|
||||
* Copyright (C) 2008-2014 SonarSource
|
||||
* mailto:contact AT sonarsource DOT com
|
||||
*
|
||||
* SonarQube is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SonarQube is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package org.sonar.batch.rule;
|
||||
|
||||
import org.sonar.batch.repository.DefaultProjectRepositoriesFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.sonar.batch.protocol.input.ActiveRule;
|
||||
import org.junit.Test;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.junit.Before;
|
||||
|
||||
public class DefaultActiveRulesLoaderTest {
|
||||
private DefaultActiveRulesLoader loader;
|
||||
private DefaultProjectRepositoriesFactory factory;
|
||||
private ProjectRepositories projectRepositories;
|
||||
|
||||
private ActiveRule response;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
response = mock(ActiveRule.class);
|
||||
when(response.ruleKey()).thenReturn("rule");
|
||||
|
||||
projectRepositories = new ProjectRepositories();
|
||||
projectRepositories.addActiveRule(response);
|
||||
|
||||
factory = mock(DefaultProjectRepositoriesFactory.class);
|
||||
when(factory.create()).thenReturn(projectRepositories);
|
||||
loader = new DefaultActiveRulesLoader(factory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Collection<String> profiles = ImmutableList.of("profile1");
|
||||
Collection<ActiveRule> activeRules = loader.load(profiles, "project");
|
||||
|
||||
assertThat(activeRules).hasSize(1);
|
||||
assertThat(activeRules.iterator().next().ruleKey()).isEqualTo("rule");
|
||||
|
||||
verify(factory).create();
|
||||
verifyNoMoreInteractions(factory);
|
||||
}
|
||||
|
||||
}
|
@ -19,9 +19,11 @@
|
||||
*/
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Table;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@ -29,10 +31,13 @@ import org.junit.rules.ExpectedException;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.api.config.PropertyDefinitions;
|
||||
import org.sonar.api.utils.MessageException;
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.bootstrap.GlobalSettings;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -43,15 +48,23 @@ public class ModuleSettingsTest {
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
ProjectRepositories projectRef;
|
||||
private DefaultAnalysisMode mode;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
projectRef = new ProjectRepositories();
|
||||
mode = mock(DefaultAnalysisMode.class);
|
||||
}
|
||||
|
||||
private ProjectSettingsRepo createSettings(String module, Map<String, String> settingsMap) {
|
||||
Table<String, String, FileData> fileData = ImmutableTable.of();
|
||||
Table<String, String, String> settings = HashBasedTable.create();
|
||||
|
||||
for (Map.Entry<String, String> e : settingsMap.entrySet()) {
|
||||
settings.put(module, e.getKey(), e.getValue());
|
||||
}
|
||||
return new ProjectSettingsRepo(settings, fileData, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOrderedProjects() {
|
||||
ProjectDefinition grandParent = ProjectDefinition.create();
|
||||
@ -74,11 +87,12 @@ public class ModuleSettingsTest {
|
||||
"overridding", "batch",
|
||||
"on-batch", "true"
|
||||
));
|
||||
projectRef.addSettings("struts-core", ImmutableMap.of("on-module", "true", "overridding", "module"));
|
||||
|
||||
ProjectSettingsRepo projSettingsRepo = createSettings("struts-core", ImmutableMap.of("on-module", "true", "overridding", "module"));
|
||||
|
||||
ProjectDefinition module = ProjectDefinition.create().setKey("struts-core");
|
||||
|
||||
ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projectRef, mode);
|
||||
ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projSettingsRepo, mode);
|
||||
|
||||
assertThat(moduleSettings.getString("overridding")).isEqualTo("module");
|
||||
assertThat(moduleSettings.getString("on-batch")).isEqualTo("true");
|
||||
@ -93,11 +107,12 @@ public class ModuleSettingsTest {
|
||||
when(batchSettings.getProperties()).thenReturn(ImmutableMap.of(
|
||||
"sonar.foo.secured", "bar"
|
||||
));
|
||||
projectRef.addSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
|
||||
|
||||
ProjectSettingsRepo projSettingsRepo = createSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
|
||||
|
||||
ProjectDefinition module = ProjectDefinition.create().setKey("struts-core");
|
||||
|
||||
ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projectRef, mode);
|
||||
ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projSettingsRepo, mode);
|
||||
|
||||
assertThat(moduleSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
|
||||
assertThat(moduleSettings.getString("sonar.foo.secured")).isEqualTo("bar");
|
||||
@ -110,13 +125,14 @@ public class ModuleSettingsTest {
|
||||
when(batchSettings.getProperties()).thenReturn(ImmutableMap.of(
|
||||
"sonar.foo.secured", "bar"
|
||||
));
|
||||
projectRef.addSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
|
||||
|
||||
ProjectSettingsRepo projSettingsRepo = createSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
|
||||
|
||||
when(mode.isIssues()).thenReturn(true);
|
||||
|
||||
ProjectDefinition module = ProjectDefinition.create().setKey("struts-core");
|
||||
|
||||
ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projectRef, mode);
|
||||
ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projSettingsRepo, mode);
|
||||
|
||||
assertThat(moduleSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
|
||||
|
||||
|
@ -20,7 +20,8 @@
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.sonar.api.batch.AnalysisMode;
|
||||
import org.sonar.batch.analysis.AnalysisProperties;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.junit.Rule;
|
||||
@ -38,6 +39,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ProjectReactorBuilderTest {
|
||||
@ -45,6 +49,13 @@ public class ProjectReactorBuilderTest {
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnalysisMode mode;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mode = mock(AnalysisMode.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDefineSimpleProject() {
|
||||
ProjectDefinition projectDefinition = loadProjectDefinition("simple-project");
|
||||
@ -78,12 +89,11 @@ public class ProjectReactorBuilderTest {
|
||||
public void shouldNotFailIfBlankSourceDirectory() {
|
||||
loadProjectDefinition("simple-project-with-blank-source-dir");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void modulesRepeatedIds() {
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("Two modules have the same id: module1");
|
||||
|
||||
loadProjectDefinition("multi-module-repeated-id");
|
||||
}
|
||||
|
||||
@ -101,8 +111,8 @@ public class ProjectReactorBuilderTest {
|
||||
assertThat(rootProject.getTestDirs().contains("tests")).isFalse();
|
||||
assertThat(rootProject.getBinaries().contains("target/classes")).isFalse();
|
||||
// and module properties must have been cleaned
|
||||
assertThat(rootProject.getProperties().getProperty("module1.sonar.projectKey")).isNull();
|
||||
assertThat(rootProject.getProperties().getProperty("module2.sonar.projectKey")).isNull();
|
||||
assertThat(rootProject.properties().get("module1.sonar.projectKey")).isNull();
|
||||
assertThat(rootProject.properties().get("module2.sonar.projectKey")).isNull();
|
||||
// Check baseDir and workDir
|
||||
assertThat(rootProject.getBaseDir().getCanonicalFile())
|
||||
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-all-in-root"));
|
||||
@ -125,8 +135,8 @@ public class ProjectReactorBuilderTest {
|
||||
assertThat(module1.getTestDirs()).contains("tests");
|
||||
assertThat(module1.getBinaries()).contains("target/classes");
|
||||
// and module properties must have been cleaned
|
||||
assertThat(module1.getProperties().getProperty("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module1.getProperties().getProperty("module2.sonar.projectKey")).isNull();
|
||||
assertThat(module1.properties().get("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module1.properties().get("module2.sonar.projectKey")).isNull();
|
||||
// Check baseDir and workDir
|
||||
assertThat(module1.getBaseDir().getCanonicalFile())
|
||||
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-all-in-root/module1"));
|
||||
@ -144,8 +154,8 @@ public class ProjectReactorBuilderTest {
|
||||
assertThat(module2.getTestDirs()).contains("tests");
|
||||
assertThat(module2.getBinaries()).contains("target/classes");
|
||||
// and module properties must have been cleaned
|
||||
assertThat(module2.getProperties().getProperty("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module2.getProperties().getProperty("module2.sonar.projectKey")).isNull();
|
||||
assertThat(module2.properties().get("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module2.properties().get("module2.sonar.projectKey")).isNull();
|
||||
// Check baseDir and workDir
|
||||
assertThat(module2.getBaseDir().getCanonicalFile())
|
||||
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-all-in-root/module2"));
|
||||
@ -160,8 +170,8 @@ public class ProjectReactorBuilderTest {
|
||||
|
||||
// CHECK ROOT
|
||||
// module properties must have been cleaned
|
||||
assertThat(rootProject.getProperties().getProperty("module1.sonar.moduleKey")).isNull();
|
||||
assertThat(rootProject.getProperties().getProperty("module2.sonar.moduleKey")).isNull();
|
||||
assertThat(rootProject.properties().get("module1.sonar.moduleKey")).isNull();
|
||||
assertThat(rootProject.properties().get("module2.sonar.moduleKey")).isNull();
|
||||
|
||||
// CHECK MODULES
|
||||
List<ProjectDefinition> modules = rootProject.getSubProjects();
|
||||
@ -301,8 +311,8 @@ public class ProjectReactorBuilderTest {
|
||||
public void multiModuleProperties() {
|
||||
ProjectDefinition projectDefinition = loadProjectDefinition("big-multi-module-definitions-all-in-root");
|
||||
|
||||
assertThat(projectDefinition.getProperties().getProperty("module11.property")).isNull();
|
||||
assertThat(projectDefinition.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(projectDefinition.properties().get("module11.property")).isNull();
|
||||
assertThat(projectDefinition.properties().get("sonar.profile")).isEqualTo("Foo");
|
||||
ProjectDefinition module1 = null;
|
||||
ProjectDefinition module2 = null;
|
||||
for (ProjectDefinition prj : projectDefinition.getSubProjects()) {
|
||||
@ -312,12 +322,12 @@ public class ProjectReactorBuilderTest {
|
||||
module2 = prj;
|
||||
}
|
||||
}
|
||||
assertThat(module1.getProperties().getProperty("module11.property")).isNull();
|
||||
assertThat(module1.getProperties().getProperty("property")).isNull();
|
||||
assertThat(module1.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(module2.getProperties().getProperty("module11.property")).isNull();
|
||||
assertThat(module2.getProperties().getProperty("property")).isNull();
|
||||
assertThat(module2.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(module1.properties().get("module11.property")).isNull();
|
||||
assertThat(module1.properties().get("property")).isNull();
|
||||
assertThat(module1.properties().get("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(module2.properties().get("module11.property")).isNull();
|
||||
assertThat(module2.properties().get("property")).isNull();
|
||||
assertThat(module2.properties().get("sonar.profile")).isEqualTo("Foo");
|
||||
|
||||
ProjectDefinition module11 = null;
|
||||
ProjectDefinition module12 = null;
|
||||
@ -328,13 +338,13 @@ public class ProjectReactorBuilderTest {
|
||||
module12 = prj;
|
||||
}
|
||||
}
|
||||
assertThat(module11.getProperties().getProperty("module1.module11.property")).isNull();
|
||||
assertThat(module11.getProperties().getProperty("module11.property")).isNull();
|
||||
assertThat(module11.getProperties().getProperty("property")).isEqualTo("My module11 property");
|
||||
assertThat(module11.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(module12.getProperties().getProperty("module11.property")).isNull();
|
||||
assertThat(module12.getProperties().getProperty("property")).isNull();
|
||||
assertThat(module12.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(module11.properties().get("module1.module11.property")).isNull();
|
||||
assertThat(module11.properties().get("module11.property")).isNull();
|
||||
assertThat(module11.properties().get("property")).isEqualTo("My module11 property");
|
||||
assertThat(module11.properties().get("sonar.profile")).isEqualTo("Foo");
|
||||
assertThat(module12.properties().get("module11.property")).isNull();
|
||||
assertThat(module12.properties().get("property")).isNull();
|
||||
assertThat(module12.properties().get("sonar.profile")).isEqualTo("Foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -344,7 +354,7 @@ public class ProjectReactorBuilderTest {
|
||||
AnalysisProperties taskProperties = new AnalysisProperties(props, null);
|
||||
assertThat(taskProperties.property("module1.module11.property")).isEqualTo("My module11 property");
|
||||
|
||||
new ProjectReactorBuilder(taskProperties).execute();
|
||||
new ProjectReactorBuilder(taskProperties, mode).execute();
|
||||
|
||||
assertThat(taskProperties.property("module1.module11.property")).isNull();
|
||||
}
|
||||
@ -443,19 +453,27 @@ public class ProjectReactorBuilderTest {
|
||||
|
||||
@Test
|
||||
public void shouldInitRootWorkDir() {
|
||||
ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(Maps.<String, String>newHashMap(), null));
|
||||
ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(Maps.<String, String>newHashMap(), null), mode);
|
||||
File baseDir = new File("target/tmp/baseDir");
|
||||
|
||||
File workDir = builder.initRootProjectWorkDir(baseDir, Maps.<String, String>newHashMap());
|
||||
|
||||
assertThat(workDir).isEqualTo(new File(baseDir, ".sonar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonAssociatedMode() {
|
||||
when(mode.isIssues()).thenReturn(true);
|
||||
ProjectDefinition project = loadProjectDefinition("multi-module-with-basedir-not-associated");
|
||||
|
||||
assertThat(project.getKey()).isEqualTo("project");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldInitWorkDirWithCustomRelativeFolder() {
|
||||
Map<String, String> props = Maps.<String, String>newHashMap();
|
||||
props.put("sonar.working.directory", ".foo");
|
||||
ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null));
|
||||
ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null), mode);
|
||||
File baseDir = new File("target/tmp/baseDir");
|
||||
|
||||
File workDir = builder.initRootProjectWorkDir(baseDir, props);
|
||||
@ -467,7 +485,7 @@ public class ProjectReactorBuilderTest {
|
||||
public void shouldInitRootWorkDirWithCustomAbsoluteFolder() {
|
||||
Map<String, String> props = Maps.<String, String>newHashMap();
|
||||
props.put("sonar.working.directory", new File("src").getAbsolutePath());
|
||||
ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null));
|
||||
ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null), mode);
|
||||
File baseDir = new File("target/tmp/baseDir");
|
||||
|
||||
File workDir = builder.initRootProjectWorkDir(baseDir, props);
|
||||
@ -477,16 +495,16 @@ public class ProjectReactorBuilderTest {
|
||||
|
||||
@Test
|
||||
public void shouldFailIf2ModulesWithSameKey() {
|
||||
Properties props = new Properties();
|
||||
Map<String, String> props = new HashMap<>();
|
||||
props.put("sonar.projectKey", "root");
|
||||
ProjectDefinition root = ProjectDefinition.create().setProperties(props);
|
||||
|
||||
Properties props1 = new Properties();
|
||||
Map<String, String> props1 = new HashMap<>();
|
||||
props1.put("sonar.projectKey", "mod1");
|
||||
root.addSubProject(ProjectDefinition.create().setProperties(props1));
|
||||
|
||||
// Check uniqueness of a new module: OK
|
||||
Properties props2 = new Properties();
|
||||
Map<String, String> props2 = new HashMap<>();
|
||||
props2.put("sonar.projectKey", "mod2");
|
||||
ProjectDefinition mod2 = ProjectDefinition.create().setProperties(props2);
|
||||
ProjectReactorBuilder.checkUniquenessOfChildKey(mod2, root);
|
||||
@ -519,7 +537,7 @@ public class ProjectReactorBuilderTest {
|
||||
private ProjectDefinition loadProjectDefinition(String projectFolder) {
|
||||
Map<String, String> props = loadProps(projectFolder);
|
||||
AnalysisProperties bootstrapProps = new AnalysisProperties(props, null);
|
||||
ProjectReactor projectReactor = new ProjectReactorBuilder(bootstrapProps).execute();
|
||||
ProjectReactor projectReactor = new ProjectReactorBuilder(bootstrapProps,mode).execute();
|
||||
return projectReactor.getRoot();
|
||||
}
|
||||
|
||||
@ -594,8 +612,8 @@ public class ProjectReactorBuilderTest {
|
||||
assertThat(rootProject.getTestDirs().contains("tests")).isFalse();
|
||||
assertThat(rootProject.getBinaries().contains("target/classes")).isFalse();
|
||||
// and module properties must have been cleaned
|
||||
assertThat(rootProject.getProperties().getProperty("module1.sonar.projectKey")).isNull();
|
||||
assertThat(rootProject.getProperties().getProperty("module2.sonar.projectKey")).isNull();
|
||||
assertThat(rootProject.properties().get("module1.sonar.projectKey")).isNull();
|
||||
assertThat(rootProject.properties().get("module2.sonar.projectKey")).isNull();
|
||||
// Check baseDir and workDir
|
||||
assertThat(rootProject.getBaseDir().getCanonicalFile())
|
||||
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-same-prefix"));
|
||||
@ -618,8 +636,8 @@ public class ProjectReactorBuilderTest {
|
||||
assertThat(module1.getTestDirs()).contains("tests");
|
||||
assertThat(module1.getBinaries()).contains("target/classes");
|
||||
// and module properties must have been cleaned
|
||||
assertThat(module1.getProperties().getProperty("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module1.getProperties().getProperty("module2.sonar.projectKey")).isNull();
|
||||
assertThat(module1.properties().get("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module1.properties().get("module2.sonar.projectKey")).isNull();
|
||||
// Check baseDir and workDir
|
||||
assertThat(module1.getBaseDir().getCanonicalFile())
|
||||
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-same-prefix/module1"));
|
||||
@ -637,8 +655,8 @@ public class ProjectReactorBuilderTest {
|
||||
assertThat(module1Feature.getTestDirs()).contains("tests");
|
||||
assertThat(module1Feature.getBinaries()).contains("target/classes");
|
||||
// and module properties must have been cleaned
|
||||
assertThat(module1Feature.getProperties().getProperty("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module1Feature.getProperties().getProperty("module2.sonar.projectKey")).isNull();
|
||||
assertThat(module1Feature.properties().get("module1.sonar.projectKey")).isNull();
|
||||
assertThat(module1Feature.properties().get("module2.sonar.projectKey")).isNull();
|
||||
// Check baseDir and workDir
|
||||
assertThat(module1Feature.getBaseDir().getCanonicalFile())
|
||||
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-same-prefix/module1.feature"));
|
||||
|
@ -27,7 +27,6 @@ import org.sonar.api.CoreProperties;
|
||||
import org.sonar.api.batch.bootstrap.ProjectDefinition;
|
||||
import org.sonar.api.batch.bootstrap.ProjectReactor;
|
||||
import org.sonar.api.config.Settings;
|
||||
import org.sonar.api.utils.SonarException;
|
||||
|
||||
public class ProjectReactorValidatorTest {
|
||||
|
||||
@ -90,7 +89,7 @@ public class ProjectReactorValidatorTest {
|
||||
public void fail_with_invalid_key() {
|
||||
ProjectReactor reactor = createProjectReactor("foo$bar");
|
||||
|
||||
thrown.expect(SonarException.class);
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("\"foo$bar\" is not a valid project or module key");
|
||||
validator.validate(reactor);
|
||||
}
|
||||
@ -99,7 +98,7 @@ public class ProjectReactorValidatorTest {
|
||||
public void fail_with_backslash_in_key() {
|
||||
ProjectReactor reactor = createProjectReactor("foo\\bar");
|
||||
|
||||
thrown.expect(SonarException.class);
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("\"foo\\bar\" is not a valid project or module key");
|
||||
validator.validate(reactor);
|
||||
}
|
||||
@ -117,7 +116,7 @@ public class ProjectReactorValidatorTest {
|
||||
@Test
|
||||
public void fail_with_invalid_branch() {
|
||||
ProjectReactor reactor = createProjectReactor("foo", "bran#ch");
|
||||
thrown.expect(SonarException.class);
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("\"bran#ch\" is not a valid branch name");
|
||||
validator.validate(reactor);
|
||||
}
|
||||
@ -125,7 +124,7 @@ public class ProjectReactorValidatorTest {
|
||||
@Test
|
||||
public void fail_with_colon_in_branch() {
|
||||
ProjectReactor reactor = createProjectReactor("foo", "bran:ch");
|
||||
thrown.expect(SonarException.class);
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("\"bran:ch\" is not a valid branch name");
|
||||
validator.validate(reactor);
|
||||
}
|
||||
@ -134,7 +133,7 @@ public class ProjectReactorValidatorTest {
|
||||
public void fail_with_only_digits() {
|
||||
ProjectReactor reactor = createProjectReactor("12345");
|
||||
|
||||
thrown.expect(SonarException.class);
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("\"12345\" is not a valid project or module key");
|
||||
validator.validate(reactor);
|
||||
}
|
||||
@ -144,7 +143,7 @@ public class ProjectReactorValidatorTest {
|
||||
ProjectReactor reactor = createProjectReactor("foo");
|
||||
settings.setProperty("sonar.phase", "phase");
|
||||
|
||||
thrown.expect(SonarException.class);
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("\"sonar.phase\" is deprecated");
|
||||
validator.validate(reactor);
|
||||
}
|
||||
|
@ -19,8 +19,13 @@
|
||||
*/
|
||||
package org.sonar.batch.scan;
|
||||
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
import org.sonar.batch.analysis.DefaultAnalysisMode;
|
||||
import org.sonar.batch.bootstrap.GlobalMode;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@ -40,7 +45,6 @@ import org.sonar.api.utils.log.LoggerLevel;
|
||||
import org.sonar.batch.bootstrap.GlobalProperties;
|
||||
import org.sonar.batch.bootstrap.GlobalSettings;
|
||||
import org.sonar.batch.protocol.input.GlobalRepositories;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
@ -52,16 +56,20 @@ public class ProjectSettingsTest {
|
||||
@Rule
|
||||
public LogTester logTester = new LogTester();
|
||||
|
||||
ProjectRepositories projectRef;
|
||||
ProjectDefinition project = ProjectDefinition.create().setKey("struts");
|
||||
GlobalSettings bootstrapProps;
|
||||
private ProjectSettingsRepo projectRef;
|
||||
private ProjectDefinition project;
|
||||
private GlobalSettings bootstrapProps;
|
||||
private Table<String, String, FileData> emptyFileData;
|
||||
private Table<String, String, String> emptySettings;
|
||||
|
||||
private GlobalMode globalMode;
|
||||
private DefaultAnalysisMode mode;
|
||||
|
||||
@Before
|
||||
public void prepare() {
|
||||
projectRef = new ProjectRepositories();
|
||||
emptyFileData = ImmutableTable.of();
|
||||
emptySettings = ImmutableTable.of();
|
||||
project = ProjectDefinition.create().setKey("struts");
|
||||
globalMode = mock(GlobalMode.class);
|
||||
mode = mock(DefaultAnalysisMode.class);
|
||||
bootstrapProps = new GlobalSettings(new GlobalProperties(Collections.<String, String>emptyMap()), new PropertyDefinitions(), new GlobalRepositories(), globalMode);
|
||||
@ -71,6 +79,7 @@ public class ProjectSettingsTest {
|
||||
public void should_load_project_props() {
|
||||
project.setProperty("project.prop", "project");
|
||||
|
||||
projectRef = new ProjectSettingsRepo(emptySettings, emptyFileData, null);
|
||||
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
|
||||
|
||||
assertThat(batchSettings.getString("project.prop")).isEqualTo("project");
|
||||
@ -78,10 +87,12 @@ public class ProjectSettingsTest {
|
||||
|
||||
@Test
|
||||
public void should_load_project_root_settings() {
|
||||
projectRef.addSettings("struts", ImmutableMap.of("sonar.cpd.cross", "true", "sonar.java.coveragePlugin", "jacoco"));
|
||||
Table<String, String, String> settings = HashBasedTable.create();
|
||||
settings.put("struts", "sonar.cpd.cross", "true");
|
||||
settings.put("struts", "sonar.java.coveragePlugin", "jacoco");
|
||||
|
||||
projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
|
||||
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
|
||||
|
||||
assertThat(batchSettings.getString("sonar.java.coveragePlugin")).isEqualTo("jacoco");
|
||||
}
|
||||
|
||||
@ -89,7 +100,11 @@ public class ProjectSettingsTest {
|
||||
public void should_load_project_root_settings_on_branch() {
|
||||
project.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "mybranch");
|
||||
|
||||
projectRef.addSettings("struts:mybranch", ImmutableMap.of("sonar.cpd.cross", "true", "sonar.java.coveragePlugin", "jacoco"));
|
||||
Table<String, String, String> settings = HashBasedTable.create();
|
||||
settings.put("struts:mybranch", "sonar.cpd.cross", "true");
|
||||
settings.put("struts:mybranch", "sonar.java.coveragePlugin", "jacoco");
|
||||
|
||||
projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
|
||||
|
||||
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
|
||||
|
||||
@ -98,8 +113,11 @@ public class ProjectSettingsTest {
|
||||
|
||||
@Test
|
||||
public void should_not_fail_when_accessing_secured_properties() {
|
||||
projectRef.addSettings("struts", ImmutableMap.of("sonar.foo.secured", "bar", "sonar.foo.license.secured", "bar2"));
|
||||
Table<String, String, String> settings = HashBasedTable.create();
|
||||
settings.put("struts", "sonar.foo.secured", "bar");
|
||||
settings.put("struts", "sonar.foo.license.secured", "bar2");
|
||||
|
||||
projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
|
||||
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
|
||||
|
||||
assertThat(batchSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
|
||||
@ -108,10 +126,13 @@ public class ProjectSettingsTest {
|
||||
|
||||
@Test
|
||||
public void should_fail_when_accessing_secured_properties_in_issues_mode() {
|
||||
projectRef.addSettings("struts", ImmutableMap.of("sonar.foo.secured", "bar", "sonar.foo.license.secured", "bar2"));
|
||||
Table<String, String, String> settings = HashBasedTable.create();
|
||||
settings.put("struts", "sonar.foo.secured", "bar");
|
||||
settings.put("struts", "sonar.foo.license.secured", "bar2");
|
||||
|
||||
when(mode.isIssues()).thenReturn(true);
|
||||
|
||||
projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
|
||||
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
|
||||
|
||||
assertThat(batchSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
|
||||
@ -123,10 +144,13 @@ public class ProjectSettingsTest {
|
||||
|
||||
@Test
|
||||
public void should_log_a_warning_when_a_dropper_property_is_present() {
|
||||
GlobalSettings settings = new GlobalSettings(new GlobalProperties(ImmutableMap.of("sonar.qualitygate", "somevalue")), new PropertyDefinitions(), new GlobalRepositories(), globalMode);
|
||||
GlobalSettings settings = new GlobalSettings(new GlobalProperties(ImmutableMap.of("sonar.qualitygate", "somevalue")), new PropertyDefinitions(), new GlobalRepositories(),
|
||||
globalMode);
|
||||
projectRef = new ProjectSettingsRepo(emptySettings, emptyFileData, null);
|
||||
new ProjectSettings(new ProjectReactor(project), settings, new PropertyDefinitions(), projectRef, mode);
|
||||
|
||||
assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly("Property 'sonar.qualitygate' is not supported any more. It will be ignored.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,16 +19,16 @@
|
||||
*/
|
||||
package org.sonar.batch.scan.filesystem;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class StatusDetectionFactoryTest {
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
StatusDetectionFactory factory = new StatusDetectionFactory(mock(ProjectRepositories.class));
|
||||
StatusDetectionFactory factory = new StatusDetectionFactory(mock(ProjectSettingsRepo.class));
|
||||
StatusDetection detection = factory.create();
|
||||
assertThat(detection).isNotNull();
|
||||
}
|
||||
|
@ -19,23 +19,35 @@
|
||||
*/
|
||||
package org.sonar.batch.scan.filesystem;
|
||||
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
|
||||
import org.sonar.batch.repository.ProjectSettingsRepo;
|
||||
import org.junit.Test;
|
||||
import org.sonar.api.batch.fs.InputFile;
|
||||
import org.sonar.batch.protocol.input.FileData;
|
||||
import org.sonar.batch.protocol.input.ProjectRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class StatusDetectionTest {
|
||||
@Test
|
||||
public void detect_status() {
|
||||
ProjectRepositories ref = new ProjectRepositories();
|
||||
ref.addFileData("foo", "src/Foo.java", new FileData("ABCDE", true));
|
||||
ref.addFileData("foo", "src/Bar.java", new FileData("FGHIJ", true));
|
||||
Table<String, String, String> t = ImmutableTable.of();
|
||||
ProjectSettingsRepo ref = new ProjectSettingsRepo(t, createTable(), null);
|
||||
StatusDetection statusDetection = new StatusDetection(ref);
|
||||
|
||||
assertThat(statusDetection.status("foo", "src/Foo.java", "ABCDE")).isEqualTo(InputFile.Status.SAME);
|
||||
assertThat(statusDetection.status("foo", "src/Foo.java", "XXXXX")).isEqualTo(InputFile.Status.CHANGED);
|
||||
assertThat(statusDetection.status("foo", "src/Other.java", "QWERT")).isEqualTo(InputFile.Status.ADDED);
|
||||
}
|
||||
|
||||
private static Table<String, String, FileData> createTable() {
|
||||
Table<String, String, FileData> t = HashBasedTable.create();
|
||||
|
||||
t.put("foo", "src/Foo.java", new FileData("ABCDE", true));
|
||||
t.put("foo", "src/Bar.java", new FileData("FGHIJ", true));
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.sonar.it.samples.modules.a1;
|
||||
|
||||
public class HelloA1 {
|
||||
private int i;
|
||||
private HelloA1() {
|
||||
|
||||
}
|
||||
|
||||
public void hello() {
|
||||
System.out.println("hello" + " xoo");
|
||||
}
|
||||
|
||||
protected String getHello() {
|
||||
return "hello";
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.sonar.it.samples.modules.a2;
|
||||
|
||||
public class HelloA2 {
|
||||
private int i;
|
||||
private HelloA2() {
|
||||
|
||||
}
|
||||
|
||||
public void hello() {
|
||||
System.out.println("hello" + " xoo");
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.sonar.it.samples.modules.b1;
|
||||
|
||||
public class HelloB1 {
|
||||
private int i;
|
||||
private HelloB1() {
|
||||
|
||||
}
|
||||
|
||||
public void hello() {
|
||||
System.out.println("hello" + " world");
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.sonar.it.samples.modules.b2;
|
||||
|
||||
public class HelloB2 {
|
||||
private int i;
|
||||
private HelloB2() {
|
||||
|
||||
}
|
||||
|
||||
public void hello() {
|
||||
System.out.println("hello" + " world");
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
# Root project information
|
||||
#sonar.projectKey=com.sonarsource.it.samples:multi-modules-sample
|
||||
sonar.projectName=Sonar :: Integration Tests :: Multi-modules Sample
|
||||
sonar.projectVersion=1.0-SNAPSHOT
|
||||
|
||||
sonar.language=xoo
|
||||
|
||||
# Some properties that will be inherited by the modules
|
||||
sonar.sources=src/main/xoo
|
||||
|
||||
# List of the module identifiers
|
||||
sonar.modules=module_a,module_b
|
||||
|
||||
module_a.sonar.projectKey=module_a
|
||||
module_a.sonar.projectName=Module A
|
||||
|
||||
module_a.sonar.modules=module_a1,module_a2
|
||||
|
||||
module_a.module_a1.sonar.projectName=Sub-module A1
|
||||
|
||||
module_a.module_a2.sonar.projectName=Sub-module A2
|
||||
|
||||
|
||||
module_b.sonar.projectKey=module_b
|
||||
module_b.sonar.projectName=Module B
|
||||
|
||||
module_b.sonar.modules=module_b1,module_b2
|
||||
|
||||
module_b.module_b1.sonar.projectName=Sub-module B1
|
||||
|
||||
module_b.module_b2.sonar.projectName=Sub-module B2
|
@ -1,49 +0,0 @@
|
||||
523048e7f5ca9550505f2d8ea6d587e7
|
||||
50ff1975ec4309da19591231c6b5104b
|
||||
eba1d423f8632818ce94c4eac1b90713
|
||||
6112a40c70ed55453a0753030d5564a4
|
||||
3389dae361af79b04c9c8e7057f60cc6
|
||||
eac5fc1130394e7268b1cfbc54cd7e4d
|
||||
c0b153d8c08365f2de343e278d3b54c7
|
||||
eb4521cb5d193e1d37ecac25b0ffea43
|
||||
9210ed0dec59ed663c744d7fb68f0275
|
||||
3389dae361af79b04c9c8e7057f60cc6
|
||||
cd0fbdfa49d32525ecbdb8dab19dafe6
|
||||
ea12a10f5b7730daa639fe133867e088
|
||||
69739b9bc9312dfb1a6b8625a08c652a
|
||||
ec21e054f7f5748d0161fe27cdad6462
|
||||
3389dae361af79b04c9c8e7057f60cc6
|
||||
951a83e8074813100da0cba92092b385
|
||||
c93caecd79a332773cfb06cd5d3b8895
|
||||
5832d52d5fcb22a3350f62c856993f0d
|
||||
c4c9bdd47ee05028cb84873da0ebf2b5
|
||||
f89e422b117e518acef69df33f199d10
|
||||
|
||||
90aa2aae2384f6412c3b86d085d5ffa5
|
||||
647f262205ad09f32b0091df388992ed
|
||||
|
||||
943d54ba3e8812437c4d26ef8aa263f8
|
||||
|
||||
340385b760d1441d3b74e5e39399cc0c
|
||||
|
||||
a94613fd32125cd63160b0c1cf2bd078
|
||||
|
||||
3415664f5f4a608772e6a4c73a993804
|
||||
597b7f5598c56e77bd28b9ff15a30802
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
2c953c12d2eb6ea958b7f3045ecf8e81
|
||||
864d4d5a0cd65f52d791700443cec75e
|
||||
1b2437750694bba602fedc0a568c65de
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
2c953c12d2eb6ea958b7f3045ecf8e81
|
||||
d18a921e891f6f9af8564a882efea289
|
||||
8bc5ef2851a7dcf1cf096a68e2a47ba6
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
2c953c12d2eb6ea958b7f3045ecf8e81
|
||||
9cf0f8aa69740d88788fb437589ed33f
|
||||
0df2777822bbc7799716a10478ca58d4
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
@ -1,149 +0,0 @@
|
||||
523048e7f5ca9550505f2d8ea6d587e7
|
||||
50ff1975ec4309da19591231c6b5104b
|
||||
eba1d423f8632818ce94c4eac1b90713
|
||||
6112a40c70ed55453a0753030d5564a4
|
||||
3389dae361af79b04c9c8e7057f60cc6
|
||||
eac5fc1130394e7268b1cfbc54cd7e4d
|
||||
c0b153d8c08365f2de343e278d3b54c7
|
||||
eb4521cb5d193e1d37ecac25b0ffea43
|
||||
9210ed0dec59ed663c744d7fb68f0275
|
||||
3389dae361af79b04c9c8e7057f60cc6
|
||||
cd0fbdfa49d32525ecbdb8dab19dafe6
|
||||
ea12a10f5b7730daa639fe133867e088
|
||||
69739b9bc9312dfb1a6b8625a08c652a
|
||||
ec21e054f7f5748d0161fe27cdad6462
|
||||
3389dae361af79b04c9c8e7057f60cc6
|
||||
951a83e8074813100da0cba92092b385
|
||||
c93caecd79a332773cfb06cd5d3b8895
|
||||
5832d52d5fcb22a3350f62c856993f0d
|
||||
c4c9bdd47ee05028cb84873da0ebf2b5
|
||||
f89e422b117e518acef69df33f199d10
|
||||
|
||||
9e0ae10d6ada18721c856844d765b465
|
||||
ea3c894506f93b88c9fc6c9790da9008
|
||||
c5c303a0f47f5f15f22b6776fc1c8c93
|
||||
4f592acdcfc11c97e7f19231de9d69b0
|
||||
6aea6951956275cb62d01063a1e695fe
|
||||
293f7a3f08e54359c17d5e984f721665
|
||||
18d24bd6a2c2c15d3914502e2776e372
|
||||
107e08f15be7e18888da7e69948ac3ba
|
||||
90aa2aae2384f6412c3b86d085d5ffa5
|
||||
ef76944333105582ae8d3a51d29b3b8a
|
||||
2a592c3d07126847ae4cbbed4a2b4d46
|
||||
6f382821d6f35beb6ae4080607046898
|
||||
|
||||
943d54ba3e8812437c4d26ef8aa263f8
|
||||
6fa05171389dfbeda44181c98e580d18
|
||||
391715e38dad3a13b75205d527e82c8a
|
||||
bb3900a63a8cecc1e79592e054915c97
|
||||
7c8d40302b1200413bc859331a4f241d
|
||||
0e2ad2ad1ad56b970e4348a3967d1e81
|
||||
049ace1ff1516be8a5fd7cddc0ab2f30
|
||||
d2c44db3922004ac2ae41fb402d005b1
|
||||
b0ba7766e9e1fddaf40e86b62a5c2900
|
||||
|
||||
62e220c0092e8ae61f5937f18e4b03bc
|
||||
|
||||
a5eeb3bd06bd4499f8a9ad20ba426bbd
|
||||
|
||||
2bb44a6b46970b3efd87cc8a68848fae
|
||||
|
||||
5b9e24bad64529f3e35ba4f1aed892f2
|
||||
78f4e1ffbbf29629025b20f6b1be36f5
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
2c953c12d2eb6ea958b7f3045ecf8e81
|
||||
0f253056876c021c4fd3f3e5ddc4d5b6
|
||||
520e98566046a173f9250aa3b7a40ec9
|
||||
c31394024dee65cba7e5c526c69af278
|
||||
80d5b17efc16ace990c07580fc3e85eb
|
||||
d28bc6d296024d650b16efe1369128b0
|
||||
38ba857d93d3a54a6b7f1bfc1b8fb090
|
||||
d41f14cd3267e8d9c17b47ddcb71b0c1
|
||||
54f339c05c18199eca937a31fdc07857
|
||||
7efc34bf8e2ba01cec26c50875ac8acd
|
||||
5a29aee8cfe3a5110dc892ab8adfc17f
|
||||
d271e10accbea4cb6365b85150505b0d
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
319f70c2d340b01002c3539d09dabbec
|
||||
b225a5ae163bfc56684d172522993825
|
||||
791c95e71dd996b4d723f96df3f37ca4
|
||||
80d5b17efc16ace990c07580fc3e85eb
|
||||
2a8af480cbdcc0ee9b44187a078c8fe7
|
||||
4340b548cda0dbc6043cbf4cf49d1b12
|
||||
2df758e8d85494e7ee23a02d4c3aa6a7
|
||||
e44feb14b61ab99767239eaded464459
|
||||
eb375774c265dedeefeb29283ceea9bc
|
||||
c87c662bc284c5f9c01d3551957ee32e
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
1fcefdfae441ded6478da69428a30f12
|
||||
8fcd1ffa896d0e214539b1bfa179f3e8
|
||||
7a64b5f6e57cc9f13d5a1be99b9f7c23
|
||||
8884d72adb8d93474c6af620a7d6fdba
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
7e53b1d2085d8c7ae88417eccc5a0893
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
5f68d8059a28922be107658c3890c230
|
||||
6ded45bc62f1d535345e67001dac69d5
|
||||
34165242e2230ffca31d7942ec577e6b
|
||||
02f5ec563dbaaef9ef402c6941a36c98
|
||||
784b65e21ca0539f3cefb1710ccc7768
|
||||
982e86cf85e0f121ba1a2f0ef462aa6b
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
80d5b17efc16ace990c07580fc3e85eb
|
||||
34c0d764eb79cc7c6dccb53e711fd4be
|
||||
a5b2391dd7127292b7240c7c8c1ee92a
|
||||
54d7949984c901073fffda9956190c12
|
||||
da38c234aa3fdca9ec1e0e2b991d3568
|
||||
6b2decb38be3882440910fd75ec508cd
|
||||
ce51581950deb12616108c0e909f9c53
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
e8165f1ae4cf11035542d4b60ac7b14d
|
||||
c8272ad357e7feaf2671a0612e52d3b5
|
||||
2c953c12d2eb6ea958b7f3045ecf8e81
|
||||
209935c0f7c635d91164fe2b14314a3d
|
||||
448b1c0a64288dbeac516ba67c9f2574
|
||||
540c13e9e156b687226421b24f2df178
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
c0c97e22db5055def551d1cef15fb251
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
8983f749749a87599ea48c8bc08cac86
|
||||
f298d78afda5708f64ded32af0e7f541
|
||||
248e216059cad9c12bc8ff8b3b6289e2
|
||||
80d5b17efc16ace990c07580fc3e85eb
|
||||
318ddd60a422c3d0435acd5f7aa6923c
|
||||
7c3bca9656325d15227ffac4ce5dfde9
|
||||
7d992ab2241888573c1c7bdfe5d33a35
|
||||
cd620097a91b074942d29535e822ebb0
|
||||
a50e423de97896afb97123424a960664
|
||||
35bb4ed816814a612f9605aec97c69fb
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
280db1f26dcc577de8fc62d40627112b
|
||||
e5b027822061ae041ced3d958b6f7f37
|
||||
11a0dde589dec02e8d95c4ea6d83780f
|
||||
e5acab4c66ae60432ccc5a45d718d152
|
||||
3c4b4570f7e4c7037693b1aa1fd5a9ca
|
||||
420d9af4c91e3248bb2a4e72a683a03a
|
||||
d69bf14adaf9ea45b48c0fdfefa4f69d
|
||||
505b97969baa28c3f607a38ee02f4f2d
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
da94121a62e940229bd622927ad7702f
|
||||
9d2a20a55b185c4a864efd3484a870fa
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
daada2d57491a2d0b4d237f29fc039dc
|
||||
53220ad5b69915dec696a01167d5237b
|
||||
2fb05fbd558fb020eacca16faa325246
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
423c485e2882c1fd9a1b19983b812f50
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
||||
|
||||
cbb184dd8e05c9709e5dcaedaa0495cf
|
@ -0,0 +1 @@
|
||||
class Fake {}
|
@ -0,0 +1,14 @@
|
||||
#sonar.projectKey=com.foo.project
|
||||
sonar.projectName=Foo Project
|
||||
sonar.projectVersion=1.0-SNAPSHOT
|
||||
sonar.projectDescription=Description of Foo Project
|
||||
|
||||
sonar.sources=sources
|
||||
sonar.tests=tests
|
||||
sonar.binaries=target/classes
|
||||
|
||||
sonar.modules=module1
|
||||
|
||||
module1.sonar.projectBaseDir=modules/module1
|
||||
module1.sonar.projectKey=com.foo.project.module1
|
||||
module1.sonar.projectName=Foo Module 1
|
@ -117,7 +117,7 @@ public class FileCache {
|
||||
return new File(dir, hash);
|
||||
}
|
||||
|
||||
private void mkdirQuietly(File hashDir) {
|
||||
private static void mkdirQuietly(File hashDir) {
|
||||
try {
|
||||
Files.createDirectories(hashDir.toPath());
|
||||
} catch (IOException e) {
|
||||
|
@ -56,7 +56,7 @@ public class FileHashes {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] digest(InputStream input, MessageDigest digest) throws IOException {
|
||||
private static byte[] digest(InputStream input, MessageDigest digest) throws IOException {
|
||||
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
|
||||
int read = input.read(buffer, 0, STREAM_BUFFER_LENGTH);
|
||||
while (read > -1) {
|
||||
|
@ -19,7 +19,9 @@
|
||||
*/
|
||||
package org.sonar.home.cache;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
@ -28,6 +30,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@ -77,7 +80,7 @@ public class PersistentCache {
|
||||
@CheckForNull
|
||||
public synchronized String getString(@Nonnull String obj, @Nullable final PersistentCacheLoader<String> valueLoader) throws IOException {
|
||||
ValueLoaderDecoder decoder = valueLoader != null ? new ValueLoaderDecoder(valueLoader) : null;
|
||||
|
||||
|
||||
byte[] cached = get(obj, decoder);
|
||||
|
||||
if (cached == null) {
|
||||
@ -87,6 +90,20 @@ public class PersistentCache {
|
||||
return new String(cached, ENCODING);
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public synchronized InputStream getStream(@Nonnull String obj) throws IOException {
|
||||
String key = getKey(obj);
|
||||
|
||||
try {
|
||||
lock();
|
||||
Path path = getCacheCopy(key);
|
||||
return new DeleteOnCloseInputStream(new FileInputStream(path.toFile()), path);
|
||||
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public synchronized byte[] get(@Nonnull String obj, @Nullable PersistentCacheLoader<byte[]> valueLoader) throws IOException {
|
||||
String key = getKey(obj);
|
||||
@ -116,6 +133,16 @@ public class PersistentCache {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized void put(@Nonnull String obj, @Nonnull InputStream stream) throws IOException {
|
||||
String key = getKey(obj);
|
||||
try {
|
||||
lock();
|
||||
putCache(key, stream);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void put(@Nonnull String obj, @Nonnull byte[] value) throws IOException {
|
||||
String key = getKey(obj);
|
||||
@ -266,6 +293,11 @@ public class PersistentCache {
|
||||
Path cachePath = getCacheEntryPath(key);
|
||||
Files.write(cachePath, value, CREATE, WRITE, TRUNCATE_EXISTING);
|
||||
}
|
||||
|
||||
private void putCache(String key, InputStream stream) throws IOException {
|
||||
Path cachePath = getCacheEntryPath(key);
|
||||
Files.copy(stream, cachePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
private byte[] getCache(String key) throws IOException {
|
||||
Path cachePath = getCacheEntryPath(key);
|
||||
@ -277,6 +309,39 @@ public class PersistentCache {
|
||||
return Files.readAllBytes(cachePath);
|
||||
}
|
||||
|
||||
private Path getCacheCopy(String key) throws IOException {
|
||||
Path cachePath = getCacheEntryPath(key);
|
||||
|
||||
if (!validateCacheEntry(cachePath, this.defaultDurationToExpireMs)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Path temp = Files.createTempFile("sonar_cache", null);
|
||||
Files.copy(cachePath, temp, StandardCopyOption.REPLACE_EXISTING);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static class DeleteOnCloseInputStream extends InputStream {
|
||||
private final InputStream stream;
|
||||
private final Path p;
|
||||
|
||||
private DeleteOnCloseInputStream(InputStream stream, Path p) {
|
||||
this.stream = stream;
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return stream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
stream.close();
|
||||
Files.delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateCacheEntry(Path cacheEntryPath, long durationToExpireMs) throws IOException {
|
||||
if (!Files.exists(cacheEntryPath)) {
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user