Go模块是否支持升级传递依赖项?

huangapple go评论81阅读模式
英文:

Does go modules support upgrading transitive dependencies?

问题

假设我有一个 Go 模块,其中每个依赖项指向同一个传递依赖项的不同版本。

example.com/foo v1.1 --> example3.com/baz v0.1
example2.com/bar v2.1 --> example3.com/baz v0.2

假设我发现了一个 bug 在 v0.2 中,这是由 go modules最小版本算法解析出来的版本,并且我想升级所有指向指定版本的传递依赖项的依赖项。让我们称之为 example3.com/v0.4

是否有一个命令可以运行,以便升级 example.com/fooexample2.com/bar,以便如果存在的话,传递依赖项满足 example3.com/v0.4

理想情况下,我可以调用 go get <some flag> example3.com/bar v0.4,结果看起来会像这样:

example.com/foo v1.x --> example3.com/baz v0.4
example2.com/bar v2.x --> example3.com/baz v0.4
英文:

Say I have a go module with each dependency pointing to different versions of the same transitive dependency.

example.com/foo v1.1 --&gt; example3.com/baz v0.1
example2.com/bar v2.1 --&gt; example3.com/baz v0.2

Say I find a bug in v0.2, which is the version resolved by the go modules minimum version algorithm, and would like to upgrade all dependencies that point to a specified version of a transitive dependency. Let's call it example3.com/v0.4.

Is there a command that I can run that upgrades example.com/foo and example2.com/bar so that the transitive dependencies are satisfied by example3.com/v0.4 if they exist?

Ideally I would call go get &lt;some flag&gt; example3.com/bar v0.4 and the result would look something like:

example.com/foo v1.x --&gt; example3.com/baz v0.4
example2.com/bar v2.x --&gt; example3.com/baz v0.4

答案1

得分: 6

Go的依赖项只指定最低版本,不会固定精确或最大版本,并且假设依赖项在演进过程中保持兼容。因此,go get example3.com/bar@v0.4将升级example3.com/barv0.4,并且会降级任何依赖于高于v0.4版本的内容,但它会假设针对v0.1v0.2编写的任何内容基本上是兼容的,你可以使用go test all进行验证。

因此,没有内置的命令可以直接实现你想要做的事情。

不过,你可以使用go mod graphgrep来确定哪些外部模块依赖于任何example3.com/bar。然后,你可以使用sed将这些行截断为仅包含模块路径,并使用go get升级这些模块:

MODS=$(go mod graph | grep '@.* example3.com/bar@.*' | sed 's/@.*//')
go get -d $MODS

你甚至可以使用go list -json all更精确地完成这个任务,它会为主模块导入的包提供结构化信息。DepsImportPathModule字段可能足以确定需要更新的包。(也许可以使用jq来过滤和转换,但我今天没有时间来弄清楚。)

英文:

Go's dependencies only specific minimum versions — they don't pin exact or maximum versions, and do assume that dependencies generally remain compatible as they evolve. So go get example3.com/bar@v0.4 will upgrade example3.com/bar to v0.4, and will downgrade anything that depends on a version higher than v0.4, but it will assume that anything written against v0.1 or v0.2 is more-or-less compatible — and you could perhaps verify that using go test all.

So there isn't a built-in command that directly does what you're trying to do.


That said, you could use go mod graph and grep to figure out which external modules depend on any example3.com/bar. Then you could use sed to chop those lines down to just the module path, and upgrade those modules using go get:

MODS=$(go mod graph | grep &#39;@.* example3.com/bar@.*&#39; | sed &#39;s/@.*//&#39;)
go get -d $MODS

You could do that even more precisely using go list -json all, which would give you structured information about the packages imported by the main module. The Deps, ImportPath, and Module fields are probably sufficient to identify which packages need to be updated. (There may be an elegant way to filter and transform that using jq, but I don't have the bandwidth to figure that out today.)

huangapple
  • 本文由 发表于 2021年7月31日 06:04:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/68597514.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定