From da15a52568cbe80fe6ce70dd64aed3edd722af74 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Tue, 25 Aug 2020 14:25:04 -0500 Subject: [PATCH] SONAR-13792 Embed sonar-scm-svn --- build.gradle | 2 +- sonar-application/bundled_plugins.gradle | 1 - sonar-scanner-engine/build.gradle | 1 + .../scanner/scan/ProjectScanContainer.java | 4 +- .../java/org/sonar/scm/git/GitScmSupport.java | 6 +- .../org/sonar/scm/svn/AnnotationHandler.java | 63 ++++ .../sonar/scm/svn/ChangedLinesComputer.java | 163 +++++++++ .../main/java/org/sonar/scm/svn/FindFork.java | 118 +++++++ .../java/org/sonar/scm/svn/ForkPoint.java | 48 +++ .../org/sonar/scm/svn/SvnBlameCommand.java | 118 +++++++ .../org/sonar/scm/svn/SvnConfiguration.java | 117 +++++++ .../org/sonar/scm/svn/SvnScmProvider.java | 215 ++++++++++++ .../java/org/sonar/scm/svn/SvnScmSupport.java | 62 ++++ .../java/org/sonar/scm/svn/package-info.java | 24 ++ .../org/sonar/scm/git/GitScmSupportTest.java | 2 +- .../scm/svn/ChangedLinesComputerTest.java | 195 +++++++++++ .../java/org/sonar/scm/svn/FindForkTest.java | 143 ++++++++ .../sonar/scm/svn/SvnBlameCommandTest.java | 321 +++++++++++++++++ .../sonar/scm/svn/SvnConfigurationTest.java | 68 ++++ .../org/sonar/scm/svn/SvnScmProviderTest.java | 325 ++++++++++++++++++ .../org/sonar/scm/svn/SvnScmSupportTest.java | 51 +++ .../java/org/sonar/scm/svn/SvnTester.java | 135 ++++++++ .../java/org/sonar/scm/svn/SvnTesterTest.java | 68 ++++ .../test-repos/1.6/repo-svn-with-merge.zip | Bin 0 -> 29020 bytes .../sonar/scm/svn/test-repos/1.6/repo-svn.zip | Bin 0 -> 23239 bytes .../test-repos/1.7/repo-svn-with-merge.zip | Bin 0 -> 29020 bytes .../sonar/scm/svn/test-repos/1.7/repo-svn.zip | Bin 0 -> 23239 bytes .../test-repos/1.8/repo-svn-with-merge.zip | Bin 0 -> 29020 bytes .../sonar/scm/svn/test-repos/1.8/repo-svn.zip | Bin 0 -> 23777 bytes .../test-repos/1.9/repo-svn-with-merge.zip | Bin 0 -> 37668 bytes .../sonar/scm/svn/test-repos/1.9/repo-svn.zip | Bin 0 -> 32696 bytes 31 files changed, 2245 insertions(+), 5 deletions(-) create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/AnnotationHandler.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ChangedLinesComputer.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/FindFork.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ForkPoint.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnBlameCommand.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnConfiguration.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmProvider.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmSupport.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scm/svn/package-info.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/FindForkTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnBlameCommandTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTester.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTesterTest.java create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.6/repo-svn-with-merge.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.6/repo-svn.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.7/repo-svn-with-merge.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.7/repo-svn.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.8/repo-svn-with-merge.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.8/repo-svn.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.9/repo-svn-with-merge.zip create mode 100644 sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.9/repo-svn.zip diff --git a/build.gradle b/build.gradle index 9d5d86773f4..1211e587def 100644 --- a/build.gradle +++ b/build.gradle @@ -182,7 +182,6 @@ subprojects { dependency 'org.sonarsource.javascript:sonar-javascript-plugin:6.3.0.12464' // bundled_plugin:javascript:SonarJS dependency 'org.sonarsource.php:sonar-php-plugin:3.5.0.5655' // bundled_plugin:php:sonar-php dependency 'org.sonarsource.python:sonar-python-plugin:2.13.0.7236' // bundled_plugin:python:sonar-python - dependency 'org.sonarsource.scm.svn:sonar-scm-svn-plugin:1.10.0.1917' // bundled_plugin:scmsvn:sonar-scm-svn dependency 'org.sonarsource.slang:sonar-go-plugin:1.6.0.719' // bundled_plugin:go:slang-enterprise dependency 'org.sonarsource.slang:sonar-kotlin-plugin:1.5.0.315' // bundled_plugin:kotlin:slang-enterprise dependency 'org.sonarsource.slang:sonar-ruby-plugin:1.5.0.315' // bundled_plugin:ruby:slang-enterprise @@ -317,6 +316,7 @@ subprojects { dependency 'org.elasticsearch:mocksocket:1.0' dependency 'org.codelibs.elasticsearch.module:analysis-common:6.8.4' dependency 'org.eclipse.jgit:org.eclipse.jgit:5.7.0.202003110725-r' + dependency 'org.tmatesoft.svnkit:svnkit:1.10.1' dependency 'org.hamcrest:hamcrest-all:1.3' dependency 'org.jsoup:jsoup:1.13.1' dependency 'org.mindrot:jbcrypt:0.4' diff --git a/sonar-application/bundled_plugins.gradle b/sonar-application/bundled_plugins.gradle index 934e4c07e6d..5bcbf92af7f 100644 --- a/sonar-application/bundled_plugins.gradle +++ b/sonar-application/bundled_plugins.gradle @@ -12,7 +12,6 @@ dependencies { bundledPlugin 'org.sonarsource.slang:sonar-go-plugin@jar' bundledPlugin "org.sonarsource.slang:sonar-kotlin-plugin@jar" bundledPlugin "org.sonarsource.slang:sonar-ruby-plugin@jar" - bundledPlugin 'org.sonarsource.scm.svn:sonar-scm-svn-plugin@jar' bundledPlugin "org.sonarsource.slang:sonar-scala-plugin@jar" bundledPlugin 'org.sonarsource.xml:sonar-xml-plugin@jar' } diff --git a/sonar-scanner-engine/build.gradle b/sonar-scanner-engine/build.gradle index a555eb97561..45cc8d25ecd 100644 --- a/sonar-scanner-engine/build.gradle +++ b/sonar-scanner-engine/build.gradle @@ -29,6 +29,7 @@ dependencies { compile 'org.codehaus.woodstox:stax2-api' compile 'org.codehaus.woodstox:woodstox-core-lgpl' compile 'org.eclipse.jgit:org.eclipse.jgit' + compile 'org.tmatesoft.svnkit:svnkit' compile 'org.picocontainer:picocontainer' compile 'org.slf4j:jcl-over-slf4j' compile 'org.slf4j:jul-to-slf4j' diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java index ce29d00a358..30aac02d9f1 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java @@ -132,6 +132,7 @@ import org.sonar.scanner.sensor.ProjectSensorExtensionDictionnary; import org.sonar.scanner.sensor.ProjectSensorOptimizer; import org.sonar.scanner.sensor.ProjectSensorsExecutor; import org.sonar.scm.git.GitScmSupport; +import org.sonar.scm.svn.SvnScmSupport; import static org.sonar.api.batch.InstantiationStrategy.PER_BATCH; import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter; @@ -302,7 +303,8 @@ public class ProjectScanContainer extends ComponentContainer { AnalysisObservers.class); - add(GitScmSupport.getClasses()); + add(GitScmSupport.getObjects()); + add(SvnScmSupport.getObjects()); addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class); addIfMissing(DefaultRulesLoader.class, RulesLoader.class); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/git/GitScmSupport.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/git/GitScmSupport.java index b5a845edc9a..2e0928d275f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scm/git/GitScmSupport.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/git/GitScmSupport.java @@ -24,7 +24,11 @@ import java.util.List; import org.eclipse.jgit.util.FS; public final class GitScmSupport { - public static List> getClasses() { + private GitScmSupport() { + // static only + } + + public static List getObjects() { FS.FileStoreAttributes.setBackground(true); return Arrays.asList( JGitBlameCommand.class, diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/AnnotationHandler.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/AnnotationHandler.java new file mode 100644 index 00000000000..81d0f007612 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/AnnotationHandler.java @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import org.sonar.api.batch.scm.BlameLine; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler; + +public class AnnotationHandler implements ISVNAnnotateHandler { + + private List lines = new ArrayList<>(); + + @Override + public void handleEOF() { + // Not used + } + + @Override + public void handleLine(Date date, long revision, String author, String line) throws SVNException { + // deprecated + } + + @Override + public void handleLine(Date date, long revision, String author, String line, Date mergedDate, + long mergedRevision, String mergedAuthor, String mergedPath, int lineNumber) throws SVNException { + lines.add(new BlameLine().date(mergedDate).revision(Long.toString(mergedRevision)).author(mergedAuthor)); + } + + @Override + public boolean handleRevision(Date date, long revision, String author, File contents) throws SVNException { + /* + * We do not want our file to be annotated for each revision of the range, but only for the last + * revision of it, so we return false + */ + return false; + } + + public List getLines() { + return lines; + } + +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ChangedLinesComputer.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ChangedLinesComputer.java new file mode 100644 index 00000000000..9a737e8f3da --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ChangedLinesComputer.java @@ -0,0 +1,163 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.OutputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class ChangedLinesComputer { + + private final Tracker tracker; + + private final OutputStream receiver = new OutputStream() { + StringBuilder sb = new StringBuilder(); + + @Override + public void write(int b) { + sb.append((char) b); + if (b == '\n') { + tracker.parseLine(sb.toString()); + sb.setLength(0); + } + } + }; + + ChangedLinesComputer(Path rootBaseDir, Set included) { + this.tracker = new Tracker(rootBaseDir, included); + } + + /** + * The OutputStream to pass to svnkit's diff command. + */ + OutputStream receiver() { + return receiver; + } + + /** + * From a stream of svn-style unified diff lines, + * compute the line numbers that should be considered changed. + * + * Example input: + *
+   * Index: path/to/file
+   * ===================================================================
+   * --- lao 2002-02-21 23:30:39.942229878 -0800
+   * +++ tzu 2002-02-21 23:30:50.442260588 -0800
+   * @@ -1,7 +1,6 @@
+   * -The Way that can be told of is not the eternal Way;
+   * -The name that can be named is not the eternal name.
+   *  The Nameless is the origin of Heaven and Earth;
+   * -The Named is the mother of all things.
+   * +The named is the mother of all things.
+   * +
+   *  Therefore let there always be non-being,
+   *    so we may see their subtlety,
+   *  And let there always be being,
+   * @@ -9,3 +8,6 @@
+   *  The two are the same,
+   *  But after they are produced,
+   *    they have different names.
+   * +They both may be called deep and profound.
+   * +Deeper and more profound,
+   * +The door of all subtleties!
+   * 
+ * + * See also: http://www.gnu.org/software/diffutils/manual/html_node/Example-Unified.html#Example-Unified + */ + Map> changedLines() { + return tracker.changedLines(); + } + + private static class Tracker { + + private static final Pattern START_LINE_IN_TARGET = Pattern.compile(" \\+(\\d+)"); + private static final String ENTRY_START_PREFIX = "Index: "; + + private final Map> changedLines = new HashMap<>(); + private final Set included; + private final Path rootBaseDir; + + private int lineNumInTarget; + private Path currentPath = null; + private int skipCount = 0; + + Tracker(Path rootBaseDir, Set included) { + this.rootBaseDir = rootBaseDir; + this.included = included; + } + + private void parseLine(String line) { + if (line.startsWith(ENTRY_START_PREFIX)) { + currentPath = Paths.get(line.substring(ENTRY_START_PREFIX.length()).trim()); + if (!currentPath.isAbsolute()) { + currentPath = rootBaseDir.resolve(currentPath); + } + if (!included.contains(currentPath)) { + return; + } + skipCount = 3; + return; + } + + if (!included.contains(currentPath)) { + return; + } + + if (skipCount > 0) { + skipCount--; + return; + } + + if (line.startsWith("@@ ")) { + Matcher matcher = START_LINE_IN_TARGET.matcher(line); + if (!matcher.find()) { + throw new IllegalStateException("Invalid block header: " + line); + } + lineNumInTarget = Integer.parseInt(matcher.group(1)); + return; + } + + parseContent(line); + } + + private void parseContent(String line) { + char firstChar = line.charAt(0); + if (firstChar == ' ') { + lineNumInTarget++; + } else if (firstChar == '+') { + changedLines + .computeIfAbsent(currentPath, path -> new HashSet<>()) + .add(lineNumInTarget); + lineNumInTarget++; + } + } + + Map> changedLines() { + return changedLines; + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/FindFork.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/FindFork.java new file mode 100644 index 00000000000..534dd361c8e --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/FindFork.java @@ -0,0 +1,118 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.nio.file.Path; +import java.time.Instant; +import java.util.Optional; +import javax.annotation.CheckForNull; +import org.sonar.api.scanner.ScannerSide; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.tmatesoft.svn.core.ISVNLogEntryHandler; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLogEntry; +import org.tmatesoft.svn.core.SVNLogEntryPath; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNStatus; + +import static org.sonar.scm.svn.SvnScmSupport.newSvnClientManager; + +@ScannerSide +public class FindFork { + private static final Logger LOG = Loggers.get(FindFork.class); + + private final SvnConfiguration configuration; + + public FindFork(SvnConfiguration configuration) { + this.configuration = configuration; + } + + @CheckForNull + public Instant findDate(Path location, String referenceBranch) throws SVNException { + ForkPoint forkPoint = find(location, referenceBranch); + if (forkPoint != null) { + return forkPoint.date(); + } + return null; + } + + @CheckForNull + public ForkPoint find(Path location, String referenceBranch) throws SVNException { + SVNClientManager clientManager = newSvnClientManager(configuration); + SVNRevision revision = getSvnRevision(location, clientManager); + LOG.debug("latest revision is " + revision); + String svnRefBranch = "/" + referenceBranch; + + SVNLogEntryHolder handler = new SVNLogEntryHolder(); + SVNRevision endRevision = SVNRevision.create(1); + SVNRevision startRevision = SVNRevision.create(revision.getNumber()); + + do { + clientManager.getLogClient().doLog(new File[] {location.toFile()}, startRevision, endRevision, true, true, -1, handler); + SVNLogEntry lastEntry = handler.getLastEntry(); + Optional copyFromReference = lastEntry.getChangedPaths().values().stream() + .filter(e -> e.getCopyPath() != null && e.getCopyPath().equals(svnRefBranch)) + .findFirst(); + + if (copyFromReference.isPresent()) { + return new ForkPoint(String.valueOf(copyFromReference.get().getCopyRevision()), Instant.ofEpochMilli(lastEntry.getDate().getTime())); + } + + if (lastEntry.getChangedPaths().isEmpty()) { + // shouldn't happen since it should only stop in revisions with changed paths + return null; + } + + SVNLogEntryPath firstChangedPath = lastEntry.getChangedPaths().values().iterator().next(); + if (firstChangedPath.getCopyPath() == null) { + // we walked the history to the root, and the last commit found had no copy reference. Must be the trunk, there is no fork point + return null; + } + + // TODO Looks like a revision can have multiple changed paths. Should we iterate through all of them? + startRevision = SVNRevision.create(firstChangedPath.getCopyRevision()); + } while (true); + + } + + private static SVNRevision getSvnRevision(Path location, SVNClientManager clientManager) throws SVNException { + SVNStatus svnStatus = clientManager.getStatusClient().doStatus(location.toFile(), false); + return svnStatus.getRevision(); + } + + /** + * Handler keeping only the last entry, and count how many entries have been seen. + */ + private static class SVNLogEntryHolder implements ISVNLogEntryHandler { + SVNLogEntry value; + + public SVNLogEntry getLastEntry() { + return value; + } + + @Override + public void handleLogEntry(SVNLogEntry svnLogEntry) { + this.value = svnLogEntry; + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ForkPoint.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ForkPoint.java new file mode 100644 index 00000000000..8569ce4ac77 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/ForkPoint.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.time.Instant; + +public class ForkPoint { + private String commit; + private Instant date; + + public ForkPoint(String commit, Instant date) { + this.commit = commit; + this.date = date; + } + + public String commit() { + return commit; + } + + public Instant date() { + return date; + } + + @Override + public String toString() { + return "ForkPoint{" + + "commit='" + commit + '\'' + + ", date=" + date + + '}'; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnBlameCommand.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnBlameCommand.java new file mode 100644 index 00000000000..bb328f1c98f --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnBlameCommand.java @@ -0,0 +1,118 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.util.List; +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.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNDiffOptions; +import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNStatus; +import org.tmatesoft.svn.core.wc.SVNStatusClient; +import org.tmatesoft.svn.core.wc.SVNStatusType; + +import static org.sonar.scm.svn.SvnScmSupport.newSvnClientManager; + +public class SvnBlameCommand extends BlameCommand { + + private static final Logger LOG = Loggers.get(SvnBlameCommand.class); + private final SvnConfiguration configuration; + + public SvnBlameCommand(SvnConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void blame(final BlameInput input, final BlameOutput output) { + FileSystem fs = input.fileSystem(); + LOG.debug("Working directory: " + fs.baseDir().getAbsolutePath()); + SVNClientManager clientManager = null; + try { + clientManager = newSvnClientManager(configuration); + for (InputFile inputFile : input.filesToBlame()) { + blame(clientManager, inputFile, output); + } + } finally { + if (clientManager != null) { + try { + clientManager.dispose(); + } catch (Exception e) { + LOG.warn("Unable to dispose SVN ClientManager", e); + } + } + } + } + + private static void blame(SVNClientManager clientManager, InputFile inputFile, BlameOutput output) { + String filename = inputFile.relativePath(); + + LOG.debug("Process file {}", filename); + + AnnotationHandler handler = new AnnotationHandler(); + try { + if (!checkStatus(clientManager, inputFile)) { + return; + } + SVNLogClient logClient = clientManager.getLogClient(); + logClient.setDiffOptions(new SVNDiffOptions(true, true, true)); + logClient.doAnnotate(inputFile.file(), SVNRevision.UNDEFINED, SVNRevision.create(1), SVNRevision.BASE, true, true, handler, null); + } catch (SVNException e) { + throw new IllegalStateException("Error when executing blame for file " + filename, e); + } + + List lines = handler.getLines(); + if (lines.size() == inputFile.lines() - 1) { + // SONARPLUGINS-3097 SVN do not report blame on last empty line + lines.add(lines.get(lines.size() - 1)); + } + output.blameResult(inputFile, lines); + } + + private static boolean checkStatus(SVNClientManager clientManager, InputFile inputFile) throws SVNException { + SVNStatusClient statusClient = clientManager.getStatusClient(); + try { + SVNStatus status = statusClient.doStatus(inputFile.file(), false); + if (status == null) { + LOG.debug("File {} returns no svn state. Skipping it.", inputFile); + return false; + } + if (status.getContentsStatus() != SVNStatusType.STATUS_NORMAL) { + LOG.debug("File {} is not versionned or contains local modifications. Skipping it.", inputFile); + return false; + } + } catch (SVNException e) { + if (SVNErrorCode.WC_PATH_NOT_FOUND.equals(e.getErrorMessage().getErrorCode()) + || SVNErrorCode.WC_NOT_WORKING_COPY.equals(e.getErrorMessage().getErrorCode())) { + LOG.debug("File {} is not versionned. Skipping it.", inputFile); + return false; + } + throw e; + } + return true; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnConfiguration.java new file mode 100644 index 00000000000..83e0cc7641c --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnConfiguration.java @@ -0,0 +1,117 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import javax.annotation.CheckForNull; +import org.sonar.api.CoreProperties; +import org.sonar.api.PropertyType; +import org.sonar.api.config.Configuration; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.scanner.ScannerSide; +import org.sonar.api.utils.MessageException; + +@ScannerSide +public class SvnConfiguration { + + private static final String CATEGORY_SVN = "SVN"; + public static final String USER_PROP_KEY = "sonar.svn.username"; + public static final String PRIVATE_KEY_PATH_PROP_KEY = "sonar.svn.privateKeyPath"; + public static final String PASSWORD_PROP_KEY = "sonar.svn.password.secured"; + public static final String PASSPHRASE_PROP_KEY = "sonar.svn.passphrase.secured"; + private final Configuration config; + + public SvnConfiguration(Configuration config) { + this.config = config; + } + + public static List getProperties() { + return Arrays.asList( + PropertyDefinition.builder(USER_PROP_KEY) + .name("Username") + .description("Username to be used for SVN server or SVN+SSH 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 server or SVN+SSH authentication") + .type(PropertyType.PASSWORD) + .onQualifiers(Qualifiers.PROJECT) + .category(CoreProperties.CATEGORY_SCM) + .subCategory(CATEGORY_SVN) + .index(1) + .build(), + PropertyDefinition.builder(PRIVATE_KEY_PATH_PROP_KEY) + .name("Path to private key file") + .description("Can be used instead of password for SVN+SSH authentication") + .type(PropertyType.STRING) + .onQualifiers(Qualifiers.PROJECT) + .category(CoreProperties.CATEGORY_SCM) + .subCategory(CATEGORY_SVN) + .index(2) + .build(), + PropertyDefinition.builder(PASSPHRASE_PROP_KEY) + .name("Passphrase") + .description("Optional passphrase of your private key file") + .type(PropertyType.PASSWORD) + .onQualifiers(Qualifiers.PROJECT) + .category(CoreProperties.CATEGORY_SCM) + .subCategory(CATEGORY_SVN) + .index(3) + .build()); + } + + @CheckForNull + public String username() { + return config.get(USER_PROP_KEY).orElse(null); + } + + @CheckForNull + public String password() { + return config.get(PASSWORD_PROP_KEY).orElse(null); + } + + @CheckForNull + public File privateKey() { + Optional privateKeyOpt = config.get(PRIVATE_KEY_PATH_PROP_KEY); + if (privateKeyOpt.isPresent()) { + File privateKeyFile = new File(privateKeyOpt.get()); + if (!privateKeyFile.exists() || !privateKeyFile.isFile() || !privateKeyFile.canRead()) { + throw MessageException.of("Unable to read private key from '" + privateKeyFile + "'"); + } + return privateKeyFile; + } + return null; + } + + @CheckForNull + public String passPhrase() { + return config.get(PASSPHRASE_PROP_KEY).orElse(null); + } + +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmProvider.java new file mode 100644 index 00000000000..1e44f89c63f --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmProvider.java @@ -0,0 +1,215 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.CheckForNull; +import org.sonar.api.batch.scm.BlameCommand; +import org.sonar.api.batch.scm.ScmProvider; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLogEntryPath; +import org.tmatesoft.svn.core.SVNNodeKind; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNDiffClient; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCClient; + +import static org.sonar.scm.svn.SvnScmSupport.newSvnClientManager; + +public class SvnScmProvider extends ScmProvider { + + private static final Logger LOG = Loggers.get(SvnScmProvider.class); + + private final SvnConfiguration configuration; + private final SvnBlameCommand blameCommand; + private final FindFork findFork; + + public SvnScmProvider(SvnConfiguration configuration, SvnBlameCommand blameCommand, FindFork findFork) { + this.configuration = configuration; + this.blameCommand = blameCommand; + this.findFork = findFork; + } + + @Override + public String key() { + return "svn"; + } + + @Override + public boolean supports(File baseDir) { + File folder = baseDir; + while (folder != null) { + if (new File(folder, ".svn").exists()) { + return true; + } + folder = folder.getParentFile(); + } + return false; + } + + @Override + public BlameCommand blameCommand() { + return blameCommand; + } + + @CheckForNull + @Override + public Set branchChangedFiles(String targetBranchName, Path rootBaseDir) { + SVNClientManager clientManager = null; + try { + clientManager = newSvnClientManager(configuration); + return computeChangedPaths(rootBaseDir, clientManager); + } catch (SVNException e) { + LOG.warn(e.getMessage()); + } finally { + if (clientManager != null) { + try { + clientManager.dispose(); + } catch (Exception e) { + LOG.warn("Unable to dispose SVN ClientManager", e); + } + } + } + + return null; + } + + static Set computeChangedPaths(Path projectBasedir, SVNClientManager clientManager) throws SVNException { + SVNWCClient wcClient = clientManager.getWCClient(); + SVNInfo svnInfo = wcClient.doInfo(projectBasedir.toFile(), null); + + // SVN path of the repo root, for example: /C:/Users/JANOSG~1/AppData/Local/Temp/x/y + Path svnRootPath = toPath(svnInfo.getRepositoryRootURL()); + + // the svn root path may be "" for urls like http://svnserver/ + // -> set it to "/" to avoid crashing when using Path.relativize later + if (svnRootPath.equals(Paths.get(""))) { + svnRootPath = Paths.get("/"); + } + + // SVN path of projectBasedir, for example: /C:/Users/JANOSG~1/AppData/Local/Temp/x/y/branches/b1 + Path svnProjectPath = toPath(svnInfo.getURL()); + // path of projectBasedir, as "absolute path within the SVN repo", for example: /branches/b1 + Path inRepoProjectPath = Paths.get("/").resolve(svnRootPath.relativize(svnProjectPath)); + + // We inspect "svn log" from latest revision until copy-point. + // The same path may appear in multiple commits, the ordering of changes and removals is important. + Set paths = new HashSet<>(); + Set removed = new HashSet<>(); + + SVNLogClient svnLogClient = clientManager.getLogClient(); + svnLogClient.doLog(new File[] {projectBasedir.toFile()}, null, null, null, true, true, 0, svnLogEntry -> + svnLogEntry.getChangedPaths().values().forEach(entry -> { + if (entry.getKind().equals(SVNNodeKind.FILE)) { + Path path = projectBasedir.resolve(inRepoProjectPath.relativize(Paths.get(entry.getPath()))); + if (isModified(entry)) { + // Skip if the path is removed in a more recent commit + if (!removed.contains(path)) { + paths.add(path); + } + } else if (entry.getType() == SVNLogEntryPath.TYPE_DELETED) { + removed.add(path); + } + } + })); + return paths; + } + + private static Path toPath(SVNURL svnUrl) { + if ("file".equals(svnUrl.getProtocol())) { + try { + return Paths.get(new URL("file", svnUrl.getHost(), svnUrl.getPath()).toURI()); + } catch (URISyntaxException | MalformedURLException e) { + throw new IllegalStateException(e); + } + } + return Paths.get(svnUrl.getURIEncodedPath()); + } + + private static boolean isModified(SVNLogEntryPath entry) { + return entry.getType() == SVNLogEntryPath.TYPE_ADDED + || entry.getType() == SVNLogEntryPath.TYPE_MODIFIED; + } + + @CheckForNull + @Override + public Map> branchChangedLines(String targetBranchName, Path rootBaseDir, Set changedFiles) { + SVNClientManager clientManager = null; + try { + clientManager = newSvnClientManager(configuration); + + // find reference revision number: the copy point + SVNLogClient svnLogClient = clientManager.getLogClient(); + long[] revisionCounter = {0}; + svnLogClient.doLog(new File[] {rootBaseDir.toFile()}, null, null, null, true, true, 0, + svnLogEntry -> revisionCounter[0] = svnLogEntry.getRevision()); + + long startRev = revisionCounter[0]; + + SVNDiffClient svnDiffClient = clientManager.getDiffClient(); + File path = rootBaseDir.toFile(); + ChangedLinesComputer computer = newChangedLinesComputer(rootBaseDir, changedFiles); + svnDiffClient.doDiff(path, SVNRevision.create(startRev), path, SVNRevision.WORKING, SVNDepth.INFINITY, false, computer.receiver(), null); + return computer.changedLines(); + } catch (Exception e) { + LOG.warn("Failed to get changed lines from Subversion", e); + } finally { + if (clientManager != null) { + try { + clientManager.dispose(); + } catch (Exception e) { + LOG.warn("Unable to dispose SVN ClientManager", e); + } + } + } + + return null; + } + + @CheckForNull + @Override + public Instant forkDate(String referenceBranch, Path rootBaseDir) { + try { + return findFork.findDate(rootBaseDir, referenceBranch); + } catch (SVNException e) { + LOG.warn("Unable to find fork date with '" + referenceBranch + "'", e); + return null; + } + } + + ChangedLinesComputer newChangedLinesComputer(Path rootBaseDir, Set changedFiles) { + return new ChangedLinesComputer(rootBaseDir, changedFiles); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmSupport.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmSupport.java new file mode 100644 index 00000000000..03182cde230 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/SvnScmSupport.java @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.util.Arrays; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.wc.ISVNOptions; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNWCUtil; + +public class SvnScmSupport { + private SvnScmSupport() { + // static only + } + + static SVNClientManager newSvnClientManager(SvnConfiguration configuration) { + ISVNOptions options = SVNWCUtil.createDefaultOptions(true); + final char[] passwordValue = getCharsOrNull(configuration.password()); + final char[] passPhraseValue = getCharsOrNull(configuration.passPhrase()); + ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager( + null, + configuration.username(), + passwordValue, + configuration.privateKey(), + passPhraseValue, + false); + return SVNClientManager.newInstance(options, authManager); + } + + @CheckForNull + private static char[] getCharsOrNull(@Nullable String s) { + return s != null ? s.toCharArray() : null; + } + + public static List getObjects() { + return Arrays.asList(SvnScmProvider.class, + SvnBlameCommand.class, + SvnConfiguration.class, + FindFork.class, + SvnConfiguration.getProperties()); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/package-info.java b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/package-info.java new file mode 100644 index 00000000000..3af724b1ea4 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scm/svn/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@ParametersAreNonnullByDefault +package org.sonar.scm.svn; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java index 803b02088be..10c33f9af38 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java @@ -27,7 +27,7 @@ public class GitScmSupportTest { @Test public void getClasses() { - assertThat(GitScmSupport.getClasses()).hasSize(3); + assertThat(GitScmSupport.getObjects()).hasSize(3); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java new file mode 100644 index 00000000000..bef5eb6c57c --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java @@ -0,0 +1,195 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.junit.Test; + +import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; + +public class ChangedLinesComputerTest { + + private final Path rootBaseDir = Paths.get("/foo"); + private final ChangedLinesComputer underTest = new ChangedLinesComputer(rootBaseDir, new HashSet<>(Arrays.asList( + rootBaseDir.resolve("sample1"), + rootBaseDir.resolve("sample2"), + rootBaseDir.resolve("sample3"), + rootBaseDir.resolve("sample4")))); + + @Test + public void do_not_count_deleted_line() throws IOException { + String example = "Index: sample1\n" + + "===================================================================\n" + + "--- a/sample1\n" + + "+++ b/sample1\n" + + "@@ -1 +0,0 @@\n" + + "-deleted line\n"; + + printDiff(example); + assertThat(underTest.changedLines()).isEmpty(); + } + + @Test + public void count_single_added_line() throws IOException { + String example = "Index: sample1\n" + + "===================================================================\n" + + "--- a/sample1\n" + + "+++ b/sample1\n" + + "@@ -0,0 +1 @@\n" + + "+added line\n"; + + printDiff(example); + assertThat(underTest.changedLines()).isEqualTo(Collections.singletonMap(rootBaseDir.resolve("sample1"), singleton(1))); + } + + @Test + public void count_multiple_added_lines() throws IOException { + String example = "Index: sample1\n" + + "===================================================================\n" + + "--- a/sample1\n" + + "+++ b/sample1\n" + + "@@ -1 +1,3 @@\n" + + " same line\n" + + "+added line 1\n" + + "+added line 2\n"; + + printDiff(example); + assertThat(underTest.changedLines()).isEqualTo(Collections.singletonMap(rootBaseDir.resolve("sample1"), new HashSet<>(Arrays.asList(2, 3)))); + } + + @Test + public void handle_index_using_absolute_paths() throws IOException { + String example = "Index: /foo/sample1\n" + + "===================================================================\n" + + "--- a/sample1\n" + + "+++ b/sample1\n" + + "@@ -1 +1,3 @@\n" + + " same line\n" + + "+added line 1\n" + + "+added line 2\n"; + + printDiff(example); + assertThat(underTest.changedLines()).isEqualTo(Collections.singletonMap(rootBaseDir.resolve("sample1"), new HashSet<>(Arrays.asList(2, 3)))); + } + + @Test + public void compute_from_multiple_hunks() throws IOException { + String example = "Index: sample1\n" + + "===================================================================\n" + + "--- lao\t2002-02-21 23:30:39.942229878 -0800\n" + + "+++ tzu\t2002-02-21 23:30:50.442260588 -0800\n" + + "@@ -1,7 +1,6 @@\n" + + "-The Way that can be told of is not the eternal Way;\n" + + "-The name that can be named is not the eternal name.\n" + + " The Nameless is the origin of Heaven and Earth;\n" + + "-The Named is the mother of all things.\n" + + "+The named is the mother of all things.\n" + + "+\n" + + " Therefore let there always be non-being,\n" + + " so we may see their subtlety,\n" + + " And let there always be being,\n" + + "@@ -9,3 +8,6 @@\n" + + " The two are the same,\n" + + " But after they are produced,\n" + + " they have different names.\n" + + "+They both may be called deep and profound.\n" + + "+Deeper and more profound,\n" + + "+The door of all subtleties!\n"; + printDiff(example); + assertThat(underTest.changedLines()).isEqualTo(Collections.singletonMap(rootBaseDir.resolve("sample1"), new HashSet<>(Arrays.asList(2, 3, 11, 12, 13)))); + } + + @Test(expected = IllegalStateException.class) + public void crash_on_invalid_start_line_format() throws IOException { + String example = "Index: sample1\n" + + "===================================================================\n" + + "--- a/sample1\n" + + "+++ b/sample1\n" + + "@@ -1 +x1,3 @@\n" + + " same line\n" + + "+added line 1\n" + + "+added line 2\n"; + + printDiff(example); + underTest.changedLines(); + } + + @Test + public void parse_diff_with_multiple_files() throws IOException { + String example = "Index: sample1\n" + + "===================================================================\n" + + "--- a/sample1\n" + + "+++ b/sample1\n" + + "@@ -1 +0,0 @@\n" + + "-deleted line\n" + + "Index: sample2\n" + + "===================================================================\n" + + "--- a/sample2\n" + + "+++ b/sample2\n" + + "@@ -0,0 +1 @@\n" + + "+added line\n" + + "Index: sample3\n" + + "===================================================================\n" + + "--- a/sample3\n" + + "+++ b/sample3\n" + + "@@ -0,0 +1,2 @@\n" + + "+added line 1\n" + + "+added line 2\n" + + "Index: sample3-not-included\n" + + "===================================================================\n" + + "--- a/sample3-not-included\n" + + "+++ b/sample3-not-included\n" + + "@@ -0,0 +1,2 @@\n" + + "+added line 1\n" + + "+added line 2\n" + + "Index: sample4\n" + + "===================================================================\n" + + "--- a/sample4\n" + + "+++ b/sample4\n" + + "@@ -1 +1,3 @@\n" + + " same line\n" + + "+added line 1\n" + + "+added line 2\n"; + + printDiff(example); + Map> expected = new HashMap<>(); + expected.put(rootBaseDir.resolve("sample2"), Collections.singleton(1)); + expected.put(rootBaseDir.resolve("sample3"), new HashSet<>(Arrays.asList(1, 2))); + expected.put(rootBaseDir.resolve("sample4"), new HashSet<>(Arrays.asList(2, 3))); + + assertThat(underTest.changedLines()).isEqualTo(expected); + } + + private void printDiff(String unifiedDiff) throws IOException { + try (OutputStreamWriter writer = new OutputStreamWriter(underTest.receiver())) { + writer.write(unifiedDiff); + } + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/FindForkTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/FindForkTest.java new file mode 100644 index 00000000000..5bbc7c4d109 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/FindForkTest.java @@ -0,0 +1,143 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.tmatesoft.svn.core.SVNException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +public class FindForkTest { + + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + private static SvnTester svnTester; + + private static Path trunk; + private static Path b1; + private static Path b2; + + private FindFork findFork; + + @BeforeClass + public static void before() throws IOException, SVNException { + svnTester = new SvnTester(temp.newFolder().toPath()); + + trunk = temp.newFolder("trunk").toPath(); + svnTester.checkout(trunk, "trunk"); + createAndCommitFile(trunk, "file-1-commit-in-trunk.xoo"); + createAndCommitFile(trunk, "file-2-commit-in-trunk.xoo"); + createAndCommitFile(trunk, "file-3-commit-in-trunk.xoo"); + svnTester.checkout(trunk, "trunk"); + + svnTester.createBranch("b1"); + b1 = temp.newFolder("branches", "b1").toPath(); + svnTester.checkout(b1, "branches/b1"); + createAndCommitFile(b1, "file-1-commit-in-b1.xoo"); + createAndCommitFile(b1, "file-2-commit-in-b1.xoo"); + createAndCommitFile(b1, "file-3-commit-in-b1.xoo"); + svnTester.checkout(b1, "branches/b1"); + + svnTester.createBranch("branches/b1", "b2"); + b2 = temp.newFolder("branches", "b2").toPath(); + svnTester.checkout(b2, "branches/b2"); + + createAndCommitFile(b2, "file-1-commit-in-b2.xoo"); + createAndCommitFile(b2, "file-2-commit-in-b2.xoo"); + createAndCommitFile(b2, "file-3-commit-in-b2.xoo"); + svnTester.checkout(b2, "branches/b2"); + } + + @Before + public void setUp() { + SvnConfiguration configurationMock = mock(SvnConfiguration.class); + findFork = new FindFork(configurationMock); + } + + @Test + public void testEmptyBranch() throws SVNException, IOException { + svnTester.createBranch("empty"); + Path empty = temp.newFolder("branches", "empty").toPath(); + + svnTester.checkout(empty, "branches/empty"); + ForkPoint forkPoint = findFork.find(empty, "unknown"); + assertThat(forkPoint).isNull(); + } + + @Test + public void returnNoDate() throws SVNException { + FindFork findFork = new FindFork(mock(SvnConfiguration.class)) { + @Override + public ForkPoint find(Path location, String referenceBranch) { + return null; + } + }; + + assertThat(findFork.findDate(Paths.get(""), "branch")).isNull(); + } + + @Test + public void testTrunk() throws SVNException { + ForkPoint forkPoint = findFork.find(trunk, "unknown"); + assertThat(forkPoint).isNull(); + } + + @Test + public void testB1() throws SVNException { + ForkPoint forkPoint = findFork.find(b1, "trunk"); + assertThat(forkPoint.commit()).isEqualTo("5"); + } + + @Test + public void testB2() throws SVNException { + ForkPoint forkPoint = findFork.find(b2, "branches/b1"); + assertThat(forkPoint.commit()).isEqualTo("9"); + } + + @Test + public void testB2Date() throws SVNException { + assertThat(findFork.findDate(b2, "branches/b1")).isNotNull(); + } + + @Test + public void testB2FromTrunk() throws SVNException { + ForkPoint forkPoint = findFork.find(b2, "trunk"); + assertThat(forkPoint.commit()).isEqualTo("5"); + } + + private static void createAndCommitFile(Path worktree, String filename, String content) throws IOException, SVNException { + svnTester.createFile(worktree, filename, content); + svnTester.add(worktree, filename); + svnTester.commit(worktree); + } + + private static void createAndCommitFile(Path worktree, String filename) throws IOException, SVNException { + createAndCommitFile(worktree, filename, filename + "\n"); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnBlameCommandTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnBlameCommandTest.java new file mode 100644 index 00000000000..930853b6a18 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnBlameCommandTest.java @@ -0,0 +1,321 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.Date; +import java.util.Enumeration; +import java.util.List; +import java.util.stream.IntStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.mockito.ArgumentCaptor; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.TestInputFileBuilder; +import org.sonar.api.batch.scm.BlameCommand.BlameInput; +import org.sonar.api.batch.scm.BlameCommand.BlameOutput; +import org.sonar.api.batch.scm.BlameLine; +import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.internal.wc2.compat.SvnCodec; +import org.tmatesoft.svn.core.wc.ISVNOptions; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNUpdateClient; +import org.tmatesoft.svn.core.wc.SVNWCUtil; +import org.tmatesoft.svn.core.wc2.SvnCheckout; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@RunWith(Parameterized.class) +public class SvnBlameCommandTest { + + /* + * Note about SONARSCSVN-11: The case of a project baseDir is in a subFolder of working copy is part of method tests by default + */ + + private static final String DUMMY_JAVA = "src/main/java/org/dummy/Dummy.java"; + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private FileSystem fs; + private BlameInput input; + private String serverVersion; + private int wcVersion; + + @Parameters(name = "SVN server version {0}, WC version {1}") + public static Iterable data() { + return Arrays.asList(new Object[][] {{"1.6", 10}, {"1.7", 29}, {"1.8", 31}, {"1.9", 31}}); + } + + public SvnBlameCommandTest(String serverVersion, int wcVersion) { + this.serverVersion = serverVersion; + this.wcVersion = wcVersion; + } + + @Before + public void prepare() { + fs = mock(FileSystem.class); + input = mock(BlameInput.class); + when(input.fileSystem()).thenReturn(fs); + } + + @Test + public void testParsingOfOutput() throws Exception { + File repoDir = unzip("repo-svn.zip"); + + String scmUrl = "file:///" + unixPath(new File(repoDir, "repo-svn")); + File baseDir = new File(checkout(scmUrl), "dummy-svn"); + + when(fs.baseDir()).thenReturn(baseDir); + DefaultInputFile inputFile = new TestInputFileBuilder("foo", DUMMY_JAVA) + .setLines(27) + .setModuleBaseDir(baseDir.toPath()) + .build(); + + BlameOutput blameResult = mock(BlameOutput.class); + when(input.filesToBlame()).thenReturn(singletonList(inputFile)); + + newSvnBlameCommand().blame(input, blameResult); + ArgumentCaptor captor = ArgumentCaptor.forClass(List.class); + verify(blameResult).blameResult(eq(inputFile), captor.capture()); + List result = captor.getValue(); + assertThat(result).hasSize(27); + Date commitDate = new Date(1342691097393L); + BlameLine[] expected = IntStream.rangeClosed(1, 27).mapToObj(i -> new BlameLine().date(commitDate).revision("2").author("dgageot")).toArray(BlameLine[]::new); + assertThat(result).containsExactly(expected); + } + + private File unzip(String repoName) throws IOException { + File repoDir = temp.newFolder(); + try { + javaUnzip(Paths.get(this.getClass().getResource("test-repos").toURI()).resolve(serverVersion).resolve(repoName).toFile(), repoDir); + return repoDir; + } catch (URISyntaxException e) { + throw new IOException(e); + } + } + + private File checkout(String scmUrl) throws Exception { + ISVNOptions options = SVNWCUtil.createDefaultOptions(true); + ISVNAuthenticationManager isvnAuthenticationManager = SVNWCUtil.createDefaultAuthenticationManager(null, null, (char[]) null, false); + SVNClientManager svnClientManager = SVNClientManager.newInstance(options, isvnAuthenticationManager); + File out = temp.newFolder(); + SVNUpdateClient updateClient = svnClientManager.getUpdateClient(); + SvnCheckout co = updateClient.getOperationsFactory().createCheckout(); + co.setUpdateLocksOnDemand(updateClient.isUpdateLocksOnDemand()); + co.setSource(SvnTarget.fromURL(SVNURL.parseURIEncoded(scmUrl), SVNRevision.HEAD)); + co.setSingleTarget(SvnTarget.fromFile(out)); + co.setRevision(SVNRevision.HEAD); + co.setDepth(SVNDepth.INFINITY); + co.setAllowUnversionedObstructions(false); + co.setIgnoreExternals(updateClient.isIgnoreExternals()); + co.setExternalsHandler(SvnCodec.externalsHandler(updateClient.getExternalsHandler())); + co.setTargetWorkingCopyFormat(wcVersion); + co.run(); + return out; + } + + @Test + public void testParsingOfOutputWithMergeHistory() throws Exception { + File repoDir = unzip("repo-svn-with-merge.zip"); + + String scmUrl = "file:///" + unixPath(new File(repoDir, "repo-svn")); + File baseDir = new File(checkout(scmUrl), "dummy-svn/trunk"); + + when(fs.baseDir()).thenReturn(baseDir); + DefaultInputFile inputFile = new TestInputFileBuilder("foo", DUMMY_JAVA) + .setLines(27) + .setModuleBaseDir(baseDir.toPath()) + .build(); + + BlameOutput blameResult = mock(BlameOutput.class); + when(input.filesToBlame()).thenReturn(singletonList(inputFile)); + + newSvnBlameCommand().blame(input, blameResult); + ArgumentCaptor captor = ArgumentCaptor.forClass(List.class); + verify(blameResult).blameResult(eq(inputFile), captor.capture()); + List result = captor.getValue(); + assertThat(result).hasSize(27); + Date commitDate = new Date(1342691097393L); + Date revision6Date = new Date(1415262184300L); + + BlameLine[] expected = IntStream.rangeClosed(1, 27).mapToObj(i -> { + if (i == 2 || i == 24) { + return new BlameLine().date(revision6Date).revision("6").author("henryju"); + } else { + return new BlameLine().date(commitDate).revision("2").author("dgageot"); + } + }).toArray(BlameLine[]::new); + + assertThat(result).containsExactly(expected); + } + + @Test + public void shouldNotFailIfFileContainsLocalModification() throws Exception { + File repoDir = unzip("repo-svn.zip"); + + String scmUrl = "file:///" + unixPath(new File(repoDir, "repo-svn")); + File baseDir = new File(checkout(scmUrl), "dummy-svn"); + + when(fs.baseDir()).thenReturn(baseDir); + DefaultInputFile inputFile = new TestInputFileBuilder("foo", DUMMY_JAVA) + .setLines(28) + .setModuleBaseDir(baseDir.toPath()) + .build(); + + Files.write(baseDir.toPath().resolve(DUMMY_JAVA), "\n//foo".getBytes(), StandardOpenOption.APPEND); + + BlameOutput blameResult = mock(BlameOutput.class); + when(input.filesToBlame()).thenReturn(singletonList(inputFile)); + + newSvnBlameCommand().blame(input, blameResult); + verifyNoInteractions(blameResult); + } + + // SONARSCSVN-7 + @Test + public void shouldNotFailOnWrongFilename() throws Exception { + File repoDir = unzip("repo-svn.zip"); + + String scmUrl = "file:///" + unixPath(new File(repoDir, "repo-svn")); + File baseDir = new File(checkout(scmUrl), "dummy-svn"); + + when(fs.baseDir()).thenReturn(baseDir); + DefaultInputFile inputFile = new TestInputFileBuilder("foo", DUMMY_JAVA.toLowerCase()) + .setLines(27) + .setModuleBaseDir(baseDir.toPath()) + .build(); + + BlameOutput blameResult = mock(BlameOutput.class); + when(input.filesToBlame()).thenReturn(singletonList(inputFile)); + + newSvnBlameCommand().blame(input, blameResult); + verifyNoInteractions(blameResult); + } + + @Test + public void shouldNotFailOnUncommitedFile() throws Exception { + File repoDir = unzip("repo-svn.zip"); + + String scmUrl = "file:///" + unixPath(new File(repoDir, "repo-svn")); + File baseDir = new File(checkout(scmUrl), "dummy-svn"); + + when(fs.baseDir()).thenReturn(baseDir); + String relativePath = "src/main/java/org/dummy/Dummy2.java"; + DefaultInputFile inputFile = new TestInputFileBuilder("foo", relativePath) + .setLines(28) + .setModuleBaseDir(baseDir.toPath()) + .build(); + + Files.write(baseDir.toPath().resolve(relativePath), "package org.dummy;\npublic class Dummy2 {}".getBytes()); + + BlameOutput blameResult = mock(BlameOutput.class); + when(input.filesToBlame()).thenReturn(singletonList(inputFile)); + + newSvnBlameCommand().blame(input, blameResult); + verifyNoInteractions(blameResult); + } + + @Test + public void shouldNotFailOnUncommitedDir() throws Exception { + File repoDir = unzip("repo-svn.zip"); + + String scmUrl = "file:///" + unixPath(new File(repoDir, "repo-svn")); + File baseDir = new File(checkout(scmUrl), "dummy-svn"); + + when(fs.baseDir()).thenReturn(baseDir); + String relativePath = "src/main/java/org/dummy2/dummy/Dummy.java"; + DefaultInputFile inputFile = new TestInputFileBuilder("foo", relativePath) + .setLines(28) + .setModuleBaseDir(baseDir.toPath()) + .build(); + + Path filepath = new File(baseDir, relativePath).toPath(); + Files.createDirectories(filepath.getParent()); + Files.write(filepath, "package org.dummy;\npublic class Dummy {}".getBytes()); + + BlameOutput blameResult = mock(BlameOutput.class); + when(input.filesToBlame()).thenReturn(singletonList(inputFile)); + + newSvnBlameCommand().blame(input, blameResult); + verifyNoInteractions(blameResult); + } + + private static void javaUnzip(File zip, File toDir) { + try { + try (ZipFile zipFile = new ZipFile(zip)) { + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + File to = new File(toDir, entry.getName()); + if (entry.isDirectory()) { + Files.createDirectories(to.toPath()); + } else { + File parent = to.getParentFile(); + if (parent != null) { + Files.createDirectories(parent.toPath()); + } + + Files.copy(zipFile.getInputStream(entry), to.toPath()); + } + } + } + } catch (Exception e) { + throw new IllegalStateException("Fail to unzip " + zip + " to " + toDir, e); + } + } + + private static String unixPath(File file) { + return file.getAbsolutePath().replace('\\', '/'); + } + + private SvnBlameCommand newSvnBlameCommand() { + return new SvnBlameCommand(mock(SvnConfiguration.class)); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java new file mode 100644 index 00000000000..7a765b28160 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.utils.System2; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +public class SvnConfigurationTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void sanityCheck() throws Exception { + MapSettings settings = new MapSettings(new PropertyDefinitions(System2.INSTANCE, SvnConfiguration.getProperties())); + SvnConfiguration config = new SvnConfiguration(settings.asConfig()); + + assertThat(config.username()).isNull(); + assertThat(config.password()).isNull(); + + settings.setProperty(SvnConfiguration.USER_PROP_KEY, "foo"); + assertThat(config.username()).isEqualTo("foo"); + + settings.setProperty(SvnConfiguration.PASSWORD_PROP_KEY, "pwd"); + assertThat(config.password()).isEqualTo("pwd"); + + settings.setProperty(SvnConfiguration.PASSPHRASE_PROP_KEY, "pass"); + assertThat(config.passPhrase()).isEqualTo("pass"); + + assertThat(config.privateKey()).isNull(); + File fakeKey = temp.newFile(); + settings.setProperty(SvnConfiguration.PRIVATE_KEY_PATH_PROP_KEY, fakeKey.getAbsolutePath()); + assertThat(config.privateKey()).isEqualTo(fakeKey); + + settings.setProperty(SvnConfiguration.PRIVATE_KEY_PATH_PROP_KEY, "/not/exists"); + try { + config.privateKey(); + fail("Expected exception"); + } catch (Exception e) { + assertThat(e).hasMessageContaining("Unable to read private key from "); + } + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java new file mode 100644 index 00000000000..c815fdda0bf --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java @@ -0,0 +1,325 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +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.scm.ScmProvider; +import org.tmatesoft.svn.core.SVNCancelException; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.wc.SVNWCClient; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SvnScmProviderTest { + + // Sample content for unified diffs + // http://www.gnu.org/software/diffutils/manual/html_node/Example-Unified.html#Example-Unified + private static final String CONTENT_LAO = "The Way that can be told of is not the eternal Way;\n" + + "The name that can be named is not the eternal name.\n" + + "The Nameless is the origin of Heaven and Earth;\n" + + "The Named is the mother of all things.\n" + + "Therefore let there always be non-being,\n" + + " so we may see their subtlety,\n" + + "And let there always be being,\n" + + " so we may see their outcome.\n" + + "The two are the same,\n" + + "But after they are produced,\n" + + " they have different names.\n"; + + private static final String CONTENT_TZU = "The Nameless is the origin of Heaven and Earth;\n" + + "The named is the mother of all things.\n" + + "\n" + + "Therefore let there always be non-being,\n" + + " so we may see their subtlety,\n" + + "And let there always be being,\n" + + " so we may see their outcome.\n" + + "The two are the same,\n" + + "But after they are produced,\n" + + " they have different names.\n" + + "They both may be called deep and profound.\n" + + "Deeper and more profound,\n" + + "The door of all subtleties!"; + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private FindFork findFork = mock(FindFork.class); + private SvnConfiguration config = mock(SvnConfiguration.class); + private SvnTester svnTester; + + @Before + public void before() throws IOException, SVNException { + svnTester = new SvnTester(temp.newFolder().toPath()); + + Path worktree = temp.newFolder().toPath(); + svnTester.checkout(worktree, "trunk"); + createAndCommitFile(worktree, "file-in-first-commit.xoo"); + } + + @Test + public void sanityCheck() { + SvnBlameCommand blameCommand = new SvnBlameCommand(config); + SvnScmProvider svnScmProvider = new SvnScmProvider(config, blameCommand, findFork); + assertThat(svnScmProvider.key()).isEqualTo("svn"); + assertThat(svnScmProvider.blameCommand()).isEqualTo(blameCommand); + } + + @Test + public void testAutodetection() throws IOException { + ScmProvider scmBranchProvider = newScmProvider(); + + File baseDirEmpty = temp.newFolder(); + assertThat(scmBranchProvider.supports(baseDirEmpty)).isFalse(); + + File svnBaseDir = temp.newFolder(); + Files.createDirectory(svnBaseDir.toPath().resolve(".svn")); + assertThat(scmBranchProvider.supports(svnBaseDir)).isTrue(); + + File svnBaseDirSubFolder = temp.newFolder(); + Files.createDirectory(svnBaseDirSubFolder.toPath().resolve(".svn")); + File projectBaseDir = new File(svnBaseDirSubFolder, "folder"); + Files.createDirectory(projectBaseDir.toPath()); + assertThat(scmBranchProvider.supports(projectBaseDir)).isTrue(); + } + + @Test + public void branchChangedFiles_and_lines_from_diverged() throws IOException, SVNException { + Path trunk = temp.newFolder().toPath(); + svnTester.checkout(trunk, "trunk"); + createAndCommitFile(trunk, "file-m1.xoo"); + createAndCommitFile(trunk, "file-m2.xoo"); + createAndCommitFile(trunk, "file-m3.xoo"); + createAndCommitFile(trunk, "lao.txt", CONTENT_LAO); + + // create branch from trunk + svnTester.createBranch("b1"); + + // still on trunk + appendToAndCommitFile(trunk, "file-m3.xoo"); + createAndCommitFile(trunk, "file-m4.xoo"); + + Path b1 = temp.newFolder().toPath(); + svnTester.checkout(b1, "branches/b1"); + Files.createDirectories(b1.resolve("sub")); + createAndCommitFile(b1, "sub/file-b1.xoo"); + appendToAndCommitFile(b1, "file-m1.xoo"); + deleteAndCommitFile(b1, "file-m2.xoo"); + + createAndCommitFile(b1, "file-m5.xoo"); + deleteAndCommitFile(b1, "file-m5.xoo"); + + svnCopyAndCommitFile(b1, "file-m1.xoo", "file-m1-copy.xoo"); + appendToAndCommitFile(b1, "file-m1.xoo"); + + // modify file without committing it -> should not be included (think generated files) + svnTester.appendToFile(b1, "file-m3.xoo"); + + svnTester.update(b1); + + Set changedFiles = newScmProvider().branchChangedFiles("trunk", b1); + assertThat(changedFiles) + .containsExactlyInAnyOrder( + b1.resolve("sub/file-b1.xoo"), + b1.resolve("file-m1.xoo"), + b1.resolve("file-m1-copy.xoo")); + + // use a subset of changed files for .branchChangedLines to verify only requested files are returned + assertThat(changedFiles.remove(b1.resolve("sub/file-b1.xoo"))).isTrue(); + + // generate common sample diff + createAndCommitFile(b1, "lao.txt", CONTENT_TZU); + changedFiles.add(b1.resolve("lao.txt")); + + // a file that should not yield any results + changedFiles.add(b1.resolve("nonexistent")); + + // modify file without committing to it + svnTester.appendToFile(b1, "file-m1.xoo"); + + Map> expected = new HashMap<>(); + expected.put(b1.resolve("lao.txt"), new HashSet<>(Arrays.asList(2, 3, 11, 12, 13))); + expected.put(b1.resolve("file-m1.xoo"), new HashSet<>(Arrays.asList(2, 3, 4))); + expected.put(b1.resolve("file-m1-copy.xoo"), new HashSet<>(Arrays.asList(1, 2))); + + assertThat(newScmProvider().branchChangedLines("trunk", b1, changedFiles)) + .isEqualTo(expected); + + assertThat(newScmProvider().branchChangedLines("trunk", b1, Collections.singleton(b1.resolve("nonexistent")))) + .isEmpty(); + } + + @Test + public void branchChangedFiles_should_return_empty_when_no_local_changes() throws IOException, SVNException { + Path b1 = temp.newFolder().toPath(); + svnTester.createBranch("b1"); + svnTester.checkout(b1, "branches/b1"); + + assertThat(newScmProvider().branchChangedFiles("b1", b1)).isEmpty(); + } + + @Test + public void branchChangedFiles_should_return_null_when_repo_nonexistent() throws IOException { + assertThat(newScmProvider().branchChangedFiles("trunk", temp.newFolder().toPath())).isNull(); + } + + @Test + public void branchChangedFiles_should_return_null_when_dir_nonexistent() { + assertThat(newScmProvider().branchChangedFiles("trunk", temp.getRoot().toPath().resolve("nonexistent"))).isNull(); + } + + @Test + public void branchChangedLines_should_return_null_when_repo_nonexistent() throws IOException { + assertThat(newScmProvider().branchChangedLines("trunk", temp.newFolder().toPath(), Collections.emptySet())).isNull(); + } + + @Test + public void branchChangedLines_should_return_null_when_dir_nonexistent() { + assertThat(newScmProvider().branchChangedLines("trunk", temp.getRoot().toPath().resolve("nonexistent"), Collections.emptySet())).isNull(); + } + + @Test + public void branchChangedLines_should_return_empty_when_no_local_changes() throws IOException, SVNException { + Path b1 = temp.newFolder().toPath(); + svnTester.createBranch("b1"); + svnTester.checkout(b1, "branches/b1"); + + assertThat(newScmProvider().branchChangedLines("b1", b1, Collections.emptySet())).isEmpty(); + } + + @Test + public void branchChangedLines_should_return_null_when_invalid_diff_format() throws IOException, SVNException { + Path b1 = temp.newFolder().toPath(); + svnTester.createBranch("b1"); + svnTester.checkout(b1, "branches/b1"); + + SvnScmProvider scmProvider = new SvnScmProvider(config, new SvnBlameCommand(config), findFork) { + @Override + ChangedLinesComputer newChangedLinesComputer(Path rootBaseDir, Set changedFiles) { + throw new IllegalStateException("crash"); + } + }; + assertThat(scmProvider.branchChangedLines("b1", b1, Collections.emptySet())).isNull(); + } + + @Test + public void forkDate_returns_null_if_no_fork_found() { + assertThat(new SvnScmProvider(config, new SvnBlameCommand(config), findFork).forkDate("branch", Paths.get(""))).isNull(); + } + + @Test + public void forkDate_returns_instant_if_fork_found() throws SVNException { + Path rootBaseDir = Paths.get(""); + String referenceBranch = "branch"; + Instant forkDate = Instant.ofEpochMilli(123456789L); + SvnScmProvider provider = new SvnScmProvider(config, new SvnBlameCommand(config), findFork); + when(findFork.findDate(rootBaseDir, referenceBranch)).thenReturn(forkDate); + + assertThat(provider.forkDate(referenceBranch, rootBaseDir)).isEqualTo(forkDate); + } + + @Test + public void forkDate_returns_null_if_exception_occurs() throws SVNException { + Path rootBaseDir = Paths.get(""); + String referenceBranch = "branch"; + SvnScmProvider provider = new SvnScmProvider(config, new SvnBlameCommand(config), findFork); + when(findFork.findDate(rootBaseDir, referenceBranch)).thenThrow(new SVNCancelException()); + + assertThat(provider.forkDate(referenceBranch, rootBaseDir)).isNull(); + } + + @Test + public void computeChangedPaths_should_not_crash_when_getRepositoryRootURL_getPath_is_empty() throws SVNException { + // verify assumptions about what SVNKit returns as svn root path for urls like http://svnserver/ + assertThat(SVNURL.parseURIEncoded("http://svnserver/").getPath()).isEmpty(); + assertThat(SVNURL.parseURIEncoded("http://svnserver").getPath()).isEmpty(); + + SVNClientManager svnClientManagerMock = mock(SVNClientManager.class); + + SVNWCClient svnwcClientMock = mock(SVNWCClient.class); + when(svnClientManagerMock.getWCClient()).thenReturn(svnwcClientMock); + + SVNLogClient svnLogClient = mock(SVNLogClient.class); + when(svnClientManagerMock.getLogClient()).thenReturn(svnLogClient); + + SVNInfo svnInfoMock = mock(SVNInfo.class); + when(svnwcClientMock.doInfo(any(), any())).thenReturn(svnInfoMock); + + // Simulate repository root on /, SVNKIT then returns an repository root url WITHOUT / at the end. + when(svnInfoMock.getRepositoryRootURL()).thenReturn(SVNURL.parseURIEncoded("http://svnserver")); + when(svnInfoMock.getURL()).thenReturn(SVNURL.parseURIEncoded("http://svnserver/myproject/trunk/")); + + assertThat(SvnScmProvider.computeChangedPaths(Paths.get("/"), svnClientManagerMock)).isEmpty(); + } + + private void createAndCommitFile(Path worktree, String filename, String content) throws IOException, SVNException { + svnTester.createFile(worktree, filename, content); + svnTester.add(worktree, filename); + svnTester.commit(worktree); + } + + private void createAndCommitFile(Path worktree, String filename) throws IOException, SVNException { + createAndCommitFile(worktree, filename, filename + "\n"); + } + + private void appendToAndCommitFile(Path worktree, String filename) throws IOException, SVNException { + svnTester.appendToFile(worktree, filename); + svnTester.commit(worktree); + } + + private void deleteAndCommitFile(Path worktree, String filename) throws IOException, SVNException { + svnTester.deleteFile(worktree, filename); + svnTester.commit(worktree); + } + + private void svnCopyAndCommitFile(Path worktree, String src, String dst) throws SVNException { + svnTester.copy(worktree, src, dst); + svnTester.commit(worktree); + } + + private SvnScmProvider newScmProvider() { + return new SvnScmProvider(config, new SvnBlameCommand(config), findFork); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java new file mode 100644 index 00000000000..33c3bd37ac9 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.scm.svn.SvnScmSupport.newSvnClientManager; + +public class SvnScmSupportTest { + @Test + public void getExtensions() { + assertThat(SvnScmSupport.getObjects()).isNotEmpty(); + } + + @Test + public void newSvnClientManager_with_auth() { + SvnConfiguration config = mock(SvnConfiguration.class); + when(config.password()).thenReturn("password"); + when(config.passPhrase()).thenReturn("passPhrase"); + assertThat(newSvnClientManager(config)).isNotNull(); + } + + @Test + public void newSvnClientManager_without_auth() { + SvnConfiguration config = mock(SvnConfiguration.class); + assertThat(config.password()).isNull(); + assertThat(config.passPhrase()).isNull(); + assertThat(newSvnClientManager(config)).isNotNull(); + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTester.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTester.java new file mode 100644 index 00000000000..ec00ca50b3c --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTester.java @@ -0,0 +1,135 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.io.SVNRepositoryFactory; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNCopyClient; +import org.tmatesoft.svn.core.wc.SVNCopySource; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNUpdateClient; +import org.tmatesoft.svn.core.wc2.SvnList; +import org.tmatesoft.svn.core.wc2.SvnOperationFactory; +import org.tmatesoft.svn.core.wc2.SvnRemoteMkDir; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +public class SvnTester { + private final SVNClientManager manager = SVNClientManager.newInstance(new SvnOperationFactory()); + + private final SVNURL localRepository; + + public SvnTester(Path root) throws SVNException, IOException { + localRepository = SVNRepositoryFactory.createLocalRepository(root.toFile(), false, false); + mkdir("trunk"); + mkdir("branches"); + } + + private void mkdir(String relpath) throws IOException, SVNException { + SvnRemoteMkDir remoteMkDir = manager.getOperationFactory().createRemoteMkDir(); + remoteMkDir.addTarget(SvnTarget.fromURL(localRepository.appendPath(relpath, false))); + remoteMkDir.run(); + } + + public void createBranch(String branchName) throws IOException, SVNException { + SVNCopyClient copyClient = manager.getCopyClient(); + SVNCopySource source = new SVNCopySource(SVNRevision.HEAD, SVNRevision.HEAD, localRepository.appendPath("trunk", false)); + copyClient.doCopy(new SVNCopySource[] {source}, localRepository.appendPath("branches/" + branchName, false), false, false, true, "Create branch", null); + } + + public void createBranch(String branchSource, String branchName) throws IOException, SVNException { + SVNCopyClient copyClient = manager.getCopyClient(); + SVNCopySource source = new SVNCopySource(SVNRevision.HEAD, SVNRevision.HEAD, localRepository.appendPath(branchSource, false)); + copyClient.doCopy(new SVNCopySource[] {source}, localRepository.appendPath("branches/" + branchName, false), false, false, true, "Create branch", null); + } + + public void checkout(Path worktree, String path) throws SVNException { + SVNUpdateClient updateClient = manager.getUpdateClient(); + updateClient.doCheckout(localRepository.appendPath(path, false), + worktree.toFile(), null, null, SVNDepth.INFINITY, false); + } + + public void add(Path worktree, String filename) throws SVNException { + manager.getWCClient().doAdd(worktree.resolve(filename).toFile(), true, false, false, SVNDepth.INFINITY, false, false, true); + } + + public void copy(Path worktree, String src, String dst) throws SVNException { + SVNCopyClient copyClient = manager.getCopyClient(); + SVNCopySource source = new SVNCopySource(SVNRevision.HEAD, SVNRevision.HEAD, worktree.resolve(src).toFile()); + copyClient.doCopy(new SVNCopySource[]{source}, worktree.resolve(dst).toFile(), false, false, true); + } + + public void commit(Path worktree) throws SVNException { + manager.getCommitClient().doCommit(new File[] {worktree.toFile()}, false, "commit " + worktree, null, null, false, false, SVNDepth.INFINITY); + } + + public void update(Path worktree) throws SVNException { + manager.getUpdateClient().doUpdate(new File[] {worktree.toFile()}, SVNRevision.HEAD, SVNDepth.INFINITY, false, false); + } + + public Collection list(String... paths) throws SVNException { + Set results = new HashSet<>(); + + SvnList list = manager.getOperationFactory().createList(); + if (paths.length == 0) { + list.addTarget(SvnTarget.fromURL(localRepository)); + } else { + for (String path : paths) { + list.addTarget(SvnTarget.fromURL(localRepository.appendPath(path, false))); + } + } + list.setDepth(SVNDepth.INFINITY); + list.setReceiver((svnTarget, svnDirEntry) -> { + String path = svnDirEntry.getRelativePath(); + if (!path.isEmpty()) { + results.add(path); + } + }); + list.run(); + + return results; + } + + public void createFile(Path worktree, String filename, String content) throws IOException { + Files.write(worktree.resolve(filename), content.getBytes()); + } + + public void createFile(Path worktree, String filename) throws IOException { + createFile(worktree, filename, filename + "\n"); + } + + public void appendToFile(Path worktree, String filename) throws IOException { + Files.write(worktree.resolve(filename), (filename + "\n").getBytes(), StandardOpenOption.APPEND); + } + + public void deleteFile(Path worktree, String filename) throws SVNException { + manager.getWCClient().doDelete(worktree.resolve(filename).toFile(), false, false); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTesterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTesterTest.java new file mode 100644 index 00000000000..0740bb3960f --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnTesterTest.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.scm.svn; + +import java.io.IOException; +import java.nio.file.Path; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.tmatesoft.svn.core.SVNException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SvnTesterTest { + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private SvnTester tester; + + @Before + public void before() throws IOException, SVNException { + tester = new SvnTester(temp.newFolder().toPath()); + } + + @Test + public void test_init() throws SVNException { + assertThat(tester.list()).containsExactlyInAnyOrder("trunk", "branches"); + } + + @Test + public void test_add_and_commit() throws IOException, SVNException { + assertThat(tester.list("trunk")).isEmpty(); + + Path worktree = temp.newFolder().toPath(); + tester.checkout(worktree, "trunk"); + tester.createFile(worktree, "file1"); + + tester.add(worktree, "file1"); + tester.commit(worktree); + + assertThat(tester.list("trunk")).containsOnly("file1"); + } + + @Test + public void test_createBranch() throws IOException, SVNException { + tester.createBranch("b1"); + assertThat(tester.list()).containsExactlyInAnyOrder("trunk", "branches", "branches/b1"); + assertThat(tester.list("branches")).containsOnly("b1"); + } +} diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.6/repo-svn-with-merge.zip b/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.6/repo-svn-with-merge.zip new file mode 100644 index 0000000000000000000000000000000000000000..d3c3ee5fa1e943397520242f5c6704cc3f1021e9 GIT binary patch literal 29020 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 MNC6c-ebj&d1D^Hp#{d8T literal 0 HcmV?d00001 diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.6/repo-svn.zip b/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.6/repo-svn.zip new file mode 100644 index 0000000000000000000000000000000000000000..291d4fb86f778383fc5af65dfaf46df2ffde6206 GIT binary patch literal 23239 zcmbTe1yo+i(lv}ja3{C~cXxMpcbDMq8YH;8ySsaE_uy{9-TfzXXYQSwJ2UHh|A%#0 zz*=3sPo3(jz3X%%D*+4w3GnmdtaZiv+Yi5g`v3qBU}t1wO=a(7MWdt&4KOtaF8lMk z0R#Y${o7%%e;#IFZDstIW03(M-oJjG66t@&>Nz@?y8Sx2qr!;QGA(@D69uXbLSLZ4 zDlkORrnWo?Q&bc06dtXqnNfANm~UR$V33!4P#mspOvaAq=<-KWq?p3=9CGQm zdL2NwAq+C0+M`9|2u&k(DRbolB2-tQh%3^p4f)Sbi6FMD#B{UWDzZ9)8RiN>C9
?OPMfq3=2gTZb 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 MNC6c-ebj&d1D^Hp#{d8T literal 0 HcmV?d00001 diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.7/repo-svn.zip b/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.7/repo-svn.zip new file mode 100644 index 0000000000000000000000000000000000000000..291d4fb86f778383fc5af65dfaf46df2ffde6206 GIT binary patch literal 23239 zcmbTe1yo+i(lv}ja3{C~cXxMpcbDMq8YH;8ySsaE_uy{9-TfzXXYQSwJ2UHh|A%#0 zz*=3sPo3(jz3X%%D*+4w3GnmdtaZiv+Yi5g`v3qBU}t1wO=a(7MWdt&4KOtaF8lMk z0R#Y${o7%%e;#IFZDstIW03(M-oJjG66t@&>Nz@?y8Sx2qr!;QGA(@D69uXbLSLZ4 zDlkORrnWo?Q&bc06dtXqnNfANm~UR$V33!4P#mspOvaAq=<-KWq?p3=9CGQm zdL2NwAq+C0+M`9|2u&k(DRbolB2-tQh%3^p4f)Sbi6FMD#B{UWDzZ9)8RiN>C9
?OPMfq3=2gTZb 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 literal 0 HcmV?d00001 diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.8/repo-svn.zip b/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.8/repo-svn.zip new file mode 100644 index 0000000000000000000000000000000000000000..f31352c5e03e809b48a462b71b1460e5d205c917 GIT binary patch literal 23777 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 literal 0 HcmV?d00001 diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.9/repo-svn-with-merge.zip b/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.9/repo-svn-with-merge.zip new file mode 100644 index 0000000000000000000000000000000000000000..ca672fd66815ddd7149d317fbea93fb469077a22 GIT binary patch literal 37668 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 P@EiINANP9qc=vw*Rw>be literal 0 HcmV?d00001 diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.9/repo-svn.zip b/sonar-scanner-engine/src/test/resources/org/sonar/scm/svn/test-repos/1.9/repo-svn.zip new file mode 100644 index 0000000000000000000000000000000000000000..39b241cd698c56cf1817be744ed2ad4d6ec9ae37 GIT binary patch literal 32696 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 literal 0 HcmV?d00001 -- 2.39.5