go icon indicating copy to clipboard operation
go copied to clipboard

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

Open mvdan opened this issue 2 years ago • 10 comments

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:

  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 avatar Oct 28 '22 11:10 mvdan

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

mvdan avatar Oct 28 '22 11:10 mvdan

see also #51983

seankhliao avatar Oct 28 '22 12:10 seankhliao

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.

mvdan avatar Oct 28 '22 12:10 mvdan

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

bcmills avatar Oct 28 '22 20:10 bcmills

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 avatar Nov 08 '22 09:11 mvdan

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

mvdan avatar Nov 17 '22 22:11 mvdan

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

dylan-bourque avatar Nov 21 '22 22:11 dylan-bourque

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

andig avatar Dec 03 '22 13:12 andig

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

mvdan avatar Dec 06 '22 22:12 mvdan

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

andig avatar Dec 21 '22 07:12 andig

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.

cespare avatar Oct 23 '23 19:10 cespare

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

abhijit-hota avatar Jun 12 '24 15:06 abhijit-hota

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.

matloob avatar Jun 12 '24 17:06 matloob

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.

cespare avatar Jun 12 '24 18:06 cespare