From 9bfc8a8f4a9b8771e4cf5485df88386532e9a123 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sun, 6 Dec 2009 22:58:53 -0500 Subject: [PATCH] Better handling of invalid Scala versions --- project/build.properties | 6 +++-- project/plugins/Plugins.scala | 2 +- scripted/project/build.properties | 4 +-- src/main/scala/sbt/Main.scala | 42 +++++++++++++++++++++++++------ src/main/scala/sbt/Project.scala | 32 +++++++++++++++++------ 5 files changed, 65 insertions(+), 21 deletions(-) diff --git a/project/build.properties b/project/build.properties index 4c694537f..c3fcade05 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1,5 +1,7 @@ +#Project properties +#Sun Dec 06 21:31:48 EST 2009 project.organization=org.scala-tools.sbt project.name=Simple Build Tool sbt.version=0.5.6 -project.version=0.6.5 -scala.version=2.7.5 +project.version=0.6.6 +scala.version=2.7.7 diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index f974c9607..caa313044 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -4,6 +4,6 @@ import java.net.URL class Plugins(info: ProjectInfo) extends PluginDefinition(info) { - val scripted = "org.scala-tools.sbt" % "test" % "0.6.5" + val scripted = "org.scala-tools.sbt" % "test" % "0.6.6" val technically = Resolver.url("technically.us", new URL("http://databinder.net/repo/"))(Resolver.ivyStylePatterns) } diff --git a/scripted/project/build.properties b/scripted/project/build.properties index 7145a46bc..8cda32990 100644 --- a/scripted/project/build.properties +++ b/scripted/project/build.properties @@ -3,6 +3,6 @@ project.organization=org.scala-tools.sbt project.name=test sbt.version=0.5.6 -project.version=0.6.5 -scala.version=2.7.5 +project.version=0.6.6 +scala.version=2.7.7 project.initialize=false diff --git a/src/main/scala/sbt/Main.scala b/src/main/scala/sbt/Main.scala index c75357577..d3d573d8d 100755 --- a/src/main/scala/sbt/Main.scala +++ b/src/main/scala/sbt/Main.scala @@ -155,13 +155,24 @@ class xMain extends xsbti.AppMain case InteractiveCommand :: _ => continue(project, prompt(baseProject, project) :: arguments, interactiveContinue) case SpecificBuild(version, action) :: tail => if(Some(version) != baseProject.info.buildScalaVersion) - throw new ReloadException(rememberCurrent(action :: tail), Some(version)) + { + if(checkVersion(baseProject, version)) + throw new ReloadException(rememberCurrent(action :: tail), Some(version)) + else + failed(UsageErrorExitCode) + } else continue(project, action :: tail, failAction) case CrossBuild(action) :: tail => if(checkAction(project, action)) - process(project, CrossBuild(project, action) ::: tail, failAction) + { + CrossBuild(project, action) match + { + case Some(actions) => continue(project, actions ::: tail, failAction) + case None => failed(UsageErrorExitCode) + } + } else failed(UsageErrorExitCode) @@ -257,21 +268,35 @@ class xMain extends xsbti.AppMain None } } + def checkVersion(p: Project, version: String) = + { + try { p.getScalaInstance(version); true } + catch { case e: xsbti.RetrieveException => p.log.error(e.getMessage); false } + } object CrossBuild { def unapply(s: String) = if(s.startsWith(CrossBuildPrefix) && !s.startsWith(SpecificBuildPrefix)) Some(s.substring(1)) else None - def apply(project: Project, action: String) = + def apply(project: Project, action: String): Option[List[String]] = { val againstScalaVersions = project.crossScalaVersions if(againstScalaVersions.isEmpty) { Console.println("Project does not declare any Scala versions to cross-build against, building against current version...") - action :: Nil + Some(action :: Nil) } else - againstScalaVersions.toList.map(SpecificBuildPrefix + _ + " " + action) ::: // build against all versions - (SpecificBuildPrefix + project.buildScalaVersion) :: // reset to the version before the cross-build - Nil + { + if( !againstScalaVersions.forall(v => checkVersion(project, v)) ) + None + else + { + val actions = + againstScalaVersions.toList.map(SpecificBuildPrefix + _ + " " + action) ::: // build against all versions + (SpecificBuildPrefix + project.buildScalaVersion) :: // reset to the version before the cross-build + Nil + Some(actions) + } + } } } private def readLines(project: Project, file: File): Option[List[String]] = @@ -382,7 +407,7 @@ class xMain extends xsbti.AppMain printCmd(ShowActions, "Shows all available actions.") printCmd(RebootCommand, "Reloads sbt, picking up modifications to sbt.version or scala.version and recompiling modified project definitions.") printCmd(HelpAction, "Displays this help message.") - printCmd(ShowCurrent, "Shows the current project and logging level of that project.") + printCmd(ShowCurrent, "Shows the current project, Scala version, and logging level.") printCmd(Level.levels.mkString(", "), "Set logging for the current project to the specified level.") printCmd(TraceCommand, "Toggles whether logging stack traces is enabled.") printCmd(ProjectAction + " ", "Sets the currently active project.") @@ -408,6 +433,7 @@ class xMain extends xsbti.AppMain case ProjectAction => setProjectError(project.log) case ShowCurrent => printProject("Current project is ", project) + Console.println("Current Scala version is " + project.buildScalaVersion) Console.println("Current log level is " + project.log.getLevel) printTraceEnabled(project) true diff --git a/src/main/scala/sbt/Project.scala b/src/main/scala/sbt/Project.scala index 59e931711..53f67a754 100644 --- a/src/main/scala/sbt/Project.scala +++ b/src/main/scala/sbt/Project.scala @@ -227,10 +227,24 @@ trait Project extends TaskManager with Dag[Project] with BasicEnvironment /** The definitive source for the version of Scala being used to *build* the project.*/ def buildScalaVersion = info.buildScalaVersion.getOrElse(crossScalaVersions.first) + def componentManager = new xsbt.ComponentManager(info.launcher.globalLock, info.app.components, log) - def buildScalaInstance = - localScalaInstances.find(_.version == buildScalaVersion) getOrElse - xsbt.ScalaInstance(buildScalaVersion, info.launcher) + def buildScalaInstance = buildScalaInstance0 + final def buildScalaInstance0: ScalaInstance = + { + try { getScalaInstance(buildScalaVersion) } + catch { case e: xsbti.RetrieveException if info.buildScalaVersion.isEmpty => // only catch the exception if this is the default Scala version + log.error(e.getMessage) + SimpleReader.readLine("\nProvide a new Scala version or press enter to exit: ") match + { + case Some(v) if v.length > 0=> buildScalaVersions() = v; saveEnvironment(); buildScalaInstance0 + case _ => throw e + } + } + } + def getScalaInstance(version: String) = + localScalaInstances.find(_.version == version) getOrElse + xsbt.ScalaInstance(version, info.launcher) lazy val localScalaInstances: Seq[ScalaInstance] = localScala ++ info.parent.toList.flatMap(_.localScalaInstances) def localScala: Seq[ScalaInstance] = Nil def buildCompiler = new AnalyzingCompiler(buildScalaInstance, componentManager) @@ -348,12 +362,14 @@ object Project case e: Exception => errorLoadingProject(e, log) } } - /** Logs the stack trace and returns an error message in Left.*/ private def errorLoadingProject(e: Throwable, log: Logger) = - { - log.trace(e) - new LoadError("Error loading project: " + e.toString) - } + e match + { + case _: xsbti.RetrieveException => LoadSetupDeclined + case _ => + log.trace(e) + new LoadError("Error loading project: " + e.toString) + } /** Loads the project for the given `info` and represented by an instance of 'builderClass'.*/ private[sbt] def constructProject[P <: Project](info: ProjectInfo, builderClass: Class[P]): P = builderClass.getConstructor(classOf[ProjectInfo]).newInstance(info)