golang/go

cmd/go: add -f (format) flag to go mod edit

josharian opened this issue · 9 comments

go mod edit -json dumps the entire mod file. However, having to parse json immediately takes this out of the realm of simple bash scripts.

As part of working on #34867, I've already hit two cases in which I need targeted information out of go mod edit -json: The required version of a module, and all replacements involving that module.

Writing a quick program to parse json is easy, but the obvious language to use is Go. But in my circumstances, I can't go run a Go program, because the mod file is in a broken state.

I propose that, like go list, go mod edit have a format flag to enable easy information requests from a shell script.

cc @bcmills @jayconrod

I'm curious: why do you need go mod edit -json for this task (rather than go list)?

Two reasons:

  • go.mod is in a bad state (replace directive points to non-existent dir), so go list fails.

  • The info I need is about replace directives (in particular what versions have replace directives), which go list does not expose.

go list does expose replace directives: see the Replace field of type Module at https://golang.org/cmd/go/#hdr-List_packages_or_modules.

For the replace directive pointing to a non-existent directory: perhaps we should make go list -m -e more tolerant of bad edges in the module graph?

go list does expose replace directives: see the Replace field of type Module at https://golang.org/cmd/go/#hdr-List_packages_or_modules.

Maybe I'm holding it wrong, but I don't seem to be able to get a version out of that. Relevant parts of go.mod:

go 1.13

require (
        github.com/josharian/git2go v0.0.0-20191016055211-da2fefa41c8c
)

replace github.com/josharian/git2go v0.0.0-20191016055211-da2fefa41c8c => ./build/git2go/v0.0.0-20191016055211-da2fefa41c8c

Result of running go list:

$ go list -m -f '{{.Replace}}' github.com/josharian/git2go
./build/git2go/v0.0.0-20191016055211-da2fefa41c8c
$ go list -m -f '{{.Replace.Version}}' github.com/josharian/git2go
$

Also, I want to get all replace directives for that module, not just the active one. (This is lower priority, though.)

For the replace directive pointing to a non-existent directory: perhaps we should make go list -m -e more tolerant of bad edges in the module graph?

Seems like a good idea.

Maybe I'm holding it wrong, but I don't seem to be able to get a version out of that.

Your replace directive specified a filesystem path, not a version. (The Version field is blank because there is no version on the right side of that directive.)

To see what I mean, try:

go list -m -f '{{.Path}} {{.Version}}{{with .Replace}} => {{.Path}} {{.Version}}{{end}}' all

Your replace directive specified a filesystem path, not a version. (The Version field is blank because there is no version on the right side of that directive.)

Ah. I was focused on trying to learn what was on the left hand side of the directive, because that's what go mod edit -dropreplace needs. But I can skip doing cleanup and just use the main version. Assuming -e is made more tolerant.

I found a different way to approach this.

The goal was to remove all replace directives for a given module. The old approach was to try obtain all replace directives and remove them one by one.

Thanks to the new and improved docs by @jayconrod in CL 210340, I now see there is a much simple way: Add an versionless replace directive, which removes all existing replace directives, and then remove it:

$ go mod edit -replace path/to/module=./placeholder
$ go mod edit -dropreplace path/to/module

I still think it would be a good to make go list -m -e more tolerant of bad edges in the module graph, though.

Bryan, I'll let you decide what to do with this issue now. Thanks for your patience and assistance.

I still think it would be a good to make go list -m -e more tolerant of bad edges in the module graph, though.

Agreed: we've been trying to make go list -e more tolerant of all kinds of errors, but that seems like a separate issue.

Since you have a suitable workaround and nobody else has chimed in on this request, let's close it. (We can always revisit if we find more use-cases, or if we discover that your use-case is needed frequently enough to address directly.)