diff --git a/ivy/Ivy.scala b/ivy/Ivy.scala index f570a0761..888b15b1a 100644 --- a/ivy/Ivy.scala +++ b/ivy/Ivy.scala @@ -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 diff --git a/ivy/IvyActions.scala b/ivy/IvyActions.scala index e3105e254..a9b835976 100644 --- a/ivy/IvyActions.scala +++ b/ivy/IvyActions.scala @@ -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) diff --git a/ivy/IvyInterface.scala b/ivy/IvyInterface.scala index 79e1fc4ac..ab011eed3 100644 --- a/ivy/IvyInterface.scala +++ b/ivy/IvyInterface.scala @@ -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 diff --git a/ivy/IvyRetrieve.scala b/ivy/IvyRetrieve.scala index 328a33078..84947a5ae 100644 --- a/ivy/IvyRetrieve.scala +++ b/ivy/IvyRetrieve.scala @@ -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)) diff --git a/ivy/UpdateReport.scala b/ivy/UpdateReport.scala index 5ecad5d17..d86a3cf9e 100644 --- a/ivy/UpdateReport.scala +++ b/ivy/UpdateReport.scala @@ -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) } } } diff --git a/main/Defaults.scala b/main/Defaults.scala index 7363c1131..167e89e84 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -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 } \ No newline at end of file diff --git a/main/Keys.scala b/main/Keys.scala index 11e945c75..58281041f 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -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 diff --git a/main/actions/CacheIvy.scala b/main/actions/CacheIvy.scala index 7eb06c3fe..06b9c85ca 100644 --- a/main/actions/CacheIvy.scala +++ b/main/actions/CacheIvy.scala @@ -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] = diff --git a/sbt/package.scala b/sbt/package.scala index 77e2084c3..0634ff16d 100644 --- a/sbt/package.scala +++ b/sbt/package.scala @@ -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 }