cmd/go/internal/list: implement and test list -m -e for plain arguments

We were being lazy treating arguments like "foo" as a pattern.
That produced the weird output:

	warning: pattern "foo" matched no module dependencies

Instead, non-pattern mismatches as actual errors, making
them available to template patterns and also making the list
command fail for bad module names.

Inspired by golang/go#24149, which is already fixed by
the new loader. Added a test for that case too.

Fixes golang/go#24149.

Change-Id: I4f4b24d44623d9604f365ec2247a99129c35a507
Reviewed-on: https://go-review.googlesource.com/122402
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/vendor/cmd/go/internal/list/list.go b/vendor/cmd/go/internal/list/list.go
index 727009c..565217d 100644
--- a/vendor/cmd/go/internal/list/list.go
+++ b/vendor/cmd/go/internal/list/list.go
@@ -374,9 +374,10 @@
 		if !*listE {
 			for _, m := range mods {
 				if m.Error != nil {
-					base.Fatalf("go list -m %s: %v", m.Path, m.Error.Err)
+					base.Errorf("go list -m %s: %v", m.Path, m.Error.Err)
 				}
 			}
+			base.ExitIfErrors()
 		}
 		for _, m := range mods {
 			do(m)
diff --git a/vendor/cmd/go/internal/modload/list.go b/vendor/cmd/go/internal/modload/list.go
index 27d9667..54db550 100644
--- a/vendor/cmd/go/internal/modload/list.go
+++ b/vendor/cmd/go/internal/modload/list.go
@@ -73,10 +73,14 @@
 
 		// Module path or pattern.
 		var match func(string) bool
+		var literal bool
 		if arg == "all" {
 			match = func(string) bool { return true }
-		} else {
+		} else if strings.Contains(arg, "...") {
 			match = search.MatchPattern(arg)
+		} else {
+			match = func(p string) bool { return arg == p }
+			literal = true
 		}
 		matched := false
 		for i, m := range buildList {
@@ -89,7 +93,16 @@
 			}
 		}
 		if !matched {
-			fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
+			if literal {
+				mods = append(mods, &modinfo.ModulePublic{
+					Path: arg,
+					Error: &modinfo.ModuleError{
+						Err: fmt.Sprintf("module %q is not a known dependency", arg),
+					},
+				})
+			} else {
+				fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
+			}
 		}
 	}
 
diff --git a/vendor/cmd/go/mod_test.go b/vendor/cmd/go/mod_test.go
index 7883452..e723d4e 100644
--- a/vendor/cmd/go/mod_test.go
+++ b/vendor/cmd/go/mod_test.go
@@ -865,8 +865,24 @@
 	tg.run("list", "-m", "-f={{.Dir}}", "rsc.io/quote") // now module list should find it too
 	tg.grepStdout(`mod[\\/]rsc.io[\\/]quote@v1.2.0`, "expected cached copy of code")
 
-	tg.run("list", "std")
+	// check that list std works; also check that rsc.io/quote/buggy is a listable package
+	tg.run("list", "std", "rsc.io/quote/buggy")
 	tg.grepStdout("^math/big", "expected standard library")
+
+	tg.run("list", "-m", "-e", "-f={{.Path}} {{.Error.Err}}", "nonexist", "rsc.io/quote/buggy")
+	tg.grepStdout(`^nonexist module "nonexist" is not a known dependency`, "expected error via template")
+	tg.grepStdout(`^rsc.io/quote/buggy module "rsc.io/quote/buggy" is not a known dependency`, "expected error via template")
+
+	tg.runFail("list", "-m", "nonexist", "rsc.io/quote/buggy")
+	tg.grepStderr(`go list -m nonexist: module "nonexist" is not a known dependency`, "expected error on stderr")
+	tg.grepStderr(`go list -m rsc.io/quote/buggy: module "rsc.io/quote/buggy" is not a known dependency`, "expected error on stderr")
+
+	// Check that module loader does not interfere with list -e (golang.org/issue/24149).
+	tg.run("list", "-e", "-f={{.ImportPath}} {{.Error.Err}}", "database")
+	tg.grepStdout(`^database no Go files in `, "expected error via template")
+	tg.runFail("list", "database")
+	tg.grepStderr(`package database: no Go files`, "expected error on stderr")
+
 }
 
 func TestModInitLegacy(t *testing.T) {