diff --git a/build.sbt b/build.sbt index 89002a7ce..f437ceafe 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,7 @@ inThisBuild(List( ) )) -val coursierVersion = "1.1.0-M7" +val coursierVersion = "1.1.0-M8" lazy val `sbt-shared` = project .in(file("modules/sbt-shared")) diff --git a/modules/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala b/modules/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala index 5de7f4364..d55cc7ebb 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/CoursierPlugin.scala @@ -1,8 +1,10 @@ package coursier import java.io.OutputStreamWriter -import sbt.librarymanagement._ -import sbt.{ Configuration, Resolver, _ } + +import coursier.core.Configuration +import sbt.librarymanagement.{Configuration => _, Resolver => _, _} +import sbt.{Configuration => _, _} import sbt.Keys._ object CoursierPlugin extends AutoPlugin { @@ -77,7 +79,7 @@ object CoursierPlugin extends AutoPlugin { def makeIvyXmlBefore[T]( task: TaskKey[T], - shadedConfigOpt: Option[(String, String)] + shadedConfigOpt: Option[(String, Configuration)] ): Setting[Task[T]] = task := task.dependsOn(Def.task { val currentProject = { @@ -158,8 +160,8 @@ object CoursierPlugin extends AutoPlugin { ) def coursierSettings( - shadedConfigOpt: Option[(String, String)], - packageConfigs: Seq[(Configuration, String)] + shadedConfigOpt: Option[(String, Configuration)], + packageConfigs: Seq[(sbt.Configuration, Configuration)] ) = hackHack ++ Seq( clean := { val noWarningPlz = clean.value @@ -234,7 +236,7 @@ object CoursierPlugin extends AutoPlugin { coursierResolutions := Tasks.resolutionsTask().value, Keys.actualCoursierResolution := { - val config = Compile.name + val config = Configuration(Compile.name) coursierResolutions .value @@ -261,7 +263,7 @@ object CoursierPlugin extends AutoPlugin { None else Some( - Configuration.of( + sbt.Configuration.of( id = "Sources", name = "sources", description = "", @@ -276,7 +278,7 @@ object CoursierPlugin extends AutoPlugin { None else Some( - Configuration.of( + sbt.Configuration.of( id = "Docs", name = "docs", description = "", @@ -311,7 +313,7 @@ object CoursierPlugin extends AutoPlugin { coursierCreateLogger := { () => new TermDisplay(new OutputStreamWriter(System.err)) } ) - override lazy val projectSettings = coursierSettings(None, Seq(Compile, Test).map(c => c -> c.name)) ++ + override lazy val projectSettings = coursierSettings(None, Seq(Compile, Test).map(c => c -> Configuration(c.name))) ++ inConfig(Compile)(treeSettings) ++ inConfig(Test)(treeSettings) diff --git a/modules/sbt-coursier/src/main/scala/coursier/InterProjectRepository.scala b/modules/sbt-coursier/src/main/scala/coursier/InterProjectRepository.scala index 8a6baae31..ff6f0919d 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/InterProjectRepository.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/InterProjectRepository.scala @@ -1,5 +1,6 @@ package coursier +import coursier.core.Classifier import coursier.util.{EitherT, Monad} final case class InterProjectRepository(projects: Seq[Project]) extends Repository { @@ -18,9 +19,16 @@ final case class InterProjectRepository(projects: Seq[Project]) extends Reposito val res = map .get((module, version)) - .map((Artifact.Source.empty, _)) + .map((this, _)) .toRight("Not found") EitherT(F.point(res)) } + + override def artifacts( + dependency: Dependency, + project: Project, + overrideClassifiers: Option[Seq[Classifier]] + ) = + Nil } \ No newline at end of file diff --git a/modules/sbt-coursier/src/main/scala/coursier/IvyXml.scala b/modules/sbt-coursier/src/main/scala/coursier/IvyXml.scala index 07a706fdd..436d32b44 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/IvyXml.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/IvyXml.scala @@ -3,6 +3,7 @@ package coursier import java.nio.charset.StandardCharsets.UTF_8 import java.nio.file.Files +import coursier.core.Configuration import org.apache.ivy.core.module.id.ModuleRevisionId import scala.collection.JavaConverters._ @@ -13,7 +14,7 @@ object IvyXml { def rawContent( currentProject: Project, - shadedConfigOpt: Option[(String, String)] + shadedConfigOpt: Option[(String, Configuration)] ): String = { // Important: width = Int.MaxValue, so that no tag gets truncated. @@ -31,7 +32,7 @@ object IvyXml { // These are required for publish to be fine, later on. def writeFiles( currentProject: Project, - shadedConfigOpt: Option[(String, String)], + shadedConfigOpt: Option[(String, Configuration)], ivySbt: IvySbt, log: sbt.Logger ): Unit = { @@ -41,8 +42,8 @@ object IvyXml { ) val ivyModule = ModuleRevisionId.newInstance( - currentProject.module.organization, - currentProject.module.name, + currentProject.module.organization.value, + currentProject.module.name.value, currentProject.version, currentProject.module.attributes.asJava ) @@ -60,10 +61,10 @@ object IvyXml { Files.write(cacheIvyPropertiesFile.toPath, Array.emptyByteArray) } - def content(project0: Project, shadedConfigOpt: Option[String]): Node = { + def content(project0: Project, shadedConfigOpt: Option[Configuration]): Node = { val filterOutDependencies = - shadedConfigOpt.toSet[String].flatMap { shadedConfig => + shadedConfigOpt.toSet[Configuration].flatMap { shadedConfig => project0 .dependencies .collect { case (`shadedConfig`, dep) => dep } @@ -91,8 +92,8 @@ object IvyXml { val infoElem = { {licenseElems} @@ -101,11 +102,11 @@ object IvyXml { } % infoAttrs val confElems = project.configurations.toVector.collect { - case (name, extends0) if shadedConfigOpt != Some(name) => + case (name, extends0) if !shadedConfigOpt.contains(name) => val extends1 = shadedConfigOpt.fold(extends0)(c => extends0.filter(_ != c)) - val n = + val n = if (extends1.nonEmpty) - n % .attributes + n % .attributes else n } @@ -117,10 +118,10 @@ object IvyXml { val publicationElems = publications.map { case (pub, configs) => - val n = + val n = if (pub.classifier.nonEmpty) - n % .attributes + n % .attributes else n } @@ -129,10 +130,10 @@ object IvyXml { case (conf, dep) => val excludes = dep.exclusions.toSeq.map { case (org, name) => - + } - val n = ${dep.configuration}"}> + val n = ${dep.configuration.value}"}> {excludes} diff --git a/modules/sbt-coursier/src/main/scala/coursier/Keys.scala b/modules/sbt-coursier/src/main/scala/coursier/Keys.scala index f25029581..3e024d470 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/Keys.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/Keys.scala @@ -3,7 +3,7 @@ package coursier import java.io.File import java.net.URL -import coursier.core.Publication +import coursier.core.{Configuration, Publication} import sbt.librarymanagement.GetClassifiersModule import sbt.{InputKey, Resolver, SettingKey, TaskKey} @@ -38,17 +38,17 @@ object Keys { val coursierFallbackDependencies = TaskKey[Seq[(Module, String, URL, Boolean)]]("coursier-fallback-dependencies") val coursierProject = TaskKey[Project]("coursier-project") - val coursierConfigGraphs = TaskKey[Seq[Set[String]]]("coursier-config-graphs") + val coursierConfigGraphs = TaskKey[Seq[Set[Configuration]]]("coursier-config-graphs") val coursierInterProjectDependencies = TaskKey[Seq[Project]]("coursier-inter-project-dependencies", "Projects the current project depends on, possibly transitively") - val coursierPublications = TaskKey[Seq[(String, Publication)]]("coursier-publications") + val coursierPublications = TaskKey[Seq[(Configuration, Publication)]]("coursier-publications") val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module") - val coursierConfigurations = TaskKey[Map[String, Set[String]]]("coursier-configurations") + val coursierConfigurations = TaskKey[Map[Configuration, Set[Configuration]]]("coursier-configurations") val coursierParentProjectCache = TaskKey[Map[Seq[Resolver], Seq[ProjectCache]]]("coursier-parent-project-cache") - val coursierResolutions = TaskKey[Map[Set[String], Resolution]]("coursier-resolutions") + val coursierResolutions = TaskKey[Map[Set[Configuration], Resolution]]("coursier-resolutions") private[coursier] val actualCoursierResolution = TaskKey[Resolution]("coursier-resolution") diff --git a/modules/sbt-coursier/src/main/scala/coursier/SbtBootJars.scala b/modules/sbt-coursier/src/main/scala/coursier/SbtBootJars.scala index 6318ff698..95fc92b5f 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/SbtBootJars.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/SbtBootJars.scala @@ -4,14 +4,14 @@ import java.io.File object SbtBootJars { def apply( - scalaOrg: String, + scalaOrg: Organization, scalaVersion: String, jars: Seq[File] ): Map[(Module, String), File] = jars .collect { case jar if jar.getName.endsWith(".jar") => - val name = jar.getName.stripSuffix(".jar") + val name = ModuleName(jar.getName.stripSuffix(".jar")) val mod = Module(scalaOrg, name) (mod, scalaVersion) -> jar diff --git a/modules/sbt-coursier/src/main/scala/coursier/Tasks.scala b/modules/sbt-coursier/src/main/scala/coursier/Tasks.scala index dd58a2b98..e860e8e68 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/Tasks.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/Tasks.scala @@ -1,10 +1,10 @@ package coursier -import java.io.{File, OutputStreamWriter} +import java.io.File import java.net.URL import java.util.concurrent.{ConcurrentHashMap, ExecutorService, Executors} -import coursier.core.{Authentication, Publication} +import coursier.core._ import coursier.extra.Typelevel import coursier.interop.scalaz._ import coursier.ivy.{IvyRepository, PropertiesPattern} @@ -12,7 +12,7 @@ import coursier.Keys._ import coursier.Structure._ import coursier.util.Print.Colors import coursier.util.{Parse, Print} -import sbt.librarymanagement._ +import sbt.librarymanagement.{Configuration => _, _} import sbt.{Classpaths, Def, Resolver, UpdateReport} import sbt.Keys._ @@ -185,7 +185,7 @@ object Tasks { Nil } else Seq( - (rule.organization, FromSbt.sbtCrossVersionName(rule.name, rule.crossVersion, sv, sbv)) + (Organization(rule.organization), ModuleName(FromSbt.sbtCrossVersionName(rule.name, rule.crossVersion, sv, sbv))) ) } .toSet @@ -200,7 +200,9 @@ object Tasks { val allDependencies = allDependenciesTask.value - val configMap = configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap + val configMap = configurations + .map(cfg => Configuration(cfg.name) -> cfg.extendsConfigs.map(c => Configuration(c.name))) + .toMap val proj = FromSbt.project( projId, @@ -233,8 +235,8 @@ object Tasks { } def coursierPublicationsTask( - configsMap: (sbt.Configuration, String)* - ): Def.Initialize[sbt.Task[Seq[(String, Publication)]]] = + configsMap: (sbt.Configuration, Configuration)* + ): Def.Initialize[sbt.Task[Seq[(Configuration, Publication)]]] = Def.task { val state = sbt.Keys.state.value @@ -246,13 +248,13 @@ object Tasks { val sourcesConfigOpt = if (ivyConfigurations.value.exists(_.name == "sources")) - Some("sources") + Some(Configuration("sources")) else None val docsConfigOpt = if (ivyConfigurations.value.exists(_.name == "docs")) - Some("docs") + Some(Configuration("docs")) else None @@ -329,9 +331,9 @@ object Tasks { Publication( name, - artifact.`type`, - artifact.extension, - artifact.classifier.getOrElse("") + Type(artifact.`type`), + Extension(artifact.extension), + artifact.classifier.fold(Classifier.empty)(Classifier(_)) ) } @@ -358,23 +360,23 @@ object Tasks { artifact <- extraSbtArtifacts config <- allConfigsIfEmpty(artifact.configurations.map(x => ConfigRef(x.name))) // FIXME If some configurations from artifact.configurations are not public, they may leak here :\ - } yield config.name -> artifactPublication(artifact) + } yield Configuration(config.name) -> artifactPublication(artifact) sbtArtifactsPublication ++ extraSbtArtifactsPublication } - def coursierConfigurationsTask(shadedConfig: Option[(String, String)]) = Def.task { + def coursierConfigurationsTask(shadedConfig: Option[(String, Configuration)]) = Def.task { val configs0 = ivyConfigurations .value .map { config => - config.name -> config.extendsConfigs.map(_.name) + Configuration(config.name) -> config.extendsConfigs.map(c => Configuration(c.name)) } .toMap - def allExtends(c: String) = { + def allExtends(c: Configuration) = { // possibly bad complexity - def helper(current: Set[String]): Set[String] = { + def helper(current: Set[Configuration]): Set[Configuration] = { val newSet = current ++ current.flatMap(configs0.getOrElse(_, Nil)) if ((newSet -- current).nonEmpty) helper(newSet) @@ -392,8 +394,9 @@ object Tasks { map ++ shadedConfig.toSeq.flatMap { case (baseConfig, shadedConfig) => + val baseConfig0 = Configuration(baseConfig) Seq( - baseConfig -> (map.getOrElse(baseConfig, Set(baseConfig)) + shadedConfig), + baseConfig0 -> (map.getOrElse(baseConfig0, Set(baseConfig0)) + shadedConfig), shadedConfig -> map.getOrElse(shadedConfig, Set(shadedConfig)) ) } @@ -403,32 +406,32 @@ object Tasks { project: Project, repositories: Seq[Repository], userEnabledProfiles: Set[String], - resolution: Map[Set[String], Resolution], + resolution: Map[Set[Configuration], Resolution], sbtClassifiers: Boolean ) private[coursier] final case class ReportCacheKey( project: Project, - resolution: Map[Set[String], Resolution], + resolution: Map[Set[Configuration], Resolution], withClassifiers: Boolean, sbtClassifiers: Boolean, ignoreArtifactErrors: Boolean ) - private[coursier] val resolutionsCache = new ConcurrentHashMap[ResolutionCacheKey, Map[Set[String], Resolution]] + private[coursier] val resolutionsCache = new ConcurrentHashMap[ResolutionCacheKey, Map[Set[Configuration], Resolution]] // these may actually not need to be cached any more, now that the resolutions // are cached private[coursier] val reportsCache = new ConcurrentHashMap[ReportCacheKey, UpdateReport] private def forcedScalaModules( - scalaOrganization: String, + scalaOrganization: Organization, scalaVersion: String ): Map[Module, String] = Map( - Module(scalaOrganization, "scala-library") -> scalaVersion, - Module(scalaOrganization, "scala-compiler") -> scalaVersion, - Module(scalaOrganization, "scala-reflect") -> scalaVersion, - Module(scalaOrganization, "scalap") -> scalaVersion + Module(scalaOrganization, name"scala-library") -> scalaVersion, + Module(scalaOrganization, name"scala-compiler") -> scalaVersion, + Module(scalaOrganization, name"scala-reflect") -> scalaVersion, + Module(scalaOrganization, name"scalap") -> scalaVersion ) private[coursier] def exceptionPatternParser(): String => coursier.ivy.Pattern = { @@ -504,7 +507,7 @@ object Tasks { n.foldLeft(Map.empty[Seq[Resolver], Seq[ProjectCache]]) { case (caches, (ref, resolutions)) => val mainResOpt = resolutions.collectFirst { - case (k, v) if k("compile") => v + case (k, v) if k(Configuration.compile) => v } val r = for { @@ -526,7 +529,7 @@ object Tasks { val p = coursierProject.value - final class Wrapper(val set: mutable.HashSet[String]) { + final class Wrapper(val set: mutable.HashSet[Configuration]) { def ++=(other: Wrapper): this.type = { set ++= other.set this @@ -534,9 +537,9 @@ object Tasks { } val sets = - new mutable.HashMap[String, Wrapper] ++= p.configurations.map { + new mutable.HashMap[Configuration, Wrapper] ++= p.configurations.map { case (k, l) => - val s = new mutable.HashSet[String]() + val s = new mutable.HashSet[Configuration] s ++= l s += k k -> new Wrapper(s) @@ -568,13 +571,13 @@ object Tasks { def resolutionsTask( sbtClassifiers: Boolean = false - ): Def.Initialize[sbt.Task[Map[Set[String], coursier.Resolution]]] = Def.taskDyn { + ): Def.Initialize[sbt.Task[Map[Set[Configuration], coursier.Resolution]]] = Def.taskDyn { val projectName = thisProjectRef.value.project val sv = scalaVersion.value val sbv = scalaBinaryVersion.value - val currentProjectTask: sbt.Def.Initialize[sbt.Task[(Project, Seq[(Module, String, URL, Boolean)], Seq[Set[String]])]] = + val currentProjectTask: sbt.Def.Initialize[sbt.Task[(Project, Seq[(Module, String, URL, Boolean)], Seq[Set[Configuration]])]] = if (sbtClassifiers) Def.task { val cm = coursierSbtClassifiersModule.value @@ -586,7 +589,7 @@ object Tasks { sbv ) - (proj, fallbackDeps, Vector(cm.configurations.map(_.name).toSet)) + (proj, fallbackDeps, Vector(cm.configurations.map(c => Configuration(c.name)).toSet)) } else Def.task { @@ -607,7 +610,7 @@ object Tasks { val log = streams.value.log // are these always defined? (e.g. for Java only projects?) - val so = scalaOrganization.value + val so = Organization(scalaOrganization.value) val userForceVersions = dependencyOverrides .value @@ -624,7 +627,7 @@ object Tasks { val userEnabledProfiles = mavenProfiles.value - val typelevel = scalaOrganization.value == Typelevel.typelevelOrg + val typelevel = Organization(scalaOrganization.value) == Typelevel.typelevelOrg val globalPluginsRepos = for (p <- globalPluginPatterns(sbtBinaryVersion.value)) @@ -681,10 +684,10 @@ object Tasks { def resTask( currentProject: Project, fallbackDependencies: Seq[(Module, String, URL, Boolean)], - configGraphs: Seq[Set[String]], + configGraphs: Seq[Set[Configuration]], repositories: Seq[Repository], internalRepositories: Seq[Repository], - allStartRes: Map[Set[String], coursier.Resolution] + allStartRes: Map[Set[Configuration], coursier.Resolution] ) = Def.task { def resolution(startRes: Resolution) = { @@ -706,9 +709,9 @@ object Tasks { ): _* ) - def depsRepr(deps: Seq[(String, Dependency)]) = + def depsRepr(deps: Seq[(Configuration, Dependency)]) = deps.map { case (config, dep) => - s"${dep.module}:${dep.version}:$config->${dep.configuration}" + s"${dep.module}:${dep.version}:${config.value}->${dep.configuration.value}" }.sorted.distinct if (verbosityLevel >= 2) { @@ -894,7 +897,7 @@ object Tasks { .map(_.foldLeft[ProjectCache](Map.empty)(_ ++ _)) .getOrElse(Map.empty) - def startRes(configs: Set[String]) = Resolution( + def startRes(configs: Set[Configuration]) = Resolution( currentProject .dependencies .collect { @@ -911,10 +914,10 @@ object Tasks { forceVersions = // order matters here userForceVersions ++ - (if (autoScalaLib && (configs("compile") || configs("scala-tool"))) forcedScalaModules(so, sv) else Map()) ++ + (if (autoScalaLib && (configs(Configuration.compile) || configs(Configuration("scala-tool")))) forcedScalaModules(so, sv) else Map()) ++ interProjectDependencies.map(_.moduleVersion), projectCache = parentProjectCache, - mapDependencies = if (typelevel && (configs("compile") || configs("scala-tool"))) typelevelOrgSwap else None + mapDependencies = if (typelevel && (configs(Configuration.compile) || configs(Configuration("scala-tool")))) typelevelOrgSwap else None ) val allStartRes = configGraphs.map(configs => configs -> startRes(configs)).toMap @@ -973,12 +976,12 @@ object Tasks { else Def.task(coursierResolutions.value.values.toVector) - val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[String]]]] = + val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[Classifier]]]] = if (withClassifiers) { if (sbtClassifiers) - Def.task(Some(coursierSbtClassifiersModule.value.classifiers)) + Def.task(Some(coursierSbtClassifiersModule.value.classifiers.map(Classifier(_)))) else - Def.task(Some(transitiveClassifiers.value)) + Def.task(Some(transitiveClassifiers.value.map(Classifier(_)))) } else Def.task(None) @@ -987,16 +990,12 @@ object Tasks { val classifiers = classifiersTask.value val res = resTask.value - val allArtifacts0 = - classifiers match { - case None => res.flatMap(_.artifacts(withOptional = true)) - case Some(cl) => res.flatMap(_.classifiersArtifacts(cl)) - } + val allArtifacts0 = res.flatMap(_.dependencyArtifacts(classifiers)).map(_._3) val allArtifacts = if (includeSignatures) allArtifacts0.flatMap { a => - val sigOpt = a.extra.get("sig").map(_.copy(attributes = Attributes())) + val sigOpt = a.extra.get("sig") Seq(a) ++ sigOpt.toSeq } else @@ -1075,36 +1074,34 @@ object Tasks { log: sbt.Logger, module: Module, version: String, + attributes: Attributes, artifact: Artifact ) = { - val artifact0 = artifact - .copy(attributes = Attributes()) // temporary hack :-( - // Under some conditions, SBT puts the scala JARs of its own classpath // in the application classpath. Ensuring we return SBT's jars rather than // JARs from the coursier cache, so that a same JAR doesn't land twice in the // application classpath (once via SBT jars, once via coursier cache). val fromBootJars = - if (artifact.classifier.isEmpty && artifact.`type` == "jar") + if (attributes.classifier.isEmpty && attributes.`type` == Type.jar) sbtBootJarOverrides.get((module, version)) else None - val res = fromBootJars.orElse(artifactFiles.get(artifact0)) + val res = fromBootJars.orElse(artifactFiles.get(artifact)) - if (res.isEmpty && !erroredArtifacts(artifact0)) - log.error(s"${artifact.url} not downloaded (should not happen)") + if (res.isEmpty && !erroredArtifacts(artifact)) + sys.error(s"${artifact.url} not downloaded (should not happen)") res } // Move back to coursier.util (in core module) after 1.0? private def allDependenciesByConfig( - res: Map[String, Resolution], - depsByConfig: Map[String, Set[Dependency]], - configs: Map[String, Set[String]] - ): Map[String, Set[Dependency]] = { + res: Map[Configuration, Resolution], + depsByConfig: Map[Configuration, Set[Dependency]], + configs: Map[Configuration, Set[Configuration]] + ): Map[Configuration, Set[Dependency]] = { val allDepsByConfig = depsByConfig.map { case (config, deps) => @@ -1125,24 +1122,24 @@ object Tasks { // Move back to coursier.util (in core module) after 1.0? private def dependenciesWithConfig( - res: Map[String, Resolution], - depsByConfig: Map[String, Set[Dependency]], - configs: Map[String, Set[String]] + res: Map[Configuration, Resolution], + depsByConfig: Map[Configuration, Set[Dependency]], + configs: Map[Configuration, Set[Configuration]] ): Set[Dependency] = allDependenciesByConfig(res, depsByConfig, configs) .flatMap { case (config, deps) => - deps.map(dep => dep.copy(configuration = s"$config->${dep.configuration}")) + deps.map(dep => dep.copy(configuration = config --> dep.configuration)) } - .groupBy(_.copy(configuration = "")) + .groupBy(_.copy(configuration = Configuration.empty)) .map { case (dep, l) => - dep.copy(configuration = l.map(_.configuration).mkString(";")) + dep.copy(configuration = Configuration.join(l.map(_.configuration).toSeq: _*)) } .toSet def updateTask( - shadedConfigOpt: Option[(String, String)], + shadedConfigOpt: Option[(String, Configuration)], withClassifiers: Boolean, sbtClassifiers: Boolean = false, ignoreArtifactErrors: Boolean = false, @@ -1155,7 +1152,7 @@ object Tasks { k -> l.map { case (_, v) => v } } - val so = scalaOrganization.value + val so = Organization(scalaOrganization.value) val internalSbtScalaProvider = appConfiguration.value.provider.scalaProvider val sbtBootJarOverrides = SbtBootJars( so, // this seems plain wrong - this assumes that the scala org of the project is the same @@ -1190,7 +1187,7 @@ object Tasks { Def.task { val cm = coursierSbtClassifiersModule.value val classifiersRes = coursierSbtClassifiersResolution.value - Map(cm.configurations.map(c => c.name).toSet -> classifiersRes) + Map(cm.configurations.map(c => Configuration(c.name)).toSet -> classifiersRes) } else Def.task(coursierResolutions.value) @@ -1207,11 +1204,11 @@ object Tasks { else Keys.coursierArtifacts - val configsTask: sbt.Def.Initialize[sbt.Task[Map[String, Set[String]]]] = + val configsTask: sbt.Def.Initialize[sbt.Task[Map[Configuration, Set[Configuration]]]] = if (withClassifiers && sbtClassifiers) Def.task { val cm = coursierSbtClassifiersModule.value - cm.configurations.map(c => c.name -> Set(c.name)).toMap + cm.configurations.map(c => Configuration(c.name) -> Set(Configuration(c.name))).toMap } else Def.task { @@ -1219,25 +1216,26 @@ object Tasks { shadedConfigOpt.fold(configs0) { case (baseConfig, shadedConfig) => + val baseConfig0 = Configuration(baseConfig) (configs0 - shadedConfig) + ( - baseConfig -> (configs0.getOrElse(baseConfig, Set()) - shadedConfig) + baseConfig0 -> (configs0.getOrElse(baseConfig0, Set()) - shadedConfig) ) } } - val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[String]]]] = + val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[Classifier]]]] = if (withClassifiers) { if (sbtClassifiers) Def.task { val cm = coursierSbtClassifiersModule.value - Some(cm.classifiers) + Some(cm.classifiers.map(Classifier(_))) } else - Def.task(Some(transitiveClassifiers.value)) + Def.task(Some(transitiveClassifiers.value.map(Classifier(_)))) } else Def.task(None) - def reportTask(currentProject: Project, res: Map[Set[String], Resolution]) = Def.task { + def reportTask(currentProject: Project, res: Map[Set[Configuration], Resolution]) = Def.task { val artifactFilesOrErrors0 = artifactFilesOrErrors0Task.value val classifiers = classifiersTask.value @@ -1254,7 +1252,7 @@ object Tasks { config => shadedConfigOpt match { case Some((baseConfig, `config`)) => - baseConfig + Configuration(baseConfig) case _ => config } @@ -1280,7 +1278,7 @@ object Tasks { val artifactErrors = artifactFilesOrErrors0 .toVector .collect { - case (a, Left(err)) if !a.isOptional || !err.notFound => + case (a, Left(err)) if !a.optional || !err.notFound => a -> err } @@ -1311,6 +1309,7 @@ object Tasks { log, _, _, + _, _ ), log, @@ -1350,7 +1349,7 @@ object Tasks { } } - case class ResolutionResult(configs: Set[String], resolution: Resolution, dependencies: Seq[Dependency]) + case class ResolutionResult(configs: Set[Configuration], resolution: Resolution, dependencies: Seq[Dependency]) private def coursierResolutionTask( sbtClassifiers: Boolean = false, @@ -1372,7 +1371,7 @@ object Tasks { proj.copy(publications = publications) } - val config = configuration.value.name + val config = Configuration(configuration.value.name) val configs = coursierConfigurations.value val includedConfigs = configs.getOrElse(config, Set.empty) + config @@ -1450,7 +1449,7 @@ object Tasks { val result = new mutable.StringBuilder() for (ResolutionResult(subGraphConfigs, resolution, _) <- resolutions) { val roots: Seq[Dependency] = resolution.transitiveDependencies.filter(f => f.module == module) - val strToPrint = s"$projectName (configurations ${subGraphConfigs.toVector.sorted.mkString(", ")})" + "\n" + + val strToPrint = s"$projectName (configurations ${subGraphConfigs.toVector.sorted.map(_.value).mkString(", ")})" + "\n" + Print.reverseTree(roots, resolution, withExclusions = true) .render(_.repr(Colors.get(!sys.props.get("sbt.log.noformat").toSeq.contains("true")))); println(strToPrint) diff --git a/modules/sbt-coursier/src/sbt-test/sbt-coursier-group-2/update-sbt-classifiers/build.sbt b/modules/sbt-coursier/src/sbt-test/sbt-coursier-group-2/update-sbt-classifiers/build.sbt index 3108c1548..4cf6b148b 100644 --- a/modules/sbt-coursier/src/sbt-test/sbt-coursier-group-2/update-sbt-classifiers/build.sbt +++ b/modules/sbt-coursier/src/sbt-test/sbt-coursier-group-2/update-sbt-classifiers/build.sbt @@ -39,6 +39,6 @@ updateSbtClassifiersCheck := { ) ensureHasArtifact("org.scala-lang", "scala-library") - ensureHasArtifact("io.get-coursier", "coursier_" + scalaBinaryVersion.value) + ensureHasArtifact("io.get-coursier", "coursier-core_" + scalaBinaryVersion.value) ensureHasArtifact("io.get-coursier", "sbt-coursier") } diff --git a/modules/sbt-coursier/src/test/scala/coursier/IvyXmlTests.scala b/modules/sbt-coursier/src/test/scala/coursier/IvyXmlTests.scala index 8f695d727..74f911635 100644 --- a/modules/sbt-coursier/src/test/scala/coursier/IvyXmlTests.scala +++ b/modules/sbt-coursier/src/test/scala/coursier/IvyXmlTests.scala @@ -1,5 +1,6 @@ package coursier +import coursier.core.Configuration import utest._ object IvyXmlTests extends TestSuite { @@ -8,11 +9,11 @@ object IvyXmlTests extends TestSuite { "no truncation" - { val project = Project( - Module("org", "name"), + Module(org"org", name"name"), "ver", Nil, Map( - "foo" -> (1 to 80).map("bar" + _) // long list of configurations -> no truncation any way + Configuration("foo") -> (1 to 80).map(n => Configuration("bar" + n)) // long list of configurations -> no truncation any way ), None, Nil, @@ -21,6 +22,7 @@ object IvyXmlTests extends TestSuite { None, None, None, + relocated = false, None, Nil, Info.empty diff --git a/modules/sbt-shading/src/main/scala/coursier/Shading.scala b/modules/sbt-shading/src/main/scala/coursier/Shading.scala index 7350d4582..b410aa10d 100644 --- a/modules/sbt-shading/src/main/scala/coursier/Shading.scala +++ b/modules/sbt-shading/src/main/scala/coursier/Shading.scala @@ -8,7 +8,7 @@ import com.tonicsystems.jarjar.classpath.ClassPath import com.tonicsystems.jarjar.transform.JarTransformer import com.tonicsystems.jarjar.transform.config.ClassRename import com.tonicsystems.jarjar.transform.jar.DefaultJarProcessor -import coursier.core.Orders +import coursier.core.{Configuration, Orders, Type} import sbt.file object Shading { @@ -55,15 +55,15 @@ object Shading { def toShadeJars( currentProject: Project, res: Resolution, - configs: Map[String, Set[String]], + configs: Map[Configuration, Set[Configuration]], artifactFilesOrErrors: Map[Artifact, Either[FileError, File]], - classpathTypes: Set[String], - baseConfig: String, - shadedConf: String, + classpathTypes: Set[Type], + baseConfig: Configuration, + shadedConf: Configuration, log: sbt.Logger ): Seq[File] = { - def configDependencies(config: String) = { + def configDependencies(config: Configuration) = { def minDependencies(dependencies: Set[Dependency]): Set[Dependency] = Orders.minDependencies( @@ -90,10 +90,10 @@ object Shading { } val dependencyArtifacts = res - .dependencyArtifacts(withOptional = true) - .filter { case (_, a) => classpathTypes(a.`type`) } + .dependencyArtifacts() + .filter { case (_, attr, _) => classpathTypes(attr.`type`) } .groupBy(_._1) - .mapValues(_.map(_._2)) + .mapValues(_.map(t => (t._2, t._3))) .iterator .toMap @@ -126,7 +126,7 @@ object Shading { .toSeq .flatMap(dependencyArtifacts.get) .flatten - .map(_.url) + .map(_._2.url) .flatMap(artifactFilesOrErrors0.get) val noShadeJars = files(compileOnlyDeps) diff --git a/modules/sbt-shading/src/main/scala/coursier/ShadingPlugin.scala b/modules/sbt-shading/src/main/scala/coursier/ShadingPlugin.scala index 7d7c4ec73..88d6875cc 100644 --- a/modules/sbt-shading/src/main/scala/coursier/ShadingPlugin.scala +++ b/modules/sbt-shading/src/main/scala/coursier/ShadingPlugin.scala @@ -2,10 +2,11 @@ package coursier import java.io.File +import coursier.core.{Configuration, Type} import coursier.ivy.IvyXml.{mappings => ivyXmlMappings} import sbt.librarymanagement._ import sbt.Keys._ -import sbt.{AutoPlugin, Compile, Configuration, SettingKey, TaskKey, inConfig} +import sbt.{AutoPlugin, Compile, SettingKey, TaskKey, inConfig} object ShadingPlugin extends AutoPlugin { @@ -14,7 +15,7 @@ object ShadingPlugin extends AutoPlugin { override def requires = sbt.plugins.IvyPlugin private val baseSbtConfiguration = Compile - val Shading = Configuration.of( + val Shading = sbt.Configuration.of( id = "Shading", name = "shading", description = "", @@ -23,8 +24,8 @@ object ShadingPlugin extends AutoPlugin { transitive = true ) - private val baseDependencyConfiguration = "compile" - val Shaded = Configuration.of( + private val baseDependencyConfiguration = Configuration.compile + val Shaded = sbt.Configuration.of( id = "Shaded", name = "shaded", description = "", @@ -79,7 +80,7 @@ object ShadingPlugin extends AutoPlugin { override lazy val projectSettings = Seq( coursierConfigurations := Tasks.coursierConfigurationsTask( - Some(baseDependencyConfiguration -> Shaded.name) + Some(baseDependencyConfiguration.value -> Configuration(Shaded.name)) ).value, ivyConfigurations := Shaded +: ivyConfigurations.value.map { conf => @@ -95,8 +96,8 @@ object ShadingPlugin extends AutoPlugin { sbt.Classpaths.ivyPublishSettings ++ shadingJvmPublishSettings ++ CoursierPlugin.coursierSettings( - Some(baseDependencyConfiguration -> Shaded.name), - Seq(Shading -> Compile.name) + Some(baseDependencyConfiguration.value -> Configuration(Shaded.name)), + Seq(Shading -> Configuration.compile) ) ++ CoursierPlugin.treeSettings ++ Seq( @@ -106,7 +107,7 @@ object ShadingPlugin extends AutoPlugin { .map(c => c.withExtendsConfigs(c.extendsConfigs.toVector.filter(_.name != Shaded.name))), libraryDependencies := libraryDependencies.in(baseSbtConfiguration).value.filter { dep => val isShaded = dep.configurations.exists { mappings => - ivyXmlMappings(mappings).exists(_._1 == Shaded.name) + ivyXmlMappings(mappings).exists(_._1 == Configuration(Shaded.name)) } !isShaded @@ -128,9 +129,9 @@ object ShadingPlugin extends AutoPlugin { }, coursierConfigurations.in(baseSbtConfiguration).value, Keys.coursierArtifacts.in(baseSbtConfiguration).value, - classpathTypes.value, + classpathTypes.value.map(Type(_)), baseDependencyConfiguration, - Shaded.name, + Configuration(Shaded.name), streams.value.log ) }, diff --git a/modules/sbt-shared/src/main/scala/coursier/FromSbt.scala b/modules/sbt-shared/src/main/scala/coursier/FromSbt.scala index 204e87a3e..2f85e9a76 100644 --- a/modules/sbt-shared/src/main/scala/coursier/FromSbt.scala +++ b/modules/sbt-shared/src/main/scala/coursier/FromSbt.scala @@ -4,10 +4,9 @@ import coursier.ivy.IvyRepository import coursier.ivy.IvyXml.{mappings => ivyXmlMappings} import java.net.{MalformedURLException, URL} -import coursier.core.Authentication +import coursier.core.{Authentication, Classifier, Configuration, Type} import sbt.internal.librarymanagement.mavenint.SbtPomExtraProperties -import sbt.librarymanagement._ -import sbt.librarymanagement.Resolver +import sbt.librarymanagement.{CrossVersion, FileRepository, GetClassifiersModule, ModuleID, Patterns, RawRepository, Resolver, URLRepository} import sbt.util.Logger object FromSbt { @@ -43,7 +42,7 @@ object FromSbt { val fullName = sbtModuleIdName(module, scalaVersion, scalaBinaryVersion) - val module0 = Module(module.organization, fullName, FromSbt.attributes(module.extraDependencyAttributes)) + val module0 = Module(Organization(module.organization), ModuleName(fullName), FromSbt.attributes(module.extraDependencyAttributes)) val version = module.revision (module0, version) @@ -53,7 +52,7 @@ object FromSbt { module: ModuleID, scalaVersion: String, scalaBinaryVersion: String - ): Seq[(String, Dependency)] = { + ): Seq[(Configuration, Dependency)] = { // TODO Warn about unsupported properties in `module` @@ -64,7 +63,7 @@ object FromSbt { version, exclusions = module.exclusions.map { rule => // FIXME Other `rule` fields are ignored here - (rule.organization, rule.name) + (Organization(rule.organization), ModuleName(rule.name)) }.toSet, transitive = module.isTransitive ) @@ -74,10 +73,13 @@ object FromSbt { val attributes = if (module.explicitArtifacts.isEmpty) - Seq(Attributes("", "")) + Seq(Attributes(Type.empty, Classifier.empty)) else module.explicitArtifacts.map { a => - Attributes(`type` = a.`type`, classifier = a.classifier.getOrElse("")) + Attributes( + `type` = Type(a.`type`), + classifier = a.classifier.fold(Classifier.empty)(Classifier(_)) + ) } for { @@ -109,7 +111,7 @@ object FromSbt { val p = FromSbt.project( cm.id, cm.dependencies, - cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap, + cm.configurations.map(cfg => Configuration(cfg.name) -> cfg.extendsConfigs.map(c => Configuration(c.name))).toMap, scalaVersion, scalaBinaryVersion ) @@ -120,7 +122,7 @@ object FromSbt { case Seq(cfg) => p.copy( dependencies = p.dependencies.map { - case (_, d) => (cfg.name, d) + case (_, d) => (Configuration(cfg.name), d) } ) case _ => @@ -131,7 +133,7 @@ object FromSbt { def project( projectID: ModuleID, allDependencies: Seq[ModuleID], - ivyConfigurations: Map[String, Seq[String]], + ivyConfigurations: Map[Configuration, Seq[Configuration]], scalaVersion: String, scalaBinaryVersion: String ): Project = { @@ -140,8 +142,8 @@ object FromSbt { Project( Module( - projectID.organization, - sbtModuleIdName(projectID, scalaVersion, scalaBinaryVersion), + Organization(projectID.organization), + ModuleName(sbtModuleIdName(projectID, scalaVersion, scalaBinaryVersion)), FromSbt.attributes(projectID.extraDependencyAttributes) ), projectID.revision, @@ -154,6 +156,7 @@ object FromSbt { None, None, None, + relocated = false, None, Nil, Info.empty diff --git a/modules/sbt-shared/src/main/scala/coursier/ToSbt.scala b/modules/sbt-shared/src/main/scala/coursier/ToSbt.scala index db09141a5..9edd6c511 100644 --- a/modules/sbt-shared/src/main/scala/coursier/ToSbt.scala +++ b/modules/sbt-shared/src/main/scala/coursier/ToSbt.scala @@ -5,9 +5,10 @@ import java.net.URL import java.util.GregorianCalendar import java.util.concurrent.ConcurrentHashMap -import sbt.librarymanagement._ +import coursier.core.{Classifier, Configuration, Type} +import coursier.maven.MavenAttributes +import sbt.librarymanagement.{Configuration => _, _} import sbt.util.Logger -import coursier.maven.MavenSource object ToSbt { @@ -28,11 +29,11 @@ object ToSbt { val moduleId = caching[(Dependency, Map[String, String]), ModuleID] { case (dependency, extraProperties) => sbt.librarymanagement.ModuleID( - dependency.module.organization, - dependency.module.name, + dependency.module.organization.value, + dependency.module.name.value, dependency.version ).withConfigurations( - Some(dependency.configuration) + Some(dependency.configuration.value) ).withExtraAttributes( dependency.module.attributes ++ extraProperties ).withExclusions( @@ -42,40 +43,41 @@ object ToSbt { .map { case (org, name) => sbt.librarymanagement.InclExclRule() - .withOrganization(org) - .withName(name) + .withOrganization(org.value) + .withName(name.value) } ).withIsTransitive( dependency.transitive ) } - val artifact = caching[(Module, Map[String, String], Artifact), sbt.librarymanagement.Artifact] { - case (module, extraProperties, artifact) => - sbt.librarymanagement.Artifact(module.name) + val artifact = caching[(Module, Map[String, String], Attributes, Artifact), sbt.librarymanagement.Artifact] { + case (module, extraProperties, attr, artifact) => + sbt.librarymanagement.Artifact(module.name.value) // FIXME Get these two from publications - .withType(artifact.attributes.`type`) - .withExtension(MavenSource.typeExtension(artifact.attributes.`type`)) + .withType(attr.`type`.value) + .withExtension(MavenAttributes.typeExtension(attr.`type`).value) .withClassifier( - Some(artifact.attributes.classifier) + Some(attr.classifier) .filter(_.nonEmpty) - .orElse(MavenSource.typeDefaultClassifierOpt(artifact.attributes.`type`)) + .orElse(MavenAttributes.typeDefaultClassifierOpt(attr.`type`)) + .map(_.value) ) // .withConfigurations(Vector()) .withUrl(Some(new URL(artifact.url))) .withExtraAttributes(module.attributes ++ extraProperties) } - val moduleReport = caching[(Dependency, Seq[(Dependency, Project)], Project, Seq[(Artifact, Option[File])]), ModuleReport] { + val moduleReport = caching[(Dependency, Seq[(Dependency, Project)], Project, Seq[(Attributes, Artifact, Option[File])]), ModuleReport] { case (dependency, dependees, project, artifacts) => val sbtArtifacts = artifacts.collect { - case (artifact, Some(file)) => - (ToSbt.artifact(dependency.module, project.properties.toMap, artifact), file) + case (attr, artifact, Some(file)) => + (ToSbt.artifact(dependency.module, project.properties.toMap, attr, artifact), file) } val sbtMissingArtifacts = artifacts.collect { - case (artifact, None) => - ToSbt.artifact(dependency.module, project.properties.toMap, artifact) + case (attr, artifact, None) => + ToSbt.artifact(dependency.module, project.properties.toMap, attr, artifact) } val publicationDate = project.info.publication.map { dt => @@ -86,7 +88,7 @@ object ToSbt { case (dependee, dependeeProj) => Caller( ToSbt.moduleId(dependee, dependeeProj.properties.toMap), - dependeeProj.configurations.keys.toVector.map(ConfigRef(_)), + dependeeProj.configurations.keys.toVector.map(c => ConfigRef(c.value)), dependee.module.attributes ++ dependeeProj.properties, // FIXME Set better values here isForceDependency = false, @@ -113,77 +115,69 @@ object ToSbt { .withExtraAttributes(dependency.module.attributes ++ project.properties) // .withIsDefault(None) // .withBranch(None) - .withConfigurations(project.configurations.keys.toVector.map(ConfigRef(_))) + .withConfigurations(project.configurations.keys.toVector.map(c => ConfigRef(c.value))) .withLicenses(project.info.licenses.toVector) .withCallers(callers.toVector) } - private def grouped[K, V](map: Seq[(K, V)]): Map[K, Seq[V]] = - map.groupBy { case (k, _) => k }.map { - case (k, l) => - k -> l.map { case (_, v) => v } - } - def moduleReports( res: Resolution, - classifiersOpt: Option[Seq[String]], - artifactFileOpt: (Module, String, Artifact) => Option[File], + classifiersOpt: Option[Seq[Classifier]], + artifactFileOpt: (Module, String, Attributes, Artifact) => Option[File], log: Logger, keepPomArtifact: Boolean = false, includeSignatures: Boolean = false ) = { - val depArtifacts1 = - classifiersOpt match { - case None => res.dependencyArtifacts(withOptional = true) - case Some(cl) => res.dependencyClassifiersArtifacts(cl) - } + val depArtifacts1 = res.dependencyArtifacts(classifiersOpt) val depArtifacts0 = if (keepPomArtifact) depArtifacts1 else depArtifacts1.filter { - case (_, a) => a.attributes != Attributes("pom", "") + case (_, attr, _) => attr != Attributes(Type.pom, Classifier.empty) } val depArtifacts = if (includeSignatures) { - val notFound = depArtifacts0.filter(!_._2.extra.contains("sig")) + val notFound = depArtifacts0.filter(!_._3.extra.contains("sig")) if (notFound.isEmpty) depArtifacts0.flatMap { - case (dep, a) => - Seq(dep -> a) ++ a.extra.get("sig").toSeq.map(dep -> _) + case (dep, attr, a) => + Seq((dep, attr, a)) ++ + // not too sure about the attributes here + a.extra.get("sig").toSeq.map((dep, Attributes(Type(s"${attr.`type`.value}.asc"), attr.classifier), _)) } else { - for ((_, a) <- notFound) + for ((_, _, a) <- notFound) log.error(s"No signature found for ${a.url}") sys.error(s"${notFound.length} signature(s) not found") } } else depArtifacts0 - val groupedDepArtifacts = grouped(depArtifacts) + val groupedDepArtifacts = depArtifacts + .groupBy(_._1) + .mapValues(_.map { case (_, attr, a) => (attr, a) }) + .iterator + .toMap val versions = res.dependencies.toVector.map { dep => dep.module -> dep.version }.toMap def clean(dep: Dependency): Dependency = - dep.copy(configuration = "", exclusions = Set.empty, optional = false) + dep.copy(configuration = Configuration.empty, exclusions = Set.empty, optional = false) val reverseDependencies = res.reverseDependencies .toVector .map { case (k, v) => clean(k) -> v.map(clean) } - .groupBy { case (k, v) => k } - .mapValues { v => - v.flatMap { - case (_, l) => l - } - } + .groupBy(_._1) + .mapValues(_.flatMap(_._2)) .toVector .toMap @@ -205,17 +199,17 @@ object ToSbt { dep, dependees, proj, - artifacts.map(a => a -> artifactFileOpt(proj.module, proj.version, a)) + artifacts.map { case (attr, a) => (attr, a, artifactFileOpt(proj.module, proj.version, attr, a)) } ) } } def updateReport( - configDependencies: Map[String, Seq[Dependency]], - resolutions: Map[String, Resolution], - configs: Map[String, Set[String]], - classifiersOpt: Option[Seq[String]], - artifactFileOpt: (Module, String, Artifact) => Option[File], + configDependencies: Map[Configuration, Seq[Dependency]], + resolutions: Map[Configuration, Resolution], + configs: Map[Configuration, Set[Configuration]], + classifiersOpt: Option[Seq[Classifier]], + artifactFileOpt: (Module, String, Attributes, Artifact) => Option[File], log: Logger, keepPomArtifact: Boolean = false, includeSignatures: Boolean = false @@ -252,7 +246,7 @@ object ToSbt { reports.toVector ConfigurationReport( - ConfigRef(config), + ConfigRef(config.value), reports0, Vector() )