diff --git a/modules/definitions/src/main/scala/lmcoursier/CoursierConfiguration.scala b/modules/definitions/src/main/scala/lmcoursier/CoursierConfiguration.scala index 09c5e3349..357a11a72 100644 --- a/modules/definitions/src/main/scala/lmcoursier/CoursierConfiguration.scala +++ b/modules/definitions/src/main/scala/lmcoursier/CoursierConfiguration.scala @@ -1,12 +1,12 @@ package lmcoursier import java.io.File - -import dataclass.{ data, since } +import dataclass.{data, since} import coursier.cache.CacheDefaults +import coursier.params.rule.{Rule, RuleResolution} import lmcoursier.credentials.Credentials import lmcoursier.definitions.{Authentication, CacheLogger, CachePolicy, FromCoursier, Module, ModuleMatchers, Project, Reconciliation, Strict} -import sbt.librarymanagement.{Resolver, UpdateConfiguration, ModuleID, CrossVersion, ModuleInfo, ModuleDescriptorConfiguration} +import sbt.librarymanagement.{CrossVersion, InclExclRule, ModuleDescriptorConfiguration, ModuleID, ModuleInfo, Resolver, UpdateConfiguration} import xsbti.Logger import scala.concurrent.duration.{Duration, FiniteDuration} @@ -60,4 +60,5 @@ import java.net.URLClassLoader @since protocolHandlerDependencies: Seq[ModuleID] = Vector.empty, retry: Option[(FiniteDuration, Int)] = None, + sameVersions: Seq[Set[InclExclRule]] = Nil, ) diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala index fa4863e71..84b8a3990 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala @@ -251,7 +251,8 @@ class CoursierDependencyResolution( .withForceVersion(conf.forceVersions.map { case (k, v) => (ToCoursier.module(k), v) }.toMap) .withTypelevel(typelevel) .withReconciliation(ToCoursier.reconciliation(conf.reconciliation)) - .withExclusions(excludeDependencies), + .withExclusions(excludeDependencies) + .withRules(ToCoursier.sameVersions(conf.sameVersions)), strictOpt = conf.strict.map(ToCoursier.strict), missingOk = conf.missingOk, retry = conf.retry.getOrElse(ResolutionParams.defaultRetry), diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/definitions/ToCoursier.scala b/modules/lm-coursier/src/main/scala/lmcoursier/definitions/ToCoursier.scala index 1d47c3d85..2edaf65d8 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/definitions/ToCoursier.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/definitions/ToCoursier.scala @@ -1,6 +1,7 @@ package lmcoursier.definitions import lmcoursier.credentials.{Credentials, DirectCredentials, FileCredentials} +import sbt.librarymanagement.InclExclRule // TODO Make private[lmcoursier] // private[coursier] @@ -31,11 +32,14 @@ object ToCoursier { .withHttpsOnly(authentication.httpsOnly) .withPassOnRedirect(authentication.passOnRedirect) - def module(module: Module): coursier.core.Module = + def module(mod: Module): coursier.core.Module = + module(mod.organization.value, mod.name.value, mod.attributes) + + def module(organization: String, name: String, attributes: Map[String, String] = Map.empty): coursier.core.Module = coursier.core.Module( - coursier.core.Organization(module.organization.value), - coursier.core.ModuleName(module.name.value), - module.attributes + coursier.core.Organization(organization), + coursier.core.ModuleName(name), + attributes ) def moduleMatchers(matcher: ModuleMatchers): coursier.util.ModuleMatchers = @@ -61,6 +65,13 @@ object ToCoursier { Vector[(coursier.util.ModuleMatchers, coursier.core.Reconciliation)] = rs map { case (m, r) => (moduleMatchers(m), reconciliation(r)) } + def sameVersions(sv: Seq[Set[InclExclRule]]): + Seq[(coursier.params.rule.SameVersion, coursier.params.rule.RuleResolution)] = + sv.map { libs => + val matchers = libs.map(rule => coursier.util.ModuleMatcher(module(rule.organization, rule.name))) + coursier.params.rule.SameVersion(matchers) -> coursier.params.rule.RuleResolution.TryResolve + } + def dependency(dependency: Dependency): coursier.core.Dependency = coursier.core.Dependency( module(dependency.module), diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala b/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala index 9bb73be6e..91e30dbbf 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala @@ -39,7 +39,7 @@ object ResolutionRun { params.mainRepositories ++ params.fallbackDependenciesRepositories - val rules = params.strictOpt.map(s => Seq((s, RuleResolution.Fail))).getOrElse(Nil) + val rules = params.params.rules ++ params.strictOpt.map(s => Seq((s, RuleResolution.Fail))).getOrElse(Nil) val printOptionalMessage = verbosityLevel >= 0 && verbosityLevel <= 1 @@ -182,7 +182,7 @@ object ResolutionRun { SbtCoursierCache.default.resolutionOpt(params.resolutionKey).map(Right(_)).getOrElse { val resOrError = Lock.maybeSynchronized(needsLock = params.loggerOpt.nonEmpty || !RefreshLogger.defaultFallbackMode) { - var map = new mutable.HashMap[Configuration, Resolution] + val map = new mutable.HashMap[Configuration, Resolution] val either = params.orderedConfigs.foldLeft[Either[coursier.error.ResolutionError, Unit]](Right(())) { case (acc, (config, extends0)) => for { diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/syntax/package.scala b/modules/lm-coursier/src/main/scala/lmcoursier/syntax/package.scala index 34ae75dbb..c4c3755b6 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/syntax/package.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/syntax/package.scala @@ -74,7 +74,8 @@ package object syntax { sbtClassifiers = false, providedInCompile = false, protocolHandlerDependencies = Vector.empty, - retry = None + retry = None, + sameVersions = Nil, ) }