summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-04-02 21:09:34 +0000
committerPaul Phillips <paulp@improving.org>2010-04-02 21:09:34 +0000
commitd5c7049d4fe117e26a5e981c2449a966b017af49 (patch)
treefaaa6bfbcd86ba0de17a60361faf8547e68235d5
parentcd51ac694d82c68a5c02f9f20a9460adbac780b4 (diff)
downloadscala-d5c7049d4fe117e26a5e981c2449a966b017af49.tar.gz
scala-d5c7049d4fe117e26a5e981c2449a966b017af49.tar.bz2
scala-d5c7049d4fe117e26a5e981c2449a966b017af49.zip
Mostly IO tweaks related to my upcoming partest...
Mostly IO tweaks related to my upcoming partest patch, which to my chagrin is being held up by windows. Also updates the default ANT_OPTS to be the same as the ones the nightlies override it with. (If we know you can't build scala with those settings it seems kind of uncool to leave them for everyone else.) No review.
-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