Right precedence of sbt.boot.properties lookup, handle qualifier correctly. Fixes #651.

This commit is contained in:
Mark Harrah 2013-01-23 12:48:54 -05:00
parent b0fe85490c
commit 824000009d
2 changed files with 79 additions and 5 deletions

View File

@ -84,19 +84,24 @@ object Configuration
}
def versionParts(version: String): List[String] =
{
val pattern = Pattern.compile("""(\d+)\.(\d+)\.(\d+)(-.*)?""")
val pattern = Pattern.compile("""(\d+)(\.\d+)(\.\d+)(-.*)?""")
val m = pattern.matcher(version)
if(m.matches())
subPartsIndices map {_.map(m.group).filter(neNull).mkString(".") }
subPartsIndices flatMap { is => fullMatchOnly(is.map(m.group)) }
else
DefaultVersionPart :: fallbackParts
noMatchParts
}
def noMatchParts: List[String] = DefaultVersionPart :: fallbackParts
private[this] def fullMatchOnly(groups: List[String]): Option[String] =
if(groups.forall(neNull)) Some(groups.mkString) else None
private[this] def subPartsIndices =
(1 :: 2 :: Nil) ::
(1 :: 2 :: 3 :: Nil) ::
(1 :: 2 :: 3 :: 4 :: Nil) ::
(1 :: 2 :: 3 :: Nil) ::
(1 :: 2 :: Nil) ::
(Nil) ::
Nil
// the location of project/build.properties and the name of the property within that file
// that configures the sbt version is configured in sbt.boot.properties.
// We have to hard code them here in order to use them to determine the location of sbt.boot.properties itself

View File

@ -0,0 +1,69 @@
package xsbt.boot
import org.scalacheck._
import Prop._
object VersionParts extends Properties("VersionParts")
{
property("Valid version, no qualifier") = Prop.forAll { (x0: Int, y0: Int, z0: Int) =>
val (x,y,z) = (norm(x0), norm(y0), norm(z0))
val str = s"$x.$y.$z"
val expected =
s"$x.$y.$z" ::
s"$x.$y" ::
"" ::
Nil
check(str, expected)
}
property("Valid version with qualifier") = Prop.forAll { (x0: Int, y0: Int, z0: Int, q0: String) =>
val (x,y,z,q) = (norm(x0), norm(y0), norm(z0), normS(q0))
val str = s"$x.$y.$z-$q"
val expected =
s"$x.$y.$z-$q" ::
s"$x.$y.$z" ::
s"$x.$y" ::
"" ::
Nil
check(str, expected)
}
property("Invalid version") = Prop.forAll { (x0: Int, y0: Int, z0: Int, q0: String) =>
val (x,y,z,q) = (norm(x0), norm(y0), norm(z0), normS(q0))
val strings =
x.toString ::
s"$x.$y" ::
s"$x.$y-$q" ::
s"$x.$y.$z.$q" ::
Nil
all(strings.map(str => check(str, Configuration.noMatchParts)) : _*)
}
private[this] def check(versionString: String, expectedParts: List[String]) =
{
def printParts(s: List[String]): String = s.map("'" + _ + "'").mkString("(", ", ", ")")
val actual = Configuration.versionParts(versionString)
s"Version string '$versionString'" |:
s"Expected '${printParts(expectedParts)}'" |:
s"Actual'${printParts(actual)}'" |:
(actual == expectedParts)
}
// Make `i` non-negative
private[this] def norm(i: Int): Int =
if(i == Int.MinValue) Int.MaxValue else math.abs(i)
// Make `s` non-empty and suitable for java.util.regex input
private[this] def normS(s: String): String =
{
val filtered = s filter validChar
if(s.isEmpty) "q" else s
}
// strip whitespace and characters not supported by Pattern
private[this] def validChar(c: Char) =
!java.lang.Character.isWhitespace(c) &&
!java.lang.Character.isISOControl(c) &&
!Character.isHighSurrogate(c) &&
!Character.isLowSurrogate(c)
}