diff --git a/cache/jvm/src/main/scala/coursier/Cache.scala b/cache/jvm/src/main/scala/coursier/Cache.scala index 5564ec177..88874d8fe 100644 --- a/cache/jvm/src/main/scala/coursier/Cache.scala +++ b/cache/jvm/src/main/scala/coursier/Cache.scala @@ -1165,7 +1165,20 @@ object Cache { def gettingLength(url: String): Unit = {} def gettingLengthResult(url: String, length: Option[Long]): Unit = {} - def removedCorruptFile(url: String, file: File, reason: Option[FileError]): Unit + def removedCorruptFile(url: String, file: File, reason: Option[FileError]): Unit = {} + + /*** + * + * @param beforeOutput: called before any output is printed, iff something else is outputed. + * (That is, if that `Logger` doesn't print any progress, + * `initialMessage` won't be printed either.) + */ + def init(beforeOutput: => Unit): Unit = {} + /** + * + * @return whether any message was printed by `Logger` + */ + def stopDidPrintSomething(): Boolean = false } var bufferSize = 1024*1024 diff --git a/cache/jvm/src/main/scala/coursier/TermDisplay.scala b/cache/jvm/src/main/scala/coursier/TermDisplay.scala index 0cd0f8cfa..7f1cb95f5 100644 --- a/cache/jvm/src/main/scala/coursier/TermDisplay.scala +++ b/cache/jvm/src/main/scala/coursier/TermDisplay.scala @@ -410,13 +410,7 @@ class TermDisplay( else 1000L / 60 - /*** - * - * @param beforeOutput: called before any output is printed, iff something else is outputed. - * (That is, if that `TermDisplay` doesn't print any progress, - * `initialMessage` won't be printed either.) - */ - def init(beforeOutput: => Unit): Unit = { + override def init(beforeOutput: => Unit): Unit = { updateRunnableOpt = Some(new UpdateDisplayRunnable(beforeOutput, out, width, fallbackMode0)) updateRunnable.init() @@ -426,11 +420,7 @@ class TermDisplay( def init(): Unit = init(()) - /** - * - * @return whether any message was printed by this `TermDisplay` - */ - def stopDidPrintSomething(): Boolean = { + override def stopDidPrintSomething(): Boolean = { scheduler.shutdown() scheduler.awaitTermination(2 * refreshInterval, TimeUnit.MILLISECONDS) updateRunnable.stop() diff --git a/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala b/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala index c2d520f22..6527aabde 100644 --- a/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala +++ b/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala @@ -1,5 +1,6 @@ package coursier +import java.io.OutputStreamWriter import sbt.librarymanagement._ import sbt.{ Configuration, Resolver, _ } import sbt.Keys._ @@ -52,6 +53,8 @@ object CoursierPlugin extends AutoPlugin { val coursierClassifiersArtifacts = Keys.coursierClassifiersArtifacts val coursierSbtClassifiersArtifacts = Keys.coursierSbtClassifiersArtifacts + val coursierLoggerFactory = Keys.coursierLoggerFactory + val coursierVersion = coursier.util.Properties.version val addSbtCoursier = { addSbtPlugin("io.get-coursier" % "sbt-coursier" % coursierVersion) @@ -306,7 +309,8 @@ object CoursierPlugin extends AutoPlugin { coursierCredentials := Map.empty, coursierCache := Cache.default, coursierReorderResolvers := true, - coursierKeepPreloaded := false + coursierKeepPreloaded := false, + coursierLoggerFactory := { () => new TermDisplay(new OutputStreamWriter(System.err)) } ) override lazy val projectSettings = coursierSettings(None, Seq(Compile, Test).map(c => c -> c.name)) ++ diff --git a/sbt-coursier/src/main/scala/coursier/Keys.scala b/sbt-coursier/src/main/scala/coursier/Keys.scala index 20b66924b..6c9213590 100644 --- a/sbt-coursier/src/main/scala/coursier/Keys.scala +++ b/sbt-coursier/src/main/scala/coursier/Keys.scala @@ -17,6 +17,7 @@ object Keys { val coursierCachePolicies = SettingKey[Seq[CachePolicy]]("coursier-cache-policies") val coursierTtl = SettingKey[Option[Duration]]("coursier-ttl") val coursierKeepPreloaded = SettingKey[Boolean]("coursier-keep-preloaded", "Whether to take into account sbt preloaded repositories or not") + val coursierLoggerFactory = SettingKey[() => Cache.Logger]("coursier-logger-factory") val coursierVerbosity = SettingKey[Int]("coursier-verbosity") diff --git a/sbt-coursier/src/main/scala/coursier/Tasks.scala b/sbt-coursier/src/main/scala/coursier/Tasks.scala index 6a8e24bfc..5c874d935 100644 --- a/sbt-coursier/src/main/scala/coursier/Tasks.scala +++ b/sbt-coursier/src/main/scala/coursier/Tasks.scala @@ -431,8 +431,6 @@ object Tasks { Module(scalaOrganization, "scalap") -> scalaVersion ) - private def createLogger() = new TermDisplay(new OutputStreamWriter(System.err)) - private[coursier] def exceptionPatternParser(): String => coursier.ivy.Pattern = { val props = sys.props.toMap @@ -571,7 +569,6 @@ object Tasks { def resolutionsTask( sbtClassifiers: Boolean = false ): Def.Initialize[sbt.Task[Map[Set[String], coursier.Resolution]]] = Def.taskDyn { - val projectName = thisProjectRef.value.project val sv = scalaVersion.value @@ -605,6 +602,7 @@ object Tasks { val cachePolicies = coursierCachePolicies.value val ttl = coursierTtl.value val cache = coursierCache.value + val createLogger = coursierLoggerFactory.value val log = streams.value.log @@ -692,7 +690,7 @@ object Tasks { def resolution(startRes: Resolution) = { var pool: ExecutorService = null - var resLogger: TermDisplay = null + var resLogger: Cache.Logger = null val printOptionalMessage = verbosityLevel >= 0 && verbosityLevel <= 1 @@ -954,7 +952,6 @@ object Tasks { ignoreArtifactErrors: Boolean = false, includeSignatures: Boolean = false ) = Def.taskDyn { - val projectName = thisProjectRef.value.project val parallelDownloads = coursierParallelDownloads.value @@ -962,6 +959,7 @@ object Tasks { val cachePolicies = coursierCachePolicies.value val ttl = coursierTtl.value val cache = coursierCache.value + val createLogger = coursierLoggerFactory.value val log = streams.value.log @@ -1007,7 +1005,7 @@ object Tasks { synchronized { var pool: ExecutorService = null - var artifactsLogger: TermDisplay = null + var artifactsLogger: Cache.Logger = null val printOptionalMessage = verbosityLevel >= 0 && verbosityLevel <= 1 diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/logger/build.sbt b/sbt-coursier/src/sbt-test/sbt-coursier/logger/build.sbt new file mode 100644 index 000000000..bd0ba0011 --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/logger/build.sbt @@ -0,0 +1,68 @@ +val logFile = settingKey[File]("") + +// Arbitrary dependency with no transitive dependencies +libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.25" +// We want to control when the cache gets a hit +coursierCache := baseDirectory.value / "cache" +logFile := baseDirectory.value / "log" + +coursierLoggerFactory := { + val logStream = new java.io.PrintStream(logFile.value) + def log(msg: String): Unit = { + println(msg) + logStream.println(msg) + } + val cacheFile = coursierCache.value + ;{ () => + new coursier.Cache.Logger { + override def init(beforeOutput: => Unit): Unit = { + beforeOutput + log("init") + } + override def foundLocally(url: String, file: File): Unit = { + log(s"found $url at ${IO.relativize(cacheFile, file).getOrElse(file)}") + } + override def downloadingArtifact(url: String, file: File): Unit = { + log(s"downloading $url to ${IO.relativize(cacheFile, file).getOrElse(file)}") + } + override def downloadedArtifact(url: String, success: Boolean): Unit = { + log(s"downloaded $url: $success") + } + override def stopDidPrintSomething(): Boolean = { + log("stop") + true + } + } + } +} + +TaskKey[Unit]("checkDownloaded") := { + val log = IO.readLines(logFile.value) + if (log.head != "init") { + sys.error(s"log started with '${log.head}', not init") + } + if (log.last != "stop") { + sys.error(s"log ended with '${log.last}', not stop") + } + val url = "https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar" + val downloadedMsg = s"downloaded $url: true" + val downloadingMsgStart = s"downloading $url to " + if (!log.contains(downloadedMsg)) + sys.error(s"log doesn't contain '$downloadedMsg'") + if (!log.exists(_.startsWith(downloadingMsgStart))) + sys.error(s"log doesn't contain line starting with '$downloadingMsgStart'") +} + +TaskKey[Unit]("checkFound") := { + val log = IO.readLines(logFile.value) + if (log.head != "init") { + sys.error(s"log started with '${log.head}', not init") + } + if (log.last != "stop") { + sys.error(s"log ended with '${log.last}', not stop") + } + val url = "https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar" + val msg = s"found $url at " + if (!log.exists(_.startsWith(msg))) + sys.error(s"log doesn't contain line starting with '$msg'") +} diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/logger/project/plugins.sbt b/sbt-coursier/src/sbt-test/sbt-coursier/logger/project/plugins.sbt new file mode 100644 index 000000000..152225a9e --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/logger/project/plugins.sbt @@ -0,0 +1,11 @@ +{ + val pluginVersion = sys.props.getOrElse( + "plugin.version", + throw new RuntimeException( + """|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin + ) + ) + + addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion) +} diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/logger/test b/sbt-coursier/src/sbt-test/sbt-coursier/logger/test new file mode 100644 index 000000000..157471011 --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/logger/test @@ -0,0 +1,6 @@ +$ delete cache +> update +> checkDownloaded +> reload +> update +> checkFound