2010-02-08 05:45:19 +01:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2008, 2009, 2010 Mark Harrah
|
|
|
|
|
*/
|
2010-01-16 01:05:23 +01:00
|
|
|
package sbt
|
2009-08-16 20:29:08 +02:00
|
|
|
|
|
|
|
|
import java.io.File
|
2010-04-24 03:20:07 +02:00
|
|
|
import scala.xml.{Node,NodeSeq}
|
2009-08-16 20:29:08 +02:00
|
|
|
|
2010-09-04 14:42:37 +02:00
|
|
|
import org.apache.ivy.{core, plugins, Ivy}
|
2009-08-16 20:29:08 +02:00
|
|
|
import core.cache.DefaultRepositoryCacheManager
|
2010-12-03 01:56:19 +01:00
|
|
|
import core.{IvyPatternHelper,LogOptions}
|
2009-08-16 20:29:08 +02:00
|
|
|
import core.deliver.DeliverOptions
|
2009-08-20 06:02:06 +02:00
|
|
|
import core.install.InstallOptions
|
2009-08-16 20:29:08 +02:00
|
|
|
import core.module.descriptor.{DefaultArtifact, DefaultDependencyArtifactDescriptor, MDArtifact}
|
|
|
|
|
import core.module.descriptor.{DefaultDependencyDescriptor, DefaultModuleDescriptor, DependencyDescriptor, ModuleDescriptor}
|
|
|
|
|
import core.module.id.{ArtifactId,ModuleId, ModuleRevisionId}
|
|
|
|
|
import core.publish.PublishOptions
|
2010-09-22 04:38:18 +02:00
|
|
|
import core.report.{ArtifactDownloadReport,ResolveReport}
|
2009-08-16 20:29:08 +02:00
|
|
|
import core.resolve.ResolveOptions
|
|
|
|
|
import core.retrieve.RetrieveOptions
|
|
|
|
|
import plugins.parser.m2.{PomModuleDescriptorParser,PomModuleDescriptorWriter}
|
|
|
|
|
|
2011-04-02 03:06:07 +02:00
|
|
|
final class PublishPatterns(val deliverIvyPattern: String, val srcArtifactPatterns: Seq[String], val publishIvy: Boolean)
|
2010-12-03 01:56:19 +01:00
|
|
|
final class PublishConfiguration(val patterns: PublishPatterns, val status: String, val resolverName: String, val configurations: Option[Seq[Configuration]], val logging: UpdateLogging.Value)
|
|
|
|
|
|
2011-03-16 01:35:43 +01:00
|
|
|
final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value)
|
|
|
|
|
final class RetrieveConfiguration(val retrieveDirectory: File, val outputPattern: String)
|
2010-12-03 01:56:19 +01:00
|
|
|
final class MakePomConfiguration(val file: File, val configurations: Option[Iterable[Configuration]] = None, val extra: NodeSeq = NodeSeq.Empty, val process: Node => Node = n => n, val filterRepositories: MavenRepository => Boolean = _ => true)
|
|
|
|
|
|
2010-05-03 01:15:01 +02:00
|
|
|
/** Configures logging during an 'update'. `level` determines the amount of other information logged.
|
|
|
|
|
* `Full` is the default and logs the most.
|
|
|
|
|
* `DownloadOnly` only logs what is downloaded.
|
|
|
|
|
* `Quiet` only displays errors.*/
|
|
|
|
|
object UpdateLogging extends Enumeration
|
|
|
|
|
{
|
|
|
|
|
val Full, DownloadOnly, Quiet = Value
|
|
|
|
|
}
|
2009-08-16 20:29:08 +02:00
|
|
|
|
|
|
|
|
object IvyActions
|
|
|
|
|
{
|
2009-08-20 06:02:06 +02:00
|
|
|
/** Installs the dependencies of the given 'module' from the resolver named 'from' to the resolver named 'to'.*/
|
2011-03-22 23:19:48 +01:00
|
|
|
def install(module: IvySbt#Module, from: String, to: String, log: Logger)
|
2009-08-18 06:51:08 +02:00
|
|
|
{
|
2011-03-22 23:19:48 +01:00
|
|
|
module.withModule(log) { (ivy, md, default) =>
|
2009-08-20 06:02:06 +02:00
|
|
|
for(dependency <- md.getDependencies)
|
|
|
|
|
{
|
2011-03-22 23:19:48 +01:00
|
|
|
log.info("Installing " + dependency)
|
2009-08-20 06:02:06 +02:00
|
|
|
val options = new InstallOptions
|
2009-09-27 20:39:26 +02:00
|
|
|
options.setValidate(module.moduleSettings.validate)
|
2009-08-20 06:02:06 +02:00
|
|
|
options.setTransitive(dependency.isTransitive)
|
|
|
|
|
ivy.install(dependency.getDependencyRevisionId, from, to, options)
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-18 06:51:08 +02:00
|
|
|
}
|
|
|
|
|
|
2009-08-16 20:29:08 +02:00
|
|
|
/** Clears the Ivy cache, as configured by 'config'. */
|
2011-03-22 23:19:48 +01:00
|
|
|
def cleanCache(ivy: IvySbt, log: Logger) = ivy.withIvy(log) { iv =>
|
2010-01-30 02:31:07 +01:00
|
|
|
iv.getSettings.getResolutionCacheManager.clean()
|
|
|
|
|
iv.getSettings.getRepositoryCacheManagers.foreach(_.clean())
|
|
|
|
|
}
|
2009-08-20 06:02:06 +02:00
|
|
|
|
2009-08-16 20:29:08 +02:00
|
|
|
/** Creates a Maven pom from the given Ivy configuration*/
|
2011-03-22 23:19:48 +01:00
|
|
|
def makePom(module: IvySbt#Module, configuration: MakePomConfiguration, log: Logger)
|
2009-08-16 20:29:08 +02:00
|
|
|
{
|
2010-12-03 01:56:19 +01:00
|
|
|
import configuration.{configurations, extra, file, filterRepositories, process}
|
2011-03-22 23:19:48 +01:00
|
|
|
module.withModule(log) { (ivy, md, default) =>
|
2010-12-03 01:56:19 +01:00
|
|
|
(new MakePom).write(ivy, md, configurations, extra, process, filterRepositories, file)
|
2011-03-22 23:19:48 +01:00
|
|
|
log.info("Wrote " + file.getAbsolutePath)
|
2009-08-16 20:29:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
2009-08-20 06:02:06 +02:00
|
|
|
|
2011-03-22 23:19:48 +01:00
|
|
|
def deliver(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger)
|
2009-08-16 20:29:08 +02:00
|
|
|
{
|
2010-12-03 01:56:19 +01:00
|
|
|
import configuration._
|
|
|
|
|
import patterns._
|
2011-03-22 23:19:48 +01:00
|
|
|
module.withModule(log) { case (ivy, md, default) =>
|
2010-05-03 01:15:01 +02:00
|
|
|
resolve(logging)(ivy, md, default) // todo: set download = false for resolve
|
2009-08-16 20:29:08 +02:00
|
|
|
val revID = md.getModuleRevisionId
|
|
|
|
|
val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status)
|
2010-03-30 15:19:36 +02:00
|
|
|
options.setConfs(IvySbt.getConfigurations(md, configurations))
|
2011-04-02 03:06:07 +02:00
|
|
|
ivy.deliver(revID, revID.getRevision, patterns.deliverIvyPattern, options)
|
2009-08-16 20:29:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-03-16 01:35:43 +01:00
|
|
|
|
2009-08-16 20:29:08 +02:00
|
|
|
// todo: map configurations, extra dependencies
|
2011-03-22 23:19:48 +01:00
|
|
|
def publish(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger)
|
2009-08-16 20:29:08 +02:00
|
|
|
{
|
2010-12-03 01:56:19 +01:00
|
|
|
import configuration._
|
|
|
|
|
import patterns._
|
2011-03-22 23:19:48 +01:00
|
|
|
module.withModule(log) { case (ivy, md, default) =>
|
2009-08-16 20:29:08 +02:00
|
|
|
val revID = md.getModuleRevisionId
|
|
|
|
|
val patterns = new java.util.ArrayList[String]
|
|
|
|
|
srcArtifactPatterns.foreach(pattern => patterns.add(pattern))
|
|
|
|
|
val options = (new PublishOptions).setOverwrite(true)
|
2011-04-02 03:06:07 +02:00
|
|
|
if(publishIvy) options.setSrcIvyPattern(deliverIvyPattern)
|
2010-03-30 15:19:36 +02:00
|
|
|
options.setConfs(IvySbt.getConfigurations(md, configurations))
|
2009-08-16 20:29:08 +02:00
|
|
|
ivy.publish(revID, patterns, resolverName, options)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/** Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
|
|
|
|
* 'updateConfig' configures the actual resolution and retrieval process. */
|
2011-03-22 23:19:48 +01:00
|
|
|
def update(module: IvySbt#Module, configuration: UpdateConfiguration, log: Logger): UpdateReport =
|
|
|
|
|
module.withModule(log) { case (ivy, md, default) =>
|
2011-03-16 01:35:43 +01:00
|
|
|
val (report, err) = resolve(configuration.logging)(ivy, md, default)
|
|
|
|
|
err match
|
|
|
|
|
{
|
|
|
|
|
case Some(x) if !configuration.missingOk => throw x
|
|
|
|
|
case _ =>
|
|
|
|
|
val uReport = IvyRetrieve updateReport report
|
|
|
|
|
configuration.retrieve match
|
|
|
|
|
{
|
|
|
|
|
case Some(rConf) => retrieve(ivy, uReport, rConf)
|
|
|
|
|
case None => uReport
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-22 04:38:18 +02:00
|
|
|
}
|
2011-03-16 01:35:43 +01:00
|
|
|
|
2011-03-22 23:19:48 +01:00
|
|
|
def transitiveScratch(ivySbt: IvySbt, id: ModuleID, label: String, deps: Seq[ModuleID], classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport =
|
2011-03-16 01:35:43 +01:00
|
|
|
{
|
|
|
|
|
val base = id.copy(name = id.name + "$" + label)
|
|
|
|
|
val module = new ivySbt.Module(InlineConfiguration(base, deps).copy(ivyScala = ivyScala))
|
2011-03-22 23:19:48 +01:00
|
|
|
val report = update(module, c, log)
|
|
|
|
|
transitive(ivySbt, id, report, classifiers, c, ivyScala, log)
|
2010-09-22 04:38:18 +02:00
|
|
|
}
|
2011-03-22 23:19:48 +01:00
|
|
|
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 =
|
2011-03-16 01:35:43 +01:00
|
|
|
{
|
|
|
|
|
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))
|
2011-03-22 23:19:48 +01:00
|
|
|
update(module, configuration, log)
|
2011-03-16 01:35:43 +01:00
|
|
|
}
|
|
|
|
|
private def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String): (ResolveReport, Option[ResolveException]) =
|
2009-08-16 20:29:08 +02:00
|
|
|
{
|
|
|
|
|
val resolveOptions = new ResolveOptions
|
2010-05-03 01:15:01 +02:00
|
|
|
resolveOptions.setLog(ivyLogLevel(logging))
|
2009-08-16 20:29:08 +02:00
|
|
|
val resolveReport = ivy.resolve(module, resolveOptions)
|
2011-03-16 01:35:43 +01:00
|
|
|
val err =
|
|
|
|
|
if(resolveReport.hasError)
|
|
|
|
|
Some(new ResolveException(resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct))
|
|
|
|
|
else None
|
|
|
|
|
(resolveReport, err)
|
|
|
|
|
}
|
|
|
|
|
private def retrieve(ivy: Ivy, report: UpdateReport, config: RetrieveConfiguration): UpdateReport =
|
|
|
|
|
retrieve(ivy, report, config.retrieveDirectory, config.outputPattern)
|
|
|
|
|
|
|
|
|
|
private def retrieve(ivy: Ivy, report: UpdateReport, base: File, pattern: String): UpdateReport =
|
|
|
|
|
{
|
|
|
|
|
val toCopy = new collection.mutable.HashSet[(File,File)]
|
|
|
|
|
val retReport = report retrieve { (conf, mid, art, cached) =>
|
|
|
|
|
val to = retrieveTarget(conf, mid, art, base, pattern)
|
|
|
|
|
toCopy += ((cached, to))
|
|
|
|
|
to
|
|
|
|
|
}
|
|
|
|
|
IO.copy( toCopy )
|
|
|
|
|
retReport
|
|
|
|
|
}
|
|
|
|
|
private def retrieveTarget(conf: String, mid: ModuleID, art: Artifact, base: File, pattern: String): File =
|
|
|
|
|
new File(base, substitute(conf, mid, art, pattern))
|
|
|
|
|
|
|
|
|
|
private def substitute(conf: String, mid: ModuleID, art: Artifact, pattern: String): String =
|
|
|
|
|
{
|
|
|
|
|
val mextra = IvySbt.javaMap(mid.extraAttributes, true)
|
|
|
|
|
val aextra = IvySbt.extra(art, true)
|
|
|
|
|
IvyPatternHelper.substitute(pattern, mid.organization, mid.name, mid.revision, art.name, art.`type`, art.extension, conf, mextra, aextra)
|
2009-08-16 20:29:08 +02:00
|
|
|
}
|
2010-05-03 01:15:01 +02:00
|
|
|
|
|
|
|
|
import UpdateLogging.{Quiet, Full, DownloadOnly}
|
|
|
|
|
import LogOptions.{LOG_QUIET, LOG_DEFAULT, LOG_DOWNLOAD_ONLY}
|
|
|
|
|
private def ivyLogLevel(level: UpdateLogging.Value) =
|
|
|
|
|
level match
|
|
|
|
|
{
|
|
|
|
|
case Quiet => LOG_QUIET
|
|
|
|
|
case DownloadOnly => LOG_DOWNLOAD_ONLY
|
|
|
|
|
case Full => LOG_DEFAULT
|
|
|
|
|
}
|
2010-02-06 23:43:14 +01:00
|
|
|
}
|
2010-06-16 02:38:18 +02:00
|
|
|
final class ResolveException(messages: Seq[String]) extends RuntimeException(messages.mkString("\n"))
|