@@ -20,12 +20,16 @@ | |||
package org.sonar.server.batch; | |||
import org.apache.commons.io.IOUtils; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.batch.protocol.input.FileData; | |||
import org.sonar.batch.protocol.input.ProjectRepositories; | |||
import org.sonar.server.plugins.MimeTypes; | |||
import org.sonarqube.ws.WsBatch.WsProjectResponse; | |||
import static org.sonar.server.ws.WsUtils.writeProtobuf; | |||
public class ProjectAction implements BatchWsAction { | |||
@@ -66,13 +70,85 @@ public class ProjectAction implements BatchWsAction { | |||
} | |||
@Override | |||
public void handle(Request request, Response response) throws Exception { | |||
public void handle(Request wsRequest, Response wsResponse) throws Exception { | |||
ProjectRepositories data = projectDataLoader.load(ProjectDataQuery.create() | |||
.setModuleKey(request.mandatoryParam(PARAM_KEY)) | |||
.setProfileName(request.param(PARAM_PROFILE)) | |||
.setPreview(request.mandatoryParamAsBoolean(PARAM_PREVIEW))); | |||
response.stream().setMediaType(MimeTypes.JSON); | |||
IOUtils.write(data.toJson(), response.stream().output()); | |||
.setModuleKey(wsRequest.mandatoryParam(PARAM_KEY)) | |||
.setProfileName(wsRequest.param(PARAM_PROFILE)) | |||
.setIssuesMode(wsRequest.mandatoryParamAsBoolean(PARAM_PREVIEW))); | |||
WsProjectResponse projectResponse = buildResponse(data); | |||
writeProtobuf(projectResponse, wsRequest, wsResponse); | |||
} | |||
private static WsProjectResponse buildResponse(ProjectRepositories data) { | |||
WsProjectResponse.Builder response = WsProjectResponse.newBuilder(); | |||
setLastAnalysisDate(response, data); | |||
response.setTimestamp(data.timestamp()); | |||
response.getMutableFileDataByModuleAndPatch() | |||
.putAll(buildFileDataByModuleAndPatch(data)); | |||
response.getMutableSettingsByModule() | |||
.putAll(buildSettingsByModule(data)); | |||
return response.build(); | |||
} | |||
private static void setLastAnalysisDate(WsProjectResponse.Builder response, ProjectRepositories data) { | |||
if (data.lastAnalysisDate() != null) { | |||
response.setLastAnalysisDate(data.lastAnalysisDate().getTime()); | |||
} | |||
} | |||
private static Map<String, WsProjectResponse.FileDataByPath> buildFileDataByModuleAndPatch(ProjectRepositories data) { | |||
Map<String, WsProjectResponse.FileDataByPath> fileDataByModuleAndPathResponse = new HashMap<>(); | |||
for (Map.Entry<String, Map<String, FileData>> moduleAndFileDataByPathEntry : data.fileDataByModuleAndPath().entrySet()) { | |||
fileDataByModuleAndPathResponse.put( | |||
moduleAndFileDataByPathEntry.getKey(), | |||
buildFileDataByPath(moduleAndFileDataByPathEntry.getValue())); | |||
} | |||
return fileDataByModuleAndPathResponse; | |||
} | |||
private static WsProjectResponse.FileDataByPath buildFileDataByPath(Map<String, FileData> fileDataByPath) { | |||
WsProjectResponse.FileDataByPath.Builder response = WsProjectResponse.FileDataByPath.newBuilder(); | |||
Map<String, WsProjectResponse.FileData> fileDataByPathResponse = response.getMutableFileDataByPath(); | |||
for (Map.Entry<String, FileData> pathFileDataEntry : fileDataByPath.entrySet()) { | |||
fileDataByPathResponse.put( | |||
pathFileDataEntry.getKey(), | |||
toFileDataResponse(pathFileDataEntry.getValue())); | |||
} | |||
return response.build(); | |||
} | |||
private static Map<String, WsProjectResponse.Settings> buildSettingsByModule(ProjectRepositories data) { | |||
Map<String, WsProjectResponse.Settings> settingsByModuleResponse = new HashMap<>(); | |||
for (Map.Entry<String, Map<String, String>> moduleSettingsEntry : data.settings().entrySet()) { | |||
settingsByModuleResponse.put( | |||
moduleSettingsEntry.getKey(), | |||
toSettingsResponse(moduleSettingsEntry.getValue()) | |||
); | |||
} | |||
return settingsByModuleResponse; | |||
} | |||
private static WsProjectResponse.Settings toSettingsResponse(Map<String, String> settings) { | |||
WsProjectResponse.Settings.Builder settingsResponse = WsProjectResponse.Settings | |||
.newBuilder(); | |||
settingsResponse | |||
.getMutableSettings() | |||
.putAll(settings); | |||
return settingsResponse.build(); | |||
} | |||
private static WsProjectResponse.FileData toFileDataResponse(FileData fileData) { | |||
return WsProjectResponse.FileData.newBuilder() | |||
.setHash(fileData.hash()) | |||
.setRevision(fileData.revision()) | |||
.build(); | |||
} | |||
} |
@@ -20,20 +20,13 @@ | |||
package org.sonar.server.batch; | |||
import com.google.common.base.Function; | |||
import com.google.common.base.Optional; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.collect.Multimap; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.resources.Language; | |||
import org.sonar.api.resources.Languages; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
@@ -41,28 +34,19 @@ import org.sonar.api.web.UserRole; | |||
import org.sonar.batch.protocol.input.FileData; | |||
import org.sonar.batch.protocol.input.ProjectRepositories; | |||
import org.sonar.core.permission.GlobalPermissions; | |||
import org.sonar.core.util.UtcDateUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.MyBatis; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.FilePathWithHashDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.qualityprofile.ActiveRule; | |||
import org.sonar.server.qualityprofile.QProfileFactory; | |||
import org.sonar.server.qualityprofile.QProfileLoader; | |||
import org.sonar.server.rule.Rule; | |||
import org.sonar.server.rule.RuleService; | |||
import org.sonar.server.rule.index.RuleNormalizer; | |||
import org.sonar.server.rule.index.RuleQuery; | |||
import org.sonar.server.search.QueryContext; | |||
import org.sonar.server.search.Result; | |||
import org.sonar.server.user.UserSession; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static com.google.common.collect.Maps.newHashMap; | |||
import static java.lang.String.format; | |||
import static org.sonar.server.ws.WsUtils.checkFound; | |||
@ServerSide | |||
public class ProjectDataLoader { | |||
@@ -70,73 +54,60 @@ public class ProjectDataLoader { | |||
private static final Logger LOG = Loggers.get(ProjectDataLoader.class); | |||
private final DbClient dbClient; | |||
private final QProfileFactory qProfileFactory; | |||
private final QProfileLoader qProfileLoader; | |||
private final RuleService ruleService; | |||
private final Languages languages; | |||
private final UserSession userSession; | |||
public ProjectDataLoader(DbClient dbClient, QProfileFactory qProfileFactory, QProfileLoader qProfileLoader, RuleService ruleService, | |||
Languages languages, UserSession userSession) { | |||
public ProjectDataLoader(DbClient dbClient, UserSession userSession) { | |||
this.dbClient = dbClient; | |||
this.qProfileFactory = qProfileFactory; | |||
this.qProfileLoader = qProfileLoader; | |||
this.ruleService = ruleService; | |||
this.languages = languages; | |||
this.userSession = userSession; | |||
} | |||
public ProjectRepositories load(ProjectDataQuery query) { | |||
boolean hasScanPerm = userSession.hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION); | |||
checkPermission(query.isPreview()); | |||
checkPermission(query.isIssuesMode()); | |||
DbSession session = dbClient.openSession(false); | |||
try { | |||
ProjectRepositories ref = new ProjectRepositories(); | |||
String projectKey = query.getModuleKey(); | |||
Optional<ComponentDto> moduleOptional = dbClient.componentDao().selectByKey(session, query.getModuleKey()); | |||
// Current project/module can be null when analysing a new project | |||
if (moduleOptional.isPresent()) { | |||
ComponentDto module = moduleOptional.get(); | |||
// Scan permission is enough to analyze all projects but preview permission is limited to projects user can access | |||
if (query.isPreview() && !userSession.hasProjectPermissionByUuid(UserRole.USER, module.projectUuid())) { | |||
throw new ForbiddenException("You're not authorized to access to project '" + module.name() + "', please contact your SonarQube administrator."); | |||
} | |||
ProjectRepositories data = new ProjectRepositories(); | |||
ComponentDto module = checkFound(dbClient.componentDao().selectByKey(session, query.getModuleKey()), | |||
format("Project or module with key '%s' is not found", query.getModuleKey())); | |||
ComponentDto project = getProject(module, session); | |||
if (!project.key().equals(module.key())) { | |||
addSettings(ref, module.getKey(), getSettingsFromParents(module, hasScanPerm, session)); | |||
projectKey = project.key(); | |||
} | |||
// Scan permission is enough to analyze all projects but preview permission is limited to projects user can access | |||
if (query.isIssuesMode() && !userSession.hasProjectPermissionByUuid(UserRole.USER, module.projectUuid())) { | |||
throw new ForbiddenException("You're not authorized to access to project '" + module.name() + "', please contact your SonarQube administrator."); | |||
} | |||
ComponentDto project = getProject(module, session); | |||
if (!project.key().equals(module.key())) { | |||
addSettings(data, module.getKey(), getSettingsFromParents(module, hasScanPerm, session)); | |||
} | |||
List<ComponentDto> modulesTree = dbClient.componentDao().selectEnabledDescendantModules(session, module.uuid()); | |||
Map<String, String> moduleUuidsByKey = moduleUuidsByKey(module, modulesTree); | |||
Map<String, Long> moduleIdsByKey = moduleIdsByKey(module, modulesTree); | |||
List<ComponentDto> modulesTree = dbClient.componentDao().selectEnabledDescendantModules(session, module.uuid()); | |||
Map<String, String> moduleUuidsByKey = moduleUuidsByKey(modulesTree); | |||
Map<String, Long> moduleIdsByKey = moduleIdsByKey(modulesTree); | |||
List<PropertyDto> modulesTreeSettings = dbClient.propertiesDao().selectEnabledDescendantModuleProperties(module.uuid(), session); | |||
TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings, module); | |||
List<PropertyDto> modulesTreeSettings = dbClient.propertiesDao().selectEnabledDescendantModuleProperties(module.uuid(), session); | |||
TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings); | |||
addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm, session); | |||
List<FilePathWithHashDto> files = module.isRootProject() ? dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid()) | |||
: dbClient.componentDao().selectEnabledDescendantFiles(session, module.uuid()); | |||
addFileData(session, ref, modulesTree, files); | |||
addSettingsToChildrenModules(data, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm); | |||
List<FilePathWithHashDto> files = searchFilesWithHashAndRevision(session, module); | |||
addFileData(data, modulesTree, files); | |||
// FIXME need real value but actually only used to know if there is a previous analysis in local issue tracking mode so any value is | |||
// ok | |||
ref.setLastAnalysisDate(new Date()); | |||
} else { | |||
ref.setLastAnalysisDate(null); | |||
} | |||
// FIXME need real value but actually only used to know if there is a previous analysis in local issue tracking mode so any value is | |||
// ok | |||
data.setLastAnalysisDate(new Date()); | |||
addProfiles(ref, projectKey, query.getProfileName(), session); | |||
addActiveRules(ref); | |||
addManualRules(ref); | |||
return ref; | |||
return data; | |||
} finally { | |||
MyBatis.closeQuietly(session); | |||
} | |||
} | |||
private List<FilePathWithHashDto> searchFilesWithHashAndRevision(DbSession session, ComponentDto module) { | |||
return module.isRootProject() ? | |||
dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid()) | |||
: dbClient.componentDao().selectEnabledDescendantFiles(session, module.uuid()); | |||
} | |||
private ComponentDto getProject(ComponentDto module, DbSession session) { | |||
if (!module.isRootProject()) { | |||
return dbClient.componentDao().selectOrFailByUuid(session, module.projectUuid()); | |||
@@ -169,7 +140,7 @@ public class ProjectDataLoader { | |||
} | |||
private void addSettingsToChildrenModules(ProjectRepositories ref, String moduleKey, Map<String, String> parentProperties, TreeModuleSettings treeModuleSettings, | |||
boolean hasScanPerm, DbSession session) { | |||
boolean hasScanPerm) { | |||
Map<String, String> currentParentProperties = newHashMap(); | |||
currentParentProperties.putAll(parentProperties); | |||
currentParentProperties.putAll(getPropertiesMap(treeModuleSettings.findModuleSettings(moduleKey), hasScanPerm)); | |||
@@ -177,7 +148,7 @@ public class ProjectDataLoader { | |||
for (ComponentDto childModule : treeModuleSettings.findChildrenModule(moduleKey)) { | |||
addSettings(ref, childModule.getKey(), currentParentProperties); | |||
addSettingsToChildrenModules(ref, childModule.getKey(), currentParentProperties, treeModuleSettings, hasScanPerm, session); | |||
addSettingsToChildrenModules(ref, childModule.getKey(), currentParentProperties, treeModuleSettings, hasScanPerm); | |||
} | |||
} | |||
@@ -203,99 +174,15 @@ public class ProjectDataLoader { | |||
return !key.contains(".secured") || hasScanPerm; | |||
} | |||
private void addProfiles(ProjectRepositories ref, @Nullable String projectKey, @Nullable String profileName, DbSession session) { | |||
for (Language language : languages.all()) { | |||
String languageKey = language.getKey(); | |||
QualityProfileDto qualityProfileDto = getProfile(languageKey, projectKey, profileName, session); | |||
ref.addQProfile(new org.sonar.batch.protocol.input.QProfile( | |||
qualityProfileDto.getKey(), | |||
qualityProfileDto.getName(), | |||
qualityProfileDto.getLanguage(), | |||
UtcDateUtils.parseDateTime(qualityProfileDto.getRulesUpdatedAt()))); | |||
} | |||
} | |||
/** | |||
* First try to find a quality profile matching the given name (if provided) and current language | |||
* If no profile found, try to find the quality profile set on the project (if provided) | |||
* If still no profile found, try to find the default profile of the language | |||
* <p/> | |||
* Never return null because a default profile should always be set on each language | |||
*/ | |||
private QualityProfileDto getProfile(String languageKey, @Nullable String projectKey, @Nullable String profileName, DbSession session) { | |||
QualityProfileDto qualityProfileDto = profileName != null ? qProfileFactory.getByNameAndLanguage(session, profileName, languageKey) : null; | |||
if (qualityProfileDto == null && projectKey != null) { | |||
qualityProfileDto = qProfileFactory.getByProjectAndLanguage(session, projectKey, languageKey); | |||
} | |||
qualityProfileDto = qualityProfileDto != null ? qualityProfileDto : qProfileFactory.getDefault(session, languageKey); | |||
if (qualityProfileDto != null) { | |||
return qualityProfileDto; | |||
} else { | |||
throw new IllegalStateException(String.format("No quality profile can been found on language '%s' for project '%s'", languageKey, projectKey)); | |||
} | |||
} | |||
private void addActiveRules(ProjectRepositories ref) { | |||
for (org.sonar.batch.protocol.input.QProfile qProfile : ref.qProfiles()) { | |||
// Load all rules of the profile language (only needed fields are loaded) | |||
Map<RuleKey, Rule> languageRules = ruleByRuleKey(ruleService.search(new RuleQuery().setLanguages(newArrayList(qProfile.language())), | |||
new QueryContext(userSession).setLimit(100).setFieldsToReturn(newArrayList( | |||
RuleNormalizer.RuleField.KEY.field(), RuleNormalizer.RuleField.NAME.field(), RuleNormalizer.RuleField.INTERNAL_KEY.field(), | |||
RuleNormalizer.RuleField.TEMPLATE_KEY.field())).setScroll(true)) | |||
.scroll()); | |||
for (Iterator<ActiveRule> activeRuleIterator = qProfileLoader.findActiveRulesByProfile(qProfile.key()); activeRuleIterator.hasNext();) { | |||
ActiveRule activeRule = activeRuleIterator.next(); | |||
Rule rule = languageRules.get(activeRule.key().ruleKey()); | |||
if (rule == null) { | |||
// It should never happen, but we need some log in case it happens | |||
LOG.warn("Rule could not be found on active rule '{}'", activeRule.key()); | |||
} else { | |||
RuleKey templateKey = rule.templateKey(); | |||
org.sonar.batch.protocol.input.ActiveRule inputActiveRule = new org.sonar.batch.protocol.input.ActiveRule( | |||
activeRule.key().ruleKey().repository(), | |||
activeRule.key().ruleKey().rule(), | |||
templateKey != null ? templateKey.rule() : null, | |||
rule.name(), | |||
activeRule.severity(), | |||
rule.internalKey(), | |||
qProfile.language()); | |||
for (Map.Entry<String, String> entry : activeRule.params().entrySet()) { | |||
inputActiveRule.addParam(entry.getKey(), entry.getValue()); | |||
} | |||
ref.addActiveRule(inputActiveRule); | |||
} | |||
} | |||
} | |||
} | |||
private Map<RuleKey, Rule> ruleByRuleKey(Iterator<Rule> rules) { | |||
return Maps.uniqueIndex(rules, MatchRuleKey.INSTANCE); | |||
} | |||
private void addManualRules(ProjectRepositories ref) { | |||
Result<Rule> ruleSearchResult = ruleService.search(new RuleQuery().setRepositories(newArrayList(RuleKey.MANUAL_REPOSITORY_KEY)), new QueryContext(userSession).setScroll(true) | |||
.setFieldsToReturn(newArrayList(RuleNormalizer.RuleField.KEY.field(), RuleNormalizer.RuleField.NAME.field()))); | |||
Iterator<Rule> rules = ruleSearchResult.scroll(); | |||
while (rules.hasNext()) { | |||
Rule rule = rules.next(); | |||
ref.addActiveRule(new org.sonar.batch.protocol.input.ActiveRule( | |||
RuleKey.MANUAL_REPOSITORY_KEY, | |||
rule.key().rule(), | |||
null, rule.name(), | |||
null, null, null)); | |||
} | |||
} | |||
private static void addFileData(DbSession session, ProjectRepositories ref, List<ComponentDto> moduleChildren, List<FilePathWithHashDto> files) { | |||
private static void addFileData(ProjectRepositories data, List<ComponentDto> moduleChildren, List<FilePathWithHashDto> files) { | |||
Map<String, String> moduleKeysByUuid = newHashMap(); | |||
for (ComponentDto module : moduleChildren) { | |||
moduleKeysByUuid.put(module.uuid(), module.key()); | |||
} | |||
for (FilePathWithHashDto file : files) { | |||
// TODO should query E/S to know if blame is missing on this file | |||
FileData fileData = new FileData(file.getSrcHash(), true); | |||
ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData); | |||
FileData fileData = new FileData(file.getSrcHash(), file.getRevision()); | |||
data.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData); | |||
} | |||
} | |||
@@ -314,7 +201,7 @@ public class ProjectDataLoader { | |||
} | |||
} | |||
private static Map<String, String> moduleUuidsByKey(ComponentDto module, List<ComponentDto> moduleChildren) { | |||
private static Map<String, String> moduleUuidsByKey(List<ComponentDto> moduleChildren) { | |||
Map<String, String> moduleUuidsByKey = newHashMap(); | |||
for (ComponentDto componentDto : moduleChildren) { | |||
moduleUuidsByKey.put(componentDto.key(), componentDto.uuid()); | |||
@@ -322,7 +209,7 @@ public class ProjectDataLoader { | |||
return moduleUuidsByKey; | |||
} | |||
private static Map<String, Long> moduleIdsByKey(ComponentDto module, List<ComponentDto> moduleChildren) { | |||
private static Map<String, Long> moduleIdsByKey(List<ComponentDto> moduleChildren) { | |||
Map<String, Long> moduleIdsByKey = newHashMap(); | |||
for (ComponentDto componentDto : moduleChildren) { | |||
moduleIdsByKey.put(componentDto.key(), componentDto.getId()); | |||
@@ -338,7 +225,7 @@ public class ProjectDataLoader { | |||
private Multimap<String, ComponentDto> moduleChildrenByModuleUuid; | |||
private TreeModuleSettings(Map<String, String> moduleUuidsByKey, Map<String, Long> moduleIdsByKey, List<ComponentDto> moduleChildren, | |||
List<PropertyDto> moduleChildrenSettings, ComponentDto module) { | |||
List<PropertyDto> moduleChildrenSettings) { | |||
this.moduleIdsByKey = moduleIdsByKey; | |||
this.moduleUuidsByKey = moduleUuidsByKey; | |||
propertiesByModuleId = ArrayListMultimap.create(); | |||
@@ -366,13 +253,4 @@ public class ProjectDataLoader { | |||
return newArrayList(moduleChildrenByModuleUuid.get(moduleUuid)); | |||
} | |||
} | |||
private enum MatchRuleKey implements Function<Rule, RuleKey> { | |||
INSTANCE; | |||
@Override | |||
public RuleKey apply(@Nullable Rule input) { | |||
return input != null ? input.key() : null; | |||
} | |||
} | |||
} |
@@ -27,18 +27,18 @@ public class ProjectDataQuery { | |||
private String projectOrModuleKey; | |||
private String profileName; | |||
private boolean preview; | |||
private boolean issuesMode; | |||
private ProjectDataQuery() { | |||
// No direct call | |||
} | |||
public boolean isPreview() { | |||
return preview; | |||
public boolean isIssuesMode() { | |||
return issuesMode; | |||
} | |||
public ProjectDataQuery setPreview(boolean preview) { | |||
this.preview = preview; | |||
public ProjectDataQuery setIssuesMode(boolean issuesMode) { | |||
this.issuesMode = issuesMode; | |||
return this; | |||
} | |||
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.ws; | |||
import com.google.common.base.Optional; | |||
import com.google.protobuf.Message; | |||
import java.io.OutputStream; | |||
import java.io.OutputStreamWriter; | |||
@@ -74,4 +75,16 @@ public class WsUtils { | |||
return value; | |||
} | |||
/** | |||
* @throws NotFoundException if the value is not present | |||
* @return the value | |||
*/ | |||
public static <T> T checkFound(Optional<T> value, String message) { | |||
if (!value.isPresent()) { | |||
throw new NotFoundException(message); | |||
} | |||
return value.get(); | |||
} | |||
} |
@@ -59,7 +59,7 @@ public class ProjectActionTest { | |||
assertThat(queryArgumentCaptor.getValue().getModuleKey()).isEqualTo(projectKey); | |||
assertThat(queryArgumentCaptor.getValue().getProfileName()).isEqualTo("Default"); | |||
assertThat(queryArgumentCaptor.getValue().isPreview()).isFalse(); | |||
assertThat(queryArgumentCaptor.getValue().isIssuesMode()).isFalse(); | |||
} | |||
} |
@@ -22,43 +22,30 @@ package org.sonar.server.batch; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Date; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.server.rule.RuleParamType; | |||
import org.sonar.api.utils.DateUtils; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.batch.protocol.input.ActiveRule; | |||
import org.sonar.batch.protocol.input.FileData; | |||
import org.sonar.batch.protocol.input.ProjectRepositories; | |||
import org.sonar.batch.protocol.input.QProfile; | |||
import org.sonar.core.permission.GlobalPermissions; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.db.source.FileSourceDao; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.db.source.FileSourceDto.Type; | |||
import org.sonar.server.db.DbClient; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.qualityprofile.QProfileName; | |||
import org.sonar.server.qualityprofile.RuleActivation; | |||
import org.sonar.server.qualityprofile.RuleActivator; | |||
import org.sonar.server.tester.ServerTester; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.sonar.api.utils.DateUtils.formatDateTime; | |||
@@ -98,10 +85,10 @@ public class ProjectDataLoaderMediumTest { | |||
// Project properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty( | |||
dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId()) | |||
); | |||
); | |||
tester.get(DbClient.class).propertiesDao().insertProperty( | |||
dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId()) | |||
); | |||
); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
@@ -109,7 +96,7 @@ public class ProjectDataLoaderMediumTest { | |||
assertThat(projectSettings).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -122,17 +109,17 @@ public class ProjectDataLoaderMediumTest { | |||
// Project properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty( | |||
dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId()) | |||
); | |||
); | |||
tester.get(DbClient.class).propertiesDao().insertProperty( | |||
dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId()) | |||
); | |||
); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setPreview(true)); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setIssuesMode(true)); | |||
Map<String, String> projectSettings = ref.settings(project.key()); | |||
assertThat(projectSettings).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -163,12 +150,12 @@ public class ProjectDataLoaderMediumTest { | |||
assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
assertThat(ref.settings(module.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR-SERVER", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -195,11 +182,11 @@ public class ProjectDataLoaderMediumTest { | |||
assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
assertThat(ref.settings(module.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -237,17 +224,17 @@ public class ProjectDataLoaderMediumTest { | |||
assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
assertThat(ref.settings(module.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR-SERVER", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
assertThat(ref.settings(subModule.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR-SERVER-DAO", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -265,9 +252,11 @@ public class ProjectDataLoaderMediumTest { | |||
tester.get(DbClient.class).componentDao().insert(dbSession, module1); | |||
// Module 1 properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR-SERVER").setResourceId(module1.getId())); | |||
tester.get(DbClient.class).propertiesDao() | |||
.insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR-SERVER").setResourceId(module1.getId())); | |||
// This property should not be found on the other module | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(module1.getId())); | |||
tester.get(DbClient.class).propertiesDao() | |||
.insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(module1.getId())); | |||
ComponentDto module2 = ComponentTesting.newModuleDto(project); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, module2); | |||
@@ -282,16 +271,16 @@ public class ProjectDataLoaderMediumTest { | |||
assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
assertThat(ref.settings(module1.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR-SERVER", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
assertThat(ref.settings(module2.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR-APPLICATION", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -312,7 +301,7 @@ public class ProjectDataLoaderMediumTest { | |||
assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -334,7 +323,8 @@ public class ProjectDataLoaderMediumTest { | |||
// Sub module properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(subModule.getId())); | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(subModule.getId())); | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId())); | |||
tester.get(DbClient.class).propertiesDao() | |||
.insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId())); | |||
dbSession.commit(); | |||
@@ -345,7 +335,7 @@ public class ProjectDataLoaderMediumTest { | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -368,7 +358,8 @@ public class ProjectDataLoaderMediumTest { | |||
tester.get(DbClient.class).componentDao().insert(dbSession, subModule); | |||
// Sub module properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId())); | |||
tester.get(DbClient.class).propertiesDao() | |||
.insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId())); | |||
dbSession.commit(); | |||
@@ -379,7 +370,7 @@ public class ProjectDataLoaderMediumTest { | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -391,7 +382,8 @@ public class ProjectDataLoaderMediumTest { | |||
// Project properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId())); | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId())); | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId())); | |||
tester.get(DbClient.class).propertiesDao() | |||
.insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId())); | |||
ComponentDto module = ComponentTesting.newModuleDto(project); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, module); | |||
@@ -411,7 +403,7 @@ public class ProjectDataLoaderMediumTest { | |||
"sonar.jira.project.key", "SONAR", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
)); | |||
} | |||
@Test | |||
@@ -422,7 +414,8 @@ public class ProjectDataLoaderMediumTest { | |||
// Project properties | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId())); | |||
tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId())); | |||
tester.get(DbClient.class).propertiesDao() | |||
.insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId())); | |||
ComponentDto module = ComponentTesting.newModuleDto(project); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, module); | |||
@@ -444,285 +437,7 @@ public class ProjectDataLoaderMediumTest { | |||
"sonar.jira.project.key", "SONAR-SERVER", | |||
"sonar.jira.login.secured", "john", | |||
"sonar.coverage.exclusions", "**/*.java" | |||
)); | |||
} | |||
@Test | |||
public void return_quality_profile_from_project_profile() { | |||
Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100"); | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(ruleUpdatedAt)); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
tester.get(DbClient.class).qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profileDto.getKee(), dbSession); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<QProfile> profiles = newArrayList(ref.qProfiles()); | |||
assertThat(profiles).hasSize(1); | |||
assertThat(profiles.get(0).key()).isEqualTo("abcd"); | |||
assertThat(profiles.get(0).name()).isEqualTo("SonarQube way"); | |||
assertThat(profiles.get(0).language()).isEqualTo("xoo"); | |||
assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt); | |||
} | |||
@Test | |||
public void return_quality_profile_from_default_profile() { | |||
Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100"); | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(ruleUpdatedAt)).setDefault(true); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<QProfile> profiles = newArrayList(ref.qProfiles()); | |||
assertThat(profiles).hasSize(1); | |||
assertThat(profiles.get(0).key()).isEqualTo("abcd"); | |||
assertThat(profiles.get(0).name()).isEqualTo("SonarQube way"); | |||
assertThat(profiles.get(0).language()).isEqualTo("xoo"); | |||
assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt); | |||
} | |||
@Test | |||
public void return_quality_profile_from_given_profile_name() { | |||
Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100"); | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(ruleUpdatedAt)).setDefault(true); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setProfileName("SonarQube way")); | |||
List<QProfile> profiles = newArrayList(ref.qProfiles()); | |||
assertThat(profiles).hasSize(1); | |||
assertThat(profiles.get(0).key()).isEqualTo("abcd"); | |||
assertThat(profiles.get(0).name()).isEqualTo("SonarQube way"); | |||
assertThat(profiles.get(0).language()).isEqualTo("xoo"); | |||
assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt); | |||
} | |||
@Test | |||
public void return_quality_profiles_even_when_project_does_not_exists() { | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100"); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(ruleUpdatedAt)).setDefault(true); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey("project")); | |||
List<QProfile> profiles = newArrayList(ref.qProfiles()); | |||
assertThat(profiles).hasSize(1); | |||
assertThat(profiles.get(0).key()).isEqualTo("abcd"); | |||
assertThat(profiles.get(0).name()).isEqualTo("SonarQube way"); | |||
assertThat(profiles.get(0).language()).isEqualTo("xoo"); | |||
assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt); | |||
} | |||
@Test | |||
public void return_provisioned_project_profile() { | |||
Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100"); | |||
// No snapshot attached on the project -> provisioned project | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(ruleUpdatedAt)); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
tester.get(DbClient.class).qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profileDto.getKee(), dbSession); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<QProfile> profiles = newArrayList(ref.qProfiles()); | |||
assertThat(profiles).hasSize(1); | |||
assertThat(profiles.get(0).key()).isEqualTo("abcd"); | |||
assertThat(profiles.get(0).name()).isEqualTo("SonarQube way"); | |||
assertThat(profiles.get(0).language()).isEqualTo("xoo"); | |||
assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt); | |||
} | |||
@Test | |||
public void fail_when_no_quality_profile_for_a_language() { | |||
ComponentDto project = ComponentTesting.newProjectDto().setKey("org.codehaus.sonar:sonar"); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
dbSession.commit(); | |||
try { | |||
loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
fail(); | |||
} catch (Exception e) { | |||
assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("No quality profile can been found on language 'xoo' for project 'org.codehaus.sonar:sonar'"); | |||
} | |||
} | |||
@Test | |||
public void return_active_rules() { | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(DateUtils.parseDateTime("2014-01-14T13:00:00+0100"))).setDefault(true); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle"); | |||
RuleDto rule = RuleTesting.newDto(ruleKey).setName("Avoid Cycle").setConfigKey("squid-1").setLanguage(ServerTester.Xoo.KEY); | |||
tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, rule); | |||
tester.get(DbClient.class).deprecatedRuleDao().insertRuleParam(dbSession, rule, RuleParamDto.createFor(rule) | |||
.setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type())); | |||
RuleActivation activation = new RuleActivation(ruleKey); | |||
activation.setSeverity(Severity.MINOR); | |||
activation.setParameter("max", "2"); | |||
tester.get(RuleActivator.class).activate(dbSession, activation, profileDto.getKey()); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<ActiveRule> activeRules = newArrayList(ref.activeRules()); | |||
assertThat(activeRules).hasSize(1); | |||
assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid"); | |||
assertThat(activeRules.get(0).ruleKey()).isEqualTo("AvoidCycle"); | |||
assertThat(activeRules.get(0).name()).isEqualTo("Avoid Cycle"); | |||
assertThat(activeRules.get(0).language()).isEqualTo("xoo"); | |||
assertThat(activeRules.get(0).severity()).isEqualTo("MINOR"); | |||
assertThat(activeRules.get(0).internalKey()).isEqualTo("squid-1"); | |||
assertThat(activeRules.get(0).params()).isEqualTo(ImmutableMap.of("max", "2")); | |||
} | |||
@Test | |||
public void return_only_active_rules_from_project_profile() { | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
RuleKey ruleKey1 = RuleKey.of("squid", "AvoidCycle"); | |||
RuleKey ruleKey2 = RuleKey.of("squid", "AvoidNPE"); | |||
tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, | |||
RuleTesting.newDto(ruleKey1).setName("Avoid Cycle").setLanguage(ServerTester.Xoo.KEY), | |||
RuleTesting.newDto(ruleKey2).setName("Avoid NPE").setLanguage(ServerTester.Xoo.KEY) | |||
); | |||
QualityProfileDto profileDto1 = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd"); | |||
QualityProfileDto profileDto2 = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "Another profile"), "efgh"); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto1, profileDto2); | |||
// The first profile is the profile used but the project | |||
tester.get(DbClient.class).qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profileDto1.getKee(), dbSession); | |||
tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey1).setSeverity(Severity.MINOR), profileDto1.getKey()); | |||
// Active rule from 2nd profile | |||
tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey1).setSeverity(Severity.BLOCKER), profileDto2.getKey()); | |||
tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey2).setSeverity(Severity.BLOCKER), profileDto2.getKey()); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<ActiveRule> activeRules = newArrayList(ref.activeRules()); | |||
assertThat(activeRules).hasSize(1); | |||
assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid"); | |||
assertThat(activeRules.get(0).ruleKey()).isEqualTo("AvoidCycle"); | |||
assertThat(activeRules.get(0).name()).isEqualTo("Avoid Cycle"); | |||
assertThat(activeRules.get(0).language()).isEqualTo("xoo"); | |||
assertThat(activeRules.get(0).severity()).isEqualTo("MINOR"); | |||
} | |||
@Test | |||
public void return_more_than_10_active_rules() { | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd") | |||
.setRulesUpdatedAt(formatDateTime(DateUtils.parseDateTime("2014-01-14T13:00:00+0100"))).setDefault(true); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
for (int i = 0; i < 20; i++) { | |||
RuleKey ruleKey = RuleKey.of("squid", "Rule" + i); | |||
tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, RuleTesting.newDto(ruleKey).setName("Rule" + i).setLanguage(ServerTester.Xoo.KEY)); | |||
tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey).setSeverity(Severity.MINOR), profileDto.getKey()); | |||
} | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
assertThat(ref.activeRules()).hasSize(20); | |||
} | |||
@Test | |||
public void return_custom_rule() { | |||
Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100"); | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt( | |||
formatDateTime(ruleUpdatedAt)).setDefault(true); | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
RuleKey ruleKey = RuleKey.of("squid", "ArchitecturalConstraint"); | |||
RuleDto templateRule = RuleTesting.newTemplateRule(ruleKey).setName("Architectural Constraint").setLanguage(ServerTester.Xoo.KEY); | |||
tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, templateRule); | |||
RuleDto customRule = RuleTesting.newCustomRule(templateRule); | |||
tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, customRule); | |||
tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(customRule.getKey()).setSeverity(Severity.MINOR), profileDto.getKey()); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<ActiveRule> activeRules = newArrayList(ref.activeRules()); | |||
assertThat(activeRules).hasSize(1); | |||
assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid"); | |||
assertThat(activeRules.get(0).ruleKey()).startsWith("ArchitecturalConstraint_"); | |||
assertThat(activeRules.get(0).templateRuleKey()).isEqualTo("ArchitecturalConstraint"); | |||
assertThat(activeRules.get(0).language()).isEqualTo("xoo"); | |||
assertThat(activeRules.get(0).severity()).isEqualTo("MINOR"); | |||
} | |||
@Test | |||
public void return_manual_rules() { | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, project); | |||
addDefaultProfile(); | |||
RuleDto rule = RuleTesting.newManualRule("manualRuleKey").setName("Name manualRuleKey"); | |||
tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, rule); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key())); | |||
List<ActiveRule> activeRules = newArrayList(ref.activeRules()); | |||
assertThat(activeRules).extracting("repositoryKey").containsOnly(RuleKey.MANUAL_REPOSITORY_KEY); | |||
assertThat(activeRules).extracting("ruleKey").containsOnly("manualRuleKey"); | |||
assertThat(activeRules).extracting("name").containsOnly("Name manualRuleKey"); | |||
assertThat(activeRules).extracting("language").containsNull(); | |||
assertThat(activeRules).extracting("severity").containsNull(); | |||
)); | |||
} | |||
@Test | |||
@@ -750,7 +465,7 @@ public class ProjectDataLoaderMediumTest { | |||
dbSession.commit(); | |||
try { | |||
loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setPreview(false)); | |||
loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setIssuesMode(false)); | |||
fail(); | |||
} catch (Exception e) { | |||
assertThat(e).isInstanceOf(ForbiddenException.class).hasMessage( | |||
@@ -814,7 +529,7 @@ public class ProjectDataLoaderMediumTest { | |||
// File on project | |||
ComponentDto projectFile = ComponentTesting.newFileDto(project, "projectFile"); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, projectFile); | |||
tester.get(FileSourceDao.class).insert(newFileSourceDto(projectFile).setSrcHash("123456")); | |||
tester.get(FileSourceDao.class).insert(newFileSourceDto(projectFile).setSrcHash("123456").setRevision("987654321")); | |||
ComponentDto module = ComponentTesting.newModuleDto(project); | |||
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); | |||
@@ -823,12 +538,13 @@ public class ProjectDataLoaderMediumTest { | |||
// File on module | |||
ComponentDto moduleFile = ComponentTesting.newFileDto(module, "moduleFile"); | |||
tester.get(DbClient.class).componentDao().insert(dbSession, moduleFile); | |||
tester.get(FileSourceDao.class).insert(newFileSourceDto(moduleFile).setSrcHash("789456")); | |||
tester.get(FileSourceDao.class).insert(newFileSourceDto(moduleFile).setSrcHash("789456").setRevision("123456789")); | |||
dbSession.commit(); | |||
ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(module.key())); | |||
assertThat(ref.fileData(module.key(), moduleFile.path()).hash()).isEqualTo("789456"); | |||
assertThat(ref.fileData(module.key(), moduleFile.path()).revision()).isEqualTo("123456789"); | |||
assertThat(ref.fileData(project.key(), projectFile.path())).isNull(); | |||
} | |||
@@ -838,16 +554,17 @@ public class ProjectDataLoaderMediumTest { | |||
tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto); | |||
} | |||
private FileSourceDto newFileSourceDto(ComponentDto file) { | |||
private static FileSourceDto newFileSourceDto(ComponentDto file) { | |||
return new FileSourceDto() | |||
.setFileUuid(file.uuid()) | |||
.setProjectUuid(file.projectUuid()) | |||
//.setSourceData(",,,,,,,,,,,,,,,unchanged ,,,,,,,,,,,,,,,content ") | |||
// .setSourceData(",,,,,,,,,,,,,,,unchanged ,,,,,,,,,,,,,,,content ") | |||
.setDataHash("0263047cd758c68c27683625f072f010") | |||
.setLineHashes("8d7b3d6b83c0a517eac07e1aac94b773") | |||
.setCreatedAt(System.currentTimeMillis()) | |||
.setUpdatedAt(System.currentTimeMillis()) | |||
.setDataType(Type.SOURCE) | |||
.setRevision("123456789") | |||
.setSrcHash("123456"); | |||
} | |||
@@ -25,11 +25,11 @@ import javax.annotation.Nullable; | |||
public class FileData { | |||
private final String hash; | |||
private final boolean needBlame; | |||
private final String revision; | |||
public FileData(@Nullable String hash, boolean needBlame) { | |||
public FileData(@Nullable String hash, @Nullable String revision) { | |||
this.hash = hash; | |||
this.needBlame = needBlame; | |||
this.revision = revision; | |||
} | |||
@CheckForNull | |||
@@ -37,8 +37,12 @@ public class FileData { | |||
return hash; | |||
} | |||
public boolean needBlame() { | |||
return needBlame; | |||
@CheckForNull | |||
public String revision() { | |||
return revision; | |||
} | |||
public boolean needBlame() { | |||
return false; | |||
} | |||
} |
@@ -36,8 +36,6 @@ import org.sonar.batch.protocol.GsonHelper; | |||
public class ProjectRepositories { | |||
private long timestamp; | |||
private Map<String, QProfile> qprofilesByLanguage = new HashMap<>(); | |||
private Collection<ActiveRule> activeRules = new ArrayList<>(); | |||
private Map<String, Map<String, String>> settingsByModule = new HashMap<>(); | |||
private Map<String, Map<String, FileData>> fileDataByModuleAndPath = new HashMap<>(); | |||
private Date lastAnalysisDate; | |||
@@ -45,7 +43,7 @@ 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; | |||
} | |||
@@ -60,24 +58,6 @@ public class ProjectRepositories { | |||
return this; | |||
} | |||
public Collection<QProfile> qProfiles() { | |||
return qprofilesByLanguage.values(); | |||
} | |||
public ProjectRepositories addQProfile(QProfile qProfile) { | |||
qprofilesByLanguage.put(qProfile.language(), qProfile); | |||
return this; | |||
} | |||
public Collection<ActiveRule> activeRules() { | |||
return activeRules; | |||
} | |||
public ProjectRepositories addActiveRule(ActiveRule activeRule) { | |||
activeRules.add(activeRule); | |||
return this; | |||
} | |||
public Map<String, Map<String, FileData>> fileDataByModuleAndPath() { | |||
return fileDataByModuleAndPath; | |||
} | |||
@@ -126,4 +106,19 @@ public class ProjectRepositories { | |||
return GsonHelper.create().fromJson(json, ProjectRepositories.class); | |||
} | |||
public Collection<QProfile> qProfiles() { | |||
return new ArrayList<>(); | |||
} | |||
public Collection<ActiveRule> activeRules() { | |||
return new ArrayList<>(); | |||
} | |||
public void addQProfile(QProfile qProfile) { | |||
// do nothing | |||
} | |||
public void addActiveRule(ActiveRule activeRule) { | |||
// do nothing | |||
} | |||
} |
@@ -1,95 +0,0 @@ | |||
/* | |||
* 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.protocol.input; | |||
import org.junit.Test; | |||
import org.sonar.test.JsonAssert; | |||
import java.text.ParseException; | |||
import java.text.SimpleDateFormat; | |||
import java.util.HashMap; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class ProjectRepositoriesTest { | |||
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); | |||
@Test | |||
public void testToJson() throws Exception { | |||
ProjectRepositories ref = new ProjectRepositories(); | |||
assertThat(ref.settings("foo")).isEmpty(); | |||
ref.addQProfile(new QProfile("squid-java", "Java", "java", DATE_FORMAT.parse("2013-01-01T12:00:00+0100"))); | |||
HashMap<String, String> settings = new HashMap<>(); | |||
settings.put("prop1", "value1"); | |||
ref.addSettings("foo", settings); | |||
settings = new HashMap<>(); | |||
settings.put("prop2", "value2"); | |||
ref.addSettings("foo", settings); | |||
ref.settings("foo").put("prop", "value"); | |||
ActiveRule activeRule = new ActiveRule("repo", "rule", "templateRule", "Rule", "MAJOR", "rule", "java"); | |||
activeRule.addParam("param1", "value1"); | |||
ref.addActiveRule(activeRule); | |||
ref.setLastAnalysisDate(DATE_FORMAT.parse("2014-05-18T15:50:45+0100")); | |||
ref.setTimestamp(10); | |||
ref.addFileData("foo", "src/main/java/Foo.java", new FileData("xyz", true)); | |||
ref.addFileData("foo", "src/main/java/Foo2.java", new FileData("xyz", false)); | |||
JsonAssert.assertJson(ref.toJson()) | |||
.isSimilarTo(getClass().getResource("ProjectRepositoriesTest/testToJson.json")); | |||
} | |||
@Test | |||
public void testFromJson() throws ParseException { | |||
ProjectRepositories ref = ProjectRepositories | |||
.fromJson("{timestamp:1," | |||
+ "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"2013-01-01T12:00:00+0100\"}}," | |||
+ "activeRules:[{repositoryKey:repo,ruleKey:rule,templateRuleKey:templateRule,name:Rule,severity:MAJOR,internalKey:rule1,language:java,params:{param1:value1}}]," | |||
+ "settingsByModule:{foo:{prop:value}}," | |||
+ "fileDataByModuleAndPath:{foo:{\"src/main/java/Foo.java\":{hash:xyz,needBlame:true,scmLastCommitDatetimesByLine:\"1\u003d12345,2\u003d3456\",scmRevisionsByLine:\"1\u003d345,2\u003d345\",scmAuthorsByLine:\"1\u003dhenryju,2\u003dgaudin\"}}}," | |||
+ "lastAnalysisDate:\"2014-10-31T00:00:00+0100\"}"); | |||
assertThat(ref.timestamp()).isEqualTo(1); | |||
ActiveRule activeRule = ref.activeRules().iterator().next(); | |||
assertThat(activeRule.ruleKey()).isEqualTo("rule"); | |||
assertThat(activeRule.repositoryKey()).isEqualTo("repo"); | |||
assertThat(activeRule.templateRuleKey()).isEqualTo("templateRule"); | |||
assertThat(activeRule.name()).isEqualTo("Rule"); | |||
assertThat(activeRule.severity()).isEqualTo("MAJOR"); | |||
assertThat(activeRule.internalKey()).isEqualTo("rule1"); | |||
assertThat(activeRule.language()).isEqualTo("java"); | |||
assertThat(activeRule.params()).containsEntry("param1", "value1"); | |||
assertThat(activeRule.param("param1")).isEqualTo("value1"); | |||
QProfile qProfile = ref.qProfiles().iterator().next(); | |||
assertThat(qProfile.key()).isEqualTo("squid-java"); | |||
assertThat(qProfile.name()).isEqualTo("Java"); | |||
assertThat(qProfile.rulesUpdatedAt().getTime()).isEqualTo(DATE_FORMAT.parse("2013-01-01T12:00:00+0100").getTime()); | |||
assertThat(ref.settings("foo")).containsEntry("prop", "value"); | |||
assertThat(ref.fileData("foo2", "src/main/java/Foo3.java")).isNull(); | |||
assertThat(ref.fileData("foo", "src/main/java/Foo.java").hash()).isEqualTo("xyz"); | |||
assertThat(ref.fileData("foo", "src/main/java/Foo.java").needBlame()).isTrue(); | |||
assertThat(ref.lastAnalysisDate().getTime()).isEqualTo(DATE_FORMAT.parse("2014-10-31T00:00:00+0100").getTime()); | |||
} | |||
} |
@@ -1,25 +1,5 @@ | |||
{ | |||
"timestamp": 10, | |||
"qprofilesByLanguage": { | |||
"java": { | |||
"key": "squid-java", | |||
"name": "Java", | |||
"language": "java", | |||
"rulesUpdatedAt": "2013-01-01T12:00:00+0100" | |||
} | |||
}, | |||
"activeRules": [ | |||
{ | |||
"repositoryKey": "repo", | |||
"ruleKey": "rule", | |||
"templateRuleKey": "templateRule", | |||
"name": "Rule", | |||
"severity": "MAJOR", | |||
"internalKey": "rule", | |||
"language": "java", | |||
"params": {"param1": "value1"} | |||
} | |||
], | |||
"settingsByModule": { | |||
"foo": { | |||
"prop1": "value1", | |||
@@ -31,11 +11,11 @@ | |||
"foo": { | |||
"src/main/java/Foo.java": { | |||
"hash": "xyz", | |||
"needBlame": true, | |||
"needBlame": true | |||
}, | |||
"src/main/java/Foo2.java": { | |||
"hash": "xyz", | |||
"needBlame": false, | |||
"needBlame": false | |||
} | |||
} | |||
}, |
@@ -19,17 +19,13 @@ | |||
*/ | |||
package org.sonar.batch.repository; | |||
import org.sonar.batch.cache.WSLoaderResult; | |||
import org.sonar.batch.analysis.DefaultAnalysisMode; | |||
import org.sonar.batch.cache.WSLoader; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.mutable.MutableBoolean; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.api.utils.MessageException; | |||
import org.sonar.batch.analysis.DefaultAnalysisMode; | |||
import org.sonar.batch.cache.WSLoader; | |||
import org.sonar.batch.cache.WSLoaderResult; | |||
import org.sonar.batch.protocol.input.ProjectRepositories; | |||
import org.sonar.batch.rule.ModuleQProfiles; | |||
import org.sonar.batch.util.BatchUtils; | |||
@@ -58,7 +54,6 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad | |||
url += "&preview=" + analysisMode.isIssues(); | |||
ProjectRepositories projectRepositories = load(url, fromCache); | |||
validateProjectRepositories(projectRepositories); | |||
return projectRepositories; | |||
} | |||
@@ -69,10 +64,4 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad | |||
} | |||
return ProjectRepositories.fromJson(result.get()); | |||
} | |||
private static void validateProjectRepositories(ProjectRepositories projectRepositories) { | |||
if (projectRepositories.qProfiles().isEmpty()) { | |||
throw MessageException.of("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis."); | |||
} | |||
} | |||
} |
@@ -20,6 +20,7 @@ | |||
package org.sonar.batch.mediumtest.cache; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Date; | |||
import org.junit.After; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -31,8 +32,6 @@ 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(); | |||
@@ -49,7 +48,7 @@ public class CacheSyncTest { | |||
@Test | |||
public void testSyncFirstTime() { | |||
FileData file1 = new FileData("hash", true); | |||
FileData file1 = new FileData("hash", "123456789"); | |||
tester = BatchMediumTester.builder() | |||
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES)) | |||
@@ -64,10 +63,10 @@ public class CacheSyncTest { | |||
tester.start(); | |||
tester.syncProject("test-project"); | |||
} | |||
@Test | |||
public void testNonAssociated() { | |||
FileData file1 = new FileData("hash", true); | |||
FileData file1 = new FileData("hash", "123456789"); | |||
tester = BatchMediumTester.builder() | |||
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES)) | |||
@@ -85,7 +84,7 @@ public class CacheSyncTest { | |||
@Test | |||
public void testNoQProfile() { | |||
FileData file1 = new FileData("hash", true); | |||
FileData file1 = new FileData("hash", "123456789"); | |||
tester = BatchMediumTester.builder() | |||
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES)) |
@@ -55,7 +55,7 @@ public class ScmMediumTest { | |||
public BatchMediumTester tester = BatchMediumTester.builder() | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way") | |||
.addFileData("com.foo.project", "src/sample2.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), false)) | |||
.addFileData("com.foo.project", "src/sample2.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), null)) | |||
.build(); | |||
@Before |
@@ -54,8 +54,8 @@ public class DefaultProjectSettingsLoaderTest { | |||
projectRepositories = new ProjectRepositories(); | |||
projectRepositories.setLastAnalysisDate(new Date(1000)); | |||
f1 = new FileData("hash1", true); | |||
f2 = new FileData("hash2", true); | |||
f1 = new FileData("hash1", "123456789"); | |||
f2 = new FileData("hash2", "123456789"); | |||
projectRepositories.addFileData("module1", "file1", f1); | |||
projectRepositories.addFileData("module1", "file2", f2); | |||
@@ -19,15 +19,14 @@ | |||
*/ | |||
package org.sonar.batch.scan.filesystem; | |||
import com.google.common.collect.ImmutableTable; | |||
import com.google.common.collect.HashBasedTable; | |||
import com.google.common.collect.ImmutableTable; | |||
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.repository.ProjectSettingsRepo; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class StatusDetectionTest { | |||
@@ -45,8 +44,8 @@ public class StatusDetectionTest { | |||
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)); | |||
t.put("foo", "src/Foo.java", new FileData("ABCDE", "12345789")); | |||
t.put("foo", "src/Bar.java", new FileData("FGHIJ", "123456789")); | |||
return t; | |||
} |
@@ -26,6 +26,7 @@ public class FilePathWithHashDto { | |||
private String moduleUuid; | |||
private String path; | |||
private String srcHash; | |||
private String revision; | |||
public String getSrcHash() { | |||
return srcHash; | |||
@@ -51,6 +52,14 @@ public class FilePathWithHashDto { | |||
this.path = path; | |||
} | |||
public String getRevision() { | |||
return revision; | |||
} | |||
public void setRevision(String revision) { | |||
this.revision = revision; | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
@@ -58,4 +67,5 @@ public class FilePathWithHashDto { | |||
public void setUuid(String uuid) { | |||
this.uuid = uuid; | |||
} | |||
} |
@@ -191,7 +191,7 @@ | |||
</sql> | |||
<select id="selectEnabledFilesFromProject" parameterType="map" resultType="FilePathWithHash"> | |||
SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash | |||
SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash, fs.revision | |||
FROM projects p | |||
INNER JOIN file_sources fs ON fs.file_uuid=p.uuid and fs.data_type='SOURCE' | |||
<where> | |||
@@ -202,7 +202,7 @@ | |||
</select> | |||
<select id="selectDescendantFiles" parameterType="map" resultType="FilePathWithHash"> | |||
SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash | |||
SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash, fs.revision | |||
FROM projects p | |||
INNER JOIN file_sources fs ON fs.file_uuid=p.uuid and fs.data_type='SOURCE' | |||
<include refid="modulesTreeQuery"/> |
@@ -384,6 +384,7 @@ public class ComponentDaoTest { | |||
assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); | |||
assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); | |||
assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); | |||
assertThat(files).extracting("revision").containsOnly("123456789"); | |||
// From module | |||
files = underTest.selectEnabledDescendantFiles(dbSession, "EFGH"); | |||
@@ -391,6 +392,7 @@ public class ComponentDaoTest { | |||
assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); | |||
assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); | |||
assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); | |||
assertThat(files).extracting("revision").containsOnly("123456789"); | |||
// From sub module | |||
files = underTest.selectEnabledDescendantFiles(dbSession, "FGHI"); | |||
@@ -398,6 +400,7 @@ public class ComponentDaoTest { | |||
assertThat(files).extracting("moduleUuid").containsOnly("FGHI"); | |||
assertThat(files).extracting("srcHash").containsOnly("srcHIJK"); | |||
assertThat(files).extracting("path").containsOnly("src/org/struts/RequestContext.java"); | |||
assertThat(files).extracting("revision").containsOnly("123456789"); | |||
// From directory | |||
assertThat(underTest.selectEnabledDescendantFiles(dbSession, "GHIJ")).isEmpty(); |
@@ -23,7 +23,7 @@ | |||
binary_data=",,,,,,,,,,,,,,,unchanged ,,,,,,,,,,,,,,,content " | |||
line_hashes="lineEFGHI" | |||
data_hash="dataEFGHI" | |||
src_hash="srcEFGHI" | |||
src_hash="srcEFGHI" revision="123456789" | |||
created_at="1412952242000" updated_at="1412952242000" data_type="SOURCE"/> | |||
<!-- sub module --> | |||
@@ -50,7 +50,7 @@ | |||
binary_data=",,,,,,,,,,,,,,,unchanged ,,,,,,,,,,,,,,,content " | |||
line_hashes="lineHIJK" | |||
data_hash="dataHIJK" | |||
src_hash="srcHIJK" | |||
src_hash="srcHIJK" revision="123456789" | |||
created_at="1412952242000" updated_at="1412952242000" data_type="SOURCE"/> | |||
</dataset> |
@@ -0,0 +1,47 @@ | |||
// SonarQube, open source software quality management tool. | |||
// Copyright (C) 2008-2015 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. | |||
syntax = "proto2"; | |||
package sonarqube.ws.batch; | |||
option java_package = "org.sonarqube.ws"; | |||
option java_outer_classname = "WsBatch"; | |||
option optimize_for = SPEED; | |||
// WS api/batch/project | |||
message WsProjectResponse { | |||
optional int64 timestamp = 1; | |||
map<string, Settings> settingsByModule = 2; | |||
map<string, FileDataByPath> fileDataByModuleAndPatch = 3; | |||
optional int64 lastAnalysisDate = 4; | |||
message Settings { | |||
map<string,string> settings = 1; | |||
} | |||
message FileDataByPath { | |||
map<string, FileData> FileDataByPath = 1; | |||
} | |||
message FileData { | |||
optional string hash = 1; | |||
optional string revision = 2; | |||
} | |||
} |