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