@@ -0,0 +1,23 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
package org.sonar.cluster.internal; | |||
import javax.annotation.ParametersAreNonnullByDefault; |
@@ -174,7 +174,7 @@ public class ComponentDao implements Dao { | |||
public List<ComponentDto> selectByKeysAndBranch(DbSession session, Collection<String> keys, String branch) { | |||
List<String> dbKeys = keys.stream().map(k -> generateBranchKey(k, branch)).collect(toList()); | |||
List<String> allKeys = Stream.of(keys, dbKeys) .flatMap(x -> x.stream()) .collect(toList()); | |||
List<String> allKeys = Stream.of(keys, dbKeys) .flatMap(Collection::stream) .collect(toList()); | |||
return executeLargeInputs(allKeys, subKeys -> mapper(session).selectByKeysAndBranch(subKeys, branch)); | |||
} | |||
@@ -69,40 +69,19 @@ public class IssueLifecycle { | |||
raw.setKey(Uuids.create()); | |||
raw.setNew(false); | |||
raw.setCopied(true); | |||
raw.setType(base.type()); | |||
raw.setCreationDate(base.creationDate()); | |||
raw.setUpdateDate(base.updateDate()); | |||
raw.setCloseDate(base.closeDate()); | |||
raw.setResolution(base.resolution()); | |||
raw.setStatus(base.status()); | |||
raw.setAssignee(base.assignee()); | |||
raw.setAuthorLogin(base.authorLogin()); | |||
raw.setTags(base.tags()); | |||
raw.setAttributes(base.attributes()); | |||
raw.setEffort(debtCalculator.calculate(raw)); | |||
raw.setOnDisabledRule(base.isOnDisabledRule()); | |||
copyFields(raw, base); | |||
if (base.manualSeverity()) { | |||
raw.setManualSeverity(true); | |||
raw.setSeverity(base.severity()); | |||
} | |||
raw.setSelectedAt(base.selectedAt()); | |||
} | |||
public void mergeExistingOpenIssue(DefaultIssue raw, DefaultIssue base) { | |||
raw.setNew(false); | |||
raw.setKey(base.key()); | |||
raw.setType(base.type()); | |||
raw.setCreationDate(base.creationDate()); | |||
raw.setUpdateDate(base.updateDate()); | |||
raw.setCloseDate(base.closeDate()); | |||
raw.setResolution(base.resolution()); | |||
raw.setStatus(base.status()); | |||
raw.setAssignee(base.assignee()); | |||
raw.setAuthorLogin(base.authorLogin()); | |||
raw.setTags(base.tags()); | |||
raw.setAttributes(base.attributes()); | |||
raw.setEffort(debtCalculator.calculate(raw)); | |||
raw.setOnDisabledRule(base.isOnDisabledRule()); | |||
raw.setNew(false); | |||
copyFields(raw, base); | |||
if (base.manualSeverity()) { | |||
raw.setManualSeverity(true); | |||
raw.setSeverity(base.severity()); | |||
@@ -122,10 +101,25 @@ public class IssueLifecycle { | |||
updater.setPastMessage(raw, base.getMessage(), changeContext); | |||
updater.setPastGap(raw, base.gap(), changeContext); | |||
updater.setPastEffort(raw, base.effort(), changeContext); | |||
raw.setSelectedAt(base.selectedAt()); | |||
} | |||
public void doAutomaticTransition(DefaultIssue issue) { | |||
workflow.doAutomaticTransition(issue, changeContext); | |||
} | |||
private void copyFields(DefaultIssue toIssue, DefaultIssue fromIssue) { | |||
toIssue.setType(fromIssue.type()); | |||
toIssue.setCreationDate(fromIssue.creationDate()); | |||
toIssue.setUpdateDate(fromIssue.updateDate()); | |||
toIssue.setCloseDate(fromIssue.closeDate()); | |||
toIssue.setResolution(fromIssue.resolution()); | |||
toIssue.setStatus(fromIssue.status()); | |||
toIssue.setAssignee(fromIssue.assignee()); | |||
toIssue.setAuthorLogin(fromIssue.authorLogin()); | |||
toIssue.setTags(fromIssue.tags()); | |||
toIssue.setAttributes(fromIssue.attributes()); | |||
toIssue.setEffort(debtCalculator.calculate(toIssue)); | |||
toIssue.setOnDisabledRule(fromIssue.isOnDisabledRule()); | |||
toIssue.setSelectedAt(fromIssue.selectedAt()); | |||
} | |||
} |
@@ -22,7 +22,6 @@ package org.sonar.server.computation.task.projectanalysis.step; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Date; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
@@ -64,7 +63,7 @@ public class SendIssueNotificationsStep implements ComputationStep { | |||
private final NotificationService service; | |||
private final AnalysisMetadataHolder analysisMetadataHolder; | |||
private final NewIssuesNotificationFactory newIssuesNotificationFactory; | |||
private Map<String, Component> componentsByDbKey = new HashMap<>(); | |||
private Map<String, Component> componentsByDbKey; | |||
public SendIssueNotificationsStep(IssueCache issueCache, RuleRepository rules, TreeRootHolder treeRootHolder, | |||
NotificationService service, AnalysisMetadataHolder analysisMetadataHolder, | |||
@@ -150,7 +149,7 @@ public class SendIssueNotificationsStep implements ComputationStep { | |||
} | |||
private Optional<Component> getComponentKey(DefaultIssue issue) { | |||
if (componentsByDbKey.isEmpty()) { | |||
if (componentsByDbKey == null) { | |||
final ImmutableMap.Builder<String, Component> builder = ImmutableMap.builder(); | |||
new DepthTraversalTypeAwareCrawler( | |||
new TypeAwareVisitorAdapter(CrawlerDepthLimit.LEAVES, POST_ORDER) { |
@@ -22,7 +22,10 @@ package org.sonar.server.projectbranch.ws; | |||
import java.util.Arrays; | |||
import org.sonar.api.server.ws.WebService; | |||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.CONTROLLER; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.PARAM_BRANCH; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.PARAM_PROJECT; | |||
public class BranchesWs implements WebService { | |||
private final BranchWsAction[] actions; | |||
@@ -39,4 +42,17 @@ public class BranchesWs implements WebService { | |||
controller.done(); | |||
} | |||
static void addProjectBranchParams(NewAction action) { | |||
action | |||
.createParam(PARAM_PROJECT) | |||
.setDescription("Project key") | |||
.setExampleValue(KEY_PROJECT_EXAMPLE_001) | |||
.setRequired(true); | |||
action | |||
.createParam(PARAM_BRANCH) | |||
.setDescription("Name of the branch to delete. Can't be the main branch of the project.") | |||
.setExampleValue("branch1") | |||
.setRequired(true); | |||
} | |||
} |
@@ -34,7 +34,6 @@ import org.sonar.server.component.ComponentCleanerService; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.user.UserSession; | |||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | |||
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.ACTION_DELETE; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.PARAM_BRANCH; | |||
@@ -63,16 +62,7 @@ public class DeleteAction implements BranchWsAction { | |||
.setPost(true) | |||
.setHandler(this); | |||
action | |||
.createParam(PARAM_PROJECT) | |||
.setDescription("Project key") | |||
.setExampleValue(KEY_PROJECT_EXAMPLE_001) | |||
.setRequired(true); | |||
action | |||
.createParam(PARAM_BRANCH) | |||
.setDescription("Name of the branch to delete. Can't be the main branch of the project.") | |||
.setExampleValue("branch1") | |||
.setRequired(true); | |||
BranchesWs.addProjectBranchParams(action); | |||
} | |||
@Override |
@@ -33,7 +33,6 @@ import org.sonar.db.component.ComponentDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.user.UserSession; | |||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.ACTION_RENAME; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.PARAM_BRANCH; | |||
import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.PARAM_PROJECT; | |||
@@ -59,16 +58,7 @@ public class RenameAction implements BranchWsAction { | |||
.setPost(true) | |||
.setHandler(this); | |||
action | |||
.createParam(PARAM_PROJECT) | |||
.setDescription("Project key") | |||
.setExampleValue(KEY_PROJECT_EXAMPLE_001) | |||
.setRequired(true); | |||
action | |||
.createParam(PARAM_BRANCH) | |||
.setDescription("New name of the main branch") | |||
.setExampleValue("master") | |||
.setRequired(true); | |||
BranchesWs.addProjectBranchParams(action); | |||
} | |||
@Override |
@@ -42,7 +42,7 @@ public class FileCache { | |||
FileCache(File dir, FileHashes fileHashes, Logger logger) { | |||
this.hashes = fileHashes; | |||
this.logger = logger; | |||
this.dir = createDir(dir, "user cache"); | |||
this.dir = createDir(dir, "user cache: "); | |||
logger.info(String.format("User cache: %s", dir.getAbsolutePath())); | |||
this.tmpDir = createDir(new File(dir, "_tmp"), "temp dir"); | |||
} |
@@ -22,6 +22,8 @@ package org.sonar.home.cache; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.commons.io.FileUtils; | |||
import org.assertj.core.util.Files; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
@@ -33,6 +35,15 @@ import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class FileCacheTest { | |||
private FileHashes fileHashes; | |||
private FileCache cache; | |||
@Before | |||
public void setUp() throws IOException { | |||
fileHashes = mock(FileHashes.class); | |||
cache = new FileCache(tempFolder.getRoot(), fileHashes, mock(Logger.class)); | |||
} | |||
@Rule | |||
public TemporaryFolder tempFolder = new TemporaryFolder(); | |||
@@ -41,14 +52,11 @@ public class FileCacheTest { | |||
@Test | |||
public void not_in_cache() throws IOException { | |||
FileCache cache = FileCache.create(tempFolder.newFolder(), mock(Logger.class)); | |||
assertThat(cache.get("sonar-foo-plugin-1.5.jar", "ABCDE")).isNull(); | |||
} | |||
@Test | |||
public void found_in_cache() throws IOException { | |||
FileCache cache = FileCache.create(tempFolder.newFolder(), mock(Logger.class)); | |||
// populate the cache. Assume that hash is correct. | |||
File cachedFile = new File(new File(cache.getDir(), "ABCDE"), "sonar-foo-plugin-1.5.jar"); | |||
FileUtils.write(cachedFile, "body"); | |||
@@ -56,11 +64,42 @@ public class FileCacheTest { | |||
assertThat(cache.get("sonar-foo-plugin-1.5.jar", "ABCDE")).isNotNull().exists().isEqualTo(cachedFile); | |||
} | |||
@Test | |||
public void fail_to_download() { | |||
when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); | |||
FileCache.Downloader downloader = new FileCache.Downloader() { | |||
public void download(String filename, File toFile) throws IOException { | |||
throw new IOException("fail"); | |||
} | |||
}; | |||
thrown.expect(IllegalStateException.class); | |||
thrown.expectMessage("Fail to download"); | |||
cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", downloader); | |||
} | |||
@Test | |||
public void fail_create_hash_dir() throws IOException { | |||
File file = tempFolder.newFile(); | |||
thrown.expect(IllegalStateException.class); | |||
thrown.expectMessage("Unable to create user cache"); | |||
cache = new FileCache(file, fileHashes, mock(Logger.class)); | |||
} | |||
@Test | |||
public void fail_to_create_hash_dir() throws IOException { | |||
when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); | |||
File hashDir = new File(cache.getDir(), "ABCDE"); | |||
hashDir.createNewFile(); | |||
thrown.expect(IllegalStateException.class); | |||
thrown.expectMessage("Fail to create cache directory"); | |||
cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", mock(FileCache.Downloader.class)); | |||
} | |||
@Test | |||
public void download_and_add_to_cache() throws IOException { | |||
FileHashes hashes = mock(FileHashes.class); | |||
FileCache cache = new FileCache(tempFolder.newFolder(), hashes, mock(Logger.class)); | |||
when(hashes.of(any(File.class))).thenReturn("ABCDE"); | |||
when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); | |||
FileCache.Downloader downloader = new FileCache.Downloader() { | |||
public void download(String filename, File toFile) throws IOException { | |||
@@ -79,9 +118,7 @@ public class FileCacheTest { | |||
thrown.expect(IllegalStateException.class); | |||
thrown.expectMessage("INVALID HASH"); | |||
FileHashes hashes = mock(FileHashes.class); | |||
FileCache cache = new FileCache(tempFolder.newFolder(), hashes, mock(Logger.class)); | |||
when(hashes.of(any(File.class))).thenReturn("VWXYZ"); | |||
when(fileHashes.of(any(File.class))).thenReturn("VWXYZ"); | |||
FileCache.Downloader downloader = new FileCache.Downloader() { | |||
public void download(String filename, File toFile) throws IOException { | |||
@@ -93,9 +130,7 @@ public class FileCacheTest { | |||
@Test | |||
public void concurrent_download() throws IOException { | |||
FileHashes hashes = mock(FileHashes.class); | |||
when(hashes.of(any(File.class))).thenReturn("ABCDE"); | |||
final FileCache cache = new FileCache(tempFolder.newFolder(), hashes, mock(Logger.class)); | |||
when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); | |||
FileCache.Downloader downloader = new FileCache.Downloader() { | |||
public void download(String filename, File toFile) throws IOException { |
@@ -67,6 +67,7 @@ public class ReportPublisher implements Startable { | |||
public static final String KEEP_REPORT_PROP_KEY = "sonar.scanner.keepReport"; | |||
public static final String VERBOSE_KEY = "sonar.verbose"; | |||
public static final String METADATA_DUMP_FILENAME = "report-task.txt"; | |||
private static final String CHARACTERISTIC = "characteristic"; | |||
private final Configuration settings; | |||
private final ScannerWsClient wsClient; | |||
@@ -181,13 +182,13 @@ public class ReportPublisher implements Startable { | |||
.setPart("report", filePart); | |||
if (analysisFlags.isIncremental()) { | |||
post.setParam("characteristic", "incremental=true"); | |||
post.setParam(CHARACTERISTIC, "incremental=true"); | |||
} | |||
String branchName = branchConfiguration.branchName(); | |||
if (branchName != null) { | |||
post.setParam("characteristic", "branch=" + branchName); | |||
post.setParam("characteristic", "branchType=" + branchConfiguration.branchType().name()); | |||
post.setParam(CHARACTERISTIC, "branch=" + branchName); | |||
post.setParam(CHARACTERISTIC, "branchType=" + branchConfiguration.branchType().name()); | |||
} | |||
WsResponse response; |
@@ -53,7 +53,7 @@ public class BranchConfigurationProvider extends ProviderAdapter { | |||
return branchConfiguration; | |||
} | |||
private Supplier<Map<String, String>> createSettingsSupplier(GlobalConfiguration globalConfiguration, ProjectKey projectKey, SettingsLoader settingsLoader) { | |||
private static Supplier<Map<String, String>> createSettingsSupplier(GlobalConfiguration globalConfiguration, ProjectKey projectKey, SettingsLoader settingsLoader) { | |||
return () -> { | |||
Map<String, String> settings = new HashMap<>(); | |||
settings.putAll(globalConfiguration.getProperties()); |