From 8c0d441fec11a92c92bac3a77f3efe6c003a6fee Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 22 Mar 2011 18:19:48 -0400 Subject: [PATCH] clean up Ivy-related logging --- ivy/Ivy.scala | 42 ++++++++++++++++++++++++------------------ ivy/IvyActions.scala | 40 ++++++++++++++++++++-------------------- ivy/IvyCache.scala | 2 +- main/Defaults.scala | 24 +++++++++++++----------- 4 files changed, 58 insertions(+), 50 deletions(-) diff --git a/ivy/Ivy.scala b/ivy/Ivy.scala index 1a25cb1d1..21ba28bff 100644 --- a/ivy/Ivy.scala +++ b/ivy/Ivy.scala @@ -22,20 +22,20 @@ import plugins.latest.LatestRevisionStrategy import plugins.matcher.PatternMatcher import plugins.parser.m2.PomModuleDescriptorParser import plugins.resolver.ChainResolver -import util.Message +import util.{Message, MessageLogger} import scala.xml.NodeSeq final class IvySbt(val configuration: IvyConfiguration) { - import configuration.{log, baseDirectory} + import configuration.baseDirectory + /** ========== Configuration/Setup ============ * This part configures the Ivy instance by first creating the logger interface to ivy, then IvySettings, and then the Ivy instance. * These are lazy so that they are loaded within the right context. This is important so that no Ivy XML configuration needs to be loaded, * saving some time. This is necessary because Ivy has global state (IvyContext, Message, DocumentBuilder, ...). */ - private lazy val logger = new IvyLoggerInterface(log) - private def withDefaultLogger[T](f: => T): T = + private def withDefaultLogger[T](logger: MessageLogger)(f: => T): T = { def action() = IvySbt.synchronized @@ -55,7 +55,7 @@ final class IvySbt(val configuration: IvyConfiguration) case None => action() } } - private lazy val settings = + private lazy val settings: IvySettings = { val is = new IvySettings is.setBaseDir(baseDirectory) @@ -65,17 +65,17 @@ final class IvySbt(val configuration: IvyConfiguration) case e: ExternalIvyConfiguration => is.load(e.file) case i: InlineIvyConfiguration => IvySbt.configureCache(is, i.paths.cacheDirectory, i.localOnly) - IvySbt.setResolvers(is, i.resolvers, i.otherResolvers, i.localOnly, log) + IvySbt.setResolvers(is, i.resolvers, i.otherResolvers, i.localOnly, configuration.log) IvySbt.setModuleConfigurations(is, i.moduleConfigurations) } is } - private lazy val ivy = + private lazy val ivy: Ivy = { val i = new Ivy() { private val loggerEngine = new SbtMessageLoggerEngine; override def getLoggerEngine = loggerEngine } i.setSettings(settings) i.bind() - i.getLoggerEngine.pushLogger(logger) + i.getLoggerEngine.pushLogger(new IvyLoggerInterface(configuration.log)) i } // Must be the same file as is used in Update in the launcher @@ -83,24 +83,30 @@ final class IvySbt(val configuration: IvyConfiguration) /** ========== End Configuration/Setup ============*/ /** Uses the configured Ivy instance within a safe context.*/ - def withIvy[T](f: Ivy => T): T = - withDefaultLogger + def withIvy[T](log: Logger)(f: Ivy => T): T = + withIvy(new IvyLoggerInterface(log))(f) + + def withIvy[T](log: MessageLogger)(f: Ivy => T): T = + withDefaultLogger(log) { ivy.pushContext() + ivy.getLoggerEngine.pushLogger(log) try { f(ivy) } - finally { ivy.popContext() } + finally { + ivy.getLoggerEngine.popLogger() + ivy.popContext() + } } final class Module(rawModuleSettings: ModuleSettings) { val moduleSettings: ModuleSettings = IvySbt.substituteCross(rawModuleSettings) def owner = IvySbt.this - def logger = configuration.log - def withModule[T](f: (Ivy,DefaultModuleDescriptor,String) => T): T = - withIvy[T] { ivy => f(ivy, moduleDescriptor0, defaultConfig0) } + def withModule[T](log: Logger)(f: (Ivy,DefaultModuleDescriptor,String) => T): T = + withIvy[T](log) { ivy => f(ivy, moduleDescriptor0, defaultConfig0) } - def moduleDescriptor = withModule((_,md,_) => md) - def defaultConfig = withModule( (_,_,dc) => dc) + def moduleDescriptor(log: Logger): DefaultModuleDescriptor = withModule(log)((_,md,_) => md) + def defaultConfig(log: Logger): String = withModule(log)( (_,_,dc) => dc) // these should only be referenced by withModule because lazy vals synchronize on this object // withIvy explicitly locks the IvySbt object, so they have to be done in the right order to avoid deadlock private[this] lazy val (moduleDescriptor0: DefaultModuleDescriptor, defaultConfig0: String) = @@ -108,7 +114,7 @@ final class IvySbt(val configuration: IvyConfiguration) val (baseModule, baseConfiguration) = moduleSettings match { - case ic: InlineConfiguration => configureInline(ic) + case ic: InlineConfiguration => configureInline(ic, configuration.log) case ec: EmptyConfiguration => configureEmpty(ec.module) case pc: PomConfiguration => readPom(pc.file, pc.validate) case ifc: IvyFileConfiguration => readIvyFile(ifc.file, ifc.validate) @@ -117,7 +123,7 @@ final class IvySbt(val configuration: IvyConfiguration) baseModule.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String,String]].put("e", "http://ant.apache.org/ivy/extra") (baseModule, baseConfiguration) } - private def configureInline(ic: InlineConfiguration) = + private def configureInline(ic: InlineConfiguration, log: Logger) = { import ic._ val moduleID = newConfiguredModuleID(module, configurations) diff --git a/ivy/IvyActions.scala b/ivy/IvyActions.scala index 203331e21..95e779e43 100644 --- a/ivy/IvyActions.scala +++ b/ivy/IvyActions.scala @@ -39,12 +39,12 @@ object UpdateLogging extends Enumeration object IvyActions { /** Installs the dependencies of the given 'module' from the resolver named 'from' to the resolver named 'to'.*/ - def install(module: IvySbt#Module, from: String, to: String) + def install(module: IvySbt#Module, from: String, to: String, log: Logger) { - module.withModule { (ivy, md, default) => + module.withModule(log) { (ivy, md, default) => for(dependency <- md.getDependencies) { - module.logger.info("Installing " + dependency) + log.info("Installing " + dependency) val options = new InstallOptions options.setValidate(module.moduleSettings.validate) options.setTransitive(dependency.isTransitive) @@ -54,26 +54,26 @@ object IvyActions } /** Clears the Ivy cache, as configured by 'config'. */ - def cleanCache(ivy: IvySbt) = ivy.withIvy { iv => + def cleanCache(ivy: IvySbt, log: Logger) = ivy.withIvy(log) { iv => iv.getSettings.getResolutionCacheManager.clean() iv.getSettings.getRepositoryCacheManagers.foreach(_.clean()) } /** Creates a Maven pom from the given Ivy configuration*/ - def makePom(module: IvySbt#Module, configuration: MakePomConfiguration) + def makePom(module: IvySbt#Module, configuration: MakePomConfiguration, log: Logger) { import configuration.{configurations, extra, file, filterRepositories, process} - module.withModule { (ivy, md, default) => + module.withModule(log) { (ivy, md, default) => (new MakePom).write(ivy, md, configurations, extra, process, filterRepositories, file) - module.logger.info("Wrote " + file.getAbsolutePath) + log.info("Wrote " + file.getAbsolutePath) } } - def deliver(module: IvySbt#Module, configuration: PublishConfiguration) + def deliver(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger) { import configuration._ import patterns._ - module.withModule { case (ivy, md, default) => + module.withModule(log) { case (ivy, md, default) => resolve(logging)(ivy, md, default) // todo: set download = false for resolve val revID = md.getModuleRevisionId val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status) @@ -85,11 +85,11 @@ object IvyActions def getDeliverIvyPattern(patterns: PublishPatterns) = patterns.deliverIvyPattern.getOrElse(error("No Ivy pattern specified")) // todo: map configurations, extra dependencies - def publish(module: IvySbt#Module, configuration: PublishConfiguration) + def publish(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger) { import configuration._ import patterns._ - module.withModule { case (ivy, md, default) => + module.withModule(log) { case (ivy, md, default) => val revID = md.getModuleRevisionId val patterns = new java.util.ArrayList[String] srcArtifactPatterns.foreach(pattern => patterns.add(pattern)) @@ -101,8 +101,8 @@ object IvyActions } /** Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration. * 'updateConfig' configures the actual resolution and retrieval process. */ - def update(module: IvySbt#Module, configuration: UpdateConfiguration): UpdateReport = - module.withModule { case (ivy, md, default) => + def update(module: IvySbt#Module, configuration: UpdateConfiguration, log: Logger): UpdateReport = + module.withModule(log) { case (ivy, md, default) => val (report, err) = resolve(configuration.logging)(ivy, md, default) err match { @@ -117,23 +117,23 @@ object IvyActions } } - def transitiveScratch(ivySbt: IvySbt, id: ModuleID, label: String, deps: Seq[ModuleID], classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala]): UpdateReport = + def transitiveScratch(ivySbt: IvySbt, id: ModuleID, label: String, deps: Seq[ModuleID], classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport = { val base = id.copy(name = id.name + "$" + label) val module = new ivySbt.Module(InlineConfiguration(base, deps).copy(ivyScala = ivyScala)) - val report = update(module, c) - transitive(ivySbt, id, report, classifiers, c, ivyScala) + val report = update(module, c, log) + transitive(ivySbt, id, report, classifiers, c, ivyScala, log) } - def transitive(ivySbt: IvySbt, module: ModuleID, report: UpdateReport, classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala]): UpdateReport = - updateClassifiers(ivySbt, module, report.allModules, classifiers, new UpdateConfiguration(c.retrieve, true, c.logging), ivyScala) - def updateClassifiers(ivySbt: IvySbt, id: ModuleID, modules: Seq[ModuleID], classifiers: Seq[String], configuration: UpdateConfiguration, ivyScala: Option[IvyScala]): UpdateReport = + def transitive(ivySbt: IvySbt, module: ModuleID, report: UpdateReport, classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport = + updateClassifiers(ivySbt, module, report.allModules, classifiers, new UpdateConfiguration(c.retrieve, true, c.logging), ivyScala, log) + def updateClassifiers(ivySbt: IvySbt, id: ModuleID, modules: Seq[ModuleID], classifiers: Seq[String], configuration: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport = { assert(!classifiers.isEmpty, "classifiers cannot be empty") val baseModules = modules map { m => ModuleID(m.organization, m.name, m.revision, crossVersion = m.crossVersion) } val deps = baseModules.distinct map { m => m.copy(explicitArtifacts = classifiers map { c => Artifact(m.name, c) }) } val base = id.copy(name = id.name + classifiers.mkString("$","_","")) val module = new ivySbt.Module(InlineConfiguration(base, deps).copy(ivyScala = ivyScala)) - update(module, configuration) + update(module, configuration, log) } private def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String): (ResolveReport, Option[ResolveException]) = { diff --git a/ivy/IvyCache.scala b/ivy/IvyCache.scala index 9724e1009..c46d0fce7 100644 --- a/ivy/IvyCache.scala +++ b/ivy/IvyCache.scala @@ -74,7 +74,7 @@ object IvyCache def withDefaultCache[T](lock: Option[xsbti.GlobalLock], log: Logger)(f: DefaultRepositoryCacheManager => T): T = { val (ivy, local) = basicLocalIvy(lock, log) - ivy.withIvy { ivy => + ivy.withIvy(log) { ivy => val cache = ivy.getSettings.getDefaultRepositoryCacheManager.asInstanceOf[DefaultRepositoryCacheManager] cache.setUseOrigin(false) f(cache) diff --git a/main/Defaults.scala b/main/Defaults.scala index 382768a58..4c74d1e9e 100755 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -440,7 +440,7 @@ object Classpaths deliverDepends <<= (publishMavenStyle, makePom.setting, packageToPublish.setting) { (mavenStyle, mkpom, ptp) => if(mavenStyle) mkpom.map(_ => ()) else ptp }, - makePom <<= (ivyModule, makePomConfiguration, packageToPublish) map { (module, config, _) => IvyActions.makePom(module, config); config.file }, + makePom <<= (ivyModule, makePomConfiguration, packageToPublish, streams) map { (module, config, _, s) => IvyActions.makePom(module, config, s.log); config.file }, deliver <<= deliverTask(publishConfiguration), deliverLocal <<= deliverTask(publishLocalConfiguration), publish <<= publishTask(publishConfiguration, deliver), @@ -503,9 +503,11 @@ object Classpaths cachedUpdate(cacheDirectory / "update", module, config, s.log) }, transitiveClassifiers :== Seq("sources", "javadoc"), - updateClassifiers <<= (ivySbt, projectID, update, transitiveClassifiers, updateConfiguration, ivyScala) map IvyActions.transitive, - updateSbtClassifiers <<= (ivySbt, projectID, transitiveClassifiers, updateConfiguration, sbtDependency, ivyScala) map { (is, pid, classifiers, c, sbtDep, ivyScala) => - IvyActions.transitiveScratch(is, pid, "sbt", sbtDep :: Nil, classifiers, c, ivyScala) + updateClassifiers <<= (ivySbt, projectID, update, transitiveClassifiers, updateConfiguration, ivyScala, streams) map { (is, pid, up, classifiers, c, ivyScala, s) => + IvyActions.transitive(is, pid, up, classifiers, c, ivyScala, s.log) + }, + updateSbtClassifiers <<= (ivySbt, projectID, transitiveClassifiers, updateConfiguration, sbtDependency, ivyScala, streams) map { (is, pid, classifiers, c, sbtDep, ivyScala, s) => + IvyActions.transitiveScratch(is, pid, "sbt", sbtDep :: Nil, classifiers, c, ivyScala, s.log) }, sbtResolver in GlobalScope :== dbResolver, sbtDependency in GlobalScope <<= appConfiguration { app => @@ -516,9 +518,9 @@ object Classpaths def deliverTask(config: TaskKey[PublishConfiguration]): Initialize[Task[Unit]] = - (ivyModule, config, deliverDepends) map { (module, config, _) => IvyActions.deliver(module, config) } + (ivyModule, config, deliverDepends, streams) map { (module, config, _, s) => IvyActions.deliver(module, config, s.log) } def publishTask(config: TaskKey[PublishConfiguration], deliverKey: TaskKey[_]): Initialize[Task[Unit]] = - (ivyModule, config, deliverKey) map { (module, config, _) => IvyActions.publish(module, config) } + (ivyModule, config, deliverKey, streams) map { (module, config, _, s) => IvyActions.publish(module, config, s.log) } import Cache._ import CacheIvy.{classpathFormat, publishIC, updateIC, updateReportF} @@ -530,7 +532,7 @@ object Classpaths type In = IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil def work = (_: In) match { case conf :+: settings :+: config :+: HNil => log.info("Updating...") - val r = IvyActions.update(module, config) + val r = IvyActions.update(module, config, log) log.info("Done updating.") r } @@ -583,15 +585,15 @@ object Classpaths } def depMap: Initialize[Task[Map[ModuleRevisionId, ModuleDescriptor]]] = - (thisProject, thisProjectRef, settings) flatMap { (root, rootRef, data) => + (thisProject, thisProjectRef, settings, streams) flatMap { (root, rootRef, data, s) => val dependencies = (p: (ProjectRef, ResolvedProject)) => p._2.dependencies.flatMap(pr => thisProject in pr.project get data map { (pr.project, _) }) - depMap(Dag.topologicalSort((rootRef,root))(dependencies).dropRight(1), data) + depMap(Dag.topologicalSort((rootRef,root))(dependencies).dropRight(1), data, s.log) } - def depMap(projects: Seq[(ProjectRef,ResolvedProject)], data: Settings[Scope]): Task[Map[ModuleRevisionId, ModuleDescriptor]] = + def depMap(projects: Seq[(ProjectRef,ResolvedProject)], data: Settings[Scope], log: Logger): Task[Map[ModuleRevisionId, ModuleDescriptor]] = projects.flatMap { case (p,_) => ivyModule in p get data }.join.map { mods => (mods.map{ mod => - val md = mod.moduleDescriptor + val md = mod.moduleDescriptor(log) (md.getModuleRevisionId, md) }).toMap }