1package watch
2
3import (
4	"go/build"
5	"regexp"
6)
7
8var ginkgoAndGomegaFilter = regexp.MustCompile(`github\.com/onsi/ginkgo|github\.com/onsi/gomega`)
9var ginkgoIntegrationTestFilter = regexp.MustCompile(`github\.com/onsi/ginkgo/integration`) //allow us to integration test this thing
10
11type Dependencies struct {
12	deps map[string]int
13}
14
15func NewDependencies(path string, maxDepth int) (Dependencies, error) {
16	d := Dependencies{
17		deps: map[string]int{},
18	}
19
20	if maxDepth == 0 {
21		return d, nil
22	}
23
24	err := d.seedWithDepsForPackageAtPath(path)
25	if err != nil {
26		return d, err
27	}
28
29	for depth := 1; depth < maxDepth; depth++ {
30		n := len(d.deps)
31		d.addDepsForDepth(depth)
32		if n == len(d.deps) {
33			break
34		}
35	}
36
37	return d, nil
38}
39
40func (d Dependencies) Dependencies() map[string]int {
41	return d.deps
42}
43
44func (d Dependencies) seedWithDepsForPackageAtPath(path string) error {
45	pkg, err := build.ImportDir(path, 0)
46	if err != nil {
47		return err
48	}
49
50	d.resolveAndAdd(pkg.Imports, 1)
51	d.resolveAndAdd(pkg.TestImports, 1)
52	d.resolveAndAdd(pkg.XTestImports, 1)
53
54	delete(d.deps, pkg.Dir)
55	return nil
56}
57
58func (d Dependencies) addDepsForDepth(depth int) {
59	for dep, depDepth := range d.deps {
60		if depDepth == depth {
61			d.addDepsForDep(dep, depth+1)
62		}
63	}
64}
65
66func (d Dependencies) addDepsForDep(dep string, depth int) {
67	pkg, err := build.ImportDir(dep, 0)
68	if err != nil {
69		println(err.Error())
70		return
71	}
72	d.resolveAndAdd(pkg.Imports, depth)
73}
74
75func (d Dependencies) resolveAndAdd(deps []string, depth int) {
76	for _, dep := range deps {
77		pkg, err := build.Import(dep, ".", 0)
78		if err != nil {
79			continue
80		}
81		if !pkg.Goroot && (!ginkgoAndGomegaFilter.Match([]byte(pkg.Dir)) || ginkgoIntegrationTestFilter.Match([]byte(pkg.Dir))) {
82			d.addDepIfNotPresent(pkg.Dir, depth)
83		}
84	}
85}
86
87func (d Dependencies) addDepIfNotPresent(dep string, depth int) {
88	_, ok := d.deps[dep]
89	if !ok {
90		d.deps[dep] = depth
91	}
92}
93