Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor forAllProjects to use ScopeFilter #62

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
package coursier.sbtcoursiershared

import lmcoursier.definitions.{Attributes, Classifier, Configuration, Dependency, Extension, Info, Module, ModuleName, Organization, Project, Publication, Strict, Type}
import java.net.URL
import lmcoursier.definitions.{
Classifier => CClassifier,
Configuration => CConfiguration,
Dependency => CDependency,
Extension => CExtension,
Info => CInfo,
Module => CModule,
ModuleName => CModuleName,
Organization => COrganization,
Project => CProject,
Publication => CPublication,
Strict => CStrict,
Type => CType
}
import lmcoursier.{FallbackDependency, FromSbt, Inputs}
import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.sbtcoursiershared.Structure._
import lmcoursier.credentials.DirectCredentials
import sbt.{Def, SettingKey}
import sbt._
import sbt.Keys._
import sbt.librarymanagement.{ConflictManager, InclExclRule, ModuleID}
import sbt.util.Logger
Expand All @@ -15,7 +29,7 @@ import scala.language.reflectiveCalls

object InputsTasks {

lazy val actualExcludeDependencies =
lazy val actualExcludeDependencies: SettingKey[scala.Seq[InclExclRule]] =
try {
sbt.Keys
.asInstanceOf[{ def allExcludeDependencies: SettingKey[scala.Seq[InclExclRule]] }]
Expand All @@ -31,73 +45,67 @@ object InputsTasks {
configurations: Seq[sbt.librarymanagement.Configuration],
sv: String,
sbv: String,
auOpt: Option[URL],
log: Logger
): Project = {
): CProject = {

val configMap = Inputs.configExtendsSeq(configurations).toMap

FromSbt.project(
val proj0 = FromSbt.project(
projId,
dependencies,
configMap,
sv,
sbv
)
auOpt match {
case Some(au) =>
val props = proj0.properties :+ ("info.apiURL" -> au.toString)
proj0.withProperties(props)
case _ => proj0
}
}

private[sbtcoursiershared] def coursierProjectTask: Def.Initialize[sbt.Task[Project]] =
Def.taskDyn {

val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value

val allDependenciesTask = allDependencies.in(projectRef).get(state)

Def.task {
coursierProject0(
projectID.in(projectRef).get(state),
allDependenciesTask.value,
// should projectID.configurations be used instead?
ivyConfigurations.in(projectRef).get(state),
scalaVersion.in(projectRef).get(state),
scalaBinaryVersion.in(projectRef).get(state),
state.log
)
}
private[sbtcoursiershared] def coursierProjectTask: Def.Initialize[sbt.Task[CProject]] =
Def.task {
coursierProject0(
projectID.value,
allDependencies.value,
// should projectID.configurations be used instead?
ivyConfigurations.value,
scalaVersion.value,
scalaBinaryVersion.value,
apiURL.value,
streams.value.log
)
}

private def moduleFromIvy(id: org.apache.ivy.core.module.id.ModuleRevisionId): Module =
Module(
Organization(id.getOrganisation),
ModuleName(id.getName),
id.getExtraAttributes
.asScala
.map {
case (k0, v0) => k0.asInstanceOf[String] -> v0.asInstanceOf[String]
}
.toMap
private def moduleFromIvy(id: org.apache.ivy.core.module.id.ModuleRevisionId): CModule =
CModule(
COrganization(id.getOrganisation),
CModuleName(id.getName),
id.getExtraAttributes.asScala.map {
case (k0, v0) => k0.asInstanceOf[String] -> v0.asInstanceOf[String]
}.toMap
)

private def dependencyFromIvy(desc: org.apache.ivy.core.module.descriptor.DependencyDescriptor): Seq[(Configuration, Dependency)] = {
private def dependencyFromIvy(
desc: org.apache.ivy.core.module.descriptor.DependencyDescriptor
): Seq[(CConfiguration, CDependency)] = {

val id = desc.getDependencyRevisionId
val module = moduleFromIvy(id)
val exclusions = desc
.getAllExcludeRules
.map { rule =>
// we're ignoring rule.getConfigurations and rule.getMatcher here
val modId = rule.getId.getModuleId
// we're ignoring modId.getAttributes here
(Organization(modId.getOrganisation), ModuleName(modId.getName))
}
.toSet

val configurations = desc
.getModuleConfigurations
.toVector
val exclusions = desc.getAllExcludeRules.map { rule =>
// we're ignoring rule.getConfigurations and rule.getMatcher here
val modId = rule.getId.getModuleId
// we're ignoring modId.getAttributes here
(COrganization(modId.getOrganisation), CModuleName(modId.getName))
}.toSet

val configurations = desc.getModuleConfigurations.toVector
.flatMap(Inputs.ivyXmlMappings)

def dependency(conf: Configuration, pub: Publication) = Dependency(
def dependency(conf: CConfiguration, pub: CPublication) = CDependency(
module,
id.getRevision,
conf,
Expand All @@ -107,18 +115,18 @@ object InputsTasks {
desc.isTransitive
)

val publications: Configuration => Publication = {
val publications: CConfiguration => CPublication = {

val artifacts = desc.getAllDependencyArtifacts

val m = artifacts.toVector.flatMap { art =>
val pub = Publication(art.getName, Type(art.getType), Extension(art.getExt), Classifier(""))
art.getConfigurations.map(Configuration(_)).toVector.map { conf =>
val pub = CPublication(art.getName, CType(art.getType), CExtension(art.getExt), CClassifier(""))
art.getConfigurations.map(CConfiguration(_)).toVector.map { conf =>
conf -> pub
}
}.toMap

c => m.getOrElse(c, Publication("", Type(""), Extension(""), Classifier("")))
c => m.getOrElse(c, CPublication("", CType(""), CExtension(""), CClassifier("")))
}

configurations.map {
Expand All @@ -127,29 +135,20 @@ object InputsTasks {
}
}

private[sbtcoursiershared] def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[Project]]] =
private[sbtcoursiershared] def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[CProject]]] =
Def.taskDyn {

val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value

val projectRefs = Structure.allRecursiveInterDependencies(state, projectRef)

val t = coursierProject.forAllProjectsOpt(state, projectRefs :+ projectRef)
val projectRefs = transitiveInterDependencies(state, projectRef)

Def.task {
t.value.toVector.flatMap {
case (ref, None) =>
if (ref.build != projectRef.build)
state.log.warn(s"Cannot get coursier info for project under ${ref.build}, is sbt-coursier also added to it?")
Nil
case (_, Some(p)) =>
Seq(p)
}
coursierProject.all(ScopeFilter(inProjects(projectRefs: _*))).value
}
}

private[sbtcoursiershared] def coursierExtraProjectsTask: Def.Initialize[sbt.Task[Seq[Project]]] =
private[sbtcoursiershared] def coursierExtraProjectsTask: Def.Initialize[sbt.Task[Seq[CProject]]] =
Def.task {
val projects = coursierInterProjectDependencies.value
val projectModules = projects.map(_.module).toSet
Expand All @@ -170,42 +169,37 @@ object InputsTasks {
val configurations = v
.getConfigurations
.map { c =>
Configuration(c.getName) -> c.getExtends.map(Configuration(_)).toSeq
CConfiguration(c.getName) -> c.getExtends.map(CConfiguration(_)).toSeq
}
.toMap
val deps = v.getDependencies.flatMap(dependencyFromIvy)
Project(
CProject(
module,
v.getModuleRevisionId.getRevision,
deps,
configurations,
Nil,
None,
Nil,
Info("", "", Nil, Nil, None)
CInfo("", "", Nil, Nil, None)
)
}
}

private[sbtcoursiershared] def coursierFallbackDependenciesTask: Def.Initialize[sbt.Task[Seq[FallbackDependency]]] =
Def.taskDyn {

val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value

val projects = allRecursiveInterDependencies(state, projectRef)

val allDependenciesTask = allDependencies
.forAllProjects(state, projectRef +: projects)
.map(_.values.toVector.flatten)
val s = state.value
val projectRef = thisProjectRef.value
val projects = transitiveInterDependencies(s, projectRef)

Def.task {
val allDependencies = allDependenciesTask.value
val allDeps =
allDependencies.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten

FromSbt.fallbackDependencies(
allDependencies,
scalaVersion.in(projectRef).get(state),
scalaBinaryVersion.in(projectRef).get(state)
allDeps,
scalaVersion.value,
scalaBinaryVersion.value
)
}
}
Expand Down Expand Up @@ -257,7 +251,7 @@ object InputsTasks {
case ConflictManager.latestRevision.name =>
None
case ConflictManager.strict.name =>
val strict = Strict()
val strict = CStrict()
.withInclude(Set((cm.organization, cm.module)))
Some(strict)
case other =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package coursier.sbtcoursiershared

import coursier.sbtcoursiershared.SbtCoursierShared.autoImport._
import coursier.sbtcoursiershared.Structure._
import sbt.{Classpaths, Def}
import sbt._
import sbt.Keys._
import sbt.librarymanagement.{Resolver, URLRepository}

Expand Down Expand Up @@ -95,17 +95,11 @@ private[sbtcoursiershared] object RepositoriesTasks {

def coursierRecursiveResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] =
Def.taskDyn {

val state = sbt.Keys.state.value
val projectRef = sbt.Keys.thisProjectRef.value

val projects = allRecursiveInterDependencies(state, projectRef)

val t = coursierResolvers
.forAllProjects(state, projectRef +: projects)
.map(_.values.toVector.flatten)

Def.task(t.value)
val s = state.value
val projectRef = thisProjectRef.value
val projects = transitiveInterDependencies(s, projectRef)
Def.task {
coursierResolvers.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,36 @@ package coursier.sbtcoursiershared
import sbt._

object Structure {

def allRecursiveInterDependencies(state: sbt.State, projectRef: sbt.ProjectRef) = {

def dependencies(map: Map[String, Seq[String]], id: String): Set[String] = {

def helper(map: Map[String, Seq[String]], acc: Set[String]): Set[String] =
import sbt.Project.structure

def transitiveInterDependencies(
state: State,
projectRef: ProjectRef
): Seq[ProjectRef] = {
def dependencies(map: Map[ProjectRef, Seq[ProjectRef]], id: ProjectRef): Set[ProjectRef] = {
def helper(map: Map[ProjectRef, Seq[ProjectRef]], acc: Set[ProjectRef]): Set[ProjectRef] =
if (acc.exists(map.contains)) {
val (kept, rem) = map.partition { case (k, _) => acc(k) }
helper(rem, acc ++ kept.valuesIterator.flatten)
} else
acc

helper(map - id, map.getOrElse(id, Nil).toSet)
}

val allProjectsDeps =
for (p <- structure(state).allProjects)
yield p.id -> p.dependencies.map(_.project.project)

val deps = dependencies(allProjectsDeps.toMap, projectRef.project)

structure(state).allProjectRefs.filter(p => deps(p.project))
val allProjectsDeps: Map[ProjectRef, Seq[ProjectRef]] =
(for {
(p, ref) <- allProjectPairs(state)
} yield ref -> p.dependencies.map(_.project)).toMap
val deps = dependencies(allProjectsDeps.toMap, projectRef)
structure(state).allProjectRefs.filter(p => deps(p))
}

// vv things from sbt-structure vv
private def allProjectPairs(state: State): Seq[(ResolvedProject, ProjectRef)] =
for {
(build, unit) <- structure(state).units.toSeq
p: ResolvedProject <- unit.defined.values.toSeq
} yield (p, ProjectRef(build, p.id))

def structure(state: State) =
sbt.Project.structure(state)
// vv things from sbt-structure vv

implicit class `enrich SettingKey`[T](key: SettingKey[T]) {
def find(state: State): Option[T] =
Expand All @@ -43,32 +45,5 @@ object Structure {
find(state).getOrElse(default)
}

implicit class `enrich TaskKey`[T](key: TaskKey[T]) {
def find(state: State): Option[sbt.Task[T]] =
key.get(structure(state).data)

def get(state: State): sbt.Task[T] =
find(state).get

def forAllProjects(state: State, projects: Seq[ProjectRef]): sbt.Task[Map[ProjectRef, T]] = {
val tasks = projects.flatMap(p => key.in(p).get(structure(state).data).map(_.map(it => (p, it))))
std.TaskExtra.joinTasks(tasks).join.map(_.toMap)
}

// ^^ things from sbt-structure ^^

def forAllProjectsOpt(state: State, projects: Seq[ProjectRef]): sbt.Task[Map[ProjectRef, Option[T]]] = {
val settings = structure(state).data
val tasks = projects.map { p =>
val taskOpt = key.in(p).get(settings)
taskOpt match {
case None =>
Def.task(p -> Option.empty[T]).evaluate(settings)
case Some(t) =>
t.map(p -> Option(_))
}
}
std.TaskExtra.joinTasks(tasks).join.map(_.toMap)
}
}
// ^^ things from sbt-structure ^^
}
Loading