英文:
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/foo
和 example2.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 --> example3.com/baz v0.1
example2.com/bar v2.1 --> 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 <some flag> example3.com/bar v0.4
and the result would look something like:
example.com/foo v1.x --> example3.com/baz v0.4
example2.com/bar v2.x --> example3.com/baz v0.4
答案1
得分: 6
Go的依赖项只指定最低版本,不会固定精确或最大版本,并且假设依赖项在演进过程中保持兼容。因此,go get example3.com/bar@v0.4
将升级example3.com/bar
到v0.4
,并且会降级任何依赖于高于v0.4
版本的内容,但它会假设针对v0.1
或v0.2
编写的任何内容基本上是兼容的,你可以使用go test all
进行验证。
因此,没有内置的命令可以直接实现你想要做的事情。
不过,你可以使用go mod graph和grep
来确定哪些外部模块依赖于任何example3.com/bar
。然后,你可以使用sed
将这些行截断为仅包含模块路径,并使用go get
升级这些模块:
MODS=$(go mod graph | grep '@.* example3.com/bar@.*' | sed 's/@.*//')
go get -d $MODS
你甚至可以使用go list -json all
更精确地完成这个任务,它会为主模块导入的包提供结构化信息。Deps
、ImportPath
和Module
字段可能足以确定需要更新的包。(也许可以使用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 '@.* example3.com/bar@.*' | sed 's/@.*//')
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.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论