artifact and cross-naming fixes/improvements

This commit is contained in:
Mark Harrah 2011-04-15 19:55:22 -04:00
parent 0b4d0e1062
commit a15bd90309
9 changed files with 66 additions and 43 deletions

View File

@ -290,17 +290,17 @@ private object IvySbt
case ic: InlineConfiguration => ic.copy(module = substituteCross(ic.module, cross), dependencies = substituteCrossM(ic.dependencies, cross))
case _ => m
}
private def crossName(name: String, cross: String): String =
def crossName(name: String, cross: String): String =
name + "_" + cross
private def substituteCross(a: Artifact, cross: String): Artifact =
def substituteCross(a: Artifact, cross: String): Artifact =
a.copy(name = crossName(a.name, cross))
private def substituteCrossA(as: Seq[Artifact], cross: String): Seq[Artifact] =
def substituteCrossA(as: Seq[Artifact], cross: String): Seq[Artifact] =
as.map(art => substituteCross(art, cross))
private def substituteCrossM(ms: Seq[ModuleID], cross: String): Seq[ModuleID] =
def substituteCrossM(ms: Seq[ModuleID], cross: String): Seq[ModuleID] =
ms.map(m => substituteCross(m, cross))
private def substituteCross(m: ModuleID, cross: String): ModuleID =
def substituteCross(m: ModuleID, cross: String): ModuleID =
if(m.crossVersion)
m.copy(name = crossName(m.name, cross), crossVersion = false, explicitArtifacts = substituteCrossA(m.explicitArtifacts, cross))
m.copy(name = crossName(m.name, cross), explicitArtifacts = substituteCrossA(m.explicitArtifacts, cross))
else
m

View File

@ -90,14 +90,24 @@ object IvyActions
module.withModule(log) { case (ivy, md, default) =>
val resolver = ivy.getSettings.getResolver(resolverName)
val ivyArtifact = ivyFile map { file => (MDArtifact.newIvyArtifact(md), file) }
val as = mapArtifacts(md, artifacts) ++ ivyArtifact.toList
val is = crossIvyScala(module.moduleSettings)
val as = mapArtifacts(md, is, artifacts) ++ ivyArtifact.toList
publish(md, as, resolver, overwrite = true)
}
}
def mapArtifacts(module: ModuleDescriptor, artifacts: Map[Artifact, File]): Seq[(IArtifact, File)] =
private def crossIvyScala(moduleSettings: ModuleSettings): Option[IvyScala] =
moduleSettings match {
case i: InlineConfiguration if i.module.crossVersion => i.ivyScala
case e: EmptyConfiguration if e.module.crossVersion => e.ivyScala
case _ => None
}
def substituteCross(ivyScala: Option[IvyScala], artifacts: Seq[Artifact]): Seq[Artifact] =
ivyScala match { case None => artifacts; case Some(is) => IvySbt.substituteCrossA(artifacts, is.scalaVersion) }
def mapArtifacts(module: ModuleDescriptor, ivyScala: Option[IvyScala], artifacts: Map[Artifact, File]): Seq[(IArtifact, File)] =
{
val seqa = artifacts.keys.toSeq
val zipped = seqa zip IvySbt.mapArtifacts(module, seqa)
val rawa = artifacts.keys.toSeq
val seqa = substituteCross(ivyScala, rawa)
val zipped = rawa zip IvySbt.mapArtifacts(module, seqa)
zipped map { case (a, ivyA) => (ivyA, artifacts(a)) }
}
/** Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
@ -109,7 +119,8 @@ object IvyActions
{
case Some(x) if !configuration.missingOk => throw x
case _ =>
val uReport = IvyRetrieve updateReport report
val cachedDescriptor = ivy.getSettings.getResolutionCacheManager.getResolvedIvyFileInCache(md.getModuleRevisionId)
val uReport = IvyRetrieve.updateReport(report, cachedDescriptor)
configuration.retrieve match
{
case Some(rConf) => retrieve(ivy, uReport, rConf)

View File

@ -359,12 +359,14 @@ object Artifact
val base = if(i >= 0) name.substring(0, i) else name
Artifact(base, extract(name, defaultType), extract(name, defaultExtension), None, Nil, Some(file.toURI.toURL))
}
def artifactName(module: ModuleID, artifact: Artifact): String =
def artifactName(scalaVersion: String, module: ModuleID, artifact: Artifact): String =
{
import artifact._
val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c }
artifact.name + "-" + module.revision + classifierStr + "." + artifact.extension
val base = if(module.crossVersion) IvySbt.crossName(artifact.name, scalaVersion) else artifact.name
base + "-" + module.revision + classifierStr + "." + artifact.extension
}
def cross(enable: Boolean, scalaVersion: String): String = if(enable) "_" + scalaVersion else ""
}
final case class ModuleConfiguration(organization: String, name: String, revision: String, resolver: Resolver)
object ModuleConfiguration

View File

@ -44,8 +44,8 @@ object IvyRetrieve
Artifact(getName, getType, getExt, Option(getExtraAttribute("classifier")), getConfigurations map Configurations.config, Option(getUrl))
}
def updateReport(report: ResolveReport): UpdateReport =
new UpdateReport(reports(report) map configurationReport)
def updateReport(report: ResolveReport, cachedDescriptor: File): UpdateReport =
new UpdateReport(cachedDescriptor, reports(report) map configurationReport)
def configurationReport(confReport: ConfigurationResolveReport): ConfigurationReport =
new ConfigurationReport(confReport.getConfiguration, moduleReports(confReport))

View File

@ -8,10 +8,11 @@ package sbt
/** Provides information about dependency resolution.
* It does not include information about evicted modules, only about the modules ultimately selected by the conflict manager.
* This means that for a given configuration, there should only be one revision for a given organization and module name.
* @param cachedDescriptor the location of the resolved module descriptor in the cache
* @param configurations a sequence containing one report for each configuration resolved.
* @see sbt.RichUpdateReport
*/
final class UpdateReport(val configurations: Seq[ConfigurationReport])
final class UpdateReport(val cachedDescriptor: File, val configurations: Seq[ConfigurationReport])
{
override def toString = "Update report:\n" + configurations.mkString
@ -19,7 +20,7 @@ final class UpdateReport(val configurations: Seq[ConfigurationReport])
def allModules: Seq[ModuleID] = configurations.flatMap(_.allModules).distinct
def retrieve(f: (String, ModuleID, Artifact, File) => File): UpdateReport =
new UpdateReport(configurations map { _ retrieve f} )
new UpdateReport(cachedDescriptor, configurations map { _ retrieve f} )
/** Gets the report for the given configuration, or `None` if the configuration was not resolved.*/
def configuration(s: String) = configurations.find(_.configuration == s)
@ -99,7 +100,7 @@ object UpdateReport
}
new ConfigurationReport(configuration, newModules)
}
new UpdateReport(newConfigurations)
new UpdateReport(report.cachedDescriptor, newConfigurations)
}
def substitute(f: (String, ModuleID, Seq[(Artifact, File)]) => Seq[(Artifact, File)]): UpdateReport =
{
@ -112,7 +113,7 @@ object UpdateReport
}
new ConfigurationReport(configuration, newModules)
}
new UpdateReport(newConfigurations)
new UpdateReport(report.cachedDescriptor, newConfigurations)
}
}
}

