golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.67k stars 17.49k forks source link

cmd/go: mod tidy should join "require" sections if there are more than two #56471

Open mvdan opened 1 year ago

mvdan commented 1 year ago

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:

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%29*require%5C+%5C%28%28.%7C%5Cn%29*require%29+ found:

None of those four appear to be on purpose. I think they could have appeared unintentionally due to a number of reasons, such as:

1) 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. 2) Manual editing. I've seen some users not fully grasp how go get works, and resorting to editing go.mod directly to update or add require lines. When doing it quickly or copy-pasting, I imagine it's tempting to just add a require 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

mvdan commented 1 year ago

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%29*require%5C+%28.%7C%5Cn%29*require%5C+%29+&sq=, which also matches require X Y and not just require (X Y; ...). It found one more, funnily enough, in gopls:

seankhliao commented 1 year ago

see also #51983

mvdan commented 1 year ago

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.

bcmills commented 1 year ago

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.)

mvdan commented 1 year ago

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.

mvdan commented 1 year ago

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

dylan-bourque commented 1 year ago

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

andig commented 1 year ago

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 ;)

mvdan commented 1 year ago

@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 :)

andig commented 1 year ago

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.

go.mod
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
cespare commented 10 months ago

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.

abhijit-hota commented 2 months ago

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

matloob commented 2 months ago

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.

cespare commented 2 months ago

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.

stevenh commented 1 week ago

I found this while trying to use golang.org/x/mod/modfile to add new requires to a go.mod file.

It's behaviour is to always add requires to last block, which typically contains indirect requires, instead of adding to the correct block depending if it was an indirect or not.

Running go mod tidy on this results in three blocked, its not clear why but this is clearly broken.