From 7a05375735f6eb130cfcd1d3b972213af2930074 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 2 Oct 2019 13:05:09 -0700 Subject: [PATCH] cmdget: accept package paths DO NOT MERGE The test fails because go-internal's proxy doesn't support .../@v/list requests. Fixes #62 --- cmdget.go | 40 +++++++++++++++++++++++++++++++++++----- testdata/get-pkg.txt | 34 ++++++++++++++++++++++++++++++++++ testdata/help.txt | 4 ++-- 3 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 testdata/get-pkg.txt diff --git a/cmdget.go b/cmdget.go index b922079..8473f1c 100644 --- a/cmdget.go +++ b/cmdget.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "path/filepath" + "sort" "strings" "gopkg.in/errgo.v2/fmt/errors" @@ -14,11 +15,13 @@ import ( ) var getCommand = &Command{ - UsageLine: "get [-vcs] [-u] [-f] [module...]", + UsageLine: "get [-vcs] [-u] [-f] [module/package...]", Short: "start hacking a module", Long: ` The get command checks out Go module dependencies into a directory where they can be edited. +If a package is named, its containing module +is checked out. It uses $GOHACK/ as the destination directory, or $HOME/gohack/ if $GOHACK is empty. @@ -61,12 +64,39 @@ func runGet1(args []string) error { // Perhaps we should be more resilient in that case? return errors.Notef(err, nil, "cannot get module info") } - for _, mpath := range args { - m := mods[mpath] - if m == nil { - errorf("module %q does not appear to be in use", mpath) + // Args could be package paths or modules. + // Resolve them all to modules, deduplicate, and sort. + resolved := make(map[string]bool) + for _, arg := range args { + if _, ok := mods[arg]; ok { + // module in use + resolved[arg] = true continue } + // Either a package path, or an unused module. + // Try to resolve as a package path. + out, err := runCmd(cwd, "go", "list", "-f", "{{with .Module}}{{.Path}}{{end}}", arg) + if err == nil { + // Resolved to a module. Is it in use? + out = strings.TrimSpace(out) + if _, ok := mods[out]; ok { + resolved[out] = true + continue + } + } + // Either an unused module, or an invalid package path, + // or a valid package path that resolves to an unused module, + // or something else. + errorf("module/package %q does not appear to be in use", arg) + } + mpaths := make([]string, 0, len(resolved)) + for mpath := range resolved { + mpaths = append(mpaths, mpath) + } + sort.Strings(mpaths) + + for _, mpath := range mpaths { + m := mods[mpath] // must be present, by construction (above) // Early check that we can replace the module, so we don't // do all the work to check it out only to find we can't // add the replace directive. diff --git a/testdata/get-pkg.txt b/testdata/get-pkg.txt new file mode 100644 index 0000000..b6e3aa9 --- /dev/null +++ b/testdata/get-pkg.txt @@ -0,0 +1,34 @@ +cd repo +go get golang.org/x/text +env GOHACK=$WORK/gohack +gohack get golang.org/x/text/language +# Check that golang.org/x/text/language resolved +# to golang.org/x/text by examining stdout. +# Trust the other get tests to ensure that everything else went ok. +stdout '^golang.org/x/text => .*/gohack/golang.org/x/text$' +! stderr .+ + +gohack undo +! stderr .+ + +# Check that deduplication works across modules and packages. +gohack get golang.org/x/text golang.org/x/text/language golang.org/x/text/unused +stdout '^golang.org/x/text => .*/gohack/golang.org/x/text$' +! stdout language +! stdout unused +! stderr .+ + +-- repo/main.go -- +package main +import ( + "golang.org/x/text/language" + _ "golang.org/x/text/unused" +) + +var _ = language.Make + +func main() { +} + +-- repo/go.mod -- +module example.com/repo diff --git a/testdata/help.txt b/testdata/help.txt index d9fb4c8..9ee51d6 100644 --- a/testdata/help.txt +++ b/testdata/help.txt @@ -1,8 +1,8 @@ # --help flag produces output to stderr and fails ! gohack get --help -stderr '^usage: get \[-vcs] \[-u] \[-f] \[module...]\nRun ''gohack help get'' for details.\n' +stderr '^usage: get \[-vcs] \[-u] \[-f] \[module/package...]\nRun ''gohack help get'' for details.\n' ! stdout .+ gohack help get -stdout '^usage: get \[-vcs] \[-u] \[-f] \[module...]$' +stdout '^usage: get \[-vcs] \[-u] \[-f] \[module/package...]$' ! stderr .+