mirror of https://github.com/sbt/sbt.git
* limit stack trace length: trace 'on' | 'off' | 'nosbt' | 1 | 2 | ...
* updating license/copyright
This commit is contained in:
parent
791c7a2a14
commit
b6cb89fea4
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2008, 2009 Steven Blundy, Mark Harrah, David MacIver, Mikko Peltonen
|
||||
Copyright (c) 2008, 2009, 2010 Steven Blundy, Josh Cough, Nathan Hamblen, Mark Harrah, David MacIver, Mikko Peltonen, Tony Sloane, Vesa Vilhonen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
29
NOTICE
29
NOTICE
|
|
@ -1,5 +1,6 @@
|
|||
Simple Build Tool (sbt)
|
||||
Copyright 2008, 2009 Steven Blundy, Mark Harrah, David MacIver, Mikko Peltonen
|
||||
Copyright 2008, 2009, 2010 Steven Blundy, Josh Cough, Nathan Hamblen, Mark Harrah, David MacIver, Mikko Peltonen, Tony Sloane, Vesa Vilhonen
|
||||
Licensed under BSD-style license (see LICENSE)
|
||||
|
||||
|
||||
Portions based on code by Mike Clark in JDepend
|
||||
|
|
@ -14,30 +15,12 @@ Portions based on code from the Scala compiler
|
|||
Copyright 2002-2008 EPFL, Lausanne
|
||||
Licensed under BSD-style license (see licenses/LICENSE_Scala)
|
||||
|
||||
Portions based on code from specs
|
||||
Copyright 2007-2008 Eric Torreborre
|
||||
Licensed under MIT license (see licenses/LICENSE_specs)
|
||||
|
||||
Portions based on code from ScalaTest
|
||||
Copyright 2001-2008 Artima, Inc.
|
||||
Licensed under the Apache License, Version 2.0(see licenses/LICENSE_Apache)
|
||||
|
||||
Portions based on code from ScalaCheck
|
||||
Copyright 2007, Rickard Nilsson
|
||||
Licensed under BSD-style license (see licenses/LICENSE_ScalaCheck)
|
||||
|
||||
Jetty is licensed under the Apache License, Version 2.0 (see licenses/LICENSE_Apache).
|
||||
|
||||
ScalaTest is distributed with sbt (in the subversion repository)
|
||||
and requires the following notice:
|
||||
|
||||
This product includes software developed by
|
||||
Artima, Inc. (http://www.artima.com/).
|
||||
|
||||
JLine is distributed with the sbt launcher.
|
||||
It is licensed under a BSD-style license (see licenses/LICENSE_JLine)
|
||||
|
||||
Apache Ivy, licensed under the Apache License, Version 2.0
|
||||
(see licenses/LICENSE_Apache) is distributed with sbt and
|
||||
requires the following notice:
|
||||
(see licenses/LICENSE_Apache) is distributed with the sbt launcher.
|
||||
It requires the following notice:
|
||||
|
||||
This product includes software developed by
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2008 Mark Harrah, David MacIver
|
||||
Copyright (c) 2008, 2009, 2010 Steven Blundy, Josh Cough, Nathan Hamblen, Mark Harrah, David MacIver, Mikko Peltonen, Tony Sloane, Vesa Vilhonen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -22,4 +22,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ final class Success(val msg: String) extends LogEvent
|
|||
final class Log(val level: Level.Value, val msg: String) extends LogEvent
|
||||
final class Trace(val exception: Throwable) extends LogEvent
|
||||
final class SetLevel(val newLevel: Level.Value) extends LogEvent
|
||||
final class SetTrace(val enabled: Boolean) extends LogEvent
|
||||
final class SetTrace(val level: Int) extends LogEvent
|
||||
final class ControlEvent(val event: ControlEvent.Value, val msg: String) extends LogEvent
|
||||
|
||||
object ControlEvent extends Enumeration
|
||||
|
|
@ -22,8 +22,9 @@ abstract class Logger extends xsbt.CompileLogger with xsbt.IvyLogger
|
|||
{
|
||||
def getLevel: Level.Value
|
||||
def setLevel(newLevel: Level.Value)
|
||||
def enableTrace(flag: Boolean)
|
||||
def traceEnabled: Boolean
|
||||
def setTrace(flag: Int)
|
||||
def getTrace: Int
|
||||
final def traceEnabled = getTrace >= 0
|
||||
def ansiCodesSupported = false
|
||||
|
||||
def atLevel(level: Level.Value) = level.id >= getLevel.id
|
||||
|
|
@ -47,7 +48,7 @@ abstract class Logger extends xsbt.CompileLogger with xsbt.IvyLogger
|
|||
case l: Log => log(l.level, l.msg)
|
||||
case t: Trace => trace(t.exception)
|
||||
case setL: SetLevel => setLevel(setL.newLevel)
|
||||
case setT: SetTrace => enableTrace(setT.enabled)
|
||||
case setT: SetTrace => setTrace(setT.level)
|
||||
case c: ControlEvent => control(c.event, c.msg)
|
||||
}
|
||||
}
|
||||
|
|
@ -64,12 +65,12 @@ abstract class Logger extends xsbt.CompileLogger with xsbt.IvyLogger
|
|||
/** Implements the level-setting methods of Logger.*/
|
||||
abstract class BasicLogger extends Logger
|
||||
{
|
||||
private var traceEnabledVar = true
|
||||
private var traceEnabledVar = java.lang.Integer.MAX_VALUE
|
||||
private var level: Level.Value = Level.Info
|
||||
def getLevel = level
|
||||
def setLevel(newLevel: Level.Value) { level = newLevel }
|
||||
def enableTrace(flag: Boolean) { traceEnabledVar = flag }
|
||||
def traceEnabled = traceEnabledVar
|
||||
def setTrace(level: Int) { traceEnabledVar = level }
|
||||
def getTrace = traceEnabledVar
|
||||
}
|
||||
|
||||
final class SynchronizedLogger(delegate: Logger) extends Logger
|
||||
|
|
@ -77,8 +78,8 @@ final class SynchronizedLogger(delegate: Logger) extends Logger
|
|||
override lazy val ansiCodesSupported = delegate.ansiCodesSupported
|
||||
def getLevel = { synchronized { delegate.getLevel } }
|
||||
def setLevel(newLevel: Level.Value) { synchronized { delegate.setLevel(newLevel) } }
|
||||
def enableTrace(enabled: Boolean) { synchronized { delegate.enableTrace(enabled) } }
|
||||
def traceEnabled: Boolean = { synchronized { delegate.traceEnabled } }
|
||||
def setTrace(level: Int) { synchronized { delegate.setTrace(level) } }
|
||||
def getTrace: Int = { synchronized { delegate.getTrace } }
|
||||
|
||||
def trace(t: => Throwable) { synchronized { delegate.trace(t) } }
|
||||
def log(level: Level.Value, message: => String) { synchronized { delegate.log(level, message) } }
|
||||
|
|
@ -95,10 +96,10 @@ final class MultiLogger(delegates: List[Logger]) extends BasicLogger
|
|||
super.setLevel(newLevel)
|
||||
dispatch(new SetLevel(newLevel))
|
||||
}
|
||||
override def enableTrace(enabled: Boolean)
|
||||
override def setTrace(level: Int)
|
||||
{
|
||||
super.enableTrace(enabled)
|
||||
dispatch(new SetTrace(enabled))
|
||||
super.setTrace(level)
|
||||
dispatch(new SetTrace(level))
|
||||
}
|
||||
def trace(t: => Throwable) { dispatch(new Trace(t)) }
|
||||
def log(level: Level.Value, message: => String) { dispatch(new Log(level, message)) }
|
||||
|
|
@ -119,6 +120,8 @@ final class FilterLogger(delegate: Logger) extends BasicLogger
|
|||
if(traceEnabled)
|
||||
delegate.trace(t)
|
||||
}
|
||||
override def setTrace(level: Int) { delegate.setTrace(level) }
|
||||
override def getTrace = delegate.getTrace
|
||||
def log(level: Level.Value, message: => String)
|
||||
{
|
||||
if(atLevel(level))
|
||||
|
|
@ -216,12 +219,12 @@ final class BufferedLogger(delegate: Logger) extends Logger
|
|||
delegate.setLevel(newLevel)
|
||||
}
|
||||
def getLevel = synchronized { delegate.getLevel }
|
||||
def traceEnabled = synchronized { delegate.traceEnabled }
|
||||
def enableTrace(flag: Boolean): Unit =
|
||||
def getTrace = synchronized { delegate.getTrace }
|
||||
def setTrace(level: Int): Unit =
|
||||
synchronized
|
||||
{
|
||||
buffer.foreach{_ += new SetTrace(flag) }
|
||||
delegate.enableTrace(flag)
|
||||
buffer.foreach{_ += new SetTrace(level) }
|
||||
delegate.setTrace(level)
|
||||
}
|
||||
|
||||
def trace(t: => Throwable): Unit =
|
||||
|
|
@ -295,8 +298,9 @@ class ConsoleLogger extends BasicLogger
|
|||
def trace(t: => Throwable): Unit =
|
||||
System.out.synchronized
|
||||
{
|
||||
if(traceEnabled)
|
||||
t.printStackTrace
|
||||
val traceLevel = getTrace
|
||||
if(traceLevel >= 0)
|
||||
System.out.synchronized { System.out.print(StackTrace.trimmed(t, traceLevel)) }
|
||||
}
|
||||
def log(level: Level.Value, message: => String)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ object Main
|
|||
val UsageErrorExitCode = 4
|
||||
val BuildErrorExitCode = 5
|
||||
val ProgramErrorExitCode = 6
|
||||
val MaxInt = java.lang.Integer.MAX_VALUE
|
||||
}
|
||||
|
||||
import Main._
|
||||
|
|
@ -385,6 +386,8 @@ class xMain extends xsbti.AppMain
|
|||
setProperty(currentProject, action.substring(SetAction.length + 1))
|
||||
else if(action.startsWith(GetAction + " "))
|
||||
getProperty(currentProject, action.substring(GetAction.length + 1))
|
||||
else if(action.startsWith(TraceCommand + " "))
|
||||
setTrace(currentProject, action.substring(TraceCommand.length + 1))
|
||||
else
|
||||
handleCommand(currentProject, action)
|
||||
}
|
||||
|
|
@ -432,6 +435,7 @@ class xMain extends xsbti.AppMain
|
|||
case GetAction => getArgumentError(project.log)
|
||||
case SetAction => setArgumentError(project.log)
|
||||
case ProjectAction => setProjectError(project.log)
|
||||
case TraceCommand => setTraceError(project.log); true
|
||||
case ShowCurrent =>
|
||||
printProject("Current project is ", project)
|
||||
Console.println("Current Scala version is " + project.buildScalaVersion)
|
||||
|
|
@ -439,7 +443,6 @@ class xMain extends xsbti.AppMain
|
|||
printTraceEnabled(project)
|
||||
true
|
||||
case ShowActions => showActions(project); true
|
||||
case TraceCommand => toggleTrace(project); true
|
||||
case Level(level) => setLevel(project, level); true
|
||||
case ContinuousCompileCommand => compileContinuously(project)
|
||||
case action if action.startsWith(ContinuousExecutePrefix) => executeContinuously(project, action.substring(ContinuousExecutePrefix.length).trim)
|
||||
|
|
@ -493,15 +496,21 @@ class xMain extends xsbti.AppMain
|
|||
}
|
||||
|
||||
/** Toggles whether stack traces are enabled.*/
|
||||
private def toggleTrace(project: Project)
|
||||
private def setTrace(project: Project, value: String): Boolean =
|
||||
{
|
||||
val newValue = !project.log.traceEnabled
|
||||
project.projectClosure.foreach(_.log.enableTrace(newValue))
|
||||
printTraceEnabled(project)
|
||||
try
|
||||
{
|
||||
val newValue = if(value == "on") MaxInt else if(value == "off") -1 else if(value == "nosbt") 0 else value.toInt
|
||||
project.projectClosure.foreach(_.log.setTrace(newValue))
|
||||
printTraceEnabled(project)
|
||||
true
|
||||
}
|
||||
catch { case _: NumberFormatException => setTraceError(project.log) }
|
||||
}
|
||||
private def printTraceEnabled(project: Project)
|
||||
{
|
||||
Console.println("Stack traces are " + (if(project.log.traceEnabled) "enabled" else "disabled"))
|
||||
def traceLevel(level: Int) = if(level == 0) " (no stack elements)" else if(level == MaxInt) "" else " (maximum " + level + " stack elements per exception)"
|
||||
Console.println("Stack traces are " + (if(project.log.traceEnabled) "enabled" + traceLevel(project.log.getTrace) else "disabled"))
|
||||
}
|
||||
/** Sets the logging level on the given project.*/
|
||||
private def setLevel(project: Project, level: Level.Value)
|
||||
|
|
@ -688,6 +697,7 @@ class xMain extends xsbti.AppMain
|
|||
}
|
||||
|
||||
private def isTerminateAction(s: String) = TerminateActions.elements.contains(s.toLowerCase)
|
||||
private def setTraceError(log: Logger) = logError(log)("Invalid arguments for 'trace': expected 'on', 'off', or integer number of stack elements to show per exception.")
|
||||
private def setArgumentError(log: Logger) = logError(log)("Invalid arguments for 'set': expected property name and new value.")
|
||||
private def getArgumentError(log: Logger) = logError(log)("Invalid arguments for 'get': expected property name.")
|
||||
private def setProjectError(log: Logger) = logError(log)("Invalid arguments for 'project': expected project name.")
|
||||
|
|
|
|||
|
|
@ -311,7 +311,6 @@ object Project
|
|||
{
|
||||
val log = new ConsoleLogger
|
||||
log.setLevel(Level.Debug)
|
||||
log.enableTrace(true)
|
||||
log
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ class Resources(val baseDirectory: File, additional: ClassLoader, app: AppProvid
|
|||
{
|
||||
val buffered = new BufferedLogger(log)
|
||||
buffered.setLevel(Level.Debug)
|
||||
buffered.enableTrace(true)
|
||||
def error(msg: String) =
|
||||
{
|
||||
buffered.stopAll()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Tony Sloane
|
||||
*/
|
||||
package sbt
|
||||
|
||||
object StackTrace
|
||||
{
|
||||
def isSbtClass(name: String) = name.startsWith("sbt") || name.startsWith("xsbt")
|
||||
/**
|
||||
* Return a printable representation of the stack trace associated
|
||||
* with t. Information about t and its Throwable causes is included.
|
||||
* The number of lines to be included for each Throwable is configured
|
||||
* via d which should be greater than or equal to zero. If d is zero,
|
||||
* then all elements are included up to (but not including) the first
|
||||
* element that comes from sbt. If d is greater than zero, then up to
|
||||
* that many lines are included, where the line for the Throwable is
|
||||
* counted plus one line for each stack element. Less lines will be
|
||||
* included if there are not enough stack elements.
|
||||
*/
|
||||
def trimmed(t : Throwable, d : Int) : String = {
|
||||
require(d >= 0)
|
||||
val b = new StringBuilder ()
|
||||
|
||||
def appendStackTrace (t : Throwable, first : Boolean) {
|
||||
|
||||
val include : StackTraceElement => Boolean =
|
||||
if (d == 0)
|
||||
element => !isSbtClass(element.getClassName)
|
||||
else {
|
||||
var count = d - 1
|
||||
(_ => { count -= 1; count >= 0 })
|
||||
}
|
||||
|
||||
def appendElement (e : StackTraceElement) {
|
||||
b.append ("\tat ")
|
||||
b.append (e)
|
||||
b.append ('\n')
|
||||
}
|
||||
|
||||
if (!first)
|
||||
b.append ("Caused by: ")
|
||||
b.append (t)
|
||||
b.append ('\n')
|
||||
|
||||
val els = t.getStackTrace ()
|
||||
var i = 0
|
||||
while ((i < els.size) && include (els (i))) {
|
||||
appendElement (els (i))
|
||||
i += 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
appendStackTrace (t, true)
|
||||
var c = t
|
||||
while (c.getCause () != null) {
|
||||
c = c.getCause ()
|
||||
appendStackTrace (c, false)
|
||||
}
|
||||
b.toString ()
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008 Mark Harrah
|
||||
* Copyright 2008, 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
|
|
@ -82,9 +82,6 @@ private trait JettyRun
|
|||
}
|
||||
sealed trait JettyConfiguration extends NotNull
|
||||
{
|
||||
def war: Path
|
||||
def scanDirectories: Seq[File]
|
||||
def scanInterval: Int
|
||||
/** The classpath to get Jetty from. */
|
||||
def jettyClasspath: PathFinder
|
||||
def classpathName: String
|
||||
|
|
@ -92,6 +89,10 @@ sealed trait JettyConfiguration extends NotNull
|
|||
}
|
||||
trait DefaultJettyConfiguration extends JettyConfiguration
|
||||
{
|
||||
def war: Path
|
||||
def scanDirectories: Seq[File]
|
||||
def scanInterval: Int
|
||||
|
||||
def contextPath: String
|
||||
def port: Int
|
||||
/** The classpath containing the classes, jars, and resources for the web application. */
|
||||
|
|
@ -129,7 +130,27 @@ private object LazyJettyRun extends JettyRun
|
|||
Log.setLog(new JettyLogger(configuration.log))
|
||||
val server = new Server
|
||||
|
||||
val listener =
|
||||
def configureScanner(listener: Scanner.BulkListener, scanDirectories: Seq[File], scanInterval: Int) =
|
||||
{
|
||||
if(scanDirectories.isEmpty)
|
||||
None
|
||||
else
|
||||
{
|
||||
configuration.log.debug("Scanning for changes to: " + scanDirectories.mkString(", "))
|
||||
val scanner = new Scanner
|
||||
val list = new java.util.ArrayList[File]
|
||||
scanDirectories.foreach(x => list.add(x))
|
||||
scanner.setScanDirs(list)
|
||||
scanner.setRecursive(true)
|
||||
scanner.setScanInterval(scanInterval)
|
||||
scanner.setReportExistingFilesOnStartup(false)
|
||||
scanner.addListener(listener)
|
||||
scanner.start()
|
||||
Some(new WeakReference(scanner))
|
||||
}
|
||||
}
|
||||
|
||||
val (listener, scanner) =
|
||||
configuration match
|
||||
{
|
||||
case c: DefaultJettyConfiguration =>
|
||||
|
|
@ -144,43 +165,23 @@ private object LazyJettyRun extends JettyRun
|
|||
setLoader()
|
||||
server.setHandler(webapp)
|
||||
|
||||
Some(new Scanner.BulkListener with Reload {
|
||||
val listener = new Scanner.BulkListener with Reload {
|
||||
def reloadApp() = reload(server, setLoader(), log)
|
||||
def filesChanged(files: java.util.List[_]) { reloadApp() }
|
||||
})
|
||||
}
|
||||
(Some(listener), configureScanner(listener, c.scanDirectories, c.scanInterval))
|
||||
case c: CustomJettyConfiguration =>
|
||||
for(x <- c.jettyConfigurationXML)
|
||||
(new XmlConfiguration(x.toString)).configure(server)
|
||||
for(file <- c.jettyConfigurationFiles)
|
||||
(new XmlConfiguration(file.toURI.toURL)).configure(server)
|
||||
None
|
||||
(None, None)
|
||||
}
|
||||
|
||||
def configureScanner() =
|
||||
{
|
||||
val scanDirectories = configuration.scanDirectories
|
||||
if(listener.isEmpty || scanDirectories.isEmpty)
|
||||
None
|
||||
else
|
||||
{
|
||||
configuration.log.debug("Scanning for changes to: " + scanDirectories.mkString(", "))
|
||||
val scanner = new Scanner
|
||||
val list = new java.util.ArrayList[File]
|
||||
scanDirectories.foreach(x => list.add(x))
|
||||
scanner.setScanDirs(list)
|
||||
scanner.setRecursive(true)
|
||||
scanner.setScanInterval(configuration.scanInterval)
|
||||
scanner.setReportExistingFilesOnStartup(false)
|
||||
scanner.addListener(listener.get)
|
||||
scanner.start()
|
||||
Some(new WeakReference(scanner))
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
server.start()
|
||||
new StopServer(new WeakReference(server), listener.map(new WeakReference(_)), configureScanner(), oldLog)
|
||||
new StopServer(new WeakReference(server), listener.map(new WeakReference(_)), scanner, oldLog)
|
||||
}
|
||||
catch { case e => server.stop(); throw e }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import sbt._
|
||||
|
||||
class BlankProject(info: ProjectInfo) extends DefaultProject(info)
|
||||
Loading…
Reference in New Issue