diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2014-09-25 13:48:35 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2014-10-02 17:52:23 +0200 |
commit | cb639f864815f8dfd7dbbd0f21fd4ad08b7db8cc (patch) | |
tree | 89798ee35e415d2a024e320e6369636654780520 /plugins | |
parent | a1cb900c90178390776c987462a4f2501b1e4e2c (diff) | |
download | sonarqube-cb639f864815f8dfd7dbbd0f21fd4ad08b7db8cc.tar.gz sonarqube-cb639f864815f8dfd7dbbd0f21fd4ad08b7db8cc.zip |
SONAR-5644 Rework SCM API
Diffstat (limited to 'plugins')
17 files changed, 560 insertions, 219 deletions
diff --git a/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitBlameCommand.java b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitBlameCommand.java new file mode 100644 index 00000000000..0d8b447cdd8 --- /dev/null +++ b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitBlameCommand.java @@ -0,0 +1,96 @@ +/* + * 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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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; + +public class GitBlameCommand implements BlameCommand { + + private static final Logger LOG = LoggerFactory.getLogger(GitBlameCommand.class); + private final CommandExecutor commandExecutor; + + public GitBlameCommand() { + this(CommandExecutor.create()); + } + + GitBlameCommand(CommandExecutor commandExecutor) { + this.commandExecutor = commandExecutor; + } + + @Override + public void blame(FileSystem fs, Iterable<InputFile> files, BlameResult result) { + for (InputFile inputFile : files) { + String filename = inputFile.relativePath(); + Command cl = createCommandLine(fs.baseDir(), filename); + GitBlameConsumer consumer = new GitBlameConsumer(LOG); + StringStreamConsumer stderr = new StringStreamConsumer(); + + int exitCode = execute(cl, consumer, stderr); + if (exitCode != 0) { + throw new IllegalStateException("The git blame command [" + cl.toString() + "] failed: " + stderr.getOutput()); + } + result.add(inputFile, consumer.getLines()); + } + } + + 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); + } + + private Command createCommandLine(File workingDirectory, String filename) { + Command cl = Command.create("git"); + cl.addArgument("blame"); + if (workingDirectory != null) { + cl.setDirectory(workingDirectory); + } + cl.addArgument("--porcelain"); + cl.addArgument(filename); + cl.addArgument("-w"); + 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-git-plugin/src/main/java/org/sonar/plugins/scm/git/SonarGitBlameConsumer.java b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitBlameConsumer.java index 3102b00f105..1c7ef86cb98 100644 --- a/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/SonarGitBlameConsumer.java +++ b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitBlameConsumer.java @@ -1,23 +1,22 @@ /* - * Sonar SCM Activity Plugin - * Copyright (C) 2010 SonarSource - * dev@sonar.codehaus.org + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com * - * This program is free software; you can redistribute it and/or + * 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. * - * This program is distributed in the hope that it will be useful, + * 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 02 + * 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.annotations.VisibleForTesting; @@ -45,7 +44,7 @@ import java.util.Map; * * @since 1.5.1 */ -public class SonarGitBlameConsumer implements StreamConsumer { +public class GitBlameConsumer implements StreamConsumer { private static final String GIT_COMMITTER_PREFIX = "committer"; private static final String GIT_COMMITTER_TIME = GIT_COMMITTER_PREFIX + "-time "; @@ -78,7 +77,7 @@ public class SonarGitBlameConsumer implements StreamConsumer { return logger; } - public SonarGitBlameConsumer(Logger logger) { + public GitBlameConsumer(Logger logger) { this.logger = logger; } diff --git a/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitPlugin.java b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitPlugin.java index 033cef7b7de..e5c12c42900 100644 --- a/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitPlugin.java +++ b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitPlugin.java @@ -28,7 +28,8 @@ public final class GitPlugin extends SonarPlugin { public List getExtensions() { return ImmutableList.of( - GitScmProvider.class); + GitScmProvider.class, + GitBlameCommand.class); } } diff --git a/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitScmProvider.java b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitScmProvider.java index 7fbfe516c20..a0dfeb92601 100644 --- a/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitScmProvider.java +++ b/plugins/sonar-git-plugin/src/main/java/org/sonar/plugins/scm/git/GitScmProvider.java @@ -19,20 +19,18 @@ */ package org.sonar.plugins.scm.git; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -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.batch.scm.ScmProvider; -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; -public class GitScmProvider implements ScmProvider { +public class GitScmProvider extends ScmProvider { - private static final Logger LOG = LoggerFactory.getLogger(GitScmProvider.class); + private GitBlameCommand blameCommand; + + public GitScmProvider(GitBlameCommand blameCommand) { + this.blameCommand = blameCommand; + } @Override public String key() { @@ -45,53 +43,8 @@ public class GitScmProvider implements ScmProvider { } @Override - public void blame(FileSystem fs, Iterable<InputFile> files, BlameResult result) { - for (InputFile inputFile : files) { - String filename = inputFile.relativePath(); - Command cl = createCommandLine(fs.baseDir(), filename); - SonarGitBlameConsumer consumer = new SonarGitBlameConsumer(LOG); - StringStreamConsumer stderr = new StringStreamConsumer(); - - int exitCode = execute(cl, consumer, stderr); - if (exitCode != 0) { - throw new IllegalStateException("The git blame command [" + cl.toString() + "] failed: " + stderr.getOutput()); - } - result.add(inputFile, consumer.getLines()); - } - } - - public static int execute(Command cl, StreamConsumer consumer, StreamConsumer stderr) { - LOG.info("Executing: " + cl); - LOG.info("Working directory: " + cl.getDirectory().getAbsolutePath()); - - return CommandExecutor.create().execute(cl, consumer, stderr, 10 * 1000); - } - - private static Command createCommandLine(File workingDirectory, String filename) { - Command cl = Command.create("git"); - cl.addArgument("blame"); - if (workingDirectory != null) { - cl.setDirectory(workingDirectory); - } - cl.addArgument("--porcelain"); - cl.addArgument(filename); - cl.addArgument("-w"); - 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(); - } + public BlameCommand blameCommand() { + return this.blameCommand; } } diff --git a/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitBlameCommandTest.java b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitBlameCommandTest.java new file mode 100644 index 00000000000..805b0222af3 --- /dev/null +++ b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitBlameCommandTest.java @@ -0,0 +1,108 @@ +/* + * 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 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 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 GitBlameCommandTest { + + @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]; + outConsumer.consumeLine("2c68c473da7fc293e12ca50f19380c5118be7ead 68 54 1"); + outConsumer.consumeLine("author Simon Brandhof"); + outConsumer.consumeLine("author-mail <simon.brandhof@gmail.com>"); + outConsumer.consumeLine("author-time 1312534171"); + outConsumer.consumeLine("author-tz +0200"); + outConsumer.consumeLine("committer Simon Brandhof"); + outConsumer.consumeLine("committer-mail <simon.brandhof@gmail.com>"); + outConsumer.consumeLine("committer-time 1312534171"); + outConsumer.consumeLine("committer-tz +0200"); + outConsumer.consumeLine("summary Move to nexus.codehaus.org + configuration of maven release plugin is back"); + outConsumer.consumeLine("previous 1bec1c3a77f6957175be13e4433110f7fc8e387e pom.xml"); + outConsumer.consumeLine("filename pom.xml"); + outConsumer.consumeLine("\t<id>codehaus-nexus-staging</id>"); + outConsumer.consumeLine("2c68c473da7fc293e12ca50f19380c5118be7ead 72 60 1"); + outConsumer.consumeLine("\t<url>${sonar.snapshotRepository.url}</url>"); + return 0; + } + }); + + new GitBlameCommand(commandExecutor).blame(fs, Arrays.<InputFile>asList(inputFile), result); + verify(result).add(inputFile, + Arrays.asList(new BlameLine(DateUtils.parseDateTime("2011-08-05T10:49:31+0200"), "2c68c473da7fc293e12ca50f19380c5118be7ead", "simon.brandhof@gmail.com"), + new BlameLine(DateUtils.parseDateTime("2011-08-05T10:49:31+0200"), "2c68c473da7fc293e12ca50f19380c5118be7ead", "simon.brandhof@gmail.com"))); + } + +} diff --git a/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitPluginTest.java b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitPluginTest.java index d65e0eb5844..d175cdcbe91 100644 --- a/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitPluginTest.java +++ b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitPluginTest.java @@ -27,6 +27,6 @@ public class GitPluginTest { @Test public void getExtensions() { - assertThat(new GitPlugin().getExtensions()).hasSize(1); + assertThat(new GitPlugin().getExtensions()).hasSize(2); } } diff --git a/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitScmProviderTest.java b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitScmProviderTest.java new file mode 100644 index 00000000000..9bc5801d055 --- /dev/null +++ b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/GitScmProviderTest.java @@ -0,0 +1,53 @@ +/* + * 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 org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; + +import static org.fest.assertions.Assertions.assertThat; + +public class GitScmProviderTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void sanityCheck() { + assertThat(new GitScmProvider(null).key()).isEqualTo("git"); + GitBlameCommand blameCommand = new GitBlameCommand(); + assertThat(new GitScmProvider(blameCommand).blameCommand()).isEqualTo(blameCommand); + } + + @Test + public void testAutodetection() throws IOException { + File baseDirEmpty = temp.newFolder(); + assertThat(new GitScmProvider(null).supports(baseDirEmpty)).isFalse(); + + File gitBaseDir = temp.newFolder(); + new File(gitBaseDir, ".git").mkdir(); + assertThat(new GitScmProvider(null).supports(gitBaseDir)).isTrue(); + } + +} diff --git a/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/medium/GitMediumTest.java b/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/medium/GitMediumTest.java deleted file mode 100644 index a1f34593f1b..00000000000 --- a/plugins/sonar-git-plugin/src/test/java/org/sonar/plugins/scm/git/medium/GitMediumTest.java +++ /dev/null @@ -1,119 +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.plugins.scm.git.medium; - -import com.google.common.collect.ImmutableMap; -import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.sensor.duplication.DuplicationGroup; -import org.sonar.batch.mediumtest.BatchMediumTester; -import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult; -import org.sonar.plugins.scm.git.GitPlugin; -import org.sonar.xoo.XooPlugin; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -import static org.fest.assertions.Assertions.assertThat; - -public class GitMediumTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - public BatchMediumTester tester = BatchMediumTester.builder() - .registerPlugin("xoo", new XooPlugin()) - .registerPlugin("git", new GitPlugin()) - .addDefaultQProfile("xoo", "Sonar Way") - .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor")) - .build(); - - private File baseDir; - - private ImmutableMap.Builder<String, String> builder; - - @Before - public void prepare() throws IOException { - tester.start(); - - baseDir = temp.newFolder(); - - builder = ImmutableMap.<String, String>builder() - .put("sonar.task", "scan") - .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) - .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project"); - } - - @After - public void stop() { - tester.stop(); - } - - @Test - public void testDuplications() throws IOException { - File srcDir = new File(baseDir, "src"); - srcDir.mkdir(); - - String duplicatedStuff = "Sample xoo\ncontent\nfoo\nbar\ntoto\ntiti\nfoo\nbar\ntoto\ntiti\nbar\ntoto\ntiti\nfoo\nbar\ntoto\ntiti"; - - File xooFile1 = new File(srcDir, "sample1.xoo"); - FileUtils.write(xooFile1, duplicatedStuff); - - File xooFile2 = new File(srcDir, "sample2.xoo"); - FileUtils.write(xooFile2, duplicatedStuff); - - TaskResult result = tester.newTask() - .properties(builder - .put("sonar.sources", "src") - .put("sonar.cpd.xoo.minimumTokens", "10") - .put("sonar.verbose", "true") - .build()) - .start(); - - assertThat(result.inputFiles()).hasSize(2); - - // 4 measures per file - assertThat(result.measures()).hasSize(8); - - InputFile inputFile = result.inputFiles().get(0); - // One clone group - List<DuplicationGroup> duplicationGroups = result.duplicationsFor(inputFile); - assertThat(duplicationGroups).hasSize(1); - - DuplicationGroup cloneGroup = duplicationGroups.get(0); - assertThat(cloneGroup.duplicates()).hasSize(1); - assertThat(cloneGroup.originBlock().startLine()).isEqualTo(1); - assertThat(cloneGroup.originBlock().length()).isEqualTo(17); - } - -} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index e1988ac37ab..148a6df0b7c 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -25,13 +25,14 @@ import org.sonar.xoo.lang.MeasureSensor; import org.sonar.xoo.lang.SymbolReferencesSensor; import org.sonar.xoo.lang.SyntaxHighlightingSensor; import org.sonar.xoo.lang.TestCaseSensor; -import org.sonar.xoo.lang.XooScmProvider; import org.sonar.xoo.lang.XooTokenizerSensor; import org.sonar.xoo.rule.CreateIssueByInternalKeySensor; import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor; import org.sonar.xoo.rule.OneIssuePerLineSensor; import org.sonar.xoo.rule.XooQualityProfile; import org.sonar.xoo.rule.XooRulesDefinition; +import org.sonar.xoo.scm.XooBlameCommand; +import org.sonar.xoo.scm.XooScmProvider; import java.util.Arrays; import java.util.List; @@ -53,6 +54,7 @@ public class XooPlugin extends SonarPlugin { // SCM XooScmProvider.class, + XooBlameCommand.class, // sensors MeasureSensor.class, diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/package-info.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/package-info.java new file mode 100644 index 00000000000..9963cc34bd9 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/package-info.java @@ -0,0 +1,23 @@ +/* + * 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.xoo.lang; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java index 7a11c639e38..31db08c01f2 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java @@ -32,7 +32,7 @@ public class OneIssuePerLineSensor implements Sensor { public static final String RULE_KEY = "OneIssuePerLine"; private static final String EFFORT_TO_FIX_PROPERTY = "sonar.oneIssuePerLine.effortToFix"; - private static final String FORCE_SEVERITY_PROPERTY = "sonar.oneIssuePerLine.forceSeverity"; + public static final String FORCE_SEVERITY_PROPERTY = "sonar.oneIssuePerLine.forceSeverity"; @Override public void describe(SensorDescriptor descriptor) { diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/XooScmProvider.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/XooBlameCommand.java index 895d47dfbbe..7d492cc315b 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/XooScmProvider.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/XooBlameCommand.java @@ -17,18 +17,16 @@ * 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.xoo.lang; +package org.sonar.xoo.scm; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +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.batch.scm.BlameLine; -import org.sonar.api.batch.scm.ScmProvider; -import org.sonar.api.config.Settings; import org.sonar.api.utils.DateUtils; import java.io.File; @@ -37,37 +35,19 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -public class XooScmProvider implements ScmProvider { - - private static final Logger LOG = LoggerFactory.getLogger(XooScmProvider.class); +public class XooBlameCommand implements BlameCommand { private static final String SCM_EXTENSION = ".scm"; - private final Settings settings; - - public XooScmProvider(Settings settings) { - this.settings = settings; - } - - @Override - public String key() { - return "xoo"; - } - - @Override - public boolean supports(File baseDir) { - return false; - } - @Override - public void blame(Iterable<InputFile> files, BlameResult handler) { + public void blame(FileSystem fs, Iterable<InputFile> files, BlameResult result) { for (InputFile inputFile : files) { - processFile(inputFile, handler); + processFile(inputFile, result); } } @VisibleForTesting - protected void processFile(InputFile inputFile, BlameResult handler) { + protected void processFile(InputFile inputFile, BlameResult result) { File ioFile = inputFile.file(); File scmDataFile = new java.io.File(ioFile.getParentFile(), ioFile.getName() + SCM_EXTENSION); if (!scmDataFile.exists()) { @@ -94,7 +74,7 @@ public class XooScmProvider implements ScmProvider { blame.add(new BlameLine(date, revision, author)); } } - handler.add(inputFile, blame); + result.add(inputFile, blame); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/XooScmProvider.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/XooScmProvider.java new file mode 100644 index 00000000000..5807d820043 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/XooScmProvider.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.xoo.scm; + +import org.sonar.api.batch.scm.BlameCommand; +import org.sonar.api.batch.scm.ScmProvider; + +public class XooScmProvider extends ScmProvider { + + private final XooBlameCommand blame; + + public XooScmProvider(XooBlameCommand blame) { + this.blame = blame; + } + + @Override + public String key() { + return "xoo"; + } + + @Override + public BlameCommand blameCommand() { + return blame; + } + +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/package-info.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/package-info.java new file mode 100644 index 00000000000..f5c68e3c563 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/scm/package-info.java @@ -0,0 +1,23 @@ +/* + * 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.xoo.scm; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index 96ea0ea923c..e8100740345 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -27,6 +27,6 @@ public class XooPluginTest { @Test public void provide_extensions() { - assertThat(new XooPlugin().getExtensions()).hasSize(13); + assertThat(new XooPlugin().getExtensions()).hasSize(14); } } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java new file mode 100644 index 00000000000..31d109e3653 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java @@ -0,0 +1,104 @@ +/* + * 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.xoo.rule; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorStorage; +import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; +import org.sonar.api.batch.sensor.issue.Issue; +import org.sonar.api.batch.sensor.issue.Issue.Severity; +import org.sonar.api.batch.sensor.issue.internal.DefaultIssue; +import org.sonar.api.config.Settings; +import org.sonar.xoo.Xoo; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class OneIssuePerLineSensorTest { + + private OneIssuePerLineSensor sensor = new OneIssuePerLineSensor(); + + @Test + public void testDescriptor() { + DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor(); + sensor.describe(descriptor); + assertThat(descriptor.ruleRepositories()).containsOnly(XooRulesDefinition.XOO_REPOSITORY); + } + + @Test + public void testRule() { + DefaultFileSystem fs = new DefaultFileSystem(); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY).setLines(10); + fs.add(inputFile); + + SensorContext context = mock(SensorContext.class); + final SensorStorage sensorStorage = mock(SensorStorage.class); + when(context.settings()).thenReturn(new Settings()); + when(context.fileSystem()).thenReturn(fs); + when(context.newIssue()).thenAnswer(new Answer<Issue>() { + @Override + public Issue answer(InvocationOnMock invocation) throws Throwable { + return new DefaultIssue(sensorStorage); + } + }); + sensor.execute(context); + + ArgumentCaptor<DefaultIssue> argCaptor = ArgumentCaptor.forClass(DefaultIssue.class); + verify(sensorStorage, times(10)).store(argCaptor.capture()); + assertThat(argCaptor.getAllValues()).hasSize(10); // One issue per line + assertThat(argCaptor.getValue().overridenSeverity()).isNull(); + } + + @Test + public void testForceSeverity() { + DefaultFileSystem fs = new DefaultFileSystem(); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY).setLines(10); + fs.add(inputFile); + + SensorContext context = mock(SensorContext.class); + final SensorStorage sensorStorage = mock(SensorStorage.class); + Settings settings = new Settings(); + settings.setProperty(OneIssuePerLineSensor.FORCE_SEVERITY_PROPERTY, "MINOR"); + when(context.settings()).thenReturn(settings); + when(context.fileSystem()).thenReturn(fs); + when(context.newIssue()).thenAnswer(new Answer<Issue>() { + @Override + public Issue answer(InvocationOnMock invocation) throws Throwable { + return new DefaultIssue(sensorStorage); + } + }); + sensor.execute(context); + + ArgumentCaptor<DefaultIssue> argCaptor = ArgumentCaptor.forClass(DefaultIssue.class); + verify(sensorStorage, times(10)).store(argCaptor.capture()); + assertThat(argCaptor.getAllValues()).hasSize(10); // One issue per line + assertThat(argCaptor.getValue().overridenSeverity()).isEqualTo(Severity.MINOR); + } + +} diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/scm/XooBlameCommandTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/scm/XooBlameCommandTest.java new file mode 100644 index 00000000000..bba495dd400 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/scm/XooBlameCommandTest.java @@ -0,0 +1,75 @@ +/* + * 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.xoo.scm; + +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.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.xoo.Xoo; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class XooBlameCommandTest { + + @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(); + } + + @Test + public void testBlame() throws IOException { + File source = new File(baseDir, "src/foo.xoo"); + FileUtils.write(source, "sample content"); + File scm = new File(baseDir, "src/foo.xoo.scm"); + FileUtils.write(scm, "123,julien,2014-12-12\n234,julien,2014-12-24"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage(Xoo.KEY); + fs.add(inputFile); + + BlameResult result = mock(BlameResult.class); + new XooBlameCommand().blame(fs, Arrays.<InputFile>asList(inputFile), result); + verify(result).add(inputFile, Arrays.asList(new BlameLine(DateUtils.parseDate("2014-12-12"), "123", "julien"), + new BlameLine(DateUtils.parseDate("2014-12-24"), "234", "julien"))); + } + +} |