Skip to content

Commit

Permalink
Allow multiple exclude files per version to be loaded from a directory
Browse files Browse the repository at this point in the history
So, instead of creating a single

mima-filters/10.1.5.backwards.excludes

file to which everyone appends, you can now create a directory with the same name
containing multiple exclude files per change like that:

mima-filters/10.1.5.backwards.excludes/pr1234.excludes
mima-filters/10.1.5.backwards.excludes/pr5678.excludes

etc.

This will prevent the common merge conflicts when everyone tries to append
to the same file when in fact the ordering of entries is not interesting.
  • Loading branch information
jrudolph committed Sep 27, 2018
1 parent 6f4187b commit c7dcab7
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.typesafe.tools.mima
package plugin

import java.io.File

import com.typesafe.tools.mima.core._
import com.typesafe.tools.mima.core.util.log.Logging
import sbt.Keys.TaskStreams
Expand Down Expand Up @@ -119,32 +121,48 @@ object SbtMima {
val ExclusionPattern = """ProblemFilters\.exclude\[([^\]]+)\]\("([^"]+)"\)""".r

def findFiles(): Seq[(File, String)] = directory.listFiles().flatMap(f => fileExtension.findFirstIn(f.getName).map((f, _)))
def parseFile(file: File, extension: String): Either[Seq[Throwable], (String, Seq[ProblemFilter])] = {
val version = file.getName.dropRight(extension.size)

def parseLine(text: String, line: Int): Try[ProblemFilter] =
Try {
text match {
case ExclusionPattern(className, target) => ProblemFilters.exclude(className, target)
case x => throw new RuntimeException(s"Couldn't parse '$x'")
}
}.transform(Success(_), ex => Failure(new ParsingException(file, line, ex)))

val lines = try {
Source.fromFile(file).getLines().toVector
} catch {
case NonFatal(t) => throw new RuntimeException(s"Couldn't load '$file'", t)
def parseFile(fileOrDir: File, extension: String): Either[Seq[Throwable], (String, Seq[ProblemFilter])] = {
val version = fileOrDir.getName.dropRight(extension.size)

def parseOneFile(file: File): Either[Seq[Throwable],Seq[ProblemFilter]] = {
def parseLine(text: String, line: Int): Try[ProblemFilter] =
Try {
text match {
case ExclusionPattern(className, target) => ProblemFilters.exclude(className, target)
case x => throw new RuntimeException(s"Couldn't parse '$x'")
}
}.transform(Success(_), ex => Failure(new ParsingException(file, line, ex)))

val lines = try {
Source.fromFile(file).getLines().toVector
} catch {
case NonFatal(t) => throw new RuntimeException(s"Couldn't load '$file'", t)
}

val (excludes, failures) =
lines
.zipWithIndex
.filterNot { case (str, line) => str.trim.isEmpty || str.trim.startsWith("#") }
.map((parseLine _).tupled)
.partition(_.isSuccess)

if (failures.isEmpty) Right(excludes.map(_.get))
else Left(failures.map(_.failed.get))
}

val (excludes, failures) =
lines
.zipWithIndex
.filterNot { case (str, line) => str.trim.isEmpty || str.trim.startsWith("#") }
.map((parseLine _).tupled)
.partition(_.isSuccess)

if (failures.isEmpty) Right(version -> excludes.map(_.get))
else Left(failures.map(_.failed.get))
if (fileOrDir.isDirectory) {
val allResults =
fileOrDir.listFiles().filter(_.getName.endsWith(".excludes"))
.toSeq
.map(parseOneFile)
val (mappings, failures) = allResults.partition(_.isRight)
if (failures.nonEmpty) Left(failures.flatMap(_.left.get))
else {
val allMappings = mappings.flatMap(_.right.get)
Right(version -> allMappings)
}
} else
parseOneFile(fileOrDir).right.map(version -> _)
}

require(directory.exists(), s"Mima filter directory did not exist: ${directory.getAbsolutePath}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mimaPreviousArtifacts := Set(organization.value %% name.value % "0.0.1-SNAPSHOT")
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % System.getProperty("plugin.version"))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ProblemFilters.exclude[MissingMethodProblem]("A.foz")
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ProblemFilters.exclude[MissingMethodProblem]("A.baz")
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ProblemFilters.exclude[MissingMethodProblem]("A.bar")
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class A {
def foo = 1
def bar = foo
def baz = foo
def foz = foo
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class A {
def foo = 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
> set scalaSource in Compile := baseDirectory.value /"src" /"main" /"scala" /"v1"
> set version := s"0.0.1-SNAPSHOT"
> publishLocal

> set scalaSource in Compile := baseDirectory.value /"src" /"main" /"scala" /"v2"
> set version := s"0.0.2-SNAPSHOT"

# filters are read from file, so mima check should pass
> mimaReportBinaryIssues

# remove all filters so mima check fails
> set mimaBackwardIssueFilters := Map.empty
-> mimaReportBinaryIssues

0 comments on commit c7dcab7

Please sign in to comment.