diff --git a/core/shared/src/main/scala/coursier/core/Definitions.scala b/core/shared/src/main/scala/coursier/core/Definitions.scala index 8576d835c..c741d6a2d 100644 --- a/core/shared/src/main/scala/coursier/core/Definitions.scala +++ b/core/shared/src/main/scala/coursier/core/Definitions.scala @@ -47,7 +47,10 @@ case class Dependency( case class Attributes( `type`: String, classifier: String -) +) { + def publication(name: String, ext: String): Publication = + Publication(name, `type`, ext, classifier) +} case class Project( module: Module, @@ -133,8 +136,11 @@ case class SnapshotVersioning( case class Publication( name: String, `type`: String, - ext: String -) + ext: String, + classifier: String +) { + def attributes: Attributes = Attributes(`type`, classifier) +} case class Artifact( url: String, @@ -146,6 +152,10 @@ case class Artifact( object Artifact { trait Source { - def artifacts(dependency: Dependency, project: Project): Seq[Artifact] + def artifacts( + dependency: Dependency, + project: Project, + overrideClassifiers: Option[Seq[String]] + ): Seq[Artifact] } } diff --git a/core/shared/src/main/scala/coursier/core/Resolution.scala b/core/shared/src/main/scala/coursier/core/Resolution.scala index f2e240bfd..4b9d16e15 100644 --- a/core/shared/src/main/scala/coursier/core/Resolution.scala +++ b/core/shared/src/main/scala/coursier/core/Resolution.scala @@ -746,16 +746,22 @@ case class Resolution( .getOrElse(Map.empty) ) - def artifacts: Seq[Artifact] = + private def artifacts0(overrideClassifiers: Option[Seq[String]]): Seq[Artifact] = for { dep <- minDependencies.toSeq (source, proj) <- projectCache .get(dep.moduleVersion) .toSeq artifact <- source - .artifacts(dep, proj) + .artifacts(dep, proj, overrideClassifiers) } yield artifact + def classifiersArtifacts(classifiers: Seq[String]): Seq[Artifact] = + artifacts0(Some(classifiers)) + + def artifacts: Seq[Artifact] = + artifacts0(None) + def dependencyArtifacts: Seq[(Dependency, Artifact)] = for { dep <- minDependencies.toSeq @@ -763,7 +769,7 @@ case class Resolution( .get(dep.moduleVersion) .toSeq artifact <- source - .artifacts(dep, proj) + .artifacts(dep, proj, None) } yield dep -> artifact def errors: Seq[(Dependency, Seq[String])] = diff --git a/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala b/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala index ac24d534a..b1ce1a788 100644 --- a/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala +++ b/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala @@ -165,37 +165,53 @@ case class IvyRepository( val source: Artifact.Source = new Artifact.Source { - def artifacts(dependency: Dependency, project: Project) = - project - .publications - .collect { - case (conf, p) - if conf == "*" || - conf == dependency.configuration || - project.allConfigurations.getOrElse(dependency.configuration, Set.empty).contains(conf) => - p - } - .flatMap { p => - substitute(variables( - dependency.module.organization, - dependency.module.name, - dependency.version, - p.`type`, - p.name, - p.ext - )).toList.map(p -> _) - } - .map { case (p, url) => - Artifact( - url, - Map.empty, - Map.empty, - Attributes(p.`type`, p.ext), - changing = changing.getOrElse(project.version.contains("-SNAPSHOT")) // could be more reliable - ) - .withDefaultChecksums - .withDefaultSignature + def artifacts( + dependency: Dependency, + project: Project, + overrideClassifiers: Option[Seq[String]] + ) = { + + val retained = + overrideClassifiers match { + case None => + project.publications.collect { + case (conf, p) + if conf == "*" || + conf == dependency.configuration || + project.allConfigurations.getOrElse(dependency.configuration, Set.empty).contains(conf) => + p + } + case Some(classifiers) => + val classifiersSet = classifiers.toSet + project.publications.collect { + case (_, p) if classifiersSet(p.classifier) => + p + } } + + val retainedWithUrl = retained.flatMap { p => + substitute(variables( + dependency.module.organization, + dependency.module.name, + dependency.version, + p.`type`, + p.name, + p.ext + )).toList.map(p -> _) + } + + retainedWithUrl.map { case (p, url) => + Artifact( + url, + Map.empty, + Map.empty, + p.attributes, + changing = changing.getOrElse(project.version.contains("-SNAPSHOT")) // could be more reliable + ) + .withDefaultChecksums + .withDefaultSignature + } + } } diff --git a/core/shared/src/main/scala/coursier/ivy/IvyXml.scala b/core/shared/src/main/scala/coursier/ivy/IvyXml.scala index bc3d52ebb..62b70cb8d 100644 --- a/core/shared/src/main/scala/coursier/ivy/IvyXml.scala +++ b/core/shared/src/main/scala/coursier/ivy/IvyXml.scala @@ -71,7 +71,8 @@ object IvyXml { val type0 = node.attribute("type").getOrElse("jar") val ext = node.attribute("ext").getOrElse(type0) val confs = node.attribute("conf").toOption.fold(Seq("*"))(_.split(',')) - confs.map(_ -> Publication(name, type0, ext)) + val classifier = node.attribute("classifier").toOption.getOrElse("") + confs.map(_ -> Publication(name, type0, ext, classifier)) } .groupBy { case (conf, _) => conf } .map { case (conf, l) => conf -> l.map { case (_, p) => p } } @@ -115,7 +116,7 @@ object IvyXml { None, if (publicationsOpt.isEmpty) // no publications node -> default JAR artifact - Seq("*" -> Publication(module.name, "jar", "jar")) + Seq("*" -> Publication(module.name, "jar", "jar", "")) else { // publications node is there -> only its content (if it is empty, no artifacts, // as per the Ivy manual) diff --git a/core/shared/src/main/scala/coursier/maven/MavenRepository.scala b/core/shared/src/main/scala/coursier/maven/MavenRepository.scala index d0522f13e..d05fcf472 100644 --- a/core/shared/src/main/scala/coursier/maven/MavenRepository.scala +++ b/core/shared/src/main/scala/coursier/maven/MavenRepository.scala @@ -244,7 +244,10 @@ case class MavenRepository( xml <- \/.fromEither(compatibility.xmlParse(str)) _ <- if (xml.label == "project") \/-(()) else -\/("Project definition not found") proj <- Pom.project(xml) - } yield proj.copy(configurations = defaultConfigurations)): (String \/ Project) + } yield proj.copy( + configurations = defaultConfigurations, + publications = ??? + )): (String \/ Project) } } } diff --git a/core/shared/src/main/scala/coursier/maven/MavenSource.scala b/core/shared/src/main/scala/coursier/maven/MavenSource.scala index 06921e82d..467c8584a 100644 --- a/core/shared/src/main/scala/coursier/maven/MavenSource.scala +++ b/core/shared/src/main/scala/coursier/maven/MavenSource.scala @@ -39,86 +39,74 @@ case class MavenSource( def artifacts( dependency: Dependency, - project: Project + project: Project, + overrideClassifiers: Option[Seq[String]] ): Seq[Artifact] = { - def ivyLikePath0(subDir: String, baseSuffix: String, ext: String) = - ivyLikePath( - dependency.module.organization, - dependency.module.name, - project.version, - subDir, - baseSuffix, - ext - ) - - val path = - if (ivyLike) - ivyLikePath0(dependency.attributes.`type` + "s", "", dependency.attributes.`type`) - else { - val versioning = - project - .snapshotVersioning - .flatMap(versioning => - mavenVersioning(versioning, dependency.attributes.classifier, dependency.attributes.`type`) - ) - - dependency.module.organization.split('.').toSeq ++ Seq( - dependency.module.name, + def artifactOf(module: Module, publication: Publication) = { + def ivyLikePath0(subDir: String, baseSuffix: String, ext: String) = + ivyLikePath( + module.organization, + module.name, project.version, - s"${dependency.module.name}-${versioning getOrElse project.version}${Some(dependency.attributes.classifier).filter(_.nonEmpty).map("-"+_).mkString}.${dependency.attributes.`type`}" + subDir, + baseSuffix, + ext ) + + val path = + if (ivyLike) + ivyLikePath0(publication.`type` + "s", "", publication.ext) + else { + val versioning = + project + .snapshotVersioning + .flatMap(versioning => + mavenVersioning(versioning, publication.classifier, publication.`type`) + ) + + module.organization.split('.').toSeq ++ Seq( + module.name, + project.version, + s"${module.name}-${versioning getOrElse project.version}${Some(publication.classifier).filter(_.nonEmpty).map("-" + _).mkString}.${publication.ext}" + ) + } + + val changing0 = changing.getOrElse(project.version.contains("-SNAPSHOT")) + var artifact = + Artifact( + root + path.mkString("/"), + Map.empty, + Map.empty, + publication.attributes, + changing = changing0 + ) + .withDefaultChecksums + + if (publication.ext == "jar") { + artifact = artifact.withDefaultSignature } - val changing0 = changing.getOrElse(project.version.contains("-SNAPSHOT")) - var artifact = - Artifact( - root + path.mkString("/"), - Map.empty, - Map.empty, - dependency.attributes, - changing = changing0 - ) - .withDefaultChecksums - - if (dependency.attributes.`type` == "jar") { - artifact = artifact.withDefaultSignature - - // FIXME Snapshot versioning of sources and javadoc is not taken into account here. - // Will be ok if it's the same as the main JAR though. - - artifact = - if (ivyLike) { - val srcPath = root + ivyLikePath0("srcs", "-sources", "jar").mkString("/") - val javadocPath = root + ivyLikePath0("docs", "-javadoc", "jar").mkString("/") - - artifact - .copy( - extra = artifact.extra ++ Map( - "sources" -> Artifact( - srcPath, - Map.empty, - Map.empty, - Attributes("jar", "src"), // Are these the right attributes? - changing = changing0 - ) - .withDefaultChecksums - .withDefaultSignature, - "javadoc" -> Artifact( - javadocPath, - Map.empty, - Map.empty, - Attributes("jar", "javadoc"), // Same comment as above - changing = changing0 - ) - .withDefaultChecksums - .withDefaultSignature - )) - } else - artifact - .withJavadocSources + artifact } - Seq(artifact) + overrideClassifiers match { + case Some(classifiers) => + val classifiersSet = classifiers.toSet + project.publications.collect { + case (_, p) if classifiersSet(p.classifier) => + artifactOf(dependency.module, p) + } + case None => + Seq( + artifactOf( + dependency.module, + dependency.attributes.publication( + dependency.module.name, + dependency.attributes.`type` + ) + ) + ) + } } } diff --git a/plugin/src/main/scala/coursier/InterProjectRepository.scala b/plugin/src/main/scala/coursier/InterProjectRepository.scala index 18233c8fe..62b086989 100644 --- a/plugin/src/main/scala/coursier/InterProjectRepository.scala +++ b/plugin/src/main/scala/coursier/InterProjectRepository.scala @@ -3,12 +3,21 @@ package coursier import scalaz.{ -\/, \/-, Monad, EitherT } case class InterProjectSource(artifacts: Map[(Module, String), Map[String, Seq[Artifact]]]) extends Artifact.Source { - def artifacts(dependency: Dependency, project: Project): Seq[Artifact] = - artifacts - .get(dependency.moduleVersion) - .toSeq - .flatMap(_.get(dependency.configuration)) - .flatten + def artifacts( + dependency: Dependency, + project: Project, + overrideClassifiers: Option[Seq[String]] + ): Seq[Artifact] = + overrideClassifiers match { + case None => + artifacts + .get(dependency.moduleVersion) + .toSeq + .flatMap(_.get(dependency.configuration)) + .flatten + case Some(_) => + Nil + } } case class InterProjectRepository(projects: Seq[(Project, Seq[(String, Seq[Artifact])])]) extends Repository { diff --git a/tests/shared/src/test/scala/coursier/test/TestRepository.scala b/tests/shared/src/test/scala/coursier/test/TestRepository.scala index fcbe0030f..bc851b8e1 100644 --- a/tests/shared/src/test/scala/coursier/test/TestRepository.scala +++ b/tests/shared/src/test/scala/coursier/test/TestRepository.scala @@ -8,7 +8,11 @@ import scalaz.Scalaz._ class TestRepository(projects: Map[(Module, String), Project]) extends Repository { val source = new core.Artifact.Source { - def artifacts(dependency: Dependency, project: Project) = ??? + def artifacts( + dependency: Dependency, + project: Project, + overrideClassifiers: Option[Seq[String]] + ) = ??? } def find[F[_]]( module: Module,