You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I noticed that go mod tidy (in Go 1.20.4 and at tip) sorts lines in exclude blocks lexicographically. For some sequences of module versions it will cause a diff like this:
// ... some explanation for why this exclude is needed ...
+ example.com/module v1.10.0+ example.com/module v1.11.0+ example.com/module v1.12.0
- example.com/module v1.10.0- example.com/module v1.11.0- example.com/module v1.12.0
It's certainly not at all a big deal especially since exclude directives are rare, but it might still be slightly unexpected for it not to maintain the consistent semantic version sorting.
I took a quick look at what it might take to make it not do that. It turned out to be working as intended: all blocks (other than the newer retract one) sort lines via a simple lexicographic sort. It's just that exclude blocks are a rare situation where multiple versions of the same module may happen in practice and run into this edge case.
The go command currently gates some accepted changes to go mod tidy behavior on the Go language version specified in go.mod (e.g., tidyGoModSumVersionV = "v1.21") to avoid introducing unnecessary churn. (I think the concern of invalidating checksums doesn't apply to tidy behavior changes?) It'd also be possible to check what percentage of go.mod files in a corpus of public modules would be affected, though that misses private modules where exclude might be used more.
So fixing this or any other potential formatting change deemed worthwhile can also begin to apply upon reaching a future Go version. It probably belongs in package modfile since there's no intended change to meaning.
A formatting change that is gated behind Go version (current + 2) means by the time it happens all supported Go toolchains would handle it consistently. But since go mod tidy in Go 1.N refuses to tidy a go.mod with Go 1.(N+1), maybe just current + 1 would be sufficient?
I've sketched a possible implementation of this to see what it might look like, and perhaps it's not worth the implementation complexity (that needs to stay around) for such a small improvement to one block type. Maybe it's better to wait and solve this in bulk with some other minor changes, or when some bigger change happens and makes this obsolete. I'll let package owners chime in on if you think it's worth doing anything about this or just leaving it.