Skip to content

Please add a non-internal API to read go.mod files #30147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nim-nim opened this issue Feb 9, 2019 · 3 comments
Closed

Please add a non-internal API to read go.mod files #30147

nim-nim opened this issue Feb 9, 2019 · 3 comments

Comments

@nim-nim
Copy link

nim-nim commented Feb 9, 2019

So starting with Go 1.11 we have go.mod module descriptor files, and it was recognized that the go command would not be the only one needing to manipulate those, so go help mod edit helpfully states

Edit provides a command-line interface for editing go.mod,
for use primarily by tools or scripts. It reads only go.mod;
it does not look up information about the modules involved.

Except the go.mod on-disk syntax is clearly one of a kind, so anyone actually needing to read go.mod in scripts will obviously use the -json flag to get something more regular.

And then, since it's hard to parse json in shell, the next step is obviously to use a json parsing lib in your favorite language and write some kind of helper. That language, for someone interested in parsing go module files, is likely to be go.

So you end up with things like:

  // Run “go help mod edit” on new go versions to get the current structure to parse
  // You may need to reorder the type declarations for the compiler to be happy
  type Module struct {
    Path    string
    Version string
  }

  type Require struct {
    Path     string
    Version  string
    Indirect bool
  }

  type Replace struct {
    Old Module
    New Module
  }

  type GoMod struct {
    Module  Module
    Go      string
    Require []Require
    Exclude []Module
    Replace []Replace
  }

  cmd := exec.Command("go", "mod", "edit", "-fmt", "-json")
  stdout, _ := cmd.StdoutPipe()
  cmd.Stderr = os.Stderr
  if err := cmd.Start(); err != nil {
                fmt.Fprintf(os.Stderr,"error invoking “go mod edit -fmt -json”, %v:\n", err)
    os.Exit(1)
        }
  var gomod GoMod
        if err := json.NewDecoder(stdout).Decode(&gomod); err != nil {
                fmt.Fprintf(os.Stderr,"error parsing “go mod edit -fmt -json”, %v\n", err)
    os.Exit(1)
        }

This is a pretty ridiculous way to access information the language already knows how to parse (and parse better). You need to redirect stderr to get any kind of error handling (and can not do anything about it unless you also parse the stderr messages).

Please just make it a function that takes a path as argument (default current dir) and
returns a GoMod object, with all the sanity checks of go mod edit -fmt -json

@mvdan
Copy link
Member

mvdan commented Feb 9, 2019

I believe this is planned, but I couldn't find an open issue to track that. Until then, you can use https://godoc.org/github.com/rogpeppe/go-internal/modfile.

@oiooj oiooj added the modules label Feb 10, 2019
@thepudds
Copy link
Contributor

I think this might be tracked as #28101?

@mvdan
Copy link
Member

mvdan commented Feb 10, 2019

Ah, that's the issue I couldn't find :) Closing as a duplicate.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants