diff --git a/util/env/src/main/scala/sbt/BasicEnvironment.scala b/util/env/src/main/scala/sbt/BasicEnvironment.scala deleted file mode 100644 index 363013597..000000000 --- a/util/env/src/main/scala/sbt/BasicEnvironment.scala +++ /dev/null @@ -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("") - /** 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) -} \ No newline at end of file diff --git a/util/env/src/main/scala/sbt/Environment.scala b/util/env/src/main/scala/sbt/Environment.scala deleted file mode 100644 index c6bf802e9..000000000 --- a/util/env/src/main/scala/sbt/Environment.scala +++ /dev/null @@ -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 - } -} diff --git a/util/env/src/main/scala/sbt/Format.scala b/util/env/src/main/scala/sbt/Format.scala deleted file mode 100644 index 949a48ba9..000000000 --- a/util/env/src/main/scala/sbt/Format.scala +++ /dev/null @@ -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) - }*/ -} \ No newline at end of file diff --git a/util/env/src/main/scala/sbt/LazyVar.scala b/util/env/src/main/scala/sbt/LazyVar.scala deleted file mode 100644 index c27a29c15..000000000 --- a/util/env/src/main/scala/sbt/LazyVar.scala +++ /dev/null @@ -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) } -} \ No newline at end of file diff --git a/util/env/src/main/scala/sbt/MapIO.scala b/util/env/src/main/scala/sbt/MapIO.scala deleted file mode 100644 index 9c25884bc..000000000 --- a/util/env/src/main/scala/sbt/MapIO.scala +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/util/env/src/main/scala/sbt/PropertyResolution.scala b/util/env/src/main/scala/sbt/PropertyResolution.scala deleted file mode 100644 index da086cf0d..000000000 --- a/util/env/src/main/scala/sbt/PropertyResolution.scala +++ /dev/null @@ -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) } -} \ No newline at end of file diff --git a/util/env/src/main/scala/sbt/Version.scala b/util/env/src/main/scala/sbt/Version.scala deleted file mode 100644 index fadc08524..000000000 --- a/util/env/src/main/scala/sbt/Version.scala +++ /dev/null @@ -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)) -} diff --git a/util/env/src/test/scala/EnvironmentSpecification.scala b/util/env/src/test/scala/EnvironmentSpecification.scala deleted file mode 100644 index 0468ee397..000000000 --- a/util/env/src/test/scala/EnvironmentSpecification.scala +++ /dev/null @@ -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 } -} \ No newline at end of file