mirror of
https://github.com/SonarSource/sonarqube.git
synced 2024-08-08 03:05:57 +02:00
SONAR-5643 Provide a default SVN SCM Provider
This commit is contained in:
parent
327799ec3e
commit
2d60412e14
@ -47,23 +47,6 @@
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
<artifactId>sonar-batch</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>sonar-deprecated</artifactId>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar.plugins</groupId>
|
||||
<artifactId>sonar-xoo-plugin</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -48,10 +48,11 @@ public class GitBlameCommand implements BlameCommand, BatchComponent {
|
||||
|
||||
@Override
|
||||
public void blame(FileSystem fs, Iterable<InputFile> files, BlameResult result) {
|
||||
LOG.info("Working directory: " + fs.baseDir().getAbsolutePath());
|
||||
for (InputFile inputFile : files) {
|
||||
String filename = inputFile.relativePath();
|
||||
Command cl = createCommandLine(fs.baseDir(), filename);
|
||||
GitBlameConsumer consumer = new GitBlameConsumer(LOG);
|
||||
GitBlameConsumer consumer = new GitBlameConsumer();
|
||||
StringStreamConsumer stderr = new StringStreamConsumer();
|
||||
|
||||
int exitCode = execute(cl, consumer, stderr);
|
||||
@ -64,9 +65,7 @@ public class GitBlameCommand implements BlameCommand, BatchComponent {
|
||||
|
||||
public int execute(Command cl, StreamConsumer consumer, StreamConsumer stderr) {
|
||||
LOG.info("Executing: " + cl);
|
||||
LOG.info("Working directory: " + cl.getDirectory().getAbsolutePath());
|
||||
|
||||
return commandExecutor.execute(cl, consumer, stderr, 10 * 1000);
|
||||
return commandExecutor.execute(cl, consumer, stderr, 0);
|
||||
}
|
||||
|
||||
private Command createCommandLine(File workingDirectory, String filename) {
|
||||
|
@ -20,30 +20,15 @@
|
||||
package org.sonar.plugins.scm.git;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.sonar.api.batch.scm.BlameLine;
|
||||
import org.sonar.api.utils.command.StreamConsumer;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Plain copy of package org.apache.maven.scm.provider.git.gitexe.command.blame.GitBlameConsumer
|
||||
* Patched to allow user email retrieval when parsing Git blame results.
|
||||
*
|
||||
* @Todo: hack - to be submitted as an update in maven-scm-api for a future release
|
||||
*
|
||||
* <p/>
|
||||
* For more information, see:
|
||||
* <a href="http://jira.sonarsource.com/browse/DEVACT-103">DEVACT-103</a>
|
||||
*
|
||||
* @since 1.5.1
|
||||
*/
|
||||
public class GitBlameConsumer implements StreamConsumer {
|
||||
|
||||
private static final String GIT_COMMITTER_PREFIX = "committer";
|
||||
@ -71,15 +56,6 @@ public class GitBlameConsumer implements StreamConsumer {
|
||||
private String author = null;
|
||||
private String committer = null;
|
||||
private Date time = null;
|
||||
private Logger logger;
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public GitBlameConsumer(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void consumeLine(String line) {
|
||||
if (line == null) {
|
||||
@ -123,21 +99,6 @@ public class GitBlameConsumer implements StreamConsumer {
|
||||
return false;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected String getCommitter() {
|
||||
return committer;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
private String extractEmail(String line) {
|
||||
|
||||
int emailStartIndex = line.indexOf(OPENING_EMAIL_FIELD);
|
||||
@ -156,11 +117,6 @@ public class GitBlameConsumer implements StreamConsumer {
|
||||
// keep commitinfo for this sha-1
|
||||
commitInfo.put(revision, blameLine);
|
||||
|
||||
if (getLogger().isDebugEnabled()) {
|
||||
DateFormat df = SimpleDateFormat.getDateTimeInstance();
|
||||
getLogger().debug(author + " " + df.format(time));
|
||||
}
|
||||
|
||||
expectRevisionLine = true;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.sonar.plugins.scm.git;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.sonar.api.CoreProperties;
|
||||
import org.sonar.api.PropertyType;
|
||||
import org.sonar.api.SonarPlugin;
|
||||
import org.sonar.api.config.PropertyDefinition;
|
||||
@ -28,6 +29,7 @@ import java.util.List;
|
||||
|
||||
public final class GitPlugin extends SonarPlugin {
|
||||
|
||||
static final String CATEGORY_GIT = "Git";
|
||||
static final String GIT_IMPLEMENTATION_PROP_KEY = "sonar.git.implementation";
|
||||
static final String JGIT = "jgit";
|
||||
static final String EXE = "exe";
|
||||
@ -40,10 +42,12 @@ public final class GitPlugin extends SonarPlugin {
|
||||
|
||||
PropertyDefinition.builder(GIT_IMPLEMENTATION_PROP_KEY)
|
||||
.name("Git implementation")
|
||||
.description("Use pure Java implementation by default but you can use command line git executable in case of issue.")
|
||||
.description("By default pure Java implementation is used. You can force use of command line git executable in case of issue.")
|
||||
.defaultValue(JGIT)
|
||||
.type(PropertyType.SINGLE_SELECT_LIST)
|
||||
.options(EXE, JGIT)
|
||||
.category(CoreProperties.CATEGORY_SCM)
|
||||
.subCategory(CATEGORY_GIT)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
@ -105,4 +105,30 @@ public class GitBlameCommandTest {
|
||||
new BlameLine(DateUtils.parseDateTime("2011-08-05T10:49:31+0200"), "2c68c473da7fc293e12ca50f19380c5118be7ead", "simon.brandhof@gmail.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecutionError() throws IOException {
|
||||
File source = new File(baseDir, "src/foo.xoo");
|
||||
FileUtils.write(source, "sample content");
|
||||
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath());
|
||||
fs.add(inputFile);
|
||||
|
||||
BlameResult result = mock(BlameResult.class);
|
||||
CommandExecutor commandExecutor = mock(CommandExecutor.class);
|
||||
|
||||
when(commandExecutor.execute(any(Command.class), any(StreamConsumer.class), any(StreamConsumer.class), anyLong())).thenAnswer(new Answer<Integer>() {
|
||||
|
||||
@Override
|
||||
public Integer answer(InvocationOnMock invocation) throws Throwable {
|
||||
StreamConsumer errConsumer = (StreamConsumer) invocation.getArguments()[2];
|
||||
errConsumer.consumeLine("My error");
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("The git blame command [git blame --porcelain src/foo.xoo -w] failed: My error");
|
||||
|
||||
new GitBlameCommand(commandExecutor).blame(fs, Arrays.<InputFile>asList(inputFile), result);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
* 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.plugins.scm.git;
|
||||
|
||||
import com.google.common.io.Closeables;
|
||||
|
60
plugins/sonar-svn-plugin/pom.xml
Normal file
60
plugins/sonar-svn-plugin/pom.xml
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
<artifactId>sonar</artifactId>
|
||||
<version>5.0-SNAPSHOT</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
<groupId>org.codehaus.sonar.plugins</groupId>
|
||||
<artifactId>sonar-svn-plugin</artifactId>
|
||||
<name>SonarQube :: Plugins :: SVN</name>
|
||||
<packaging>sonar-plugin</packaging>
|
||||
<description>SVN SCM Provider.</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
<artifactId>sonar-plugin-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- unit tests -->
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
<artifactId>sonar-testing-harness</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
<artifactId>sonar-packaging-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<pluginKey>svn</pluginKey>
|
||||
<pluginName>SVN</pluginName>
|
||||
<pluginClass>org.sonar.plugins.scm.svn.SvnPlugin</pluginClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonar.api.BatchComponent;
|
||||
import org.sonar.api.batch.InstantiationStrategy;
|
||||
import org.sonar.api.batch.fs.FileSystem;
|
||||
import org.sonar.api.batch.fs.InputFile;
|
||||
import org.sonar.api.batch.scm.BlameCommand;
|
||||
import org.sonar.api.utils.command.Command;
|
||||
import org.sonar.api.utils.command.CommandExecutor;
|
||||
import org.sonar.api.utils.command.StreamConsumer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
|
||||
public class SvnBlameCommand implements BlameCommand, BatchComponent {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SvnBlameCommand.class);
|
||||
private final CommandExecutor commandExecutor;
|
||||
private final SvnConfiguration configuration;
|
||||
|
||||
public SvnBlameCommand(SvnConfiguration configuration) {
|
||||
this(CommandExecutor.create(), configuration);
|
||||
}
|
||||
|
||||
SvnBlameCommand(CommandExecutor commandExecutor, SvnConfiguration configuration) {
|
||||
this.commandExecutor = commandExecutor;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blame(final FileSystem fs, Iterable<InputFile> files, final BlameResult result) {
|
||||
LOG.info("Working directory: " + fs.baseDir().getAbsolutePath());
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
|
||||
List<Future<Void>> tasks = new ArrayList<Future<Void>>();
|
||||
for (InputFile inputFile : files) {
|
||||
tasks.add(submitTask(fs, result, executorService, inputFile));
|
||||
}
|
||||
|
||||
for (Future<Void> task : tasks) {
|
||||
try {
|
||||
task.get();
|
||||
} catch (ExecutionException e) {
|
||||
throw e.getCause() instanceof RuntimeException ? (RuntimeException) e.getCause() : new IllegalStateException(e.getCause());
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Future<Void> submitTask(final FileSystem fs, final BlameResult result, ExecutorService executorService, final InputFile inputFile) {
|
||||
return executorService.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
String filename = inputFile.relativePath();
|
||||
Command cl = createCommandLine(fs.baseDir(), filename);
|
||||
SvnBlameConsumer consumer = new SvnBlameConsumer();
|
||||
StringStreamConsumer stderr = new StringStreamConsumer();
|
||||
|
||||
int exitCode = execute(cl, consumer, stderr);
|
||||
if (exitCode != 0) {
|
||||
throw new IllegalStateException("The svn blame command [" + cl.toString() + "] failed: " + stderr.getOutput());
|
||||
}
|
||||
result.add(inputFile, consumer.getLines());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int execute(Command cl, StreamConsumer consumer, StreamConsumer stderr) {
|
||||
LOG.info("Executing: " + cl);
|
||||
return commandExecutor.execute(cl, consumer, stderr, 0);
|
||||
}
|
||||
|
||||
public Command createCommandLine(File workingDirectory, String filename) {
|
||||
Command cl = Command.create("svn");
|
||||
for (Entry<String, String> env : System.getenv().entrySet()) {
|
||||
cl.setEnvironmentVariable(env.getKey(), env.getValue());
|
||||
}
|
||||
cl.setEnvironmentVariable("LC_MESSAGES", "en");
|
||||
|
||||
if (workingDirectory != null) {
|
||||
cl.setDirectory(workingDirectory);
|
||||
}
|
||||
cl.addArgument("blame");
|
||||
cl.addArgument("--xml");
|
||||
cl.addArgument(filename);
|
||||
cl.addArgument("--non-interactive");
|
||||
String configDir = configuration.configDir();
|
||||
if (configDir != null) {
|
||||
cl.addArgument("--config-dir");
|
||||
cl.addArgument(configDir);
|
||||
}
|
||||
String username = configuration.username();
|
||||
if (username != null) {
|
||||
cl.addArgument("--username");
|
||||
cl.addArgument(username);
|
||||
String password = configuration.password();
|
||||
if (password != null) {
|
||||
cl.addArgument("--password");
|
||||
cl.addArgument(password);
|
||||
}
|
||||
}
|
||||
if (configuration.trustServerCert()) {
|
||||
cl.addArgument("--trust-server-cert");
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
private static class StringStreamConsumer implements StreamConsumer {
|
||||
private StringBuffer string = new StringBuffer();
|
||||
|
||||
private String ls = System.getProperty("line.separator");
|
||||
|
||||
@Override
|
||||
public void consumeLine(String line) {
|
||||
string.append(line + ls);
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return string.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonar.api.batch.scm.BlameLine;
|
||||
import org.sonar.api.utils.command.StreamConsumer;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SvnBlameConsumer implements StreamConsumer {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SvnBlameConsumer.class);
|
||||
|
||||
private static final String SVN_TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
private static final Pattern LINE_PATTERN = Pattern.compile("line-number=\"(.*)\"");
|
||||
|
||||
private static final Pattern REVISION_PATTERN = Pattern.compile("revision=\"(.*)\"");
|
||||
|
||||
private static final Pattern AUTHOR_PATTERN = Pattern.compile("<author>(.*)</author>");
|
||||
|
||||
private static final Pattern DATE_PATTERN = Pattern.compile("<date>(.*)T(.*)\\.(.*)Z</date>");
|
||||
|
||||
private SimpleDateFormat dateFormat;
|
||||
|
||||
private List<BlameLine> lines = new ArrayList<BlameLine>();
|
||||
|
||||
public SvnBlameConsumer() {
|
||||
dateFormat = new SimpleDateFormat(SVN_TIMESTAMP_PATTERN);
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
}
|
||||
|
||||
private int lineNumber;
|
||||
|
||||
private String revision;
|
||||
|
||||
private String author;
|
||||
|
||||
@Override
|
||||
public void consumeLine(String line) {
|
||||
Matcher matcher;
|
||||
if ((matcher = LINE_PATTERN.matcher(line)).find()) {
|
||||
String lineNumberStr = matcher.group(1);
|
||||
lineNumber = Integer.parseInt(lineNumberStr);
|
||||
}
|
||||
else if ((matcher = REVISION_PATTERN.matcher(line)).find()) {
|
||||
revision = matcher.group(1);
|
||||
}
|
||||
else if ((matcher = AUTHOR_PATTERN.matcher(line)).find()) {
|
||||
author = matcher.group(1);
|
||||
}
|
||||
else if ((matcher = DATE_PATTERN.matcher(line)).find()) {
|
||||
String date = matcher.group(1);
|
||||
String time = matcher.group(2);
|
||||
Date dateTime = parseDateTime(date + " " + time);
|
||||
lines.add(new BlameLine(dateTime, revision, author));
|
||||
}
|
||||
}
|
||||
|
||||
protected Date parseDateTime(String dateTimeStr) {
|
||||
try {
|
||||
return dateFormat.parse(dateTimeStr);
|
||||
} catch (ParseException e) {
|
||||
LOG.error("skip ParseException: " + e.getMessage() + " during parsing date " + dateTimeStr, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<BlameLine> getLines() {
|
||||
return lines;
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.sonar.api.BatchComponent;
|
||||
import org.sonar.api.CoreProperties;
|
||||
import org.sonar.api.PropertyType;
|
||||
import org.sonar.api.batch.InstantiationStrategy;
|
||||
import org.sonar.api.config.PropertyDefinition;
|
||||
import org.sonar.api.config.Settings;
|
||||
import org.sonar.api.resources.Qualifiers;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
|
||||
public class SvnConfiguration implements BatchComponent {
|
||||
|
||||
private static final String CATEGORY_SVN = "SVN";
|
||||
private static final String USER_PROP_KEY = "sonar.svn.username";
|
||||
private static final String PASSWORD_PROP_KEY = "sonar.svn.password";
|
||||
private static final String CONFIG_DIR_PROP_KEY = "sonar.svn.config_dir";
|
||||
private static final String TRUST_SERVER_PROP_KEY = "sonar.svn.trust_server_cert";
|
||||
private final Settings settings;
|
||||
|
||||
public SvnConfiguration(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public static List<PropertyDefinition> getProperties() {
|
||||
return ImmutableList.of(
|
||||
PropertyDefinition.builder(USER_PROP_KEY)
|
||||
.name("Username")
|
||||
.description("Username to be used for SVN authentication")
|
||||
.type(PropertyType.STRING)
|
||||
.onQualifiers(Qualifiers.PROJECT)
|
||||
.category(CoreProperties.CATEGORY_SCM)
|
||||
.subCategory(CATEGORY_SVN)
|
||||
.index(0)
|
||||
.build(),
|
||||
PropertyDefinition.builder(PASSWORD_PROP_KEY)
|
||||
.name("Password")
|
||||
.description("Password to be used for SVN authentication")
|
||||
.type(PropertyType.STRING)
|
||||
.onQualifiers(Qualifiers.PROJECT)
|
||||
.category(CoreProperties.CATEGORY_SCM)
|
||||
.subCategory(CATEGORY_SVN)
|
||||
.index(1)
|
||||
.build(),
|
||||
PropertyDefinition.builder(CONFIG_DIR_PROP_KEY)
|
||||
.name("Configuration directory")
|
||||
.description("Folder containing configuration files (see --config-dir)")
|
||||
.type(PropertyType.STRING)
|
||||
.onQualifiers(Qualifiers.PROJECT)
|
||||
.category(CoreProperties.CATEGORY_SCM)
|
||||
.subCategory(CATEGORY_SVN)
|
||||
.index(2)
|
||||
.build(),
|
||||
PropertyDefinition.builder(TRUST_SERVER_PROP_KEY)
|
||||
.name("Trust server certificate")
|
||||
.description("Accept unknown SSL certificates (like self-signed)")
|
||||
.type(PropertyType.BOOLEAN)
|
||||
.defaultValue("false")
|
||||
.onQualifiers(Qualifiers.PROJECT)
|
||||
.category(CoreProperties.CATEGORY_SCM)
|
||||
.subCategory(CATEGORY_SVN)
|
||||
.index(3)
|
||||
.build());
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public String username() {
|
||||
return settings.getString(USER_PROP_KEY);
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public String password() {
|
||||
return settings.getString(PASSWORD_PROP_KEY);
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public String configDir() {
|
||||
return settings.getString(CONFIG_DIR_PROP_KEY);
|
||||
}
|
||||
|
||||
public boolean trustServerCert() {
|
||||
return settings.getBoolean(TRUST_SERVER_PROP_KEY);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.sonar.api.SonarPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class SvnPlugin extends SonarPlugin {
|
||||
|
||||
public List getExtensions() {
|
||||
ArrayList result = new ArrayList();
|
||||
result.addAll(ImmutableList.of(
|
||||
SvnScmProvider.class,
|
||||
SvnBlameCommand.class,
|
||||
SvnConfiguration.class));
|
||||
result.addAll(SvnConfiguration.getProperties());
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import org.sonar.api.batch.scm.BlameCommand;
|
||||
import org.sonar.api.batch.scm.ScmProvider;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class SvnScmProvider extends ScmProvider {
|
||||
|
||||
private final SvnBlameCommand blameCommand;
|
||||
|
||||
public SvnScmProvider(SvnBlameCommand blameCommand) {
|
||||
this.blameCommand = blameCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String key() {
|
||||
return "svn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(File baseDir) {
|
||||
return new File(baseDir, ".svn").exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlameCommand blameCommand() {
|
||||
return blameCommand;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
package org.sonar.plugins.scm.svn;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.sonar.api.batch.fs.InputFile;
|
||||
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
|
||||
import org.sonar.api.batch.fs.internal.DefaultInputFile;
|
||||
import org.sonar.api.batch.scm.BlameCommand.BlameResult;
|
||||
import org.sonar.api.batch.scm.BlameLine;
|
||||
import org.sonar.api.utils.DateUtils;
|
||||
import org.sonar.api.utils.command.Command;
|
||||
import org.sonar.api.utils.command.CommandExecutor;
|
||||
import org.sonar.api.utils.command.StreamConsumer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SvnBlameCommandTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private DefaultFileSystem fs;
|
||||
private File baseDir;
|
||||
|
||||
@Before
|
||||
public void prepare() throws IOException {
|
||||
baseDir = temp.newFolder();
|
||||
fs = new DefaultFileSystem();
|
||||
fs.setBaseDir(baseDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsingOfOutput() throws IOException {
|
||||
File source = new File(baseDir, "src/foo.xoo");
|
||||
FileUtils.write(source, "sample content");
|
||||
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath());
|
||||
fs.add(inputFile);
|
||||
|
||||
BlameResult result = mock(BlameResult.class);
|
||||
CommandExecutor commandExecutor = mock(CommandExecutor.class);
|
||||
|
||||
when(commandExecutor.execute(any(Command.class), any(StreamConsumer.class), any(StreamConsumer.class), anyLong())).thenAnswer(new Answer<Integer>() {
|
||||
|
||||
@Override
|
||||
public Integer answer(InvocationOnMock invocation) throws Throwable {
|
||||
StreamConsumer outConsumer = (StreamConsumer) invocation.getArguments()[1];
|
||||
List<String> lines = FileUtils.readLines(new File("src/test/resources/blame.xml"), "UTF-8");
|
||||
for (String line : lines) {
|
||||
outConsumer.consumeLine(line);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
new SvnBlameCommand(commandExecutor, mock(SvnConfiguration.class)).blame(fs, Arrays.<InputFile>asList(inputFile), result);
|
||||
verify(result).add(inputFile,
|
||||
Arrays.asList(
|
||||
new BlameLine(DateUtils.parseDateTime("2009-04-18T10:29:59+0000"), "9491", "simon.brandhof"),
|
||||
new BlameLine(DateUtils.parseDateTime("2009-04-18T10:29:59+0000"), "9491", "simon.brandhof"),
|
||||
new BlameLine(DateUtils.parseDateTime("2009-08-31T22:32:17+0000"), "10558", "david")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecutionError() throws IOException {
|
||||
File source = new File(baseDir, "src/foo.xoo");
|
||||
FileUtils.write(source, "sample content");
|
||||
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath());
|
||||
fs.add(inputFile);
|
||||
|
||||
BlameResult result = mock(BlameResult.class);
|
||||
CommandExecutor commandExecutor = mock(CommandExecutor.class);
|
||||
|
||||
when(commandExecutor.execute(any(Command.class), any(StreamConsumer.class), any(StreamConsumer.class), anyLong())).thenAnswer(new Answer<Integer>() {
|
||||
|
||||
@Override
|
||||
public Integer answer(InvocationOnMock invocation) throws Throwable {
|
||||
StreamConsumer errConsumer = (StreamConsumer) invocation.getArguments()[2];
|
||||
errConsumer.consumeLine("My error");
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("The svn blame command [svn blame --xml src/foo.xoo --non-interactive] failed: My error");
|
||||
|
||||
new SvnBlameCommand(commandExecutor, mock(SvnConfiguration.class)).blame(fs, Arrays.<InputFile>asList(inputFile), result);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
public class SvnPluginTest {
|
||||
|
||||
@Test
|
||||
public void getExtensions() {
|
||||
assertThat(new SvnPlugin().getExtensions()).hasSize(7);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.plugins.scm.svn;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class SvnScmProviderTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void sanityCheck() {
|
||||
SvnBlameCommand blameCommand = new SvnBlameCommand(mock(SvnConfiguration.class));
|
||||
SvnScmProvider svnScmProvider = new SvnScmProvider(blameCommand);
|
||||
assertThat(svnScmProvider.key()).isEqualTo("svn");
|
||||
assertThat(svnScmProvider.blameCommand()).isEqualTo(blameCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetection() throws IOException {
|
||||
File baseDirEmpty = temp.newFolder();
|
||||
assertThat(new SvnScmProvider(null).supports(baseDirEmpty)).isFalse();
|
||||
|
||||
File svnBaseDir = temp.newFolder();
|
||||
new File(svnBaseDir, ".svn").mkdir();
|
||||
assertThat(new SvnScmProvider(null).supports(svnBaseDir)).isTrue();
|
||||
}
|
||||
|
||||
}
|
30
plugins/sonar-svn-plugin/src/test/resources/blame.xml
Normal file
30
plugins/sonar-svn-plugin/src/test/resources/blame.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<blame>
|
||||
<target
|
||||
path="pom.xml">
|
||||
<entry
|
||||
line-number="1">
|
||||
<commit
|
||||
revision="9491">
|
||||
<author>simon.brandhof</author>
|
||||
<date>2009-04-18T10:29:59.077093Z</date>
|
||||
</commit>
|
||||
</entry>
|
||||
<entry
|
||||
line-number="2">
|
||||
<commit
|
||||
revision="9491">
|
||||
<author>simon.brandhof</author>
|
||||
<date>2009-04-18T10:29:59.077093Z</date>
|
||||
</commit>
|
||||
</entry>
|
||||
<entry
|
||||
line-number="3">
|
||||
<commit
|
||||
revision="10558">
|
||||
<author>david</author>
|
||||
<date>2009-08-31T22:32:17.361675Z</date>
|
||||
</commit>
|
||||
</entry>
|
||||
</target>
|
||||
</blame>
|
BIN
plugins/sonar-svn-plugin/test-repos/dummy-git.zip
Normal file
BIN
plugins/sonar-svn-plugin/test-repos/dummy-git.zip
Normal file
Binary file not shown.
7
pom.xml
7
pom.xml
@ -36,6 +36,7 @@
|
||||
<module>plugins/sonar-l10n-en-plugin</module>
|
||||
<module>plugins/sonar-email-notifications-plugin</module>
|
||||
<module>plugins/sonar-git-plugin</module>
|
||||
<module>plugins/sonar-svn-plugin</module>
|
||||
<module>plugins/sonar-xoo-plugin</module>
|
||||
</modules>
|
||||
|
||||
@ -597,6 +598,12 @@
|
||||
<version>${project.version}</version>
|
||||
<type>sonar-plugin</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar.plugins</groupId>
|
||||
<artifactId>sonar-svn-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>sonar-plugin</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar</groupId>
|
||||
<artifactId>sonar-squid</artifactId>
|
||||
|
@ -137,6 +137,12 @@
|
||||
<type>sonar-plugin</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.sonar.plugins</groupId>
|
||||
<artifactId>sonar-svn-plugin</artifactId>
|
||||
<type>sonar-plugin</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.sonatype.jsw-binaries</groupId>
|
||||
<artifactId>jsw-binaries</artifactId>
|
||||
|
@ -27,7 +27,11 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Synchronously execute a native command line. It's much more limited than the Apache Commons Exec library.
|
||||
@ -52,6 +56,7 @@ public class CommandExecutor {
|
||||
/**
|
||||
* @throws org.sonar.api.utils.command.TimeoutException on timeout, since 4.4
|
||||
* @throws CommandException on any other error
|
||||
* @param timeoutMilliseconds set it to 0 for no timeout.
|
||||
* @since 3.0
|
||||
*/
|
||||
public int execute(Command command, StreamConsumer stdOut, StreamConsumer stdErr, long timeoutMilliseconds) {
|
||||
@ -80,7 +85,12 @@ public class CommandExecutor {
|
||||
return finalProcess.waitFor();
|
||||
}
|
||||
});
|
||||
int exitCode = ft.get(timeoutMilliseconds, TimeUnit.MILLISECONDS);
|
||||
int exitCode;
|
||||
if (timeoutMilliseconds == 0) {
|
||||
exitCode = ft.get();
|
||||
} else {
|
||||
exitCode = ft.get(timeoutMilliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
waitUntilFinish(outputGobbler);
|
||||
waitUntilFinish(errorGobbler);
|
||||
verifyGobbler(command, outputGobbler, "stdOut");
|
||||
|
Loading…
Reference in New Issue
Block a user