From 1c8b55107d0439457d5605e35a7c5d75b1edf4c5 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 2 May 2021 20:32:31 -0400 Subject: [PATCH] Fix new command leaving behind target, take 2 Fixes #2835 Somehow the fix in #4033 due to various initialization. Here's a bit more aggressive rebasing of the base directory that should fix the `project` and `target` directory created during sbt new. --- main/src/main/scala/sbt/Main.scala | 58 ++++++++++++++----- .../main/scala/sbt/TemplateCommandUtil.scala | 25 +++----- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 2064fa514..7f18bf70e 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -71,22 +71,54 @@ private[sbt] object xMain { .filterNot(_ == DashDashServer) val isClient: String => Boolean = cmd => (cmd == DashClient) || (cmd == DashDashClient) val isBsp: String => Boolean = cmd => (cmd == "-bsp") || (cmd == "--bsp") - val isServer = !userCommands.exists(c => isBsp(c) || isClient(c)) - val bootServerSocket = if (isServer) getSocketOrExit(configuration) match { + val isNew: String => Boolean = cmd => (cmd == "new") + lazy val isServer = !userCommands.exists(c => isBsp(c) || isClient(c)) + // keep this lazy to prevent project directory created prematurely + lazy val bootServerSocket = if (isServer) getSocketOrExit(configuration) match { case (_, Some(e)) => return e case (s, _) => s } else None - if (userCommands.exists(isBsp)) { - BspClient.run(dealiasBaseDirectory(configuration)) - } else { - bootServerSocket.foreach(l => ITerminal.setBootStreams(l.inputStream, l.outputStream)) - val detachStdio = userCommands.exists(_ == BasicCommandStrings.DashDashDetachStdio) - ITerminal.withStreams(true, isSubProcess = detachStdio) { - if (clientModByEnv || userCommands.exists(isClient)) { + lazy val detachStdio = userCommands.exists(_ == BasicCommandStrings.DashDashDetachStdio) + def withStreams[A](f: => A): A = + try { + bootServerSocket.foreach(l => ITerminal.setBootStreams(l.inputStream, l.outputStream)) + ITerminal.withStreams(true, isSubProcess = detachStdio) { + f + } + } finally { + if (ITerminal.isAnsiSupported) { + // Clear any stray progress lines + System.out.print(ConsoleAppender.ClearScreenAfterCursor) + System.out.flush() + } + } + + userCommands match { + case cmds if cmds.exists(isBsp) => + BspClient.run(dealiasBaseDirectory(configuration)) + case cmds if cmds.exists(isNew) => + IO.withTemporaryDirectory { tempDir => + val rebasedConfig = new xsbti.AppConfiguration { + override def arguments: Array[String] = configuration.arguments() + override val baseDirectory: File = tempDir / "new" + override def provider: AppProvider = configuration.provider() + } + val state = StandardMain + .initialState( + rebasedConfig, + Seq(defaults, early), + runEarly(DefaultsCommand) :: runEarly(InitCommand) :: BootCommand :: Nil + ) + StandardMain.runManaged(state) + } + case _ if clientModByEnv || userCommands.exists(isClient) => + withStreams { val args = userCommands.toList.filterNot(isClient) Exit(NetworkClient.run(dealiasBaseDirectory(configuration), args)) - } else { + } + case _ => + withStreams { val state0 = StandardMain .initialState( dealiasBaseDirectory(configuration), @@ -101,15 +133,9 @@ private[sbt] object xMain { try StandardMain.runManaged(state) finally bootServerSocket.foreach(_.close()) } - } } } finally { - // Clear any stray progress lines ShutdownHooks.close() - if (ITerminal.isAnsiSupported) { - System.out.print(ConsoleAppender.ClearScreenAfterCursor) - System.out.flush() - } } } diff --git a/main/src/main/scala/sbt/TemplateCommandUtil.scala b/main/src/main/scala/sbt/TemplateCommandUtil.scala index 34b1181ef..6c8831bbe 100644 --- a/main/src/main/scala/sbt/TemplateCommandUtil.scala +++ b/main/src/main/scala/sbt/TemplateCommandUtil.scala @@ -33,30 +33,19 @@ private[sbt] object TemplateCommandUtil { private def runTemplate(s0: State, inputArg: Seq[String]): State = { import BuildPaths._ - val extracted0 = (Project extract s0) val globalBase = getGlobalBase(s0) - val stagingDirectory = getStagingDirectory(s0, globalBase).getCanonicalFile - val templateStage = stagingDirectory / "new" - // This moves the target directory to a staging directory - // https://github.com/sbt/sbt/issues/2835 - val state = extracted0.appendWithSession( - Seq( - Keys.target := templateStage - ), - s0 - ) - val infos = (state get templateResolverInfos getOrElse Nil).toList - val log = state.globalLogging.full - val extracted = (Project extract state) - val (s2, ivyConf) = extracted.runTask(Keys.ivyConfiguration, state) + val infos = (s0 get templateResolverInfos getOrElse Nil).toList + val log = s0.globalLogging.full + val extracted = (Project extract s0) + val (s1, ivyConf) = extracted.runTask(Keys.ivyConfiguration, s0) val scalaModuleInfo = extracted.get(Keys.updateSbtClassifiers / Keys.scalaModuleInfo) val arguments = inputArg.toList ++ - (state.remainingCommands match { + (s0.remainingCommands match { case exec :: Nil if exec.commandLine == "shell" => Nil case xs => xs map (_.commandLine) }) - run(infos, arguments, state.configuration, ivyConf, globalBase, scalaModuleInfo, log) - TerminateAction :: s2.copy(remainingCommands = Nil) + run(infos, arguments, s0.configuration, ivyConf, globalBase, scalaModuleInfo, log) + TerminateAction :: s1.copy(remainingCommands = Nil) } private def run(