mirror of https://github.com/sbt/sbt.git
detailed UpdateReport replaces Map[String,Seq[File]]
the information included is: configuration -> module -> artifact -> file
This commit is contained in:
parent
26d834e926
commit
787f00985b
|
|
@ -105,44 +105,14 @@ 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) =
|
||||
def update(module: IvySbt#Module, configuration: UpdateConfiguration): UpdateReport =
|
||||
{
|
||||
module.withModule { case (ivy, md, default) =>
|
||||
import configuration.{retrieve => rConf, logging}
|
||||
val report = resolve(logging)(ivy, md, default)
|
||||
rConf match
|
||||
{
|
||||
case None => IvyRetrieve.cachePaths(report)
|
||||
case Some(conf) => retrieve(ivy, md, conf, logging)
|
||||
}
|
||||
IvyRetrieve.updateReport(report)
|
||||
}
|
||||
}
|
||||
// doesn't work. perhaps replace retrieve/determineArtifactsToCopy with custom code
|
||||
private def retrieve(ivy: Ivy, md: ModuleDescriptor, conf: RetrieveConfiguration, logging: UpdateLogging.Value) =
|
||||
{
|
||||
import conf._
|
||||
val retrieveOptions = new RetrieveOptions
|
||||
retrieveOptions.setSync(synchronize)
|
||||
val patternBase = retrieveDirectory.getAbsolutePath
|
||||
val pattern =
|
||||
if(patternBase.endsWith(File.separator))
|
||||
patternBase + outputPattern
|
||||
else
|
||||
patternBase + File.separatorChar + outputPattern
|
||||
|
||||
val engine = ivy.getRetrieveEngine
|
||||
engine.retrieve(md.getModuleRevisionId, pattern, retrieveOptions)
|
||||
|
||||
//TODO: eliminate the duplication for better efficiency (retrieve already calls determineArtifactsToCopy once)
|
||||
val rawMap = engine.determineArtifactsToCopy(md.getModuleRevisionId, pattern, retrieveOptions)
|
||||
val map = rawMap.asInstanceOf[java.util.Map[ArtifactDownloadReport,java.util.Set[String]]]
|
||||
val confMap = new collection.mutable.HashMap[String, Seq[File]]
|
||||
|
||||
import collection.JavaConversions._
|
||||
for( (report, all) <- map; retrieved <- all; val file = new File(retrieved); conf <- report.getArtifact.getConfigurations)
|
||||
confMap.put(conf, file +: confMap.getOrElse(conf, Nil))
|
||||
confMap.toMap
|
||||
}
|
||||
private def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String): ResolveReport =
|
||||
{
|
||||
val resolveOptions = new ResolveOptions
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package sbt
|
|||
import java.io.File
|
||||
|
||||
import org.apache.ivy.core.{module, report}
|
||||
import module.descriptor.{Artifact => IvyArtifact}
|
||||
import module.id.ModuleRevisionId
|
||||
import report.{ArtifactDownloadReport, ConfigurationResolveReport, ResolveReport}
|
||||
|
||||
|
|
@ -14,21 +15,49 @@ object IvyRetrieve
|
|||
def reports(report: ResolveReport): Map[String, ConfigurationResolveReport] =
|
||||
( for( conf <- report.getConfigurations) yield (conf, report.getConfigurationReport(conf)) ).toMap
|
||||
|
||||
def artifactReports(confReport: ConfigurationResolveReport): Seq[ArtifactDownloadReport] =
|
||||
def moduleReports(confReport: ConfigurationResolveReport): Map[ModuleID, ModuleReport] =
|
||||
moduleReportMap(confReport) map { case (mid, arts) => (mid, new ModuleReport(mid, artifactReports(arts)) ) }
|
||||
|
||||
def moduleReportMap(confReport: ConfigurationResolveReport): Map[ModuleID, Seq[ArtifactDownloadReport]] =
|
||||
{
|
||||
val all = new scala.collection.mutable.HashSet[ArtifactDownloadReport]
|
||||
for( revId <- confReport.getModuleRevisionIds.toArray collect { case revId: ModuleRevisionId => revId })
|
||||
all ++= confReport.getDownloadReports(revId)
|
||||
all.toSeq
|
||||
val modules =
|
||||
for( revId <- confReport.getModuleRevisionIds.toArray collect { case revId: ModuleRevisionId => revId }) yield
|
||||
(toModuleID(revId), (confReport getDownloadReports revId).toSeq)
|
||||
modules.toMap
|
||||
}
|
||||
def artifactReports(artReport: Seq[ArtifactDownloadReport]): Map[Artifact, File] =
|
||||
artReport map { r =>
|
||||
val art = r.getArtifact
|
||||
val file0 = r.getLocalFile
|
||||
val file = if(file0 eq null) error("No file for " + art) else file0
|
||||
(toArtifact(art), file)
|
||||
} toMap;
|
||||
|
||||
def toModuleID(revID: ModuleRevisionId): ModuleID =
|
||||
ModuleID(revID.getOrganisation, revID.getName, revID.getRevision)
|
||||
|
||||
def toArtifact(art: IvyArtifact): Artifact =
|
||||
{
|
||||
import art._
|
||||
Artifact(getName, getType, getExt, Option(getExtraAttribute("classifier")), getConfigurations map Configurations.config, Option(getUrl))
|
||||
}
|
||||
|
||||
def cachePath(reports: Seq[ArtifactDownloadReport]): Seq[File] =
|
||||
for(r <- reports) yield
|
||||
{
|
||||
val file = r.getLocalFile
|
||||
if(file eq null) error("No file for " + r.getArtifact) else file
|
||||
}
|
||||
def updateReport(report: ResolveReport): UpdateReport =
|
||||
new UpdateReport(reports(report) mapValues configurationReport)
|
||||
|
||||
def cachePaths(report: ResolveReport): Map[String, Seq[File]] =
|
||||
reports(report).mapValues(confReport => cachePath(artifactReports(confReport)))
|
||||
def configurationReport(confReport: ConfigurationResolveReport): ConfigurationReport =
|
||||
new ConfigurationReport(confReport.getConfiguration, moduleReports(confReport))
|
||||
}
|
||||
|
||||
final class UpdateReport(val configurations: Map[String, ConfigurationReport])
|
||||
{
|
||||
override def toString = "Update report:\n" + configurations.values.mkString
|
||||
}
|
||||
final class ConfigurationReport(val configuration: String, val modules: Map[ModuleID, ModuleReport])
|
||||
{
|
||||
override def toString = "\t" + configuration + ":\n" + modules.values.mkString
|
||||
}
|
||||
final class ModuleReport(val module: ModuleID, val artifacts: Map[Artifact, File])
|
||||
{
|
||||
override def toString = "\t\t" + module + ": " + (if(artifacts.size <= 1) "" else "\n") + artifacts.mkString("\n\t\t\t") + "\n"
|
||||
}
|
||||
|
|
@ -7,9 +7,11 @@ package sbt
|
|||
|
||||
import FileInfo.{exists, hash}
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import Types.:+:
|
||||
import scala.xml.NodeSeq
|
||||
import sbinary.{DefaultProtocol,Format}
|
||||
import DefaultProtocol.{immutableMapFormat, optionsAreFormat}
|
||||
import RepositoryHelpers._
|
||||
import Ordering._
|
||||
|
||||
|
|
@ -53,6 +55,31 @@ object CacheIvy
|
|||
def updateIC: InputCache[IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil] = implicitly
|
||||
def publishIC: InputCache[IvyConfiguration :+: ModuleSettings :+: PublishConfiguration :+: HNil] = implicitly
|
||||
|
||||
def updateReportF: Format[UpdateReport] =
|
||||
{
|
||||
import DefaultProtocol.{BooleanFormat, FileFormat, StringFormat}
|
||||
updateReportFormat
|
||||
}
|
||||
implicit def updateReportFormat(implicit m: Format[String], cr: Format[ConfigurationReport]): Format[UpdateReport] =
|
||||
wrap[UpdateReport, Map[String,ConfigurationReport]](_.configurations, c => new UpdateReport(c))
|
||||
implicit def confReportFormat(implicit mf: Format[ModuleID], mr: Format[ModuleReport]): Format[ConfigurationReport] =
|
||||
wrap[ConfigurationReport, (String,Map[ModuleID,ModuleReport])]( r => (r.configuration, r.modules), { case (c,m) => new ConfigurationReport(c,m) })
|
||||
implicit def moduleReportFormat(implicit f: Format[Artifact], ff: Format[File], mid: Format[ModuleID]): Format[ModuleReport] =
|
||||
wrap[ModuleReport, (ModuleID, Map[Artifact, File])]( m => (m.module, m.artifacts), { case (m, as) => new ModuleReport(m, as) })
|
||||
implicit def artifactFormat(implicit sf: Format[String], of: Format[Seq[Configuration]], cf: Format[Configuration], uf: Format[Option[URL]]): Format[Artifact] =
|
||||
wrap[Artifact, (String,String,String,Option[String],Seq[Configuration],Option[URL],Map[String,String])](
|
||||
a => (a.name, a.`type`, a.extension, a.classifier, a.configurations.toSeq, a.url, a.extraAttributes),
|
||||
{ case (n,t,x,c,cs,u,e) => Artifact(n,t,x,c,cs,u,e) }
|
||||
)
|
||||
implicit def moduleIDFormat(implicit sf: Format[String], af: Format[Artifact], bf: Format[Boolean]): Format[ModuleID] =
|
||||
wrap[ModuleID, (String,String,String,Option[String],Boolean,Boolean,Seq[Artifact],Map[String,String],Boolean)](
|
||||
m => (m.organization,m.name,m.revision,m.configurations, m.isChanging, m.isTransitive, m.explicitArtifacts, m.extraAttributes, m.crossVersion),
|
||||
{ case (o,n,r,cs,ch,t,as,x,cv) => ModuleID(o,n,r,cs,ch,t,as,x,cv) }
|
||||
)
|
||||
|
||||
implicit def configurationFormat(implicit sf: Format[String]): Format[Configuration] =
|
||||
wrap[Configuration, String](_.name, s => new Configuration(s))
|
||||
|
||||
implicit def classpathFormat =
|
||||
{
|
||||
import DefaultProtocol.FileFormat
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ object Classpaths
|
|||
internalDependencyClasspath <<= internalDependencies,
|
||||
unmanagedClasspath <<= unmanagedDependencies,
|
||||
products <<= makeProducts,
|
||||
managedClasspath <<= (configuration, update) map { (config, up) => up.getOrElse(config.name, error("Configuration '" + config.name + "' unresolved by 'update'.")) },
|
||||
managedClasspath <<= (configuration, update) map managedJars,
|
||||
unmanagedJars <<= (configuration, unmanagedBase, classpathFilter, defaultExcludes) map { (config, base, filter, excl) =>
|
||||
(base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).getFiles.toSeq
|
||||
}
|
||||
|
|
@ -500,11 +500,12 @@ object Classpaths
|
|||
(ivyModule, config, deliverKey) map { (module, config, _) => IvyActions.publish(module, config) }
|
||||
|
||||
import Cache._
|
||||
import CacheIvy.{classpathFormat, publishIC, updateIC}
|
||||
import CacheIvy.{classpathFormat, publishIC, updateIC, updateReportF}
|
||||
|
||||
def cachedUpdate(cacheFile: File, module: IvySbt#Module, config: UpdateConfiguration, log: Logger): Map[String, Seq[File]] =
|
||||
def cachedUpdate(cacheFile: File, module: IvySbt#Module, config: UpdateConfiguration, log: Logger): UpdateReport =
|
||||
{
|
||||
implicit val updateCache = updateIC
|
||||
implicit val updateReport = updateReportF
|
||||
val work = (_: IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil) match { case conf :+: settings :+: config :+: HNil =>
|
||||
log.info("Updating...")
|
||||
val r = IvyActions.update(module, config)
|
||||
|
|
@ -667,4 +668,23 @@ object Classpaths
|
|||
def defaultConfigurationTask(p: ResolvedReference, data: Settings[Scope]): Configuration =
|
||||
flatten(defaultConfiguration in p get data) getOrElse Configurations.Default
|
||||
def flatten[T](o: Option[Option[T]]): Option[T] = o flatMap identity
|
||||
|
||||
def managedJars(config: Configuration, up: UpdateReport): Classpath =
|
||||
allJars( confReport(config.name, up) )
|
||||
def confReport(config: String, up: UpdateReport): ConfigurationReport =
|
||||
up.configurations.getOrElse(config, error("Configuration '" + config + "' unresolved by 'update'."))
|
||||
def allJars(cr: ConfigurationReport): Seq[File] = cr.modules.values.toSeq.flatMap(mr => allJars(mr.artifacts))
|
||||
def allJars(as: Iterable[(Artifact,File)]): Iterable[File] = as collect { case (a, f) if isJar(a) => f }
|
||||
def isJar(a: Artifact): Boolean = a.`type` == "jar"
|
||||
}
|
||||
trait Defaults
|
||||
{
|
||||
def addSbtDependency: Setting[Seq[ModuleID]] =
|
||||
libraryDependencies <<= (libraryDependencies, appConfiguration) { (libs, app) =>
|
||||
val id = app.provider.id
|
||||
libs :+ ModuleID(id.groupID, id.name, id.version, crossVersion = true)
|
||||
}
|
||||
|
||||
def addSbtRepository: Setting[Seq[Resolver]] =
|
||||
resolvers += Resolver.url("sbt-db", new URL("http://databinder.net/repo/"))(Resolver.ivyStylePatterns)
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ object Keys
|
|||
val ivySbt = TaskKey[IvySbt]("ivy-sbt")
|
||||
val ivyModule = TaskKey[IvySbt#Module]("ivy-module")
|
||||
val classpathFilter = SettingKey[FileFilter]("classpath-filter")
|
||||
val update = TaskKey[Map[String,Seq[File]]]("update")
|
||||
val update = TaskKey[UpdateReport]("update")
|
||||
|
||||
val publishConfiguration = TaskKey[PublishConfiguration]("publish-configuration")
|
||||
val publishLocalConfiguration = TaskKey[PublishConfiguration]("publish-local-configuration")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders with sbt.PathExtra with sbt.ProjectConstructors
|
||||
package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders with sbt.PathExtra with sbt.ProjectConstructors with sbt.Defaults
|
||||
{
|
||||
type Setting[T] = Project.Setting[T]
|
||||
type ScopedKey[T] = Project.ScopedKey[T]
|
||||
|
|
|
|||
Loading…
Reference in New Issue