From dc6584ff68c37b1a51cb6dbcce83ecfa1c0ecc37 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Mon, 18 Apr 2011 18:26:57 -0400 Subject: [PATCH] scripts: change base directory --- compile/Eval.scala | 2 +- main/Main.scala | 28 +++++++++++++++++++++------- main/Project.scala | 29 +++++++++++++---------------- main/Script.scala | 22 +++++++++++++++------- 4 files changed, 50 insertions(+), 31 deletions(-) diff --git a/compile/Eval.scala b/compile/Eval.scala index 82a6691a8..0c24db64d 100644 --- a/compile/Eval.scala +++ b/compile/Eval.scala @@ -180,7 +180,7 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se val DefaultStartLine = 0 private[this] def makeModuleName(hash: String): String = "$" + halve(hash) - private[this] def halve(s: String) = if(s.length > 2) s.substring(0, s.length / 2) + private[this] def halve(s: String): String = if(s.length > 2) s.substring(0, s.length / 2) else s private[this] def noImports = new EvalImports(Nil, "") private[this] def mkUnit(srcName: String, firstLine: Int, s: String) = new CompilationUnit(new EvalSourceFile(srcName, firstLine, s)) private[this] def checkError(label: String) = if(reporter.hasErrors) throw new EvalException(label) diff --git a/main/Main.scala b/main/Main.scala index 2d658d2a3..0b502f8c1 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -20,19 +20,30 @@ package sbt import java.io.File /** This class is the entry point for sbt.*/ -class xMain extends xsbti.AppMain +final class xMain extends xsbti.AppMain { - final def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = + def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = { - import BuiltinCommands.{initialize, defaults, DefaultBootCommands} + import BuiltinCommands.{initialAttributes, initialize, defaults, DefaultBootCommands} import CommandSupport.{DefaultsCommand, InitCommand} val initialCommandDefs = Seq(initialize, defaults) val commands = DefaultsCommand +: InitCommand +: (DefaultBootCommands ++ configuration.arguments.map(_.trim)) val state = State( configuration, initialCommandDefs, Set.empty, None, commands, initialAttributes, Next.Continue ) - run(state) + MainLoop.run(state) } - def initialAttributes = AttributeMap.empty.put(logged, ConsoleLogger()) - +} +final class ScriptMain extends xsbti.AppMain +{ + def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = + { + import BuiltinCommands.{initialAttributes, ScriptCommands} + val commands = Script.Name +: configuration.arguments.map(_.trim) + val state = State( configuration, ScriptCommands, Set.empty, None, commands, initialAttributes, Next.Continue ) + MainLoop.run(state) + } +} +object MainLoop +{ @tailrec final def run(state: State): xsbti.MainResult = { import Next._ @@ -59,7 +70,10 @@ class xMain extends xsbti.AppMain import CommandSupport._ object BuiltinCommands { - def DefaultCommands: Seq[Command] = Seq(ignore, help, reboot, read, history, continuous, exit, loadProject, loadProjectImpl, loadFailed, Script.command, Cross.crossBuild, Cross.switchVersion, + def initialAttributes = AttributeMap.empty.put(logged, ConsoleLogger()) + + def ScriptCommands: Seq[Command] = Seq(ignore, exit, Script.command, act, nop) + def DefaultCommands: Seq[Command] = Seq(ignore, help, reboot, read, history, continuous, exit, loadProject, loadProjectImpl, loadFailed, Cross.crossBuild, Cross.switchVersion, projects, project, setOnFailure, clearOnFailure, ifLast, multi, shell, set, inspect, eval, alias, append, last, lastGrep, nop, sessionCommand, act) def DefaultBootCommands: Seq[String] = LoadProject :: (IfLast + " " + Shell) :: Nil diff --git a/main/Project.scala b/main/Project.scala index d30e03623..927986716 100644 --- a/main/Project.scala +++ b/main/Project.scala @@ -8,6 +8,7 @@ package sbt import Project._ import Keys.{appConfiguration, stateBuildStructure, commands, configuration, historyPath, logged, projectCommand, sessionSettings, shellPrompt, streams, thisProject, thisProjectRef, watch} import Scope.{GlobalScope,ThisScope} + import Load.BuildStructure import CommandSupport.logger import Types.idFun @@ -58,7 +59,7 @@ sealed trait Project extends ProjectDefinition[ProjectReference] } sealed trait ResolvedProject extends ProjectDefinition[ProjectRef] -final case class Extracted(structure: Load.BuildStructure, session: SessionSettings, currentRef: ProjectRef, rootProject: URI => String) +final case class Extracted(structure: BuildStructure, session: SessionSettings, currentRef: ProjectRef, rootProject: URI => String) { lazy val currentUnit = structure units currentRef.build lazy val currentProject = currentUnit defined currentRef.project @@ -93,22 +94,18 @@ object Project extends Init[Scope] with ProjectExtra } def getOrError[T](state: State, key: AttributeKey[T], msg: String): T = state get key getOrElse error(msg) - def structure(state: State): Load.BuildStructure = getOrError(state, stateBuildStructure, "No build loaded.") + def structure(state: State): BuildStructure = getOrError(state, stateBuildStructure, "No build loaded.") def session(state: State): SessionSettings = getOrError(state, sessionSettings, "Session not initialized.") - def extract(state: State): Extracted = - { - val se = session(state) - val st = structure(state) - Extracted(st, se, se.current, Load.getRootProject(st.units)) - } + def extract(state: State): Extracted = extract( session(state), structure(state) ) + def extract(se: SessionSettings, st: BuildStructure): Extracted = Extracted(st, se, se.current, Load.getRootProject(st.units)) - def getProjectForReference(ref: Reference, structure: Load.BuildStructure): Option[ResolvedProject] = + def getProjectForReference(ref: Reference, structure: BuildStructure): Option[ResolvedProject] = ref match { case pr: ProjectRef => getProject(pr, structure); case _ => None } - def getProject(ref: ProjectRef, structure: Load.BuildStructure): Option[ResolvedProject] = + def getProject(ref: ProjectRef, structure: BuildStructure): Option[ResolvedProject] = (structure.units get ref.build).flatMap(_.defined get ref.project) - def setProject(session: SessionSettings, structure: Load.BuildStructure, s: State): State = + def setProject(session: SessionSettings, structure: BuildStructure, s: State): State = { val newAttrs = s.attributes.put(stateBuildStructure, structure).put(sessionSettings, session) val newState = s.copy(attributes = newAttrs) @@ -185,10 +182,10 @@ object Project extends Init[Scope] with ProjectExtra throw new MessageOnlyException(c.getMessage) } - def delegates(structure: Load.BuildStructure, scope: Scope, key: AttributeKey[_]): Seq[ScopedKey[_]] = + def delegates(structure: BuildStructure, scope: Scope, key: AttributeKey[_]): Seq[ScopedKey[_]] = structure.delegates(scope).map(d => ScopedKey(d, key)) - def details(structure: Load.BuildStructure, actual: Boolean, scope: Scope, key: AttributeKey[_]): String = + def details(structure: BuildStructure, actual: Boolean, scope: Scope, key: AttributeKey[_]): String = { val scoped = ScopedKey(scope,key) val value = @@ -213,13 +210,13 @@ object Project extends Init[Scope] with ProjectExtra printScopes("Delegates", delegates(structure, scope, key)) + printScopes("Related", related) } - def graphSettings(structure: Load.BuildStructure, basedir: File) + def graphSettings(structure: BuildStructure, basedir: File) { def graph(actual: Boolean, name: String) = graphSettings(structure, actual, name, new File(basedir, name + ".dot")) graph(true, "actual_dependencies") graph(false, "declared_dependencies") } - def graphSettings(structure: Load.BuildStructure, actual: Boolean, graphName: String, file: File) + def graphSettings(structure: BuildStructure, actual: Boolean, graphName: String, file: File) { type Rel = Relation[ScopedKey[_], ScopedKey[_]] val cMap = compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal) @@ -267,7 +264,7 @@ object Project extends Init[Scope] with ProjectExtra EvaluateTask.evaluateTask(extracted.structure, taskKey, state, extracted.currentRef, checkCycles, maxWorkers) } def globalLoggerKey = fillTaskAxis(ScopedKey(GlobalScope, streams.key)) - def installGlobalLogger(s: State, structure: Load.BuildStructure): State = + def installGlobalLogger(s: State, structure: BuildStructure): State = { val str = structure.streams(globalLoggerKey) str.open() diff --git a/main/Script.scala b/main/Script.scala index 70aaad390..fbc4ed228 100644 --- a/main/Script.scala +++ b/main/Script.scala @@ -10,25 +10,33 @@ package sbt object Script { + final val Name = "script" lazy val command = - Command.command("script") { state => + Command.command(Name) { state => val scriptArg = state.remainingCommands.headOption getOrElse error("No script file specified") val script = new File(scriptArg).getAbsoluteFile - val extracted = Project.extract(state) + val hash = halve(Hash.toHex(Hash(script.getAbsolutePath))) + val base = new File(state.configuration.provider.scalaProvider.launcher.bootDirectory, hash) + IO.createDirectory(base) + + val (eval, structure) = Load.defaultLoad(state, base, CommandSupport.logger(state)) + val session = Load.initialSession(structure, eval) + val extracted = Project.extract(session, structure) import extracted._ - val eval = session.currentEval() - val settings = blocks(script).flatMap { block => - evaluate(eval, script.getPath, block.lines, currentUnit.imports, block.offset+1) + val embeddedSettings = blocks(script).flatMap { block => + evaluate(eval(), script.getPath, block.lines, currentUnit.imports, block.offset+1) } val scriptAsSource = sources in Compile := script :: Nil val asScript = scalacOptions ++= Seq("-Xscript", script.getName.stripSuffix(".scala")) - val logQuiet = (logLevel in Global := Level.Warn) :: (showSuccess in Global := false) :: Nil - val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, asScript +: (logQuiet ++ settings)) + val scriptSettings = Seq(asScript, scriptAsSource, logLevel in Global := Level.Warn, showSuccess in Global := false) + val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, scriptSettings ++ embeddedSettings) + val newStructure = Load.reapply(session.original ++ append, structure) val newState = "run" :: state.copy(remainingCommands = state.remainingCommands.drop(1)) Project.setProject(session, newStructure, newState) } + def halve(s: String): String = if(s.length > 3) s.substring(0, s.length / 2) else s final case class Block(offset: Int, lines: Seq[String]) def blocks(file: File): Seq[Block] =