cmd/go: test and fix missing deep dependencies in list Deps output

Fixes #21522.

Change-Id: Ifec1681b265576c47a4d736f6f124cc25485c593
Reviewed-on: https://go-review.googlesource.com/57011
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/cmd/dist/deps_test.go b/src/cmd/dist/deps_test.go
index 675ed55..15adafa 100644
--- a/src/cmd/dist/deps_test.go
+++ b/src/cmd/dist/deps_test.go
@@ -53,7 +53,13 @@
 		// Very simple minded diff.
 		t.Log("-current +generated")
 		clines := strings.Split(string(current), "\n")
+		for i, line := range clines {
+			clines[i] = strings.Join(strings.Fields(line), " ")
+		}
 		ulines := strings.Split(string(updated), "\n")
+		for i, line := range ulines {
+			ulines[i] = strings.Join(strings.Fields(line), " ")
+		}
 		for len(clines) > 0 {
 			cl := clines[0]
 			switch {
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 3aecc75..65b7aa4 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -1703,6 +1703,20 @@
 	}
 }
 
+func TestGoListDeps(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.parallel()
+	tg.tempDir("src/p1/p2/p3/p4")
+	tg.setenv("GOPATH", tg.path("."))
+	tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
+	tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
+	tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
+	tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
+	tg.run("list", "-f", "{{.Deps}}", "p1")
+	tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
+}
+
 // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
 	tg := testgo(t)
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 597f54c..d3d1922 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -1050,17 +1050,6 @@
 
 	// Build list of imported packages and full dependency list.
 	imports := make([]*Package, 0, len(p.Imports))
-	deps := make(map[string]*Package)
-	save := func(path string, p1 *Package) {
-		// The same import path could produce an error or not,
-		// depending on what tries to import it.
-		// Prefer to record entries with errors, so we can report them.
-		p0 := deps[path]
-		if p0 == nil || p1.Error != nil && (p0.Error == nil || len(p0.Error.ImportStack) > len(p1.Error.ImportStack)) {
-			deps[path] = p1
-		}
-	}
-
 	for i, path := range importPaths {
 		if path == "C" {
 			continue
@@ -1083,17 +1072,33 @@
 			p.Imports[i] = path
 		}
 
-		save(path, p1)
 		imports = append(imports, p1)
-		for _, dep := range p1.Internal.Imports {
-			save(dep.ImportPath, dep)
-		}
 		if p1.Incomplete {
 			p.Incomplete = true
 		}
 	}
 	p.Internal.Imports = imports
 
+	deps := make(map[string]*Package)
+	var q []*Package
+	q = append(q, imports...)
+	for i := 0; i < len(q); i++ {
+		p1 := q[i]
+		path := p1.ImportPath
+		// The same import path could produce an error or not,
+		// depending on what tries to import it.
+		// Prefer to record entries with errors, so we can report them.
+		p0 := deps[path]
+		if p0 == nil || p1.Error != nil && (p0.Error == nil || len(p0.Error.ImportStack) > len(p1.Error.ImportStack)) {
+			deps[path] = p1
+			for _, p2 := range p1.Internal.Imports {
+				if deps[p2.ImportPath] != p2 {
+					q = append(q, p2)
+				}
+			}
+		}
+	}
+
 	p.Deps = make([]string, 0, len(deps))
 	for dep := range deps {
 		p.Deps = append(p.Deps, dep)