9 // Visit visits all the packages in the import graph whose roots are
10 // pkgs, calling the optional pre function the first time each package
11 // is encountered (preorder), and the optional post function after a
12 // package's dependencies have been visited (postorder).
13 // The boolean result of pre(pkg) determines whether
14 // the imports of package pkg are visited.
15 func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
16 seen := make(map[*Package]bool)
17 var visit func(*Package)
18 visit = func(pkg *Package) {
22 if pre == nil || pre(pkg) {
23 paths := make([]string, 0, len(pkg.Imports))
24 for path := range pkg.Imports {
25 paths = append(paths, path)
27 sort.Strings(paths) // Imports is a map, this makes visit stable
28 for _, path := range paths {
29 visit(pkg.Imports[path])
38 for _, pkg := range pkgs {
43 // PrintErrors prints to os.Stderr the accumulated errors of all
44 // packages in the import graph rooted at pkgs, dependencies first.
45 // PrintErrors returns the number of errors printed.
46 func PrintErrors(pkgs []*Package) int {
48 Visit(pkgs, nil, func(pkg *Package) {
49 for _, err := range pkg.Errors {
50 fmt.Fprintln(os.Stderr, err)