1// rdeps scans GOPATH for all reverse dependencies of a set of Go 2// packages. 3// 4// rdeps will not sort its output, and the order of the output is 5// undefined. Pipe its output through sort if you need stable output. 6package main 7 8import ( 9 "bufio" 10 "flag" 11 "fmt" 12 "go/build" 13 "os" 14 15 "honnef.co/go/tools/version" 16 17 "github.com/kisielk/gotool" 18 "golang.org/x/tools/go/buildutil" 19 "golang.org/x/tools/refactor/importgraph" 20) 21 22func main() { 23 var tags buildutil.TagsFlag 24 flag.Var(&tags, "tags", "List of build tags") 25 stdin := flag.Bool("stdin", false, "Read packages from stdin instead of the command line") 26 recursive := flag.Bool("r", false, "Print reverse dependencies recursively") 27 printVersion := flag.Bool("version", false, "Print version and exit") 28 flag.Parse() 29 30 if *printVersion { 31 version.Print() 32 os.Exit(0) 33 } 34 35 ctx := build.Default 36 ctx.BuildTags = tags 37 var args []string 38 if *stdin { 39 s := bufio.NewScanner(os.Stdin) 40 for s.Scan() { 41 args = append(args, s.Text()) 42 } 43 } else { 44 args = flag.Args() 45 } 46 if len(args) == 0 { 47 return 48 } 49 wd, err := os.Getwd() 50 if err != nil { 51 fmt.Fprintln(os.Stderr, err) 52 os.Exit(1) 53 } 54 pkgs := gotool.ImportPaths(args) 55 for i, pkg := range pkgs { 56 bpkg, err := ctx.Import(pkg, wd, build.FindOnly) 57 if err != nil { 58 continue 59 } 60 pkgs[i] = bpkg.ImportPath 61 } 62 _, reverse, errors := importgraph.Build(&ctx) 63 _ = errors 64 65 seen := map[string]bool{} 66 var printRDeps func(pkg string) 67 printRDeps = func(pkg string) { 68 for rdep := range reverse[pkg] { 69 if seen[rdep] { 70 continue 71 } 72 seen[rdep] = true 73 fmt.Println(rdep) 74 if *recursive { 75 printRDeps(rdep) 76 } 77 } 78 } 79 80 for _, pkg := range pkgs { 81 printRDeps(pkg) 82 } 83 for pkg, err := range errors { 84 fmt.Fprintf(os.Stderr, "error in package %s: %s\n", pkg, err) 85 } 86} 87