This repository has been archived by the owner on Sep 9, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathreachmap.go
79 lines (68 loc) · 2.32 KB
/
reachmap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package pkgtree
import (
"sort"
"strings"
"github.com/golang/dep/internal/gps/internal"
)
// ReachMap maps a set of import paths (keys) to the sets of transitively
// reachable tree-internal packages, and all the tree-external packages
// reachable through those internal packages.
//
// See PackageTree.ToReachMap() for more information.
type ReachMap map[string]struct {
Internal, External []string
}
// FlattenAll flattens a reachmap into a sorted, deduplicated list of all the
// external imports named by its contained packages.
//
// If stdlib is false, then stdlib imports are excluded from the result.
func (rm ReachMap) FlattenAll(stdlib bool) []string {
return rm.flatten(func(pkg string) bool { return true }, stdlib)
}
// Flatten flattens a reachmap into a sorted, deduplicated list of all the
// external imports named by its contained packages, but excludes imports coming
// from packages with disallowed patterns in their names: any path element with
// a leading dot, a leading underscore, with the name "testdata".
//
// If stdlib is false, then stdlib imports are excluded from the result.
func (rm ReachMap) Flatten(stdlib bool) []string {
f := func(pkg string) bool {
// Eliminate import paths with any elements having leading dots, leading
// underscores, or testdata. If these are internally reachable (which is
// a no-no, but possible), any external imports will have already been
// pulled up through ExternalReach. The key here is that we don't want
// to treat such packages as themselves being sources.
for _, elem := range strings.Split(pkg, "/") {
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
return false
}
}
return true
}
return rm.flatten(f, stdlib)
}
func (rm ReachMap) flatten(filter func(string) bool, stdlib bool) []string {
exm := make(map[string]struct{})
for pkg, ie := range rm {
if filter(pkg) {
for _, ex := range ie.External {
if !stdlib && internal.IsStdLib(ex) {
continue
}
exm[ex] = struct{}{}
}
}
}
if len(exm) == 0 {
return []string{}
}
ex := make([]string, 0, len(exm))
for p := range exm {
ex = append(ex, p)
}
sort.Strings(ex)
return ex
}