在 tools.deps 中,当使用 git 依赖时,以下声明的依赖项
{io.github.xadecimal/riddley {...}}
{com.github.xadecimal/riddley {...}}
{com.xadecimal/riddley {:git/url "https://github.com/xadecimal/riddley.git" ...}}
{com.xadecimal/riddley {:mvn/version ...}}
{garbage/whatever {:git/url "https://github.com/xadecimal/riddley.git" ...}}
都将解决,但它们之间不会发生冲突,尽管它们都是相同的库。
目前,声明依赖项的消费者可以从所有这些等效声明中选择,但如果它选择的与任何其转置依赖项不同,则会创建一个隐藏的冲突,并且类路径中将引入多个版本的库,使得运行时实际使用的代码版本不可预测。
可以通过让库作者选择用户声明对其依赖时必须始终使用的规范库 group/name 来解决这个问题。
这可以通过向 deps.edn
添加一个新的键来实现,例如 :lib
,它接受一个完全限定的符号,将与消费库的 :deps
映射中声明的符号进行验证。
所依赖的库的 deps.edn
{:lib com.xadecimal/riddley ;; <-- This new key is added to deps.edn, declaring the canonical lib name
:paths ["src"]
:deps {...}
...}
声明对上述库有依赖的库的 deps.edn
{:paths ["src"]
:deps {com.xadecimal/riddley {...}}
...}
当 tools.deps 解决上述问题时,它将检查拉取的库是否在其 deps.edn
中声明了 :lib
键,如果声明了,它将断言此处使用的符号与声明的 :lib
符号匹配,如果不匹配,它将报错给用户,使这成为一个非法的依赖声明。在上面的例子中这是正确的,但在以下例子中是错误的
声明了对上述库非法依赖的库的 deps.edn
{:paths ["src"]
:deps {com.github.xadecimal/riddley {...}}
...}
这会报错,因为即使库可在 github.com/xadecimal/riddley.git
中找到并且因此解决,位于 github.com/xadecimal/riddley.git
的库已经声明其规范库名称为 com.xadecimal/riddley
而不是 com.github.xadecimal/riddley
。因此,在这种情况下,唯一有效的 git 依赖声明是
{:paths ["src"]
:deps {com.xadecimal/riddley {:git/url "https://github.com/xadecimal/riddley.git" ...}}
...}
此验证将遵循类似于断言 git/tag 与 git/sha 匹配的思想,即断言使用的库名与库期望的独特标识符匹配。
执行此操作可以使冲突解决按预期工作,并避免传递依赖使用不同名称的可能性,从而避免工具.deps无法检测和解决隐藏的运行时版本冲突。