Remove env subproject, which hasn't been built or published in many releases.

This commit is contained in:
Mark Harrah 2013-06-05 12:47:27 -04:00
parent 96f7a0dc3c
commit c7ee375812
8 changed files with 0 additions and 602 deletions

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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)
}*/
}

View File

@ -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) }
}

View File

@ -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
}

View File

@ -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) }
}

View File

@ -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))
}

View File

@ -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 }
}