summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml2
-rw-r--r--src/compiler/scala/tools/nsc/ObjectRunner.scala3
-rw-r--r--src/compiler/scala/tools/nsc/io/Directory.scala3
-rw-r--r--src/compiler/scala/tools/nsc/io/File.scala30
-rw-r--r--src/compiler/scala/tools/nsc/io/Path.scala33
-rw-r--r--src/compiler/scala/tools/nsc/io/PlainFile.scala4
-rw-r--r--src/compiler/scala/tools/nsc/io/Process.scala2
-rw-r--r--src/compiler/scala/tools/nsc/io/ZipArchive.scala7
-rw-r--r--src/compiler/scala/tools/nsc/util/CommandLineParser.scala23
9 files changed, 78 insertions, 29 deletions
diff --git a/build.xml b/build.xml
index 441f160731..3ef75d1998 100644
--- a/build.xml
+++ b/build.xml
@@ -184,7 +184,7 @@ PROPERTIES
<!-- if ANT_OPTS is already set by the environment, it will be unaltered,
but if it is unset it will take this default value. -->
- <property name="env.ANT_OPTS" value="-Xms512M -Xmx1024M -Xss1M -XX:MaxPermSize=128M" />
+ <property name="env.ANT_OPTS" value="-Xms512M -Xmx1536M -Xss1M -XX:MaxPermSize=128M" />
<!-- to find max heap usage: -Xaprof ; currently at 980M for locker.comp -->
<echo message="Using ANT_OPTS: ${env.ANT_OPTS}" />
diff --git a/src/compiler/scala/tools/nsc/ObjectRunner.scala b/src/compiler/scala/tools/nsc/ObjectRunner.scala
index befdf94072..210f9a1785 100644
--- a/src/compiler/scala/tools/nsc/ObjectRunner.scala
+++ b/src/compiler/scala/tools/nsc/ObjectRunner.scala
@@ -15,8 +15,7 @@ import util.ScalaClassLoader
* @author Lex Spoon
* @version 1.1, 2007/7/13
*/
-object ObjectRunner
-{
+object ObjectRunner {
/** Check whether a class with the specified name
* exists on the specified class path. */
def classExists(urls: List[URL], objectName: String): Boolean =
diff --git a/src/compiler/scala/tools/nsc/io/Directory.scala b/src/compiler/scala/tools/nsc/io/Directory.scala
index 5355fcf681..7c279a79e2 100644
--- a/src/compiler/scala/tools/nsc/io/Directory.scala
+++ b/src/compiler/scala/tools/nsc/io/Directory.scala
@@ -53,6 +53,9 @@ class Directory(jfile: JFile) extends Path(jfile) {
def dirs: Iterator[Directory] = list collect { case x: Directory => x }
def files: Iterator[File] = list collect { case x: File => x }
+ override def walkFilter(cond: Path => Boolean): Iterator[Path] =
+ list filter cond flatMap (_ walkFilter cond)
+
def deepDirs: Iterator[Directory] = Path.onlyDirs(deepList())
def deepFiles: Iterator[File] = Path.onlyFiles(deepList())
diff --git a/src/compiler/scala/tools/nsc/io/File.scala b/src/compiler/scala/tools/nsc/io/File.scala
index 7f2c736408..efa4ab46da 100644
--- a/src/compiler/scala/tools/nsc/io/File.scala
+++ b/src/compiler/scala/tools/nsc/io/File.scala
@@ -17,8 +17,7 @@ import java.io.{
import java.nio.channels.{ Channel, FileChannel }
import scala.io.Codec
-object File
-{
+object File {
def pathSeparator = JFile.pathSeparator
def separator = JFile.separator
@@ -34,6 +33,17 @@ object File
def closeQuietly(target: Closeable) {
try target.close() catch { case e: IOException => }
}
+
+ // this is a workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6503430
+ // we are using a static initializer to statically initialize a java class so we don't
+ // trigger java.lang.InternalErrors later when using it concurrently.
+ {
+ val tmp = JFile.createTempFile("bug6503430", null, null)
+ val in = new FileInputStream(tmp).getChannel()
+ val out = new FileOutputStream(tmp, true).getChannel()
+ out.transferFrom(in, 0, 0)
+ ()
+ }
}
import File._
import Path._
@@ -58,6 +68,8 @@ with Streamable.Chars {
override def normalize: File = super.normalize.toFile
override def isValid = jfile.isFile() || !jfile.exists()
override def length = super[Path].length
+ override def walkFilter(cond: Path => Boolean): Iterator[Path] =
+ if (cond(this)) Iterator.single(this) else Iterator.empty
/** Obtains an InputStream. */
def inputStream() = new FileInputStream(jfile)
@@ -86,8 +98,14 @@ with Streamable.Chars {
finally out close
}
- def copyFile(destPath: Path, preserveFileDate: Boolean = false) = {
- val FIFTY_MB = 1024 * 1024 * 50
+ def appendAll(strings: String*): Unit = {
+ val out = bufferedWriter(append = true)
+ try strings foreach (out write _)
+ finally out close
+ }
+
+ def copyTo(destPath: Path, preserveFileDate: Boolean = false): Boolean = {
+ val CHUNK = 1024 * 1024 * 16 // 16 MB
val dest = destPath.toFile
if (!isValid) fail("Source %s is not a valid file." format name)
if (this.normalize == dest.normalize) fail("Source and destination are the same.")
@@ -104,7 +122,7 @@ with Streamable.Chars {
val size = in.size()
var pos, count = 0L
while (pos < size) {
- count = (size - pos) min FIFTY_MB
+ count = (size - pos) min CHUNK
pos += out.transferFrom(in, pos, count)
}
}
@@ -116,6 +134,6 @@ with Streamable.Chars {
if (preserveFileDate)
dest.lastModified = this.lastModified
- ()
+ true
}
}
diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/compiler/scala/tools/nsc/io/Path.scala
index 2b5acaed0c..6b88f3cfca 100644
--- a/src/compiler/scala/tools/nsc/io/Path.scala
+++ b/src/compiler/scala/tools/nsc/io/Path.scala
@@ -35,12 +35,10 @@ object Path
/** If examineFile is true, it will look at the first four bytes of the file
* and see if the magic number indicates it may be a jar or zip.
*/
+ private def magicNumberIsZip(f: Path) = f.isFile && (f.toFile.bytes().take(4).toList == ZipMagicNumber)
def isJarOrZip(f: Path): Boolean = isJarOrZip(f, false)
- def isJarOrZip(f: Path, examineFile: Boolean): Boolean = (
- (f hasExtension "zip")
- || (f hasExtension "jar")
- || (examineFile && f.isFile && (f.toFile.bytes().take(4).toList == ZipMagicNumber))
- )
+ def isJarOrZip(f: Path, examineFile: Boolean): Boolean =
+ f.hasExtension("zip", "jar") || (examineFile && magicNumberIsZip(f))
// not certain these won't be problematic, but looks good so far
implicit def string2path(s: String): Path = apply(s)
@@ -109,6 +107,22 @@ class Path private[io] (val jfile: JFile) {
def /(child: Directory): Directory = /(child: Path).toDirectory
def /(child: File): File = /(child: Path).toFile
+ /** If this path is a container, recursively iterate over its contents.
+ * The supplied condition is a filter which is applied to each element,
+ * with that branch of the tree being closed off if it is true. So for
+ * example if the condition is true for some subdirectory, nothing
+ * under that directory will be in the Iterator; but otherwise each
+ * file and subdirectory underneath it will appear.
+ */
+ def walkFilter(cond: Path => Boolean): Iterator[Path] =
+ if (isFile) toFile walkFilter cond
+ else if (isDirectory) toDirectory walkFilter cond
+ else Iterator.empty
+
+ /** Equivalent to walkFilter(_ => false).
+ */
+ def walk: Iterator[Path] = walkFilter(_ => true)
+
// identity
def name: String = jfile.getName()
def path: String = jfile.getPath()
@@ -158,12 +172,17 @@ class Path private[io] (val jfile: JFile) {
case -1 => ""
case idx => name drop (idx + 1)
}
- // compares against extension in a CASE INSENSITIVE way.
- def hasExtension(ext: String) = extension.toLowerCase == ext.toLowerCase
+ // compares against extensions in a CASE INSENSITIVE way.
+ def hasExtension(ext: String, exts: String*) = {
+ val xs = (ext +: exts) map (_.toLowerCase)
+ xs contains extension.toLowerCase
+ }
// returns the filename without the extension.
def stripExtension: String = name stripSuffix ("." + extension)
// returns the Path with the extension.
def addExtension(ext: String): Path = Path(path + "." + ext)
+ // changes the existing extension out for a new one
+ def changeExtension(ext: String): Path = Path((path stripSuffix extension) + ext)
// conditionally execute
def ifFile[T](f: File => T): Option[T] = if (isFile) Some(f(toFile)) else None
diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala
index df24880f32..a40d01d1f5 100644
--- a/src/compiler/scala/tools/nsc/io/PlainFile.scala
+++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala
@@ -57,8 +57,8 @@ class PlainFile(val givenPath: Path) extends AbstractFile {
/** Returns all abstract subfiles of this abstract directory. */
def iterator: Iterator[AbstractFile] = {
- assert(isDirectory, "not a directory '%s'" format this)
- givenPath.toDirectory.list filter (_.exists) map (new PlainFile(_))
+ if (!isDirectory) Iterator.empty
+ else givenPath.toDirectory.list filter (_.exists) map (new PlainFile(_))
}
/**
diff --git a/src/compiler/scala/tools/nsc/io/Process.scala b/src/compiler/scala/tools/nsc/io/Process.scala
index 7580cf22ab..746c5f1a8d 100644
--- a/src/compiler/scala/tools/nsc/io/Process.scala
+++ b/src/compiler/scala/tools/nsc/io/Process.scala
@@ -46,7 +46,6 @@ object Process
val p = Process(cmd)
xs foreach (x => p.stdin println stringify(x))
p.stdin.close()
- p.stdin.flush()
p.stdout.toList
}
}
@@ -168,6 +167,7 @@ class Process(processCreator: () => JProcess) extends Iterable[String] {
override def run() {
reader.readLine match {
case null =>
+ in.close()
case x =>
queue put x
run()
diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/compiler/scala/tools/nsc/io/ZipArchive.scala
index f4af0f5a8f..4ee3a29671 100644
--- a/src/compiler/scala/tools/nsc/io/ZipArchive.scala
+++ b/src/compiler/scala/tools/nsc/io/ZipArchive.scala
@@ -236,10 +236,9 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file)
}
private def zipTraversableFromZipFile(z: ZipFile): ZipTrav =
- new Traversable[ZipEntry] {
- def zis: ZipInputStream = null // not valid for this type
- val itStream = asIterator(z.entries()).toStream
- def foreach[U](f: ZipEntry => U) = itStream foreach f
+ new Iterable[ZipEntry] {
+ def zis: ZipInputStream = null // not valid for this type
+ def iterator = asIterator(z.entries())
}
}
diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
index 09398ca2c4..8c950322e0 100644
--- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
+++ b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
@@ -42,8 +42,8 @@ case class CommandLine(
val Terminator = "--"
val ValueForUnaryOption = "true" // so if --opt is given, x(--opt) = true
- def mapForUnary(opt: String) = Map(opt -> ValueForUnaryOption)
+ def mapForUnary(opt: String) = Map(opt -> ValueForUnaryOption)
def errorFn(msg: String) = println(msg)
/** argMap is option -> argument (or "" if it is a unary argument)
@@ -51,10 +51,17 @@ case class CommandLine(
*/
lazy val (argMap, residualArgs) = {
val residualBuffer = new ListBuffer[String]
+
+ def stripQuotes(s: String) = {
+ def isQuotedBy(c: Char) = s.length > 0 && s.head == c && s.last == c
+ if (List('"', '\'') exists isQuotedBy) s.tail.init else s
+ }
+
def isValidOption(s: String) = !onlyKnownOptions || (unaryArguments contains s) || (binaryArguments contains s)
def isOption(s: String) = (s startsWith "-") && (isValidOption(s) || { unknownOption(s) ; false })
def isUnary(s: String) = isOption(s) && (unaryArguments contains s)
def isBinary(s: String) = isOption(s) && !isUnary(s) && (assumeBinary || (binaryArguments contains s))
+
def unknownOption(opt: String) =
errorFn("Option '%s' not recognized.".format(opt))
def missingArg(opt: String, what: String) =
@@ -78,8 +85,12 @@ case class CommandLine(
if (hd2 == Terminator) mapForUnary(hd1) ++ residual(rest)
else if (isUnary(hd1)) mapForUnary(hd1) ++ loop(hd2 :: rest)
else if (isBinary(hd1)) {
- if (isOption(hd2) && enforceArity)
- missingArg(hd1, hd2)
+ // Disabling this check so
+ // --scalacopts "-verbose" works. We can't tell if it's quoted,
+ // the shell does us in.
+ //
+ // if (isOption(hd2) && enforceArity)
+ // missingArg(hd1, hd2)
Map(hd1 -> hd2) ++ loop(rest)
}
@@ -87,7 +98,7 @@ case class CommandLine(
}
}
- (loop(args), residualBuffer.toList)
+ (loop(args), residualBuffer map stripQuotes toList)
}
def isSet(arg: String) = args contains arg
@@ -110,8 +121,8 @@ object CommandLineParser extends RegexParsers with ParserUtil {
)
/** Apparently windows can't deal with the quotes sticking around. */
- lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x)
- lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"")
+ lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x)
+ lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"")
lazy val token: Parser[String] = """\S+""".r
lazy val argument: Parser[String] = squoted | dquoted | token