View File

@ -244,7 +244,7 @@ object Defaults
(rs --- rdirs) x relativeTo(rdirs) toSeq
}
def artifactPathSetting = (crossTarget, projectID, artifact, artifactName) { (t, module, n, toString) => t / toString(module, n) asFile }
def artifactPathSetting(art: ScopedSetting[Artifact]) = (crossTarget, projectID, art, scalaVersion, artifactName) { (t, module, a, sv, toString) => t / toString(sv, module, a) asFile }
def pairID[A,B] = (a: A, b: B) => (a,b)
def packageTasks(key: TaskKey[File], mappingsTask: Initialize[Task[Seq[(File,String)]]]) =
@ -259,7 +259,7 @@ object Defaults
a.copy(classifier = if(combined.isEmpty) None else Some(combined mkString "-"))
},
cacheDirectory <<= cacheDirectory / key.key.label,
artifactPath <<= artifactPathSetting
artifactPath <<= artifactPathSetting(artifact)
))
def packageTask: Initialize[Task[File]] =
(packageConfiguration, cacheDirectory, streams) map { (config, cacheDir, s) =>
@ -468,9 +468,6 @@ object Classpaths
def forallIn[T](key: ScopedSetting[T], pkgTasks: Seq[ScopedTask[_]]): Initialize[Seq[T]] =
pkgTasks.map( pkg => key in pkg.scope in pkg ).join
/* def addArtifact(a: Artifact, taskDef: ScopedTask[File]): SettingsDefinition =
new Project.SettingsList( Seq( artifacts += a, artifacts2 += (a, taskDef.task) ) )*/
val publishSettings: Seq[Setting[_]] = Seq(
publishMavenStyle in GlobalScope :== true,
publishArtifact in GlobalScope in Compile :== true,
@ -512,9 +509,7 @@ object Classpaths
ivyScala in GlobalScope <<= scalaVersion(v => Some(new IvyScala(v, Nil, filterImplicit = true, checkExplicit = true, overrideScalaVersion = true))),
moduleConfigurations in GlobalScope :== Nil,
publishTo in GlobalScope :== None,
artifactPath in makePom <<= (crossTarget, projectID, artifact in makePom, artifactName) {
(t, module, art, toString) => t / toString(module, art)
},
artifactPath in makePom <<= artifactPathSetting(artifact in makePom),
publishArtifact in makePom :== publishMavenStyle,
artifact in makePom <<= moduleID( name => Artifact(name, "pom", "pom") ),
projectID <<= (organization,moduleID,version,artifacts){ (org,module,version,as) =>
@ -593,7 +588,7 @@ object Classpaths
val f =
Tracked.inputChanged(cacheFile / "inputs") { (inChanged: Boolean, in: In) =>
val outCache = Tracked.lastOutput[In, UpdateReport](cacheFile / "output") {
case (_, Some(out)) if !inChanged && out.allFiles.forall(_.exists) => out
case (_, Some(out)) if !inChanged && out.allFiles.forall(_.exists) && out.cachedDescriptor.exists => out
case _ => work(in)
}
outCache(in)
@ -772,11 +767,33 @@ object Classpaths
}
}
trait CompilerPluginExtra
trait BuildExtra
{
def compilerPlugin(dependency: ModuleID): ModuleID =
dependency.copy(configurations = Some("plugin->default(compile)"))
def addCompilerPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
libraryDependencies += compilerPlugin(dependency)
def addArtifact(a: Artifact, taskDef: ScopedTask[File]): SettingsDefinition =
{
val pkgd = packagedArtifacts <<= (packagedArtifacts, taskDef) map ( (pas,file) => pas updated (a, file) )
seq( artifacts += a, pkgd )
}
def addArtifact(artifact: ScopedSetting[Artifact], taskDef: ScopedTask[File]): SettingsDefinition =
{
val art = artifacts <<= (artifact, artifacts)( _ +: _ )
val pkgd = packagedArtifacts <<= (packagedArtifacts, artifact, taskDef) map ( (pas,a,file) => pas updated (a, file))
seq( art, pkgd )
}
implicit def globFilter(expression: String): NameFilter = GlobFilter(expression)
implicit def richAttributed(s: Seq[Attributed[File]]): RichAttributed = new RichAttributed(s)
final class RichAttributed private[sbt](s: Seq[Attributed[File]])
{
def files: Seq[File] = Build data s
}
def seq(settings: Setting[_]*): SettingsDefinition = new Project.SettingList(settings)
implicit def settingsDefinitionToSeq(sd: SettingsDefinition): Seq[Setting[_]] = sd.settings
}

View File

@ -109,7 +109,7 @@ object Keys
val artifactPath = SettingKey[File]("artifact-path")
val artifact = SettingKey[Artifact]("artifact")
val artifactClassifier = SettingKey[Option[String]]("artifact-classifier")
val artifactName = SettingKey[(ModuleID, Artifact) => String]("artifact-name")
val artifactName = SettingKey[(String, ModuleID, Artifact) => String]("artifact-name")
val mappings = TaskKey[Seq[(File,String)]]("mappings")
// Run Keys

View File

@ -62,7 +62,10 @@ object CacheIvy
updateReportFormat
}
implicit def updateReportFormat(implicit m: Format[String], cr: Format[ConfigurationReport]): Format[UpdateReport] =
wrap[UpdateReport, Seq[ConfigurationReport]](_.configurations, c => new UpdateReport(c))
{
import DefaultProtocol.FileFormat
wrap[UpdateReport, (File, Seq[ConfigurationReport])](rep => (rep.cachedDescriptor, rep.configurations), { case (cd, cs) => new UpdateReport(cd, cs) })
}
implicit def confReportFormat(implicit mf: Format[ModuleID], mr: Format[ModuleReport]): Format[ConfigurationReport] =
wrap[ConfigurationReport, (String,Seq[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] =

View File

@ -2,7 +2,7 @@
* Copyright 2010, 2011 Mark Harrah
*/
package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders
with sbt.PathExtra with sbt.ProjectExtra with sbt.DependencyFilterExtra with sbt.CompilerPluginExtra
with sbt.PathExtra with sbt.ProjectExtra with sbt.DependencyFilterExtra with sbt.BuildExtra
{
type Setting[T] = Project.Setting[T]
type ScopedKey[T] = Project.ScopedKey[T]
@ -28,15 +28,4 @@ package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtr
// def System = C.System
def Optional = C.Optional
def config(s: String): Configuration = Configurations.config(s)
implicit def globFilter(expression: String): NameFilter = GlobFilter(expression)
implicit def richAttributed(s: Seq[Attributed[File]]): RichAttributed = new RichAttributed(s)
final class RichAttributed private[sbt](s: Seq[Attributed[File]])
{
def files: Seq[File] = Build data s
}
def all(settings: Seq[Setting[_]]): SettingsDefinition = new Project.SettingList(settings)
def seq(settings: Setting[_]*): SettingsDefinition = all(settings)
implicit def settingsDefinitionToSeq(sd: SettingsDefinition): Seq[Setting[_]] = sd.settings
}