Skip to content

Commit

Permalink
allow to specify absolute paths for reports. to support msbuild runner
Browse files Browse the repository at this point in the history
handle paths that are outside project source dir

add unit tests

support absolute paths
  • Loading branch information
Jorge Costa authored and Jorge Costa committed Nov 29, 2015
1 parent 79b472f commit 6b2fd4c
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
import org.sonar.api.resources.Resource;
import org.sonar.api.rule.RuleKey;
import org.sonar.plugins.cxx.CxxLanguage;
import static org.sonar.plugins.cxx.utils.CxxUtils.GetDirectoryScannerForReport;

/**
* This class is used as base for all sensors which import reports.
* It hosts common logic such as finding the reports and saving issues
* in SonarQube
*/
public abstract class CxxReportSensor implements Sensor {

private ResourcePerspectives perspectives;
private Set<String> notFoundFiles = new HashSet<String>();
private Set<String> uniqueIssues = new HashSet<String>();
Expand Down Expand Up @@ -156,38 +158,32 @@ public static List<File> getReports(Settings conf,
List<File> reports = new ArrayList<File>();
if (reportPath != null && !reportPath.isEmpty()) {
reportPath = FilenameUtils.normalize(reportPath);

File singleFile = new File(reportPath);
if (singleFile.exists()) {
reports.add(singleFile);
} else {
CxxUtils.LOG.debug("Using pattern '{}' to find reports", reportPath);

DirectoryScanner scanner = new DirectoryScanner();
String[] includes = new String[1];
includes[0] = reportPath;
scanner.setIncludes(includes);
String baseDirPath = baseDirPath1;
scanner.setBasedir(new File(baseDirPath));
DirectoryScannerData scanner = GetDirectoryScannerForReport(baseDirPath, reportPath);

String[] relPaths = new String[0];
try {
scanner.scan();
relPaths = scanner.getIncludedFiles();
} catch (IllegalStateException e) {
CxxUtils.LOG.error("Invalid report baseDir '{}'", baseDirPath);
}

if (relPaths.length < 1 && !baseDirPath2.isEmpty()) {
baseDirPath = baseDirPath2;
scanner.setBasedir(new File(baseDirPath));
try {
scanner.scan();
relPaths = scanner.getIncludedFiles();
} catch (IllegalStateException e) {
CxxUtils.LOG.error("Invalid report baseDir '{}'", baseDirPath);
}
scanner = GetDirectoryScannerForReport(baseDirPath2, reportPath);
scanner.scan();
relPaths = scanner.getIncludedFiles();
}

for (String relPath : relPaths) {
String path = CxxUtils.normalizePath(new File(baseDirPath, relPath).getAbsolutePath());
CxxUtils.LOG.debug("Process report '{}'", relPath);
String path = CxxUtils.normalizePath(new File(scanner.getBaseDir(), relPath).getAbsolutePath());
try {
File reportFile = new File(path);
if (reportFile.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
package org.sonar.plugins.cxx.utils;

import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FilenameUtils;
import org.apache.tools.ant.DirectoryScanner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -63,6 +67,59 @@ public static String normalizePath(String filename) {
}
}

/**
* Creates a scanner for a string path and a baseDir
* If base dir is outside report than sets the basedir to local path
* @param rootDirPath
* @param reportPath
* @return
*/
public static DirectoryScannerData GetDirectoryScannerForReport(String rootDirPath, String reportPath) {
File singleFile = new File(reportPath);
DirectoryScannerData scanner = new DirectoryScannerData();

CxxUtils.LOG.debug("Unprocessed root directory '{}'", rootDirPath);
CxxUtils.LOG.debug("Unprocessed report file '{}'", reportPath);

if (singleFile.isAbsolute()) {
String baseNormalize = FilenameUtils.normalize(rootDirPath);
String reportNormalize = FilenameUtils.normalize(reportPath);

if (reportNormalize.contains(baseNormalize)) {
reportPath = reportPath.replace(baseNormalize, "");
if (reportPath.startsWith("/") || reportPath.startsWith("\\")) {
reportPath = reportPath.substring(1);
}
scanner.setBaseDir(FilenameUtils.normalize(baseNormalize));
} else {
Pattern p = Pattern.compile("^([a-z]):");
Matcher m = p.matcher(reportPath);
if (m.find()) {
scanner.setBaseDir(FilenameUtils.normalize(m.group()));
} else {
scanner.setBaseDir(FilenameUtils.normalize("/"));
}
}
scanner.setInclude(reportPath);

} else {
if (reportPath.startsWith("**")) {
scanner.setBaseDir(FilenameUtils.normalize(rootDirPath));
scanner.setInclude(reportPath);
} else {
File file1 = new File(rootDirPath);
File file2 = new File(file1, reportPath);
scanner.setBaseDir(FilenameUtils.normalize(file2.getParent()));
scanner.setInclude(file2.getName());
}
}

CxxUtils.LOG.debug("Processed root directory '{}'", scanner.getBaseDir());
CxxUtils.LOG.debug("Processed report file '{}'", scanner.getIncludes()[0]);

return scanner;
}

/**
* @return returns case sensitive full path
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Sonar C++ Plugin (Community)
* Copyright (C) 2010 Neticoa SAS France
* [email protected]
*
* 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 02
*/

package org.sonar.plugins.cxx.utils;

import java.io.File;
import org.apache.tools.ant.DirectoryScanner;

public class DirectoryScannerData extends DirectoryScanner {

DirectoryScannerData() {
}

public void setBaseDir(String base) {
this.setBasedir(new File(base));
}

public void setInclude(String include) {
String[] incls = new String[1];
incls[0] = include;
this.setIncludes(incls);
}

public File getBaseDir() {
return this.basedir;
}

public String [] getIncludes() {
return this.includes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,18 @@ public void getReports_patternMatching() throws java.io.IOException, java.lang.I
List<String[]> examples = new LinkedList<String[]>();

// "pattern", "matches", "matches not"
examples.add(new String[] { "A.ext", "A.ext", "dir/B.ext" }); // relative
examples.add(new String[] { "dir/A.ext", "dir/A.ext", "A.ext, dir/B.ext" }); // relative with subdir

examples.add(new String[] { "dir/../A.ext", "A.ext", "B.ext, dir/A.ext" }); // relative with subdir
examples.add(new String[] { "./A.ext", "A.ext", "B.ext" }); // relative with leading dot

examples.add(new String[] { "A?.ext", "AA.ext,AB.ext", "B.ext" }); // containing question mark
examples.add(new String[] { "A*.ext", "A.ext,AAA.ext", "B.ext" }); // containing question mark
examples.add(new String[] { "**/A.ext", "A.ext,dir/A.ext", "B.ext" }); // containing question mark
examples.add(new String[] { "", "", "" }); // empty

//TODO: decide whether to support absolute paths
//String abspattern = new File(base.getRoot(), "A.ext").getPath();
//examples.add(new String[] { abspattern, "", "A.ext" }); // absolute
//examples.add(new String[] { "A.ext", "A.ext", "dir/B.ext" }); // relative
//examples.add(new String[] { "dir/A.ext", "dir/A.ext", "A.ext, dir/B.ext" }); // relative with subdir

//examples.add(new String[] { "dir/../A.ext", "A.ext", "B.ext, dir/A.ext" }); // relative with subdir
//examples.add(new String[] { "./A.ext", "A.ext", "B.ext" }); // relative with leading dot

//examples.add(new String[] { "A?.ext", "AA.ext,AB.ext", "B.ext" }); // containing question mark
//examples.add(new String[] { "A*.ext", "A.ext,AAA.ext", "B.ext" }); // containing question mark
//examples.add(new String[] { "**/A.ext", "A.ext,dir/A.ext", "B.ext" }); // containing question mark
//examples.add(new String[] { "", "", "" }); // empty

// absolutes paths are covered in CxxUtilsTest

String pattern, match, allpaths;
List<File> reports;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Sonar C++ Plugin (Community)
* Copyright (C) 2010 Neticoa SAS France
* [email protected]
*
* 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 02
*/
package org.sonar.plugins.cxx.utils;

import org.apache.tools.ant.DirectoryScanner;
import static org.fest.assertions.Assertions.assertThat;
import org.junit.Test;
import org.sonar.plugins.cxx.TestUtils;

public class CxxUtilsTest {

@Test
public void whenPathIsAbsoluteAndOutsideBaseDirShouldUseDriveLetterWindows() {
if (TestUtils.isWindows()) {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("m:\\abc\\abs\\", "x:\\src\\abs\\abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("x:");
assertThat(scanner.getIncludes()[0]).isEqualTo("x:\\src\\abs\\abc.xml");
} else {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("/abc/abs", "/src/abs/abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("/");
assertThat(scanner.getIncludes()[0]).isEqualTo("/src/abs/abc.xml");
}
}

@Test
public void whenPathIsAbsoluteAndIsInBaseDirShouldShouldUseBaseDir() {
if (TestUtils.isWindows()) {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("x:\\src\\abs\\", "x:\\src\\abs\\abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("x:\\src\\abs");
assertThat(scanner.getIncludes()[0]).isEqualTo("abc.xml");
} else {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("/src/abs", "/src/abs/abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("/src/abs");
assertThat(scanner.getIncludes()[0]).isEqualTo("abc.xml");
}
}

@Test
public void whenPathIsAbsoluteAndIsOutsideProjectShouldShouldUseRootOrDrive() {
if (TestUtils.isWindows()) {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("x:\\mmm\\mmmm\\", "x:\\src\\abs\\abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("x:");
assertThat(scanner.getIncludes()[0]).isEqualTo("x:\\src\\abs\\abc.xml");
} else {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("/bbb/dddd", "/src/abs/abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("/");
assertThat(scanner.getIncludes()[0]).isEqualTo("/src/abs/abc.xml");
}
}

@Test
public void whenPathIsRelativeAndIsInsideProjectShouldUseProjectDir() {
if (TestUtils.isWindows()) {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("x:\\src\\abs\\", "abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("x:\\src\\abs");
assertThat(scanner.getIncludes()[0]).isEqualTo("abc.xml");
} else {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("/src/abs", "abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("/src/abs");
assertThat(scanner.getIncludes()[0]).isEqualTo("abc.xml");
}
}

@Test
public void whenPathIsRelativeAndIsOutsideProjectShouldUseFileBaseDir() {
if (TestUtils.isWindows()) {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("x:\\src\\abs\\", "../../abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("x:\\");
assertThat(scanner.getIncludes()[0]).isEqualTo("abc.xml");
} else {
DirectoryScannerData scanner = CxxUtils.GetDirectoryScannerForReport("/src/abs", "../../abc.xml");
assertThat(scanner.getBasedir().getPath()).isEqualTo("/");
assertThat(scanner.getIncludes()[0]).isEqualTo("abc.xml");
}
}
}

0 comments on commit 6b2fd4c

Please sign in to comment.