2024 年 Clojure 状态调查!分享您的想法。

欢迎!请详见关于页面以获得更多关于此如何工作的小信息。

+2
Clojure CLI
重标记

在 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无法检测和解决隐藏的运行时版本冲突。

1 个答案

0

我不认为我想向deps.edn的库名添加属性。我们通常尽量避免在deps文件本身中添加项目标识符信息。

愿意添加验证以检测“冲突”的依赖库(但这是一个基于内容的更普遍问题)。我已在https://clojure.atlassian.net/browse/TDEPS-229中提交此问题,供将来使用。

请注意,将在类路径中首先出现的库是确定的 —— 它将是您依赖树中最高的“级别”的库,然后在同一级别中按字母顺序排序。

...