go
go copied to clipboard
cmd/go: mod tidy should join "require" sections if there are more than two
Since https://github.com/golang/go/issues/45965, go.mod
files now generally consist of two sections: one require (...)
section with direct module dependencies, and one for // indirect
module dependencies.
However, if a go.mod
file somehow ends up with more than two of those sections, then go mod tidy
does not join them back. I think it should. For example, if I join the normal two sections into one, go mod tidy
, splits them again.
Here are two instances I recently found of such an unintentional "split" of sections:
- https://github.com/kortschak/gospel/blob/a5524a0364dead9e4d48f4952c2edff9007a9f09/go.mod
- https://github.com/vocdoni/vocdoni-node/pull/650#issuecomment-1294133282
Both were spotted manually and fixed, as they were indeed unintentional. Locally, I used for f in **/go.mod; do n=$(grep -F 'require (' $f | wc -l); if [[ $n -gt 2 ]]; then echo $n $f; fi; done
with Bash to find any others. I couldn't find any.
Globally, I tried using cs.github.com, but it doesn't appear to support matching regular expressions across multiple lines, like PCRE. But Googe's code search does; https://cs.opensource.google/search?q=path%3Ago.mod+AND+pcre%3Ayes+AND+%28require%5C+%5C%28%28.%7C%5Cn%29require%5C+%5C%28%28.%7C%5Cn%29require%29+ found:
- https://cs.opensource.google/knative/eventing-rabbitmq/+/main:go.mod;drc=0932f28e1db80078d67fee4a3f9ecb62f2fff09e
- https://cs.opensource.google/knative/eventing-kafka-broker/+/main:go.mod;drc=efa69d6f58637c70e5f44e35728bb471fc30cf18
None of those four appear to be on purpose. I think they could have appeared unintentionally due to a number of reasons, such as:
- Git merges. If two branches make changes to
go.mod
, depending on how the user resolves the conflicts manually, they could end up with more than two sections. I'm fairly sure that this is what happened in vocdoni-node, as the PR in question lived for over a month and had conflicts to be resolved. - Manual editing. I've seen some users not fully grasp how
go get
works, and resorting to editinggo.mod
directly to update or addrequire
lines. When doing it quickly or copy-pasting, I imagine it's tempting to just add arequire some-module v1.2.3
at the end of the file, which will work regardless of what the file looks like.
I personally can't think why anyone would want more than two require
sections today. The fact that I could only find four examples today in ten minutes of research is a double-edged sword. On one hand it's proof that basically noone wants more than two sections. On the other, it also means that this problem appears rarely, so it might not be a high priority as an improvement for go mod tidy
.
Still, I have encountered this problem myself twice now, and that's the magic number that tells me I should file a bug and propose an automated fix. This topic has been brought up a number of times on Slack (January 2022, February 2022, October 2022), so there are at least a couple of other people experiencing the problem and fixing it manually.
In the second of those Slack threads, @bcmills mentions that this might be a quirk with the go mod tidy
upgrade from go 1.16
to go 1.17
. It could be that some of the third sections came about that way; it's hard to tell for sure. I'm a bit skeptical that the problem will go away with time, as 1.17
was released over a year ago and the extra sections still pop up. For example, that vocdoni PR was finalized in April 2022, and the go.mod
file in master was already on go 1.17
since September 2021.
I think go mod tidy
should join these extra sections. The only reason I see that as potentially risky is if, in the future, another proposal like https://github.com/golang/go/issues/45965 comes along and we want more than two sections. But presumably that shouldn't be a problem, because go mod tidy
already complains if a go.mod
file has a go X.Y
version that's too new.
cc @bcmills @matloob @leitzler @seankhliao @dylan-bourque
A slightly better CS regular expression is https://cs.opensource.google/search?q=path%3Ago.mod+AND+pcre%3Ayes+AND+%28require%5C+%28.%7C%5Cn%29require%5C+%28.%7C%5Cn%29require%5C+%29+&sq=, which also matches require X Y
and not just require (X Y; ...)
. It found one more, funnily enough, in gopls:
- https://cs.opensource.google/go/x/tools/+/master:gopls/go.mod;drc=f112c43328372460f7ac5bc951711609e22b01cc
see also #51983
Properly handling comments could indeed be some work. I'm honestly not worried about it, because in all the instances I've run into this problem, there were no custom comments in any of the require sections. So I'd be fine if we start by only joining require sections without any comments inside or between them, for example.
I'm a bit skeptical that the problem will go away with time, as
1.17
was released over a year ago and the extra sections still pop up.
Note that the awkward transition happens when the go
directive in your go.mod
file crosses that boundary; it's more-or-less independent of upgrading the toolchain. (Current versions of go
still try to tidy according to the old format when in a module with an older go
version.)
Right. Note that the vocdoni example had been on go 1.17
for nearly a year by the time the duplicate section was introduced, so I think the duplication is an ongoing inconvenience regardless.
For what it's worth, it happened again in one of the projects mentioned above :) https://github.com/vocdoni/vocdoni-node/commit/ed5fb167e1a658b63318ec13b06fd65f14ca1aa5#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6
Can't share the specifics, but I just had an internal module end up with 5 require
blocks. I'm using Go 1.19.3 and the module has go 1.18
Still, I have encountered this problem myself twice now, and that's the magic number that tells me I should file a bug and propose an automated fix.
After https://github.com/golang/go/issues/51983 I've just hit this once more, this time only using go get
and not go mod edit
in https://github.com/evcc-io/evcc/pull/5342/commits/c906d1dd48d92841fb3bcf9f0bcc1005f96cd3d4. We're already on Go 1.18.
+1 for automatic fix. When I call tidy I mean tidy ;)
@bcmills I finally ran into a reproducible way to get cmd/go to add a third require
section, which presumably is a bug :) Sharing the reproducer script with the output below, hidden away as it's a bit long.
$ cat repro.sh
#!/bin/bash
docker run -i golang:1.19.4 <<-'SCRIPT'
set -ex
go version
git clone -b go-mod-tidy-bug --depth=1 https://github.com/vocdoni/vocdoni-node
cd vocdoni-node
go mod tidy
git diff
SCRIPT
$ bash repro.sh
+ go version
go version go1.19.4 linux/amd64
+ git clone -b go-mod-tidy-bug --depth=1 https://github.com/vocdoni/vocdoni-node
Cloning into 'vocdoni-node'...
+ cd vocdoni-node
+ go mod tidy
[downloads]
+ git diff
diff --git a/go.mod b/go.mod
index 2f74ea6..318809a 100644
--- a/go.mod
+++ b/go.mod
@@ -27,7 +27,7 @@ require (
github.com/fatih/color v1.13.0
github.com/frankban/quicktest v1.14.3
github.com/glendc/go-external-ip v0.1.0
- github.com/go-chi/chi v4.1.2+incompatible
+ github.com/go-chi/chi v4.1.2+incompatible // indirect
github.com/go-chi/cors v1.2.1
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
@@ -68,6 +68,8 @@ require (
google.golang.org/protobuf v1.28.1
)
+require github.com/go-chi/chi/v5 v5.0.7
+
require (
bazil.org/fuse v0.0.0-20200524192727-fb710f7dfd05 // indirect
contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
@@ -120,7 +122,6 @@ require (
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
github.com/getsentry/sentry-go v0.12.0 // indirect
- github.com/go-chi/chi/v5 v5.0.7 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
I'm sure the bug can be reproduced without Docker and with a smaller Go module, but I hope that's enough for you to identify the bug.
I know this thread is about joining the sections, but this bug feels very much related, and perhaps it's another item to add to the list of reasons why we should join the sections :)
Consider the attached go mod. Even when I manually join the three require sections, go mod tidy
will once more break it up into multiple sections. It does not only not merge them, it actually separates them.
module github.com/evcc-io/evcc
go 1.18
require (
github.com/AlecAivazis/survey/v2 v2.3.6
github.com/BurntSushi/toml v1.2.1
github.com/Masterminds/sprig/v3 v3.2.3
github.com/PuerkitoBio/goquery v1.8.0
github.com/andig/gosunspec v0.0.0-20211108155140-af2e73b86e71
github.com/andig/mbserver v0.0.0-20221101171752-364e71b0089c
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef
github.com/avast/retry-go/v3 v3.1.1
github.com/aws/aws-sdk-go v1.44.153
github.com/basgys/goxml2json v1.1.0
github.com/basvdlei/gotsmart v0.0.3
github.com/benbjohnson/clock v1.3.0
github.com/bogosj/tesla v1.1.0
github.com/cjrd/allocate v0.0.0-20220510215731-986f24f0fb18
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/containrrr/shoutrrr v0.6.1
github.com/coreos/go-oidc/v3 v3.4.0
github.com/deepmap/oapi-codegen v1.12.4
github.com/denisbrodbeck/machineid v1.0.1
github.com/dmarkham/enumer v1.5.7
github.com/dustin/go-humanize v1.0.0
github.com/dylanmei/iso8601 v0.1.0
github.com/eclipse/paho.mqtt.golang v1.4.2
github.com/enbility/cemd v0.1.5
github.com/enbility/eebus-go v0.1.5
github.com/fatih/structs v1.1.0
github.com/foogod/go-powerwall v0.2.0
github.com/glebarez/sqlite v1.5.0
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
github.com/go-ping/ping v1.1.0
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
github.com/godbus/dbus/v5 v5.1.0
github.com/gokrazy/updater v0.0.0-20211121155532-30ae8cd650ea
github.com/golang/mock v1.6.0
github.com/google/go-github/v32 v32.1.0
github.com/google/uuid v1.3.0
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/gregdel/pushover v1.1.0
github.com/grid-x/modbus v0.0.0-20221121121528-8cdd929d093f
github.com/hashicorp/go-version v1.6.0
github.com/hasura/go-graphql-client v0.8.1
github.com/imdario/mergo v0.3.13
github.com/influxdata/influxdb-client-go/v2 v2.12.1
github.com/itchyny/gojq v0.12.10
github.com/jeremywohl/flatten v1.0.1
github.com/jinzhu/copier v0.3.5
github.com/joeshaw/carwings v0.0.0-20220711204617-d90801cf2848
github.com/joho/godotenv v1.4.0
github.com/jpfielding/go-http-digest v0.0.0-20211006141426-fbc93758452e
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/koron/go-ssdp v0.0.3
github.com/korylprince/ipnetgen v1.0.1
github.com/libp2p/zeroconf/v2 v2.2.0
github.com/lorenzodonini/ocpp-go v0.16.1-0.20220927200117-d4afed542168
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/manifoldco/promptui v0.9.0
github.com/mergermarket/go-pkcs7 v0.0.0-20170926155232-153b18ea13c9
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/mlnoga/rct v0.1.2-0.20220320164346-9f2daa4d6734
github.com/muka/go-bluetooth v0.0.0-20220219050759-674a63b8741a
github.com/mxschmitt/golang-combinations v1.1.0
github.com/nicksnyder/go-i18n/v2 v2.2.1
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c
github.com/olekukonko/tablewriter v0.0.5
github.com/philippseith/signalr v0.6.1-0.20220829124759-bd5ffb679356
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/prometheus/client_golang v1.14.0
github.com/prometheus/common v0.37.0
github.com/robertkrimen/otto v0.2.1
github.com/samber/lo v1.36.0
github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/spf13/cobra v1.6.1
github.com/spf13/jwalterweatherman v1.1.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.14.0
github.com/stretchr/testify v1.8.1
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c
github.com/volkszaehler/mbmd v0.0.0-20220916220750-3b12dcc33299
github.com/writeas/go-strip-markdown v2.0.1+incompatible
gitlab.com/bboehmke/sunny v0.15.1-0.20211022160056-2fba1c86ade6
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
golang.org/x/net v0.4.0
golang.org/x/oauth2 v0.3.0
golang.org/x/sync v0.1.0
golang.org/x/text v0.5.0
google.golang.org/api v0.103.0
google.golang.org/grpc v1.51.0
google.golang.org/protobuf v1.28.1
gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.24.2
tailscale.com v1.1.1-0.20221221060240-14e8afe44444
)
require (
cloud.google.com/go/compute v1.14.0 // indirect
cloud.google.com/go/compute/metadata v0.2.2 // indirect
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/ahmetb/go-linq/v3 v3.2.0 // indirect
github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/config v1.11.0 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.6.4 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssm v1.17.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 // indirect
github.com/aws/smithy-go v1.9.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bitly/go-simplejson v0.5.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/coreos/go-iptables v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/glebarez/go-sqlite v1.20.0 // indirect
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
github.com/holoplot/go-avahi v1.0.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/illarion/gonotify v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf // indirect
github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531 // indirect
github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.12 // indirect
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mdlayher/genetlink v1.2.0 // indirect
github.com/mdlayher/netlink v1.6.0 // indirect
github.com/mdlayher/sdnotify v1.0.0 // indirect
github.com/mdlayher/socket v0.2.3 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/pascaldekloe/name v1.0.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect
github.com/rickb777/date v1.20.1 // indirect
github.com/rickb777/plural v1.4.1 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d // indirect
github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17 // indirect
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect
github.com/tailscale/wireguard-go v0.0.0-20221219190806-4fa124729667 // indirect
github.com/tcnksm/go-httpstat v0.2.0 // indirect
github.com/teivah/onecontext v1.3.0 // indirect
github.com/thoas/go-funk v0.9.2 // indirect
github.com/u-root/uio v0.0.0-20221213070652-c3537552635f // indirect
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
gitlab.com/c0b/go-ordered-json v0.0.0-20201030195603-febf46534d5a // indirect
go.opencensus.io v0.24.0 // indirect
go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect
go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf // indirect
golang.org/x/crypto v0.3.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sys v0.3.1-0.20221220025402-2204b6615fb8 // indirect
golang.org/x/term v0.3.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
golang.org/x/tools v0.4.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0 // indirect
inet.af/peercred v0.0.0-20210906144145-0893ea02156a // indirect
modernc.org/libc v1.21.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.20.0 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
replace github.com/foogod/go-powerwall => github.com/andig/go-powerwall v0.2.1-0.20220205120646-e5220ad9a9a0
replace github.com/mlnoga/rct => github.com/andig/rct v0.0.0-20221101081802-96d01efdc68c
I ran into this as well at work on a proprietary code base. We're in a situation where running go mod tidy
adds a third section and only when it is manually merged with the existing // indirect
section does go mod tidy
do the right thing.
It sounds like this is probably demonstrated by @mvdan's https://github.com/golang/go/issues/56471#issuecomment-1340095845 so I won't try to construct my own reproducer for now.
Should we open a separate issue for this since this is just some kind of straight-up bug? I agree with the proposal title that go mod tidy
should join multiple sections but that seems less important and more controversial than fixing this buggy behavior. After all, my workflow (and probably most others') mainly uses go mod tidy
to edit go.mod
, so if go mod tidy
isn't introducing new extraneous require
blocks to the file then there won't be multiple sections to merge in the first place.
I was a little bothered by this issue so until go mod tidy
does this by default a used the official modfile
parser to make my own tool: https://github.com/abhijit-hota/modfmt
I think opening a separate issue for go mod tidy
adding a third section is a good idea. I think it's a question whether we should preserve more than two require blocks in a file that already has more than two require blocks, but it's clearly a bug if go mod tidy
is adding an extra require block to a file that only has two require blocks.
I opened #67948 for the bug.
@mvdan I tried using your reproducer from the vocdoni/vocdoni-node repo but it doesn't seem to repro on master, and your branch go-mod-tidy-bug
seems to have been deleted. Fortunately I was able to find a public repro case among the issues linked to this one.