diff --git a/src/main/scala/sbt/DefaultProject.scala b/src/main/scala/sbt/DefaultProject.scala index 9b67ce97d..8397d254b 100644 --- a/src/main/scala/sbt/DefaultProject.scala +++ b/src/main/scala/sbt/DefaultProject.scala @@ -353,9 +353,13 @@ abstract class BasicWebScalaProject extends BasicScalaProject with WebScalaProje import BasicWebScalaProject._ override def watchPaths = super.watchPaths +++ webappResources + /** Override this to define paths that `prepare-webapp` and `package` should ignore. + * They will not be pruned by prepare-webapp and will not be included in the war.*/ + def webappUnmanaged: PathFinder = Path.emptyPathFinder + lazy val prepareWebapp = prepareWebappAction protected def prepareWebappAction = - prepareWebappTask(webappResources, temporaryWarPath, webappClasspath, mainDependencies.scalaJars) dependsOn(compile, copyResources) + prepareWebappTask(webappResources, temporaryWarPath, webappClasspath, mainDependencies.scalaJars, webappUnmanaged) dependsOn(compile, copyResources) lazy val jettyInstance = new JettyRunner(jettyConfiguration) @@ -414,7 +418,7 @@ abstract class BasicWebScalaProject extends BasicScalaProject with WebScalaProje override def cleanAction = super.cleanAction dependsOn jettyStop /** Redefine the `package` action to make a war file.*/ - override protected def packageAction = packageTask(descendents(temporaryWarPath ##, "*"), warPath, Nil) dependsOn(prepareWebapp) describedAs PackageWarDescription + override protected def packageAction = packageWarAction(temporaryWarPath, webappUnmanaged, warPath, Nil) dependsOn(prepareWebapp) describedAs PackageWarDescription /** Redefine the default main artifact to be a war file.*/ override protected def defaultMainArtifact = Artifact(artifactID, "war", "war") diff --git a/src/main/scala/sbt/Process.scala b/src/main/scala/sbt/Process.scala index fda7b593c..87aa314c8 100644 --- a/src/main/scala/sbt/Process.scala +++ b/src/main/scala/sbt/Process.scala @@ -3,7 +3,6 @@ */ package sbt -import sbt.impl.CommandParser import java.lang.{Process => JProcess, ProcessBuilder => JProcessBuilder} import java.io.{Closeable, File, IOException} import java.io.{BufferedReader, InputStream, InputStreamReader, OutputStream, PipedInputStream, PipedOutputStream} @@ -22,10 +21,12 @@ object Process apply(command, Some(cwd), extraEnv : _*) /** create ProcessBuilder with working dir optionaly set to File and extra environment variables */ def apply(command: String, cwd: Option[File], extraEnv: (String,String)*): ProcessBuilder = { - CommandParser.parse(command) match { + apply(command.split("""\s+"""), cwd, extraEnv : _*) + // not smart to use this on windows, because CommandParser uses \ to escape ". + /*CommandParser.parse(command) match { case Left(errorMsg) => error(errorMsg) case Right((cmd, args)) => apply(cmd :: args, cwd, extraEnv : _*) - } + }*/ } /** create ProcessBuilder with working dir optionaly set to File and extra environment variables */ def apply(command: Seq[String], cwd: Option[File], extraEnv: (String,String)*): ProcessBuilder = { diff --git a/src/main/scala/sbt/ScalaProject.scala b/src/main/scala/sbt/ScalaProject.scala index ad2aa4075..4e3d1a9ba 100644 --- a/src/main/scala/sbt/ScalaProject.scala +++ b/src/main/scala/sbt/ScalaProject.scala @@ -322,9 +322,14 @@ trait ScalaProject extends SimpleScalaProject with FileTasks with MultiTaskProje trait WebScalaProject extends ScalaProject { + protected def packageWarAction(stagedWarPath: Path, ignore: PathFinder, outputWarPath: => Path, options: => Seq[PackageOption]): Task = + packageTask(descendents(stagedWarPath ##, "*") --- ignore, outputWarPath, options) + @deprecated protected def prepareWebappTask(webappContents: PathFinder, warPath: => Path, classpath: PathFinder, extraJars: => Iterable[File]): Task = prepareWebappTask(webappContents, warPath, classpath, Path.lazyPathFinder(extraJars.map(Path.fromFile))) protected def prepareWebappTask(webappContents: PathFinder, warPath: => Path, classpath: PathFinder, extraJars: PathFinder): Task = + prepareWebappTask(webappContents, warPath, classpath, extraJars, Path.emptyPathFinder) + protected def prepareWebappTask(webappContents: PathFinder, warPath: => Path, classpath: PathFinder, extraJars: PathFinder, ignore: PathFinder): Task = task { val webInfPath = warPath / "WEB-INF" @@ -342,7 +347,7 @@ trait WebScalaProject extends ScalaProject copyFlat(libs, webLibDirectory, log).right flatMap { copiedLibs => copyFilesFlat(extraJars.get.map(_.asFile), webLibDirectory, log).right flatMap { copiedExtraLibs => { - val toRemove = scala.collection.mutable.HashSet((warPath ** "*").get.toSeq : _*) + val toRemove = scala.collection.mutable.HashSet(((warPath ** "*") --- ignore).get.toSeq : _*) toRemove --= copiedWebapp toRemove --= copiedClasses toRemove --= copiedLibs diff --git a/src/main/scala/sbt/impl/CommandParser.scala b/src/main/scala/sbt/impl/CommandParser.scala index b64011fed..a2fab873d 100644 --- a/src/main/scala/sbt/impl/CommandParser.scala +++ b/src/main/scala/sbt/impl/CommandParser.scala @@ -11,7 +11,14 @@ import scala.util.parsing.input.CharArrayReader.EofCh * identifier argument* * where argument may be quoted to include spaces and * quotes and backslashes should be escaped. -* (Most of the complexity is for decent error handling.)*/ +*/ +object Arguments +{ + def apply(commandString: String): Either[String, (String, List[String])] = + CommandParser.parse(commandString) +} + +/* Most of the complexity is for error handling.*/ private[sbt] object CommandParser extends Parsers { type Elem = Char