传递性地替换 Ivy 模块
Substituting Ivy modules transitively
我正在以编程方式使用 Ivy(在 SBT 的上下文中),我需要
能够传递地用一小组模块替换
具有不同组织但共享的兼容集
工件名称、修订等
举个具体的例子,我要替换,
org.scala-lang#scala-reflect;2.11.8
与
org.typelevel#scala-reflect;2.11.8
依赖图中的任何地方。请注意,我只想添加一个
依赖 org.typelevel#scala-reflect;2.11.8 如果有
对 org.scala-lang#scala-reflect;2.11.8 某处的依赖
图(我不知道提前),所以这还不够
无条件排除 org.scala-lang 模块并包含
org.typelevel一个。
这可能吗?如果是,指向必要机制的指针将
非常欢迎。如果不是,解决方法的建议也会
不客气。
虽然这不是最干净的解决方案,但我认为您可以通过劫持项目解析器(负责解析 SBT 中的项目间依赖关系)来实现。
构建文件中的某处:
// ...
.settings(
projectResolver <<= (projectDescriptors, streams) map { (m, s) =>
new RawRepository(new ProjectResolver("custom-resolver", m) {
import org.apache.ivy.core.module.descriptor.DependencyDescriptor
import org.apache.ivy.core.resolve.ResolveData
import org.apache.ivy.core.resolve.ResolvedModuleRevision
override def getDependency(dd: DependencyDescriptor, data: ResolveData): ResolvedModuleRevision = {
s.log.info("Resolving " + dd.getDependencyId.getName)
// adjust your dependency descriptor and possibly resolve
// from another source?
super.getDependency(dd, data)
}
})
}
)
这个新项目解析器可以调整某些依赖描述符,然后根据常规解析器链解析它们...我认为。您可能需要重写一些额外的方法。
这可以使用 Ivy DependencyDescriptorMediator
来完成。以下将执行 module
类型 DefaultModuleDescriptor
、
问题中描述的重写
class OverrideScalaMediator(scalaOrganization: String, scalaVersion: String)
extends DependencyDescriptorMediator {
def mediate(dd: DependencyDescriptor): DependencyDescriptor = {
val transformer =
new NamespaceTransformer {
def transform(mrid: ModuleRevisionId): ModuleRevisionId = {
if (mrid == null) mrid
else
mrid.getName match {
case name @ "scala-reflect" =>
ModuleRevisionId.newInstance(
scalaOrganization, name, mrid.getBranch, scalaVersion,
mrid.getQualifiedExtraAttributes
)
case _ => mrid
}
}
def isIdentity: Boolean = false
}
DefaultDependencyDescriptor.transformInstance(dd, transformer, false)
}
}
val mediator = new OverrideScalaMediator("org.typelevel", version)
module.addDependencyDescriptorMediator(
new ModuleId("org.scala-lang", "*"), ExactPatternMatcher.INSTANCE, mediator
)
您可以在 SBT here.
中看到这个
我正在以编程方式使用 Ivy(在 SBT 的上下文中),我需要 能够传递地用一小组模块替换 具有不同组织但共享的兼容集 工件名称、修订等
举个具体的例子,我要替换,
org.scala-lang#scala-reflect;2.11.8
与
org.typelevel#scala-reflect;2.11.8
依赖图中的任何地方。请注意,我只想添加一个 依赖 org.typelevel#scala-reflect;2.11.8 如果有 对 org.scala-lang#scala-reflect;2.11.8 某处的依赖 图(我不知道提前),所以这还不够 无条件排除 org.scala-lang 模块并包含 org.typelevel一个。
这可能吗?如果是,指向必要机制的指针将 非常欢迎。如果不是,解决方法的建议也会 不客气。
虽然这不是最干净的解决方案,但我认为您可以通过劫持项目解析器(负责解析 SBT 中的项目间依赖关系)来实现。
构建文件中的某处:
// ...
.settings(
projectResolver <<= (projectDescriptors, streams) map { (m, s) =>
new RawRepository(new ProjectResolver("custom-resolver", m) {
import org.apache.ivy.core.module.descriptor.DependencyDescriptor
import org.apache.ivy.core.resolve.ResolveData
import org.apache.ivy.core.resolve.ResolvedModuleRevision
override def getDependency(dd: DependencyDescriptor, data: ResolveData): ResolvedModuleRevision = {
s.log.info("Resolving " + dd.getDependencyId.getName)
// adjust your dependency descriptor and possibly resolve
// from another source?
super.getDependency(dd, data)
}
})
}
)
这个新项目解析器可以调整某些依赖描述符,然后根据常规解析器链解析它们...我认为。您可能需要重写一些额外的方法。
这可以使用 Ivy DependencyDescriptorMediator
来完成。以下将执行 module
类型 DefaultModuleDescriptor
、
class OverrideScalaMediator(scalaOrganization: String, scalaVersion: String)
extends DependencyDescriptorMediator {
def mediate(dd: DependencyDescriptor): DependencyDescriptor = {
val transformer =
new NamespaceTransformer {
def transform(mrid: ModuleRevisionId): ModuleRevisionId = {
if (mrid == null) mrid
else
mrid.getName match {
case name @ "scala-reflect" =>
ModuleRevisionId.newInstance(
scalaOrganization, name, mrid.getBranch, scalaVersion,
mrid.getQualifiedExtraAttributes
)
case _ => mrid
}
}
def isIdentity: Boolean = false
}
DefaultDependencyDescriptor.transformInstance(dd, transformer, false)
}
}
val mediator = new OverrideScalaMediator("org.typelevel", version)
module.addDependencyDescriptorMediator(
new ModuleId("org.scala-lang", "*"), ExactPatternMatcher.INSTANCE, mediator
)
您可以在 SBT here.
中看到这个