diff options
-rw-r--r-- | build.xml | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ObjectRunner.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/Directory.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/File.scala | 30 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/Path.scala | 33 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/PlainFile.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/Process.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/ZipArchive.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/CommandLineParser.scala | 23 |
9 files changed, 78 insertions, 29 deletions
@@ -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 |