diff --git a/README.md b/README.md index 048726e3..0031d2db 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Usage: codacy-coverage-reporter report --sleep-time --num-retries --language | -l - --coverage-reports | -r + --coverage-reports | -r --partial --prefix --force-coverage-parser diff --git a/src/main/scala/com/codacy/configuration/parser/ConfigurationParser.scala b/src/main/scala/com/codacy/configuration/parser/ConfigurationParser.scala index 48bd5631..9403e9a1 100644 --- a/src/main/scala/com/codacy/configuration/parser/ConfigurationParser.scala +++ b/src/main/scala/com/codacy/configuration/parser/ConfigurationParser.scala @@ -58,7 +58,7 @@ case class Report( language: Option[String], @Hidden @Name("f") forceLanguage: Int @@ Counter = Tag.of(0), - @Name("r") @ValueDescription("your project coverage file name") + @Name("r") @ValueDescription("your project coverage file name (supports globs)") coverageReports: Option[List[File]], @ValueDescription("if the report is partial") partial: Int @@ Counter = Tag.of(0), diff --git a/src/main/scala/com/codacy/rules/ReportRules.scala b/src/main/scala/com/codacy/rules/ReportRules.scala index d9389259..00150955 100644 --- a/src/main/scala/com/codacy/rules/ReportRules.scala +++ b/src/main/scala/com/codacy/rules/ReportRules.scala @@ -12,7 +12,7 @@ import com.codacy.transformation.PathPrefixer import wvlet.log.LogSupport import java.io.File -import java.nio.file.Files +import java.nio.file.{FileSystems, Files} import scala.collection.JavaConverters._ class ReportRules(coverageServices: => CoverageServices) extends LogSupport { @@ -222,6 +222,8 @@ class ReportRules(coverageServices: => CoverageServices) extends LogSupport { report.fileReports.flatMap(file => Languages.forPath(file.filename).map(_.name)).distinct } + private val fileSystems = FileSystems.getDefault() + /** * Guess the report file * @@ -262,7 +264,25 @@ class ReportRules(coverageServices: => CoverageServices) extends LogSupport { else Right(foundFiles) case value => - Right(value) + Right { + try { + value.flatMap { file => + val foundWithGlob = { + val matcher = fileSystems.getPathMatcher(s"glob:$file") + projectFiles.filter(f => matcher.matches(f.toPath())) + } + // When the glob doesn't match any file, we return it + // as a file so the later stages will fail instead of silently + // filtering it + if (foundWithGlob.isEmpty) file :: Nil + else foundWithGlob + }.distinct + } catch { + case util.control.NonFatal(e) => + logger.debug(s"""Failed to read "$value" as file glob. Cause $e""") + value + } + } } } diff --git a/src/test/scala/com/codacy/rules/ReportRulesSpec.scala b/src/test/scala/com/codacy/rules/ReportRulesSpec.scala index d88e697d..1e1d0707 100644 --- a/src/test/scala/com/codacy/rules/ReportRulesSpec.scala +++ b/src/test/scala/com/codacy/rules/ReportRulesSpec.scala @@ -174,8 +174,9 @@ class ReportRulesSpec extends WordSpec with Matchers with PrivateMethodTester wi } "provide the available report file" in { - val files = List(new File("coverage.xml")) - val reportEither = components.reportRules.guessReportFiles(files, List.empty) + val files = new File("coverage.xml") :: Nil + val projectFiles = new File("coverage.xml") :: new File("other.xml") :: Nil + val reportEither = components.reportRules.guessReportFiles(files = files, projectFiles = projectFiles) reportEither should be('right) reportEither.right.value should be(files) @@ -197,6 +198,45 @@ class ReportRulesSpec extends WordSpec with Matchers with PrivateMethodTester wi reportEither should be('right) reportEither.right.value.map(_.toString) should be(List("lcov.info", "lcov.dat", "foo.lcov")) } + + "support file globs" in { + val projectFiles = + List(new File("foo.lcov"), new File("lcov.info"), new File("bar.lcov"), new File("foobar.txt")) + val reportEither = components.reportRules.guessReportFiles(new File("*.lcov") :: Nil, projectFiles) + + reportEither should be('right) + reportEither.right.value.map(_.toString) should be(List("foo.lcov", "bar.lcov")) + } + + "return files untouched when glob doesn't find anything" in { + val reportEither = components.reportRules.guessReportFiles(new File("unexisting.xml") :: Nil, projectFiles = Nil) + + reportEither should be('right) + reportEither.right.value.map(_.toString) should be(List("unexisting.xml")) + } + + "support file globs with directories" in { + val projectFiles = + List( + new File("target/dir1/coverage.xml"), + new File("dir2/lcov.info"), + new File("dir1/bar.lcov"), + new File("dir2/other.xml") + ) + val reportEither = components.reportRules.guessReportFiles(new File("**/*.xml") :: Nil, projectFiles) + + reportEither should be('right) + reportEither.right.value.map(_.toString) should be(List("target/dir1/coverage.xml", "dir2/other.xml")) + } + + "remove duplicates when using file globs" in { + val projectFiles = List(new File("coverage.xml")) + val reportEither = + components.reportRules.guessReportFiles(new File("*.xml") :: new File("coverage.xml") :: Nil, projectFiles) + + reportEither should be('right) + reportEither.right.value.map(_.toString) should be(List("coverage.xml")) + } } "validateFileAccess" should {