golang/go

proposal: cmd/go: support go.mod.dev as default behaviour for easy local cross-package management

sabutterworth opened this issue · 7 comments

What version of Go are you using (go version)?

$ go version
1.15.1 darwin/amd64

Does this issue reproduce with the latest release?

Yes

Proposal

go mod is awesome, go mod -replace is awesome, gohack is awesome... However.....

When developing I frequently find myself modifying multiple packages across multiple projects at the same time. Committing these changes to VCS is usually done at the same time as part of the same feature. Timing on when they arrive in VCS can vary depending on numerous factors. I usually end up using gohack or just go mod edit -replace to proxy package dependencies across the numerous projects I am editing locally so that package A locally is depending on the latest local version of package B.

It mostly works well. Except for one thing.... All this activity makes me add local-dev only things that have the potential to accidentally get committed to my pull requests. So far i've been working around it using TODO's and GIT pre-push hooks (for gohack undo). It's trickier to manage than I would like and it's not easily portable from dev to dev.

As of 1.14 we have go -modfile=file which is fairly handy. But, making various go hooks & plugins in a mixed IDE & command line tool chain use it on a per project basis can be very tricky as well.

My suggestion is as follows:
When run without the -modfile flag have go check for go.mod.dev. If it exists then treat it exactly as though that file were specified via go -modfile=go.mod.dev. We can exclude that file from VCS and write tools to manage it if needed without stepping on the toes of the go mod tooling. We can hack it all we want and it won't end up affecting anyone.

When go is run without -modfile it looks for a file named go.mod.dev in the folder path resolved by GOMOD (or, if -modfile is specified look for {thatmodfile}.dev at the same path). If found (and the module is the same) it uses a merge strategy to combine that with the contents of go.mod to resolve the correct directives to use - with directives from the .dev file having a higher precedence over the things in the go.mod file when conflicts are encountered.

Alternatively..... Allow me to flag require and replace entries in go.mod as development only. Though to be honest, I prefer the first suggestion.

Related to #26640. (Also, a variant: #26640 (comment)).

This is almost exactly #26640, but replacing the entire contents of the go.mod file instead of augmenting it.

I suspect that replacing the contents will be too tedious (or too error-prone) due to the need to sync the require directives back and forth between the two files, but I'd be interested to see more evidence to support or refute that.

isn't this possible today with go env -w GOFLAGS=-modfile=go.mod.dev ?

Thank you for pointing out the go env workaround. You are correct, I could achieve the whole mod file replacement with either go env -w GOMOD=path.to.go.mod.dev or go env -w GOFLAGS=-modfile=go.mod.dev.

Having read #26640 (plus the related proposals) and thinking about it, the ability to override (via a local file merge strategy) rather than replace the whole go.mod file would be a more suitable long-term solution than using an entirely different file.

So I am going to change my suggestion to:
When go is run without -modfile it looks for a file named go.mod.dev in the folder path resolved by GOMOD (or if -modfile is specified look for {thatmodfile}.dev at the same path). If found (and the module is the same) it uses a merge strategy to combine that with the contents of go.mod to resolve the correct directives to use - with directives from the .dev file having a higher precedence over the things in the go.mod file when conflicts are encountered.

can we close it as a duplicate of #26640 then?

Closing this since there's more discussion under #26640. See #26640 (comment)