diff --git a/main/Build.scala b/main/Build.scala
index 5374eebf6..0ac1d0377 100644
--- a/main/Build.scala
+++ b/main/Build.scala
@@ -220,17 +220,17 @@ object BuildPaths
def defaultStaging = Path.userHome / ConfigDirectoryName / "staging"
def defaultGlobalPlugins = Path.userHome / ConfigDirectoryName / PluginsDirectoryName
- def definitionSources(base: File): Seq[File] = (base * "*.scala").getFiles
- def configurationSources(base: File): Seq[File] = (base * "*.sbt").getFiles
- def pluginDirectory(definitionBase: Path) = definitionBase / PluginsDirectoryName
+ def definitionSources(base: File): Seq[File] = (base * "*.scala").get
+ def configurationSources(base: File): Seq[File] = (base * "*.sbt").get
+ def pluginDirectory(definitionBase: File) = definitionBase / PluginsDirectoryName
- def evalOutputDirectory(base: Path) = outputDirectory(base) / "config-classes"
- def outputDirectory(base: Path) = base / DefaultTargetName
- def buildOutputDirectory(base: Path, compilers: Compilers) = crossPath(outputDirectory(base), compilers.scalac.scalaInstance)
+ def evalOutputDirectory(base: File) = outputDirectory(base) / "config-classes"
+ def outputDirectory(base: File) = base / DefaultTargetName
+ def buildOutputDirectory(base: File, compilers: Compilers) = crossPath(outputDirectory(base), compilers.scalac.scalaInstance)
- def projectStandard(base: Path) = base / "project"
- def projectHidden(base: Path) = base / ConfigDirectoryName
- def selectProjectDir(base: Path) =
+ def projectStandard(base: File) = base / "project"
+ def projectHidden(base: File) = base / ConfigDirectoryName
+ def selectProjectDir(base: File) =
{
val a = projectHidden(base)
val b = projectStandard(base)
diff --git a/main/Defaults.scala b/main/Defaults.scala
index 1f884ddf0..371d6f46e 100644
--- a/main/Defaults.scala
+++ b/main/Defaults.scala
@@ -124,7 +124,7 @@ object Defaults extends BuildCommon
)
def addBaseSources = Seq(
unmanagedSources <<= (unmanagedSources, baseDirectory, sourceFilter, defaultExcludes in unmanagedSources) map {
- (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles
+ (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).get
}
)
@@ -206,7 +206,7 @@ object Defaults extends BuildCommon
}
}
def unmanagedResourcesTask(dirs: Seq[File], excl: FileFilter) =
- dirs.descendentsExcept("*",excl).getFiles
+ dirs.descendentsExcept("*",excl).get
lazy val testTasks = testTaskOptions(test) ++ testTaskOptions(testOnly) ++ Seq(
testLoader <<= (fullClasspath, scalaInstance) map { (cp, si) => TestFramework.createTestLoader(data(cp), si) },
@@ -294,7 +294,7 @@ object Defaults extends BuildCommon
}
def collectFiles(dirs: ScopedTaskable[Seq[File]], filter: ScopedTaskable[FileFilter], excludes: ScopedTaskable[FileFilter]): Initialize[Task[Seq[File]]] =
- (dirs, filter, excludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles }
+ (dirs, filter, excludes) map { (d,f,excl) => d.descendentsExcept(f,excl).get }
def artifactPathSetting(art: ScopedSetting[Artifact]) = (crossTarget, projectID, art, scalaVersion, artifactName) { (t, module, a, sv, toString) => t / toString(sv, module, a) asFile }
@@ -500,7 +500,7 @@ object Classpaths
classpathConfiguration <<= (internalConfigurationMap, configuration)( _ apply _ ),
managedClasspath <<= (classpathConfiguration, classpathTypes, update) map managedJars,
unmanagedJars <<= (configuration, unmanagedBase, classpathFilter, defaultExcludes in unmanagedJars) map { (config, base, filter, excl) =>
- (base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).getFiles
+ (base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).get
}
)
def defaultPackageKeys = Seq(packageBin, packageSrc, packageDoc)
@@ -665,7 +665,7 @@ object Classpaths
def publishConfig(artifacts: Map[Artifact, File], ivyFile: Option[File], resolverName: String = "local", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) =
new PublishConfiguration(ivyFile, resolverName, artifacts, logging)
- def deliverPattern(outputPath: Path): String = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath
+ def deliverPattern(outputPath: File): String = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath
def projectDependenciesTask =
(thisProject, settings) map { (p, data) =>
diff --git a/main/Structure.scala b/main/Structure.scala
index 8db71906a..eb1f49081 100644
--- a/main/Structure.scala
+++ b/main/Structure.scala
@@ -261,7 +261,7 @@ object Scoped
def **(filter: FileFilter): Initialize[Seq[File]] = map0 { _ ** filter }
protected[this] def map0(f: PathFinder => PathFinder): Initialize[Seq[File]]
protected[this] def finder(f: PathFinder => PathFinder): Seq[File] => Seq[File] =
- in => f(in).getFiles
+ in => f(in).get
}
/*
diff --git a/main/Watched.scala b/main/Watched.scala
index 4027bc866..e3570eafe 100644
--- a/main/Watched.scala
+++ b/main/Watched.scala
@@ -36,7 +36,7 @@ object Watched
def executeContinuously(watched: Watched, s: State, next: String, repeat: String): State =
{
@tailrec def shouldTerminate: Boolean = (System.in.available > 0) && (watched.terminateWatch(System.in.read()) || shouldTerminate)
- val sourcesFinder = Path.finder { watched watchPaths s }
+ val sourcesFinder = PathFinder { watched watchPaths s }
val watchState = s get ContinuousState getOrElse WatchState.empty
if(watchState.count > 0)
diff --git a/main/actions/Doc.scala b/main/actions/Doc.scala
index cfd100125..e804ae60f 100644
--- a/main/actions/Doc.scala
+++ b/main/actions/Doc.scala
@@ -49,6 +49,6 @@ final class Scaladoc(maximumErrors: Int, compiler: AnalyzingCompiler)
}
}
- cachedDoc(inputs)(() => exists(outputDirectory.***.get))
+ cachedDoc(inputs)(() => exists(outputDirectory.***.get.toSet))
}
}
diff --git a/scripted/base/FileCommands.scala b/scripted/base/FileCommands.scala
index 00f5b4796..6c9ca1c68 100644
--- a/scripted/base/FileCommands.scala
+++ b/scripted/base/FileCommands.scala
@@ -33,7 +33,7 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler
def scriptError(message: String): Some[String] = error("Test script error: " + message)
def spaced[T](l: Seq[T]) = l.mkString(" ")
def fromStrings(paths: List[String]) = paths.map(fromString)
- def fromString(path: String) = Path.fromString(baseDirectory, path)
+ def fromString(path: String) = new File(baseDirectory, path)
def touch(paths: List[String]) = IO.touch(fromStrings(paths))
def delete(paths: List[String]): Unit = IO.delete(fromStrings(paths))
/*def sync(from: String, to: String) =
diff --git a/scripted/plugin/ScriptedPlugin.scala b/scripted/plugin/ScriptedPlugin.scala
index b83e8c7dd..e3b4c7918 100644
--- a/scripted/plugin/ScriptedPlugin.scala
+++ b/scripted/plugin/ScriptedPlugin.scala
@@ -52,7 +52,7 @@ object ScriptedPlugin extends Plugin {
sbtLauncher <<= (appConfiguration)(app => IO.classLocationFile(app.provider.scalaProvider.launcher.getClass)),
sbtTestDirectory <<= sourceDirectory / "sbt-test",
scriptedBufferLog := true,
- scriptedClasspath <<= (classpathTypes, update) map { (ct, report) => Path.finder(Classpaths.managedJars(scriptedConf, ct, report).map(_.data)) },
+ scriptedClasspath <<= (classpathTypes, update) map { (ct, report) => PathFinder(Classpaths.managedJars(scriptedConf, ct, report).map(_.data)) },
scriptedTests <<= scriptedTestsTask,
scriptedRun <<= scriptedRunTask,
scriptedDependencies <<= (compile in Test, publishLocal) map { (analysis, pub) => Unit },
diff --git a/util/classfile/Analyze.scala b/util/classfile/Analyze.scala
index f44b7f817..91f131376 100644
--- a/util/classfile/Analyze.scala
+++ b/util/classfile/Analyze.scala
@@ -13,10 +13,10 @@ import java.lang.reflect.Modifier.{STATIC, PUBLIC, ABSTRACT}
private[sbt] object Analyze
{
- def apply[T](outputDirectory: Path, sources: Seq[File], log: Logger)(analysis: xsbti.AnalysisCallback, loader: ClassLoader, readAPI: (File,Seq[Class[_]]) => Unit)(compile: => Unit)
+ def apply[T](outputDirectory: File, sources: Seq[File], log: Logger)(analysis: xsbti.AnalysisCallback, loader: ClassLoader, readAPI: (File,Seq[Class[_]]) => Unit)(compile: => Unit)
{
val sourceMap = sources.groupBy(_.getName)
- val classesFinder = outputDirectory ** GlobFilter("*.class")
+ val classesFinder = PathFinder(outputDirectory) ** "*.class"
val existingClasses = classesFinder.get
def load(tpe: String, errMsg: => Option[String]): Option[Class[_]] =
@@ -26,23 +26,22 @@ private[sbt] object Analyze
// runs after compilation
def analyze()
{
- val allClasses = Set(classesFinder.get.toSeq : _*)
+ val allClasses = Set(classesFinder.get: _*)
val newClasses = allClasses -- existingClasses
- val productToSource = new mutable.HashMap[Path, Path]
- val sourceToClassFiles = new mutable.HashMap[Path, Buffer[ClassFile]]
+ val productToSource = new mutable.HashMap[File, File]
+ val sourceToClassFiles = new mutable.HashMap[File, Buffer[ClassFile]]
// parse class files and assign classes to sources. This must be done before dependencies, since the information comes
// as class->class dependencies that must be mapped back to source->class dependencies using the source+class assignment
for(newClass <- newClasses;
- path <- Path.relativize(outputDirectory, newClass);
- classFile = Parser(newClass.asFile);
- sourceFile <- classFile.sourceFile orElse guessSourceName(newClass.asFile.getName);
+ classFile = Parser(newClass);
+ sourceFile <- classFile.sourceFile orElse guessSourceName(newClass.getName);
source <- guessSourcePath(sourceMap, classFile, log))
{
analysis.beginSource(source)
- analysis.generatedClass(source, path)
- productToSource(path) = source
+ analysis.generatedClass(source, newClass)
+ productToSource(newClass) = source
sourceToClassFiles.getOrElseUpdate(source, new ArrayBuffer[ClassFile]) += classFile
}
@@ -61,10 +60,9 @@ private[sbt] object Analyze
{
val resolved = resolveClassFile(file, tpe)
assume(resolved.exists, "Resolved class file " + resolved + " from " + source + " did not exist")
- val resolvedPath = Path.fromFile(resolved)
- if(Path.fromFile(file) == outputDirectory)
+ if(file == outputDirectory)
{
- productToSource.get(resolvedPath) match
+ productToSource.get(resolved) match
{
case Some(dependsOn) => analysis.sourceDependency(dependsOn, source)
case None => analysis.binaryDependency(resolved, clazz.getName, source)
@@ -80,7 +78,7 @@ private[sbt] object Analyze
}
classFiles.flatMap(_.types).foreach(processDependency)
- readAPI(source asFile, classFiles.toSeq.flatMap(c => load(c.className, Some("Error reading API from class file") )))
+ readAPI(source, classFiles.toSeq.flatMap(c => load(c.className, Some("Error reading API from class file") )))
analysis.endSource(source)
}
}
diff --git a/util/classpath/ClasspathUtilities.scala b/util/classpath/ClasspathUtilities.scala
index 9c6e940f4..d94fb19e0 100644
--- a/util/classpath/ClasspathUtilities.scala
+++ b/util/classpath/ClasspathUtilities.scala
@@ -54,17 +54,15 @@ object ClasspathUtilities
private[sbt] def printSource(c: Class[_]) =
println(c.getName + " loader=" +c.getClassLoader + " location=" + IO.classLocationFile(c))
- def isArchive(path: Path): Boolean = isArchive(path.asFile)
def isArchive(file: File): Boolean = isArchiveName(file.getName)
def isArchiveName(fileName: String) = fileName.endsWith(".jar") || fileName.endsWith(".zip")
// Partitions the given classpath into (jars, directories)
private[sbt] def separate(paths: Iterable[File]): (Iterable[File], Iterable[File]) = paths.partition(isArchive)
// Partitions the given classpath into (jars, directories)
- private[sbt] def separatePaths(paths: Iterable[Path]) = separate(paths.map(_.asFile.getCanonicalFile))
- private[sbt] def buildSearchPaths(classpath: Iterable[Path]): (collection.Set[File], collection.Set[File]) =
+ private[sbt] def buildSearchPaths(classpath: Iterable[File]): (collection.Set[File], collection.Set[File]) =
{
- val (jars, dirs) = separatePaths(classpath)
- (linkedSet(jars ++ extraJars.toList), linkedSet(dirs ++ extraDirs.toList))
+ val (jars, dirs) = separate(classpath)
+ (linkedSet(jars ++ extraJars), linkedSet(dirs ++ extraDirs))
}
private[sbt] def onClasspath(classpathJars: collection.Set[File], classpathDirectories: collection.Set[File], file: File): Boolean =
{
@@ -76,10 +74,10 @@ object ClasspathUtilities
}
/** Returns all entries in 'classpath' that correspond to a compiler plugin.*/
- private[sbt] def compilerPlugins(classpath: Iterable[Path]): Iterable[File] =
+ private[sbt] def compilerPlugins(classpath: Seq[File]): Iterable[File] =
{
import collection.JavaConversions._
- val loader = new URLClassLoader(Path.getURLs(classpath))
+ val loader = new URLClassLoader(Path.toURLs(classpath))
loader.getResources("scalac-plugin.xml").toList.flatMap(asFile(true))
}
/** Converts the given URL to a File. If the URL is for an entry in a jar, the File for the jar is returned. */
diff --git a/util/datatype/Generator.scala b/util/datatype/Generator.scala
index 5b573c9e5..3177b7f57 100644
--- a/util/datatype/Generator.scala
+++ b/util/datatype/Generator.scala
@@ -26,8 +26,7 @@ abstract class GeneratorBase(val basePkgName: String, val baseDirectory: File) e
def writeSource(name: String, pkgName: String, content: String)
{
- import Path._
- val file = Path.fromString(baseDirectory, packagePath(pkgName)) / (name+ ".java")
+ val file = new File(new File(baseDirectory, packagePath(pkgName)), name+ ".java")
file.getParentFile.mkdirs()
write(file, "package " + pkgName + ";\n\n" + content)
}
diff --git a/util/env/BasicEnvironment.scala b/util/env/BasicEnvironment.scala
index 7cab4d8d2..363013597 100644
--- a/util/env/BasicEnvironment.scala
+++ b/util/env/BasicEnvironment.scala
@@ -4,17 +4,18 @@
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: Path
+ 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.absolutePath
+ def environmentLabel = envBackingPath.getAbsolutePath
private[this] var isModified = false
private[sbt] def setEnvironmentModified(modified: Boolean) { synchronized { isModified = modified } }
diff --git a/util/env/Format.scala b/util/env/Format.scala
index 0b733bddf..949a48ba9 100644
--- a/util/env/Format.scala
+++ b/util/env/Format.scala
@@ -17,11 +17,6 @@ abstract class SimpleFormat[T] extends Format[T]
}
object Format
{
- def path(basePath: Path): Format[Path] = new Format[Path]
- {
- def toString(path: Path) = Path.relativize(basePath.asFile, path.asFile).getOrElse(error("Path " + path + " not in " + basePath))
- def fromString(s: String) = Path.fromString(basePath, s)
- }
implicit val file: Format[File] = new Format[File]
{
def toString(file: File) = file.getAbsolutePath
diff --git a/util/io/IO.scala b/util/io/IO.scala
index 724ecefdf..024de0375 100644
--- a/util/io/IO.scala
+++ b/util/io/IO.scala
@@ -308,7 +308,6 @@ object IO
}
private def writeZip(sources: Seq[(File,String)], output: ZipOutputStream)(createEntry: String => ZipEntry)
{
- import Path.{lazyPathFinder => pf}
val files = sources.flatMap { case (file,name) => if (file.isFile) (file, normalizeName(name)) :: Nil else Nil }
val now = System.currentTimeMillis
@@ -443,7 +442,7 @@ object IO
to
}
def copyDirectory(source: File, target: File, overwrite: Boolean = false, preserveLastModified: Boolean = false): Unit =
- copy( (Path.fromFile(source) ***) x Path.rebase(source, target), overwrite, preserveLastModified)
+ copy( (PathFinder(source) ***) x Path.rebase(source, target), overwrite, preserveLastModified)
def copyFile(sourceFile: File, targetFile: File, preserveLastModified: Boolean = false)
{
diff --git a/util/io/NameFilter.scala b/util/io/NameFilter.scala
index 7ea8dff98..ef78a6652 100644
--- a/util/io/NameFilter.scala
+++ b/util/io/NameFilter.scala
@@ -62,9 +62,13 @@ object NameFilter
def accept(name: String) = f(name)
}
}
+object FileFilter
+{
+ implicit def globFilter(s: String): NameFilter = GlobFilter(s)
+}
object GlobFilter
{
- implicit def apply(expression: String): NameFilter =
+ def apply(expression: String): NameFilter =
{
require(!expression.exists(java.lang.Character.isISOControl), "Control characters not allowed in filter expression.")
if(expression == "*")
diff --git a/util/io/Pack.scala b/util/io/Pack.scala
index afa01718b..501029d4a 100644
--- a/util/io/Pack.scala
+++ b/util/io/Pack.scala
@@ -44,7 +44,7 @@ object SignJar
override def toString = toList.mkString(" ")
}
def keyStore(url: URL) = new SignOption("-keystore" :: url.toExternalForm :: Nil, true)
- def signedJar(p: Path) = new SignOption("-signedjar" :: p.asFile.getAbsolutePath :: Nil, true)
+ def signedJar(p: File) = new SignOption("-signedjar" :: p.getAbsolutePath :: Nil, true)
def verbose = new SignOption("-verbose" :: Nil, false)
def sigFile(name: String) = new SignOption("-sigfile" :: name :: Nil, true)
def storeType(t: String) = new SignOption("-storetype" :: t :: Nil, false)
diff --git a/util/io/Path.scala b/util/io/Path.scala
index ec8c10037..11d708f83 100644
--- a/util/io/Path.scala
+++ b/util/io/Path.scala
@@ -7,54 +7,26 @@ import Path._
import IO.{pathSplit, wrapNull}
import java.io.File
import java.net.URL
-import scala.collection.{generic, immutable, mutable, TraversableLike}
+import scala.collection.{generic, immutable, mutable}
-/** A Path represents a file in a project.
-* @see sbt.PathFinder*/
-sealed abstract class Path extends PathFinder
+final class RichFile(val asFile: File)
{
- /** Creates a base directory for this path. This is used by copy and zip functions
- * to determine the relative path that should be used in the destination. For example,
- * if the following path is specified to be copied to directory 'd',
- *
- * ((a / b) ###) / x / y
- *
- * the copied path would be
- *
- * d / x / y
- *
- * The relativePath method is used to return the relative path to the base directory. */
- override def ### : Path = new BaseDirectory(this)
- private[sbt] def addTo(pathSet: mutable.Set[Path])
- {
- if(asFile.exists)
- pathSet += this
- }
- override def / (component: String): Path = if(component == ".") this else new RelativePath(this, component)
- /** True if and only if the file represented by this path exists.*/
+ def / (component: String): File = if(component == ".") asFile else new File(asFile, component)
+ /** True if and only if the wrapped file exists.*/
def exists = asFile.exists
- /** True if and only if the file represented by this path is a directory.*/
+ /** True if and only if the wrapped file is a directory.*/
def isDirectory = asFile.isDirectory
- /** The last modified time of the file represented by this path.*/
+ /** The last modified time of the wrapped file.*/
def lastModified = asFile.lastModified
- /* True if and only if file that this path represents exists and the file represented by the path 'p'
- * does not exist or was modified before the file for this path.*/
- def newerThan(p: Path): Boolean = exists && (!p.exists || lastModified > p.lastModified)
- /* True if and only if file that this path represents does not exist or the file represented by the path 'p'
- * exists and was modified after the file for this path.*/
- def olderThan(p: Path): Boolean = p newerThan this
- /** The file represented by this path.*/
- def asFile: File
- /** The file represented by this path converted to a URL.*/
+ /* True if and only if the wrapped file `asFile` exists and the file 'other'
+ * does not exist or was modified before the `asFile`.*/
+ def newerThan(other: File): Boolean = Path.newerThan(asFile, other)
+ /* True if and only if the wrapped file `asFile` does not exist or the file `other`
+ * exists and was modified after `asFile`.*/
+ def olderThan(other: File): Boolean = Path.newerThan(other, asFile)
+ /** The wrapped file converted to a URL.*/
def asURL = asFile.toURI.toURL
- /** The string representation of this path relative to the base directory. The project directory is the
- * default base directory if one is not specified explicitly using the ### operator.*/
- lazy val relativePath: String = relativePathString(sep.toString)
- def relativePathString(separator: String): String
- final def projectRelativePath: String = projectRelativePathString(sep.toString)
- def projectRelativePathString(separator: String): String
def absolutePath: String = asFile.getAbsolutePath
- private[sbt] def prependTo(s: String): String
/** The last component of this path.*/
def name = asFile.getName
@@ -68,166 +40,40 @@ sealed abstract class Path extends PathFinder
val dot = nme.lastIndexOf('.')
if(dot < 0) (nme, "") else (nme.substring(0, dot), nme.substring(dot+1))
}
-
- /** Equality of Paths is defined in terms of the underlying File.*/
- override final def equals(other: Any) =
- other match
- {
- case op: Path => asFile == op.asFile
- case _ => false
- }
- /** The hash code of a Path is that of the underlying File.*/
- override final def hashCode = asFile.hashCode
-}
-private final class BaseDirectory(private[sbt] val path: Path) extends Path
-{
- override def ### : Path = this
- override def toString = path.toString
- def asFile = path.asFile
- def relativePathString(separator: String) = ""
- def projectRelativePathString(separator: String) = path.projectRelativePathString(separator)
- private[sbt] def prependTo(s: String) = "." + sep + s
-}
-private[sbt] final class FilePath(file: File) extends Path
-{
- lazy val asFile = absolute(file)
- override def toString = absolutePath
- def relativePathString(separator: String) = asFile.getName
- def projectRelativePathString(separator: String) = relativePathString(separator)
- private[sbt] def prependTo(s: String) = absolutePath + sep + s
-}
-// toRoot is the path between this and the root project path and is used for toString
-private[sbt] final class ProjectDirectory(file: File, toRoot: Option[Path]) extends Path
-{
- def this(file: File) = this(file, None)
- lazy val asFile = absolute(file)
- override def toString = foldToRoot(_.toString, ".")
- def relativePathString(separator: String) = ""
- def projectRelativePathString(separator: String) = ""
- private[sbt] def prependTo(s: String) = foldToRoot(_.prependTo(s), "." + sep + s)
- private[sbt] def foldToRoot[T](f: Path => T, orElse: T) = toRoot.map(f).getOrElse(orElse)
-}
-private[sbt] final class RelativePath(val parentPath: Path, val component: String) extends Path
-{
- checkComponent(component)
- override def toString = parentPath prependTo component
- lazy val asFile = new File(parentPath.asFile, component)
- private[sbt] def prependTo(s: String) = parentPath prependTo (component + sep + s)
- def relativePathString(separator: String) = relative(parentPath.relativePathString(separator), separator)
- def projectRelativePathString(separator: String) = relative(parentPath.projectRelativePathString(separator), separator)
- private def relative(parentRelative: String, separator: String) =
- {
- if(parentRelative.isEmpty)
- component
- else
- parentRelative + separator + component
- }
+
+ def relativize(sub: File): Option[File] = Path.relativizeFile(asFile, sub)
+ def relativeTo(base: File): Option[File] = Path.relativizeFile(base, asFile)
+
+ def hash: Array[Byte] = Hash(asFile)
+ def hashString: String = Hash.toHex(hash)
+ def hashStringHalf: String = Hash.halve(hashString)
}
import java.io.File
import File.pathSeparator
-trait PathExtra extends Alternatives with Mapper
+trait PathLow
{
- implicit def fileToPath(file: File): Path = Path.fromFile(file)
- implicit def pathToFile(path: Path): File = path.asFile
- implicit def pathsToFiles[CC[X] <: TraversableLike[X,CC[X]]](cc: CC[Path])(implicit cb: generic.CanBuildFrom[CC[Path], File, CC[File]]): CC[File] =
- cc.map(_.asFile)
- implicit def filesToPaths[CC[X] <: TraversableLike[X,CC[X]]](cc: CC[File])(implicit cb: generic.CanBuildFrom[CC[File], Path, CC[Path]]): CC[Path] =
- cc.map(fileToPath)
- implicit def filesToFinder(cc: Traversable[File]): PathFinder = finder(cc)
- implicit def pathsToFinder(cc: Traversable[Path]): PathFinder = lazyPathFinder(cc)
+ implicit def singleFileFinder(file: File): PathFinder = PathFinder(file)
}
-object Path extends PathExtra
+trait PathExtra extends Alternatives with Mapper with PathLow
{
- def fileProperty(name: String) = Path.fromFile(System.getProperty(name))
+ implicit def richFile(file: File): RichFile = new RichFile(file)
+ implicit def filesToFinder(cc: Traversable[File]): PathFinder = PathFinder.strict(cc)
+}
+object Path extends PathExtra
+{
+ def apply(f: File): RichFile = new RichFile(f)
+ def apply(f: String): RichFile = new RichFile(new File(f))
+ def fileProperty(name: String) = Path(System.getProperty(name))
def userHome = fileProperty("user.home")
def absolute(file: File) = new File(file.toURI.normalize).getAbsoluteFile
- /** Constructs a String representation of Paths. The absolute path String of each Path is
- * separated by the platform's path separator.*/
- def makeString(paths: Iterable[Path]): String = makeString(paths, pathSeparator)
- /** Constructs a String representation of Paths. The absolute path String of each Path is
- * separated by the given separator String.*/
- def makeString(paths: Iterable[Path], sep: String): String = paths.map(_.absolutePath).mkString(sep)
-
def makeString(paths: Seq[File]): String = makeString(paths, pathSeparator)
def makeString(paths: Seq[File], sep: String): String = paths.map(_.getAbsolutePath).mkString(sep)
+ def newerThan(a: File, b: File): Boolean = a.exists && (!b.exists || a.lastModified > b.lastModified)
- /** Constructs a String representation of Paths. The relative path String of each Path is
- * separated by the platform's path separator.*/
- def makeRelativeString(paths: Iterable[Path]): String = paths.map(_.relativePathString(sep.toString)).mkString(pathSeparator)
-
- def splitString(projectPath: Path, value: String): Iterable[Path] =
- {
- for(pathString <- pathSplit(value) if pathString.length > 0) yield
- Path.fromString(projectPath, pathString)
- }
-
- /** A PathFinder that always produces the empty set of Paths.*/
- def emptyPathFinder =
- new PathFinder
- {
- private[sbt] def addTo(pathSet: mutable.Set[Path]) {}
- }
- /** A PathFinder that selects the paths provided by the paths argument, which is
- * reevaluated on each call to the PathFinder's get method. */
- def lazyPathFinder(paths: => Traversable[Path]): PathFinder =
- new PathFinder
- {
- private[sbt] def addTo(pathSet: mutable.Set[Path]) = paths.foreach(_.addTo(pathSet))
- }
- def finder(files: => Traversable[File]): PathFinder = lazyPathFinder { fromFiles(files) }
-
/** The separator character of the platform.*/
val sep = java.io.File.separatorChar
-
- /** Checks the string to verify that it is a legal path component. The string must be non-empty,
- * not a slash, and not '.' or '..'.*/
- def checkComponent(c: String): String =
- {
- require(c.length > 0, "Path component must not be empty")
- require(c.indexOf('/') == -1, "Path component '" + c + "' must not have forward slashes in it")
- require(c.indexOf('\\') == -1, "Path component '" + c + "' must not have backslashes in it")
- require(c != "..", "Path component cannot be '..'")
- require(c != ".", "Path component cannot be '.'")
- c
- }
- /** Converts a path string relative to the given base path to a Path. */
- def fromString(basePath: Path, value: String): Path =
- {
- if(value.isEmpty)
- basePath
- else
- {
- val f = new File(value)
- if(f.isAbsolute)
- fromFile(f)
- else
- {
- val components = value.split("""[/\\]""")
- (basePath /: components)( (path, component) => path / component )
- }
- }
- }
- def baseAncestor(path: Path): Option[Path] =
- path match
- {
- case pd: ProjectDirectory => None
- case fp: FilePath => None
- case rp: RelativePath => baseAncestor(rp.parentPath)
- case b: BaseDirectory => Some(b.path)
- }
-
- def relativize(basePath: Path, path: Path): Option[Path] = relativize(basePath, path.asFile)
- def relativize(basePath: Path, file: File): Option[Path] =
- basePathString(basePath) flatMap { baseString => relativize(basePath, baseString, file) }
- def relativize(basePath: Path, basePathString: String, file: File): Option[Path] =
- {
- val pathString = file.getAbsolutePath
- if(pathString.startsWith(basePathString))
- Some(fromString(basePath, pathString.substring(basePathString.length)))
- else
- None
- }
+
def relativizeFile(baseFile: File, file: File): Option[File] = relativize(baseFile, file).map { path => new File(path) }
private[sbt] def relativize(baseFile: File, file: File): Option[String] =
{
@@ -243,9 +89,7 @@ object Path extends PathExtra
}
}
}
- private[sbt] def basePathString(basePath: Path): Option[String] = baseFileString(basePath.asFile)
private def baseFileString(baseFile: File): Option[String] =
- {
if(baseFile.isDirectory)
{
val cp = baseFile.getAbsolutePath
@@ -257,27 +101,29 @@ object Path extends PathExtra
}
else
None
- }
- def fromFile(file: String): Path = fromFile(new File(file))
- def fromFile(file: File): Path = new FilePath(file)
- import collection.generic.{CanBuildFrom, FilterMonadic}
- def fromFiles[Repr, That](files: FilterMonadic[File, Repr])(implicit bf: CanBuildFrom[Repr, Path, That]): That = files.map(fromFile)
-
- def getFiles(files: Traversable[Path]): immutable.Set[File] = files.map(_.asFile).toSet
- def getURLs(files: Traversable[Path]): Array[URL] = files.map(_.asURL).toArray
def toURLs(files: Seq[File]): Array[URL] = files.map(_.toURI.toURL).toArray
}
+object PathFinder
+{
+ /** A PathFinder that always produces the empty set of Paths.*/
+ val empty = new PathFinder { private[sbt] def addTo(fileSet: mutable.Set[File]) {} }
+ def strict(files: Traversable[File]): PathFinder = apply(files)
+ def apply(files: => Traversable[File]): PathFinder = new PathFinder {
+ private[sbt] def addTo(fileSet: mutable.Set[File]) = fileSet ++= files
+ }
+ def apply(file: File): PathFinder = new SingleFile(file)
+}
/** A path finder constructs a set of paths. The set is evaluated by a call to the get
* method. The set will be different for different calls to get if the underlying filesystem
* has changed.*/
-sealed abstract class PathFinder extends NotNull
+sealed abstract class PathFinder
{
/** The union of the paths found by this PathFinder with the paths found by 'paths'.*/
def +++(paths: PathFinder): PathFinder = new Paths(this, paths)
/** Excludes all paths from excludePaths from the paths selected by this PathFinder.*/
- def ---(excludePaths: PathFinder): PathFinder = new ExcludePaths(this, excludePaths)
+ def ---(excludePaths: PathFinder): PathFinder = new ExcludeFiles(this, excludePaths)
/** Constructs a new finder that selects all paths with a name that matches filter and are
* descendents of paths selected by this finder.*/
def **(filter: FileFilter): PathFinder = new DescendentOrSelfPathFinder(this, filter)
@@ -292,11 +138,6 @@ sealed abstract class PathFinder extends NotNull
* of paths selected by this finder.*/
final def \ (literal: String): PathFinder = this / literal
- /** Makes the paths selected by this finder into base directories.
- * @see Path.###
- */
- def ### : PathFinder = new BasePathFinder(this)
-
def x_: Traversable[(File,T)] = x(mapper, false)
/** Applies `mapper` to each path selected by this PathFinder and returns the path paired with the non-empty result.
* If the result is empty (None) and `errorIfNone` is true, an exception is thrown.
@@ -304,10 +145,8 @@ sealed abstract class PathFinder extends NotNull
def x[T](mapper: File => Option[T], errorIfNone: Boolean = true): Seq[(File,T)] =
{
val apply = if(errorIfNone) mapper | fail else mapper
- for(file <- getFiles; mapped <- apply(file)) yield (file, mapped)
+ for(file <- get; mapped <- apply(file)) yield (file, mapped)
}
- /** Pairs each path selected by this PathFinder with its relativePath.*/
- def xx: Traversable[(File, String)] = get.map(path => (path.asFile, path.relativePath))
/** Selects all descendent paths with a name that matches include and do not have an intermediate
* path with a name that matches intermediateExclude. Typical usage is:
@@ -316,108 +155,89 @@ sealed abstract class PathFinder extends NotNull
def descendentsExcept(include: FileFilter, intermediateExclude: FileFilter): PathFinder =
(this ** include) --- (this ** intermediateExclude ** include)
- /** Evaluates this finder. The set returned by this method will reflect the underlying filesystem at the
+ /** Evaluates this finder and converts the results to a `Seq` of distinct `File`s. The files returned by this method will reflect the underlying filesystem at the
* time of calling. If the filesystem changes, two calls to this method might be different.*/
- final def get: immutable.Set[Path] =
- {
- val pathSet = new mutable.HashSet[Path]
- addTo(pathSet)
- pathSet.toSet
- }
- /** Evaluates this finder and converts the results to a `Seq` of `File`s.*/
- final def getFiles: Seq[File] =
+ final def get: Seq[File] =
{
import collection.JavaConversions._
- val pathSet: mutable.Set[Path] = new java.util.LinkedHashSet[Path]
+ val pathSet: mutable.Set[File] = new java.util.LinkedHashSet[File]
addTo(pathSet)
- pathSet.map(_.asFile).toSeq
+ pathSet.toSeq
}
+ @deprecated("Use `get`"/*, "0.9.7"*/) def getFiles: Seq[File] = get
/** Only keeps paths for which `f` returns true. It is non-strict, so it is not evaluated until the returned finder is evaluated.*/
- final def filter(f: Path => Boolean): PathFinder = Path.lazyPathFinder(get.filter(f))
+ final def filter(f: File => Boolean): PathFinder = PathFinder(get filter f)
/* Non-strict flatMap: no evaluation occurs until the returned finder is evaluated.*/
- final def flatMap(f: Path => PathFinder): PathFinder = Path.lazyPathFinder(get.flatMap(p => f(p).get))
+ final def flatMap(f: File => PathFinder): PathFinder = PathFinder(get.flatMap(p => f(p).get))
/** Evaluates this finder and converts the results to an `Array` of `URL`s..*/
- final def getURLs: Array[URL] = getFiles.toArray.map(_.toURI.toURL)
- /** Evaluates this finder and converts the results to a `Set` of absolute path strings.*/
- final def getPaths: immutable.Set[String] = strictMap(_.absolutePath)
- /** Evaluates this finder and converts the results to a `Set` of relative path strings.*/
- final def getRelativePaths: immutable.Set[String] = strictMap(_.relativePath)
- final def strictMap[T](f: Path => T): immutable.Set[T] = get.map(f).toSet
- private[sbt] def addTo(pathSet: mutable.Set[Path])
+ final def getURLs: Array[URL] = get.toArray.map(_.toURI.toURL)
+ /** Evaluates this finder and converts the results to a distinct sequence of absolute path strings.*/
+ final def getPaths: Seq[String] = get.map(_.absolutePath)
+ private[sbt] def addTo(fileSet: mutable.Set[File])
/** Create a PathFinder from this one where each path has a unique name.
* A single path is arbitrarily selected from the set of paths with the same name.*/
- def distinct: PathFinder = Path.lazyPathFinder((Map() ++ get.map(p => (p.asFile.getName, p))) .values.toList )
+ def distinct: PathFinder = PathFinder { get.map(p => (p.asFile.getName, p)).toMap.values }
/** Constructs a string by evaluating this finder, converting the resulting Paths to absolute path strings, and joining them with the platform path separator.*/
final def absString = Path.makeString(get)
- /** Constructs a string by evaluating this finder, converting the resulting Paths to relative path strings, and joining them with the platform path separator.*/
- final def relativeString = Path.makeRelativeString(get)
/** Constructs a debugging string for this finder by evaluating it and separating paths by newlines.*/
override def toString = get.mkString("\n ", "\n ","")
}
-private class BasePathFinder(base: PathFinder) extends PathFinder
+private class SingleFile(asFile: File) extends PathFinder
{
- private[sbt] def addTo(pathSet: mutable.Set[Path])
- {
- for(path <- base.get)
- pathSet += (path ###)
- }
+ private[sbt] def addTo(fileSet: mutable.Set[File]): Unit = if(asFile.exists) fileSet += asFile
}
-private abstract class FilterPath extends PathFinder with FileFilter
+private abstract class FilterFiles extends PathFinder with FileFilter
{
def parent: PathFinder
def filter: FileFilter
final def accept(file: File) = filter.accept(file)
- protected def handlePath(path: Path, pathSet: mutable.Set[Path])
- {
- for(matchedFile <- wrapNull(path.asFile.listFiles(this)))
- pathSet += path / matchedFile.getName
- }
+ protected def handleFile(file: File, fileSet: mutable.Set[File]): Unit =
+ for(matchedFile <- wrapNull(file.listFiles(this)))
+ fileSet += new File(file, matchedFile.getName)
}
-private class DescendentOrSelfPathFinder(val parent: PathFinder, val filter: FileFilter) extends FilterPath
+private class DescendentOrSelfPathFinder(val parent: PathFinder, val filter: FileFilter) extends FilterFiles
{
- private[sbt] def addTo(pathSet: mutable.Set[Path])
+ private[sbt] def addTo(fileSet: mutable.Set[File])
{
- for(path <- parent.get)
+ for(file <- parent.get)
{
- if(accept(path.asFile))
- pathSet += path
- handlePathDescendent(path, pathSet)
+ if(accept(file))
+ fileSet += file
+ handleFileDescendent(file, fileSet)
}
}
- private def handlePathDescendent(path: Path, pathSet: mutable.Set[Path])
+ private def handleFileDescendent(file: File, fileSet: mutable.Set[File])
{
- handlePath(path, pathSet)
- for(childDirectory <- wrapNull(path.asFile.listFiles(DirectoryFilter)))
- handlePathDescendent(path / childDirectory.getName, pathSet)
+ handleFile(file, fileSet)
+ for(childDirectory <- wrapNull(file listFiles DirectoryFilter))
+ handleFileDescendent(new File(file, childDirectory.getName), fileSet)
}
}
-private class ChildPathFinder(val parent: PathFinder, val filter: FileFilter) extends FilterPath
+private class ChildPathFinder(val parent: PathFinder, val filter: FileFilter) extends FilterFiles
{
- private[sbt] def addTo(pathSet: mutable.Set[Path])
- {
- for(path <- parent.get)
- handlePath(path, pathSet)
- }
+ private[sbt] def addTo(fileSet: mutable.Set[File]): Unit =
+ for(file <- parent.get)
+ handleFile(file, fileSet)
}
private class Paths(a: PathFinder, b: PathFinder) extends PathFinder
{
- private[sbt] def addTo(pathSet: mutable.Set[Path])
+ private[sbt] def addTo(fileSet: mutable.Set[File])
{
- a.addTo(pathSet)
- b.addTo(pathSet)
+ a.addTo(fileSet)
+ b.addTo(fileSet)
}
}
-private class ExcludePaths(include: PathFinder, exclude: PathFinder) extends PathFinder
+private class ExcludeFiles(include: PathFinder, exclude: PathFinder) extends PathFinder
{
- private[sbt] def addTo(pathSet: mutable.Set[Path])
+ private[sbt] def addTo(pathSet: mutable.Set[File])
{
- val includeSet = new mutable.HashSet[Path]
+ val includeSet = new mutable.LinkedHashSet[File]
include.addTo(includeSet)
- val excludeSet = new mutable.HashSet[Path]
+ val excludeSet = new mutable.HashSet[File]
exclude.addTo(excludeSet)
includeSet --= excludeSet
diff --git a/util/io/SourceModificationWatch.scala b/util/io/SourceModificationWatch.scala
index d6b6c7b70..43039ddd3 100644
--- a/util/io/SourceModificationWatch.scala
+++ b/util/io/SourceModificationWatch.scala
@@ -11,7 +11,7 @@ object SourceModificationWatch
{
import state._
- def sourceFiles: Iterable[java.io.File] = sourcesFinder.getFiles
+ def sourceFiles: Iterable[java.io.File] = sourcesFinder.get
val (lastModifiedTime, fileCount) =
( (0L, 0) /: sourceFiles) {(acc, file) => (math.max(acc._1, file.lastModified), acc._2 + 1)}