Merge branch 'develop' into bspBuildTargetResources

This commit is contained in:
Samuel CLARENC 2021-06-21 16:52:58 +02:00 committed by GitHub
commit c9562cb1c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 121 additions and 19 deletions

View File

@ -107,7 +107,7 @@ private[sbt] final class ProgressState(
val parts = new String(bytes, "UTF-8").split(System.lineSeparator)
def appendLine(l: String, appendNewline: Boolean): Unit = {
toWrite ++= l.getBytes("UTF-8")
toWrite ++= clearScreenBytes
if (!l.getBytes("UTF-8").endsWith("\r")) toWrite ++= clearScreenBytes
if (appendNewline) toWrite ++= lineSeparatorBytes
}
parts.dropRight(1).foreach(appendLine(_, true))

View File

@ -346,7 +346,7 @@ object Terminal {
consoleTerminalHolder.set(newConsoleTerminal())
if (hasVirtualIO) {
hasProgress.set(isServer && isAnsiSupported)
activeTerminal.set(consoleTerminalHolder.get)
Terminal.set(consoleTerminalHolder.get)
try withOut(withIn(f))
finally {
jline.TerminalFactory.reset()
@ -382,7 +382,16 @@ object Terminal {
}
private[this] object ProxyTerminal extends Terminal {
private def t: Terminal = activeTerminal.get
private def t: Terminal = {
val current = activeTerminal.get
// if the activeTerminal is yet to be initialized on use,
// initialize to the conventional simple terminal for compatibility and testing
if (current ne null) current
else {
Terminal.set(Terminal.SimpleTerminal)
activeTerminal.get
}
}
override private[sbt] def progressState: ProgressState = t.progressState
override private[sbt] def enterRawMode(): Unit = t.enterRawMode()
override private[sbt] def exitRawMode(): Unit = t.exitRawMode()

View File

@ -21,8 +21,8 @@ class ManagedLoggerSpec extends FlatSpec with Matchers {
"ManagedLogger" should "log to console" in {
val log = newLogger("foo")
context.addAppender("foo", asyncStdout -> Level.Info)
log.info("test")
log.debug("test")
log.info("test_info")
log.debug("test_debug")
}
it should "support event logging" in {

View File

@ -0,0 +1,41 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util
import java.io.{ File, PrintStream }
import org.scalatest.{ BeforeAndAfterAll, FlatSpec }
import sbt.internal.util.Terminal.SimpleTerminal
import scala.io.Source
class ProgressStateSpec extends FlatSpec with BeforeAndAfterAll {
private lazy val fileIn = new File("/tmp/tmp.txt")
private lazy val fileOut = Source.fromFile("/tmp/tmp.txt")
override def afterAll(): Unit = {
fileIn.delete()
fileOut.close()
super.afterAll()
}
"test" should "not clear after carriage return (\\r) " in {
val ps = new ProgressState(1, 8)
val in = "Hello\r\nWorld".getBytes()
ps.write(SimpleTerminal, in, new PrintStream(fileIn), hasProgress = true)
val clearScreenBytes = ConsoleAppender.ClearScreenAfterCursor.getBytes("UTF-8")
val check = fileOut.getLines().toList.map { line =>
line.getBytes("UTF-8").endsWith(clearScreenBytes)
}
assert(check === List(false, true))
}
}

View File

@ -10,29 +10,34 @@ package internal
import java.io.File
import java.nio.file.Path
import Keys._
import SlashSyntax0._
import ScopeFilter.Make._
import Project._ // for tag and inTask()
import org.apache.ivy.core.module.descriptor.{ Artifact => IArtifact, DefaultArtifact }
import org.apache.ivy.core.resolve.DownloadOptions
import org.apache.ivy.core.module.descriptor.{ DefaultArtifact, Artifact => IArtifact }
import org.apache.ivy.core.report.DownloadStatus
import org.apache.ivy.core.resolve.DownloadOptions
import org.apache.ivy.plugins.resolver.DependencyResolver
import std.TaskExtra._ // for join
import sbt.Defaults.prefix
import sbt.Keys._
import sbt.Project._
import sbt.ScopeFilter.Make._
import sbt.SlashSyntax0._
import sbt.coursierint.LMCoursier
import sbt.internal.inc.{ HashUtil, JarUtils }
import sbt.internal.librarymanagement._
import sbt.internal.remotecache._
import sbt.io.IO
import sbt.io.Path.{ flat, rebase }
import sbt.io.syntax._
import sbt.librarymanagement._
import sbt.librarymanagement.ivy.{ Credentials, IvyPaths, UpdateOptions }
import sbt.librarymanagement.syntax._
import sbt.nio.FileStamp
import sbt.nio.Keys.{ inputFileStamps, outputFileStamps }
import sbt.internal.librarymanagement._
import sbt.io.IO
import sbt.io.syntax._
import sbt.internal.remotecache._
import sbt.internal.inc.{ HashUtil, JarUtils }
import sbt.std.TaskExtra._
import sbt.util.InterfaceUtil.toOption
import sbt.util.Logger
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
import xsbti.FileConverter
import scala.annotation.nowarn
object RemoteCache {
@ -152,6 +157,25 @@ object RemoteCache {
) ++ inConfig(Compile)(configCacheSettings(compileArtifact(Compile, cachedCompileClassifier)))
++ inConfig(Test)(configCacheSettings(testArtifact(Test, cachedTestClassifier))))
def getResourceFilePaths() = Def.task {
import sbt.librarymanagement.LibraryManagementCodec._
val t = classDirectory.value
val dirs = resourceDirectories.value.toSet
val flt: File => Option[File] = flat(t)
val cacheDirectory = crossTarget.value / (prefix(configuration.value.name) + "caches")
val converter = fileConverter.value
val transform: File => Option[File] = (f: File) => rebase(dirs, t)(f).orElse(flt(f))
val resourcesInClassesDir = resources.value
.flatMap(x => transform(x).toList)
.map(f => converter.toVirtualFile(f.toPath).toString)
val json = Converter.toJson[Seq[String]](resourcesInClassesDir).get
val tmp = CompactPrinter(json)
val file = cacheDirectory / "resources.json"
IO.write(file, tmp)
file
}
@nowarn
def configCacheSettings[A <: RemoteCacheArtifact](
cacheArtifactTask: Def.Initialize[Task[A]]
@ -167,6 +191,10 @@ object RemoteCache {
if (af.exists && artp.length() > 0) {
JarUtils.includeInJar(artp, Vector(af -> s"META-INF/inc_compile.zip"))
}
val rf = getResourceFilePaths.value
if (rf.exists) {
JarUtils.includeInJar(artp, Vector(rf -> s"META-INF/resources.json"))
}
// val testStream = (test / streams).?.value
// testStream foreach { s =>
// val sf = Defaults.succeededFile(s.cacheDirectory)
@ -249,6 +277,7 @@ object RemoteCache {
val smi = scalaModuleInfo.value
val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
val nonPom = artifacts.filterNot(isPomArtifact).toVector
val converter = fileConverter.value
m.withModule(log) {
case (ivy, md, _) =>
val resolver = ivy.getSettings.getResolver(r.name)
@ -281,7 +310,7 @@ object RemoteCache {
findJar(classifier, v, jars) match {
case Some(jar) =>
extractJar(art, jar)
extractJar(art, jar, converter)
log.info(s"remote cache artifact extracted for $p $classifier")
case None =>
@ -369,11 +398,16 @@ object RemoteCache {
jars.find(_.toString.endsWith(suffix))
}
private def extractJar(cacheArtifact: RemoteCacheArtifact, jar: File): Unit =
private def extractJar(
cacheArtifact: RemoteCacheArtifact,
jar: File,
converter: FileConverter
): Unit =
cacheArtifact match {
case a: CompileRemoteCacheArtifact =>
extractCache(jar, a.extractDirectory, preserveLastModified = true) { output =>
extractAnalysis(output, a.analysisFile)
extractResourceList(output, converter)
}
case a: TestRemoteCacheArtifact =>
@ -411,6 +445,23 @@ object RemoteCache {
}
}
private def extractResourceList(output: File, converter: FileConverter): Unit = {
import sbt.librarymanagement.LibraryManagementCodec._
import sjsonnew.support.scalajson.unsafe.{ Converter, Parser }
import xsbti.VirtualFileRef
val resourceFilesToDelete = output / "META-INF" / "resources.json"
if (resourceFilesToDelete.exists) {
val readFile = IO.read(resourceFilesToDelete)
val parseFile = Parser.parseUnsafe(readFile)
val resourceFiles = Converter.fromJsonUnsafe[Seq[String]](parseFile)
val paths = resourceFiles.map(f => converter.toPath(VirtualFileRef.of(f)))
val filesToDelete = paths.map(_.toFile)
for (file <- filesToDelete if file.getAbsolutePath.startsWith(output.getAbsolutePath))
IO.delete(file)
}
}
private def extractTestResult(output: File, testResult: File): Unit = {
//val expandedTestResult = output / "META-INF" / "succeeded_tests"
//if (expandedTestResult.exists) {

View File

@ -18,6 +18,7 @@ object BuildTargetTag {
def fromConfig(config: String): Vector[String] = config match {
case "test" => Vector(test)
case "it" => Vector(integrationTest)
case "compile" => Vector(library)
case _ => Vector.empty
}