2024 Clojure状况调查问卷中分享您的看法!

欢迎!请参阅关于页面了解更多关于此如何工作的信息。

+2
Clojure CLI
重新标记

在tools.deps中使用git dependencies时,以下声明的依赖项

{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" ...}}

都将被解析,即使它们都是相同的lib,但它们之间不会发生冲突。

目前,声明依赖项的消费者可以选择所有这些等效的声明,但如果它与任何传递依赖项所选的声明不同,则会创建一个隐藏的冲突,并将在类路径中拉入多个版本库,导致在运行时使用的代码版本不可预测。

这个问题可以通过让库作者选择用户在声明对这个库的依赖时必须始终使用的规范库groupId和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以供将来工作。

请注意,第一个出现在类路径上的库是确定的 - 它将是你的依赖树中“最高级别”的库,然后在该级别按字典顺序排序。

...