mirror of https://github.com/sbt/sbt.git
Remove env subproject, which hasn't been built or published in many releases.
This commit is contained in:
parent
96f7a0dc3c
commit
c7ee375812
|
|
@ -1,219 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah, David MacIver
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import scala.reflect.Manifest
|
||||
import java.io.File
|
||||
import scala.collection.Map
|
||||
|
||||
trait BasicEnvironment extends Environment
|
||||
{
|
||||
protected def log: Logger
|
||||
/** The location of the properties file that backs the user-defined properties. */
|
||||
def envBackingPath: File
|
||||
/** The environment from which user-defined properties inherit (if enabled). */
|
||||
protected def parentEnvironment: Option[BasicEnvironment] = None
|
||||
/** The identifier used in messages to refer to this environment. */
|
||||
def environmentLabel = envBackingPath.getAbsolutePath
|
||||
|
||||
private[this] var isModified = false
|
||||
private[sbt] def setEnvironmentModified(modified: Boolean) { synchronized { isModified = modified } }
|
||||
private[this] def isEnvironmentModified = synchronized { isModified }
|
||||
|
||||
|
||||
implicit val IntFormat: Format[Int] = new SimpleFormat[Int] { def fromString(s: String) = java.lang.Integer.parseInt(s) }
|
||||
implicit val LongFormat: Format[Long] = new SimpleFormat[Long] { def fromString(s: String) = java.lang.Long.parseLong(s) }
|
||||
implicit val DoubleFormat: Format[Double] = new SimpleFormat[Double] { def fromString(s: String) = java.lang.Double.parseDouble(s) }
|
||||
implicit val BooleanFormat: Format[Boolean] = new SimpleFormat[Boolean] { def fromString(s: String) = java.lang.Boolean.valueOf(s).booleanValue }
|
||||
implicit val StringFormat: Format[String] = Format.string
|
||||
val NonEmptyStringFormat: Format[String] = new SimpleFormat[String]
|
||||
{
|
||||
def fromString(s: String) =
|
||||
{
|
||||
val trimmed = s.trim
|
||||
if(trimmed.isEmpty)
|
||||
error("The empty string is not allowed.")
|
||||
trimmed
|
||||
}
|
||||
}
|
||||
implicit val VersionFormat: Format[Version] =
|
||||
new SimpleFormat[Version]
|
||||
{
|
||||
def fromString(s: String) = Version.fromString(s).fold(msg => error(msg), x => x)
|
||||
}
|
||||
implicit val FileFormat = Format.file
|
||||
|
||||
|
||||
/** Implementation of 'Property' for user-defined properties. */
|
||||
private[sbt] class UserProperty[T](lazyDefaultValue: => Option[T], format: Format[T], inheritEnabled: Boolean,
|
||||
inheritFirst: Boolean, private[BasicEnvironment] val manifest: Manifest[T]) extends Property[T]
|
||||
{
|
||||
/** The name of this property is used for persistence in the properties file and as an identifier in messages.*/
|
||||
lazy val name = propertyMap.find( p => p._2 eq this ).map(_._1)
|
||||
/** Gets the name of this property or an alternative if the name is not available.*/
|
||||
private def nameString = name.getOrElse("<unnamed>")
|
||||
/** The lazily evaluated default value for this property.*/
|
||||
private lazy val defaultValue = lazyDefaultValue
|
||||
/** The explicitly set value for this property.*/
|
||||
private[BasicEnvironment] var explicitValue =
|
||||
{
|
||||
def initialValue = for(n <- name; stringValue <- initialValues.get(n)) yield format.fromString(stringValue)
|
||||
new LazyVar[Option[T]](initialValue) // ensure propertyMap is initialized before a read occurs
|
||||
}
|
||||
def update(v: T): Unit = synchronized { explicitValue() = Some(v); setEnvironmentModified(true) }
|
||||
def resolve: PropertyResolution[T] =
|
||||
synchronized
|
||||
{
|
||||
if(inheritFirst) resolveInheritFirst
|
||||
else resolveDefaultFirst
|
||||
}
|
||||
private def resolveInheritFirst =
|
||||
explicitValue() match
|
||||
{
|
||||
case Some(v) => DefinedValue(v, false, false)
|
||||
case None =>
|
||||
val inherited = inheritedValue
|
||||
// note that the following means the default value will not be used if an exception occurs inheriting
|
||||
inherited orElse getDefault(inherited)
|
||||
}
|
||||
private def resolveDefaultFirst =
|
||||
explicitValue() match
|
||||
{
|
||||
case Some(v) => DefinedValue(v, false, false)
|
||||
case None => getDefault(inheritedValue)
|
||||
}
|
||||
private def getDefault(orElse: => PropertyResolution[T]): PropertyResolution[T] =
|
||||
try
|
||||
{
|
||||
defaultValue match
|
||||
{
|
||||
case Some(v) => DefinedValue(v, false, true)
|
||||
case None => orElse
|
||||
}
|
||||
} catch { case e: Exception =>
|
||||
ResolutionException("Error while evaluating default value for property", Some(e))
|
||||
}
|
||||
|
||||
private def inheritedValue: PropertyResolution[T] =
|
||||
{
|
||||
val propOption = if(inheritEnabled) parentProperty else None
|
||||
propOption match
|
||||
{
|
||||
case Some(prop) => tryToInherit(prop)
|
||||
case None => UndefinedValue(nameString, environmentLabel)
|
||||
}
|
||||
}
|
||||
private def parentProperty = for(parent <- parentEnvironment; n <- name; prop <- parent.propertyMap.get(n)) yield prop
|
||||
|
||||
private def tryToInherit[R](prop: BasicEnvironment#UserProperty[R]): PropertyResolution[T] =
|
||||
{
|
||||
if(prop.manifest <:< manifest)
|
||||
markInherited(prop.resolve.asInstanceOf[PropertyResolution[T]])
|
||||
else
|
||||
ResolutionException("Could not inherit property '" + nameString + "' from '" + environmentLabel + "':\n" +
|
||||
"\t Property had type " + prop.manifest + ", expected type " + manifest, None)
|
||||
}
|
||||
private def markInherited(result: PropertyResolution[T]) =
|
||||
result match
|
||||
{
|
||||
case DefinedValue(v, isInherited, isDefault) => DefinedValue(v, true, isDefault)
|
||||
case x => x
|
||||
}
|
||||
|
||||
override def toString = nameString + "=" + resolve
|
||||
|
||||
/** Gets the explicitly set value converted to a 'String'.*/
|
||||
private[sbt] def getStringValue: Option[String] = explicitValue().map(format.toString)
|
||||
/** Explicitly sets the value for this property by converting the given string value.*/
|
||||
private[sbt] def setStringValue(s: String) { update(format.fromString(s)) }
|
||||
}
|
||||
/** Implementation of 'Property' for system properties (i.e. System.getProperty/setProperty) */
|
||||
private class SystemProperty[T](val name: String, lazyDefaultValue: => Option[T], val format: Format[T]) extends Property[T]
|
||||
{
|
||||
def resolve =
|
||||
{
|
||||
val rawValue = System.getProperty(name)
|
||||
if(rawValue == null)
|
||||
notFound
|
||||
else
|
||||
try
|
||||
DefinedValue(format.fromString(rawValue), false, false)
|
||||
catch {
|
||||
case e: Exception => ResolutionException("Error parsing system property '" + name + "': " + e.toString, Some(e))
|
||||
}
|
||||
}
|
||||
/** Handles resolution when the property has no explicit value. If there is a default value, that is returned,
|
||||
* otherwise, UndefinedValue is returned.*/
|
||||
private def notFound =
|
||||
{
|
||||
defaultValue match
|
||||
{
|
||||
case Some(dv) =>
|
||||
{
|
||||
log.debug("System property '" + name + "' does not exist, using provided default.")
|
||||
DefinedValue(dv, false, true)
|
||||
}
|
||||
case None => UndefinedValue(name, environmentLabel)
|
||||
}
|
||||
}
|
||||
protected lazy val defaultValue = lazyDefaultValue
|
||||
def update(t: T)
|
||||
{
|
||||
try System.setProperty(name, format.toString(t))
|
||||
catch {
|
||||
case e: Exception =>
|
||||
log.trace(e)
|
||||
log.warn("Error setting system property '" + name + "': " + e.toString)
|
||||
}
|
||||
}
|
||||
override def toString = name + "=" + resolve
|
||||
}
|
||||
|
||||
def system[T](propertyName: String)(implicit format: Format[T]): Property[T] =
|
||||
new SystemProperty[T](propertyName, None, format)
|
||||
def systemOptional[T](propertyName: String, defaultValue: => T)(implicit format: Format[T]): Property[T] =
|
||||
new SystemProperty[T](propertyName, Some(defaultValue), format)
|
||||
|
||||
def property[T](implicit manifest: Manifest[T], format: Format[T]): Property[T] =
|
||||
new UserProperty[T](None, format, true, false, manifest)
|
||||
def propertyLocal[T](implicit manifest: Manifest[T], format: Format[T]): Property[T] =
|
||||
new UserProperty[T](None, format, false, false, manifest)
|
||||
def propertyOptional[T](defaultValue: => T)(implicit manifest: Manifest[T], format: Format[T]): Property[T] =
|
||||
propertyOptional(defaultValue, false)(manifest, format)
|
||||
def propertyOptional[T](defaultValue: => T, inheritFirst: Boolean)(implicit manifest: Manifest[T], format: Format[T]): Property[T] =
|
||||
new UserProperty[T](Some(defaultValue), format, true, inheritFirst, manifest)
|
||||
|
||||
private type AnyUserProperty = UserProperty[_]
|
||||
/** Maps property name to property. The map is constructed by reflecting vals defined on this object,
|
||||
* so it should not be referenced during initialization or else subclass properties will be missed.**/
|
||||
private lazy val propertyMap: Map[String, AnyUserProperty] =
|
||||
{
|
||||
log.debug("Discovering properties")
|
||||
val propertyMap = new scala.collection.mutable.HashMap[String, AnyUserProperty]
|
||||
// AnyProperty is required because the return type of the property*[T] methods is Property[T]
|
||||
// and so the vals we are looking for have type Property[T] and not UserProperty[T]
|
||||
// We then only keep instances of UserProperty
|
||||
val vals = Environment.reflectiveMappings(this, classOf[Property[_]])
|
||||
for( (name, property: AnyUserProperty) <- vals)
|
||||
propertyMap(name) = property
|
||||
propertyMap //.readOnly (not currently in 2.8)
|
||||
}
|
||||
private val initialValues: Map[String, String] = MapIO.readStrings(environmentLabel, envBackingPath)
|
||||
|
||||
def propertyNames: Iterable[String] = propertyMap.keys.toList
|
||||
def getPropertyNamed(name: String): Option[UserProperty[_]] = propertyMap.get(name)
|
||||
def propertyNamed(name: String): UserProperty[_] = propertyMap(name)
|
||||
def saveEnvironment()
|
||||
{
|
||||
if(isEnvironmentModified)
|
||||
{
|
||||
val properties = new java.util.Properties
|
||||
for( (name, variable) <- propertyMap; stringValue <- variable.getStringValue)
|
||||
properties.setProperty(name, stringValue)
|
||||
IO.write(properties, "Project properties", envBackingPath)
|
||||
setEnvironmentModified(false)
|
||||
}
|
||||
}
|
||||
private[sbt] def uninitializedProperties: Iterable[(String, Property[_])] = propertyMap.filter(_._2.get.isEmpty)
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import scala.reflect.Manifest
|
||||
|
||||
trait Environment
|
||||
{
|
||||
abstract class Property[T]
|
||||
{
|
||||
/** Explicitly sets the value of this property to 'v'.*/
|
||||
def update(v: T): Unit
|
||||
/** Returns the current value of this property or throws an exception if the value could not be obtained.*/
|
||||
def value: T = resolve.value
|
||||
/** Returns the current value of this property in an 'Option'. 'None' is used to indicate that the
|
||||
* value could not obtained.*/
|
||||
def get: Option[T] = resolve.toOption
|
||||
/** Returns full information about this property's current value. */
|
||||
def resolve: PropertyResolution[T]
|
||||
|
||||
def foreach(f: T => Unit): Unit = resolve.foreach(f)
|
||||
}
|
||||
|
||||
/** Creates a system property with the given name and no default value.*/
|
||||
def system[T](propName: String)(implicit format: Format[T]): Property[T]
|
||||
/** Creates a system property with the given name and the given default value to use if no value is explicitly specified.*/
|
||||
def systemOptional[T](propName: String, defaultValue: => T)(implicit format: Format[T]): Property[T]
|
||||
/** Creates a user-defined property that has no default value. The property will try to inherit its value
|
||||
* from a parent environment (if one exists) if its value is not explicitly specified. An explicitly specified
|
||||
* value will persist between builds if the object returned by this method is assigned to a 'val' in this
|
||||
* 'Environment'.*/
|
||||
def property[T](implicit manifest: Manifest[T], format: Format[T]): Property[T]
|
||||
/** Creates a user-defined property that has no default value. The property will try to inherit its value
|
||||
* from a parent environment (if one exists) if its value is not explicitly specified. An explicitly specified
|
||||
* value will persist between builds if the object returned by this method is assigned to a 'val' in this
|
||||
* 'Environment'. The given 'format' is used to convert an instance of 'T' to and from the 'String' representation
|
||||
* used for persistence.*/
|
||||
def propertyF[T](format: Format[T])(implicit manifest: Manifest[T]): Property[T] = property(manifest, format)
|
||||
/** Creates a user-defined property with no default value and no value inheritance from a parent environment.
|
||||
* Its value will persist between builds if the returned object is assigned to a 'val' in this 'Environment'.*/
|
||||
def propertyLocal[T](implicit manifest: Manifest[T], format: Format[T]): Property[T]
|
||||
/** Creates a user-defined property with no default value and no value inheritance from a parent environment.
|
||||
* The property's value will persist between builds if the object returned by this method is assigned to a
|
||||
* 'val' in this 'Environment'. The given 'format' is used to convert an instance of 'T' to and from the
|
||||
* 'String' representation used for persistence.*/
|
||||
def propertyLocalF[T](format: Format[T])(implicit manifest: Manifest[T]): Property[T] = propertyLocal(manifest, format)
|
||||
/** Creates a user-defined property that uses the given default value if no value is explicitly specified for this property. The property's value will persist between builds
|
||||
* if the object returned by this method is assigned to a 'val' in this 'Environment'.*/
|
||||
def propertyOptional[T](defaultValue: => T)(implicit manifest: Manifest[T], format: Format[T]): Property[T]
|
||||
/** Creates a user-defined property with no value inheritance from a parent environment but with the given default
|
||||
* value if no value is explicitly specified for this property. The property's value will persist between builds
|
||||
* if the object returned by this method is assigned to a 'val' in this 'Environment'. The given 'format' is used
|
||||
* to convert an instance of 'T' to and from the 'String' representation used for persistence.*/
|
||||
def propertyOptionalF[T](defaultValue: => T, format: Format[T])(implicit manifest: Manifest[T]): Property[T] =
|
||||
propertyOptional(defaultValue)(manifest, format)
|
||||
}
|
||||
|
||||
private object Environment
|
||||
{
|
||||
def reflectiveMappings[T](obj: AnyRef, clazz: Class[T]): Map[String, T] =
|
||||
{
|
||||
var mappings = Map[String, T]()
|
||||
for ((name, value) <- ReflectUtilities.allValsC(obj, clazz))
|
||||
mappings = mappings.updated(ReflectUtilities.transformCamelCase(name, '.'), value)
|
||||
mappings
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah, David MacIver
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import scala.collection.mutable.{HashSet, Set}
|
||||
|
||||
trait Format[T]
|
||||
{
|
||||
def toString(t: T): String
|
||||
def fromString(s: String): T
|
||||
}
|
||||
abstract class SimpleFormat[T] extends Format[T]
|
||||
{
|
||||
def toString(t: T) = t.toString
|
||||
}
|
||||
object Format
|
||||
{
|
||||
implicit val file: Format[File] = new Format[File]
|
||||
{
|
||||
def toString(file: File) = file.getAbsolutePath
|
||||
def fromString(s: String) = (new File(s)).getAbsoluteFile
|
||||
}
|
||||
implicit val hash: Format[Array[Byte]] = new Format[Array[Byte]]
|
||||
{
|
||||
def toString(hash: Array[Byte]) = Hash.toHex(hash)
|
||||
def fromString(hash: String) = Hash.fromHex(hash)
|
||||
}
|
||||
def set[T](implicit format: Format[T]): Format[Set[T]] = new Format[Set[T]]
|
||||
{
|
||||
def toString(set: Set[T]) = set.toList.map(format.toString).mkString(File.pathSeparator)
|
||||
def fromString(s: String) = (new HashSet[T]) ++ IO.pathSplit(s).map(_.trim).filter(!_.isEmpty).map(format.fromString)
|
||||
}
|
||||
implicit val string: Format[String] = new SimpleFormat[String] { def fromString(s: String) = s }
|
||||
/*implicit val test: Format[Discovered] = new SimpleFormat[Discovered]
|
||||
{
|
||||
def fromString(s: String) = DiscoveredParser.parse(s).fold(error, x => x)
|
||||
}*/
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
private final class LazyVar[T](initialValue: => T) extends NotNull
|
||||
{
|
||||
private[this] var value: Option[T] = None
|
||||
def apply() =
|
||||
synchronized
|
||||
{
|
||||
value match
|
||||
{
|
||||
case Some(v) => v
|
||||
case None =>
|
||||
val newValue = initialValue
|
||||
value = Some(newValue)
|
||||
newValue
|
||||
}
|
||||
}
|
||||
def update(newValue: T) = synchronized { value = Some(newValue) }
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008, 2009 Mark Harrah
|
||||
*/
|
||||
|
||||
package sbt
|
||||
|
||||
import java.util.Properties
|
||||
import java.io.File
|
||||
import scala.collection.mutable.{HashMap, HashSet, Map, Set}
|
||||
|
||||
object MapIO
|
||||
{
|
||||
def write[Key, Value](map: Map[Key, Value], label: String, to: File)(implicit keyFormat: Format[Key], valueFormat: Format[Value])
|
||||
{
|
||||
val properties = new Properties
|
||||
map foreach { pair => properties.setProperty(keyFormat.toString(pair._1), valueFormat.toString(pair._2)) }
|
||||
IO.write(properties, label, to)
|
||||
}
|
||||
def read[Key, Value](map: Map[Key, Value], from: File)(implicit keyFormat: Format[Key], valueFormat: Format[Value])
|
||||
{
|
||||
map.clear
|
||||
val properties = new Properties
|
||||
IO.load(properties, from)
|
||||
|
||||
import collection.JavaConversions._
|
||||
for(n <- properties.propertyNames)
|
||||
{
|
||||
val name = n.toString // convert _ to String
|
||||
map.put( keyFormat.fromString(name), valueFormat.fromString(properties.getProperty(name)))
|
||||
}
|
||||
}
|
||||
def readStrings(label: String, envBackingPath: File): scala.collection.immutable.Map[String, String] =
|
||||
{
|
||||
val map = new HashMap[String, String]
|
||||
read(map, envBackingPath)
|
||||
map.toMap
|
||||
}
|
||||
def all[Key, Value](map: Map[Key, Set[Value]]): Iterable[Value] =
|
||||
map.values.toList.flatMap(set => set.toList)
|
||||
|
||||
def add[Key, Value](key: Key, value: Value, map: Map[Key, Set[Value]]): Unit =
|
||||
map.getOrElseUpdate(key, new HashSet[Value]) + value
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
sealed trait PropertyResolution[+T] extends NotNull
|
||||
{
|
||||
def value: T
|
||||
def orElse[R >: T](r: => PropertyResolution[R]): PropertyResolution[R]
|
||||
def toOption: Option[T]
|
||||
def foreach(f: T => Unit): Unit
|
||||
def map[R](f: T => R): PropertyResolution[R]
|
||||
def flatMap[R](f: T => PropertyResolution[R]): PropertyResolution[R]
|
||||
}
|
||||
sealed trait NoPropertyValue extends PropertyResolution[Nothing]
|
||||
{ self: RuntimeException with PropertyResolution[Nothing] =>
|
||||
|
||||
def value = throw this
|
||||
def toOption = None
|
||||
def map[R](f: Nothing => R): PropertyResolution[R] = this
|
||||
def flatMap[R](f: Nothing => PropertyResolution[R]): PropertyResolution[R] = this
|
||||
def foreach(f: Nothing => Unit) {}
|
||||
}
|
||||
final case class ResolutionException(message: String, exception: Option[Throwable])
|
||||
extends RuntimeException(message, exception.getOrElse(null)) with NoPropertyValue
|
||||
{
|
||||
def orElse[R](r: => PropertyResolution[R]) = this
|
||||
}
|
||||
final case class UndefinedValue(name: String, environmentLabel: String)
|
||||
extends RuntimeException("Value for property '" + name + "' from " + environmentLabel + " is undefined.") with NoPropertyValue
|
||||
{
|
||||
def orElse[R](r: => PropertyResolution[R]) =
|
||||
r match
|
||||
{
|
||||
case u: UndefinedValue => this
|
||||
case _ => r
|
||||
}
|
||||
}
|
||||
final case class DefinedValue[T](value: T, isInherited: Boolean, isDefault: Boolean) extends PropertyResolution[T]
|
||||
{
|
||||
def toOption = Some(value)
|
||||
def orElse[R >: T](r: => PropertyResolution[R]) = this
|
||||
def map[R](f: T => R) = DefinedValue[R](f(value), isInherited, isDefault)
|
||||
def flatMap[R](f: T => PropertyResolution[R]) = f(value)
|
||||
def foreach(f: T => Unit) { f(value) }
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
sealed trait Version
|
||||
case class BasicVersion(major: Int, minor: Option[Int], micro: Option[Int], extra: Option[String]) extends Version
|
||||
{
|
||||
import Version._
|
||||
require(major >= 0, "Major revision must be nonnegative.")
|
||||
require(minor.isDefined || micro.isEmpty, "Cannot define micro revision without defining minor revision.")
|
||||
requirePositive(minor)
|
||||
requirePositive(micro)
|
||||
require(isValidExtra(extra))
|
||||
|
||||
def incrementMicro = BasicVersion(major, minor orElse Some(0), increment(micro), extra)
|
||||
def incrementMinor = BasicVersion(major, increment(minor), micro, extra)
|
||||
def incrementMajor = BasicVersion(major+1, minor, micro, extra)
|
||||
def withExtra(newExtra: Option[String]) = BasicVersion(major, minor, micro, newExtra)
|
||||
|
||||
override def toString = major +
|
||||
minor.map(minorI => "." + minorI + micro.map(microI => "." + microI).getOrElse("")).getOrElse("") +
|
||||
extra.map(x => "-" + x).getOrElse("")
|
||||
}
|
||||
case class OpaqueVersion(value: String) extends Version
|
||||
{
|
||||
require(!value.trim.isEmpty)
|
||||
override def toString = value
|
||||
}
|
||||
object Version
|
||||
{
|
||||
private[sbt] def increment(i: Option[Int]) = Some(i.getOrElse(0) + 1)
|
||||
private[sbt] def requirePositive(i: Option[Int]) { i.foreach(x => require(x >= 0)) }
|
||||
|
||||
import java.util.regex.Pattern
|
||||
val versionPattern = Pattern.compile("""(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:-(.+))?""")
|
||||
def fromString(v: String): Either[String, Version] =
|
||||
{
|
||||
val trimmed = v.trim
|
||||
if(trimmed.isEmpty)
|
||||
Left("Version cannot be empty.")
|
||||
else
|
||||
{
|
||||
val matcher = versionPattern.matcher(trimmed)
|
||||
import matcher._
|
||||
if(matches)
|
||||
{
|
||||
def toOption(index: Int) =
|
||||
{
|
||||
val v = group(index)
|
||||
if(v == null) None else Some(v)
|
||||
}
|
||||
def toInt(index: Int) = toOption(index).map(_.toInt)
|
||||
val extra = toOption(4)
|
||||
if(isValidExtra(extra))
|
||||
Right(BasicVersion(group(1).toInt, toInt(2), toInt(3), extra))
|
||||
else
|
||||
Right(OpaqueVersion(trimmed))
|
||||
}
|
||||
else
|
||||
Right(OpaqueVersion(trimmed))
|
||||
}
|
||||
}
|
||||
def isValidExtra(e: Option[String]): Boolean = e.map(isValidExtra).getOrElse(true)
|
||||
def isValidExtra(s: String): Boolean = !(s.trim.isEmpty || s.exists(java.lang.Character.isISOControl))
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import org.scalacheck._
|
||||
|
||||
object EnvironmentSpecification extends Properties("Environment")
|
||||
{ s =>
|
||||
private[this] type Env = BasicEnvironment { def x: Property[Int] }
|
||||
|
||||
val log = new ConsoleLogger
|
||||
|
||||
specify("Non-optional user property assignment", testAssign _)
|
||||
specify("Optional user property assignment", testDefaultAssign _)
|
||||
specify("Optional user property default and assignment", testDefault _)
|
||||
specify("Optional user property default and then assignment", testDefaultThenAssign _)
|
||||
specify("Uninitialized empty when all properties are initialized", testUninitializedEmpty _)
|
||||
specify("Uninitialized empty when all properties have defaults", testDefaultUninitializedEmpty _)
|
||||
specify("Property defaulting to another property ok", propertyDefaultsToProperty _)
|
||||
specify("Project-style name+organization", (name: String) => projectEmulation(name.trim))
|
||||
|
||||
private def projectEmulation(testName: String) =
|
||||
{
|
||||
import Prop._
|
||||
(!testName.isEmpty) ==>
|
||||
withBacking { backing =>
|
||||
def env = new DefaultEnv(backing) {
|
||||
final def name: String = projectName.value
|
||||
final val projectName = propertyLocalF[String](NonEmptyStringFormat)
|
||||
final val projectOrganization = propertyOptional[String](name, true)
|
||||
}
|
||||
val first = env
|
||||
first.projectName() = testName
|
||||
first.saveEnvironment
|
||||
val second = env
|
||||
env.projectOrganization.value == testName
|
||||
}
|
||||
}
|
||||
private def propertyDefaultsToProperty(value: Int) =
|
||||
{
|
||||
withBacking { backing =>
|
||||
val env = new DefaultEnv(backing) {
|
||||
val base = propertyOptional[Int](value)
|
||||
val chained = propertyOptional[Int](base.value)
|
||||
}
|
||||
env.chained.value == value
|
||||
}
|
||||
}
|
||||
private def testAssign(value: Int) =
|
||||
{
|
||||
withEnvironment { env =>
|
||||
env.x() = value
|
||||
env.x.value == value
|
||||
}
|
||||
}
|
||||
private def testDefaultAssign(value: Int, default: Int) =
|
||||
{
|
||||
withDefaultEnvironment(default) { env =>
|
||||
env.x() = value
|
||||
env.x.value == value
|
||||
}
|
||||
}
|
||||
private def testDefault(value: Int, default: Int) =
|
||||
{
|
||||
withDefaultEnvironment(default) { env =>
|
||||
env.x.value == default
|
||||
}
|
||||
}
|
||||
private def testDefaultThenAssign(value: Int, default: Int) =
|
||||
{
|
||||
withDefaultEnvironment(default) { env =>
|
||||
env.x.value == default &&
|
||||
{
|
||||
env.x() = value
|
||||
env.x.value == value
|
||||
}
|
||||
}
|
||||
}
|
||||
private def testUninitializedEmpty(value: Int) =
|
||||
{
|
||||
withEnvironment { env =>
|
||||
env.x() = value
|
||||
env.uninitializedProperties.isEmpty
|
||||
}
|
||||
}
|
||||
private def testDefaultUninitializedEmpty(default: Int) = withDefaultEnvironment(default)(_.uninitializedProperties.isEmpty)
|
||||
|
||||
private def defaultEnvironment(default: Int)(backing: Path) = new DefaultEnv(backing) { val x = propertyOptional[Int](default) }
|
||||
private def environment(backing: Path) = new DefaultEnv(backing) { val x = property[Int] }
|
||||
|
||||
private def withBacking[T](f: Path => T): T = Control.getOrError( FileUtilities.withTemporaryFile(log, "env", "")(file => Right(f(Path.fromFile(file))) ) )
|
||||
private def withEnvironment[T](f: Env => T): T = withEnvironmentImpl(environment)(f)
|
||||
private def withDefaultEnvironment[T](default: Int)(f: Env => T): T = withEnvironmentImpl(defaultEnvironment(default))(f)
|
||||
private def withEnvironmentImpl[T](env: Path => Env)(f: Env => T): T = withBacking(f compose env)
|
||||
|
||||
private class DefaultEnv(val envBackingPath: Path) extends BasicEnvironment { def log = s.log }
|
||||
}
|
||||
Loading…
Reference in New Issue