diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2014-09-30 16:49:55 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2014-10-02 17:52:23 +0200 |
commit | 2d60412e140a950436349f80f928c0e3a073c287 (patch) | |
tree | e5f864261e0b66c0aeca092e431a82c40c8ab0d2 /plugins/sonar-svn-plugin/src | |
parent | 327799ec3efa6e9cb6180cd40a7d41cee0c1ce43 (diff) | |
download | sonarqube-2d60412e140a950436349f80f928c0e3a073c287.tar.gz sonarqube-2d60412e140a950436349f80f928c0e3a073c287.zip |
SONAR-5643 Provide a default SVN SCM Provider
Diffstat (limited to 'plugins/sonar-svn-plugin/src')
10 files changed, 737 insertions, 0 deletions
diff --git a/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnBlameCommand.java b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnBlameCommand.java new file mode 100644 index 00000000000..147d9644621 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnBlameCommand.java @@ -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(); + } + } + +} diff --git a/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnBlameConsumer.java b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnBlameConsumer.java new file mode 100644 index 00000000000..525f3651048 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnBlameConsumer.java @@ -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; + } +} diff --git a/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnConfiguration.java b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnConfiguration.java new file mode 100644 index 00000000000..79da661fe83 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnConfiguration.java @@ -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); + } + +} diff --git a/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnPlugin.java b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnPlugin.java new file mode 100644 index 00000000000..bf628688eb7 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnPlugin.java @@ -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; + } +} diff --git a/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnScmProvider.java b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnScmProvider.java new file mode 100644 index 00000000000..6e7fb3ac8a4 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/SvnScmProvider.java @@ -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; + } +} diff --git a/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/package-info.java b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/package-info.java new file mode 100644 index 00000000000..e68270ddbe0 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/main/java/org/sonar/plugins/scm/svn/package-info.java @@ -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; + diff --git a/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnBlameCommandTest.java b/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnBlameCommandTest.java new file mode 100644 index 00000000000..7b07dac96ce --- /dev/null +++ b/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnBlameCommandTest.java @@ -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); + } + +} diff --git a/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnPluginTest.java b/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnPluginTest.java new file mode 100644 index 00000000000..7c8ea23a91a --- /dev/null +++ b/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnPluginTest.java @@ -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); + } +} diff --git a/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnScmProviderTest.java b/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnScmProviderTest.java new file mode 100644 index 00000000000..36359e68f41 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/test/java/org/sonar/plugins/scm/svn/SvnScmProviderTest.java @@ -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(); + } + +} diff --git a/plugins/sonar-svn-plugin/src/test/resources/blame.xml b/plugins/sonar-svn-plugin/src/test/resources/blame.xml new file mode 100644 index 00000000000..479dee9c692 --- /dev/null +++ b/plugins/sonar-svn-plugin/src/test/resources/blame.xml @@ -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> |