forked from jharlap/affected
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
154 lines (133 loc) · 3.41 KB
/
main.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
)
var ignoreDirs []string
var onlyGoFiles bool
func main() {
d := flag.String("ignore-dirs", ".checkout_git", "Dir patterns (static string) to ignore, comma-separated")
o := flag.String("only-go", "false", "Any value to set this flag to true")
flag.Parse()
if len(*d) > 0 {
ignoreDirs = strings.Split(*d, ",")
}
if *o == "true" {
onlyGoFiles = true
}
var commitRange string
args := flag.Args()
if len(args) >= 1 {
commitRange = args[0]
}
files := changedFiles(commitRange)
module := currentModule()
pkgsToDeps := packagePathsToDeps()
editedPackages := make(map[string]bool)
for _, f := range files {
if isIgnored(f) {
continue
}
editedPackages[filepath.Dir(filepath.Join(module, f))] = true
}
affectedPackages := make(map[string]bool)
for pkg, deps := range pkgsToDeps {
// Was this package itself modified?
if _, ok := editedPackages[pkg]; ok {
affectedPackages[pkg] = true
}
// Were any of this package's recursive dependencies modified?
for _, dep := range deps {
if _, ok := editedPackages[dep]; ok {
affectedPackages[pkg] = true
}
}
}
var affectedPackageList []string
if onlyGoFiles {
for pkg := range affectedPackages {
affectedPackageList = append(affectedPackageList, pkg)
}
} else {
for pkg := range editedPackages {
affectedPackageList = append(affectedPackageList, pkg)
}
}
sort.Strings(affectedPackageList)
fmt.Println(strings.Join(affectedPackageList, "\n"))
}
func die(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format, args...)
os.Exit(1)
}
func isIgnored(f string) bool {
for _, d := range ignoreDirs {
if strings.Contains(f, d) {
return true
}
}
return false
}
func currentModule() string {
cmd := exec.Command("go", "list", "-m")
dat, err := cmd.Output()
if err != nil {
die("Could not run git go list -m: %v", err)
}
return strings.TrimSpace(string(dat))
}
func packagePathsToDeps() map[string][]string {
cmd := exec.Command("go", "list", "-f", "{{ .ImportPath}} {{ .Deps }}", "./...")
dat, err := cmd.Output()
if err != nil {
die("Could not find git root: %s", err)
}
var result = make(map[string][]string)
datString := string(dat)
for _, pkgLine := range strings.Split(datString, "\n") {
stringParts := strings.SplitN(pkgLine, " ", 2)
importPath := stringParts[0]
if len(stringParts) == 2 {
result[importPath] = strings.Split(strings.Trim(stringParts[1], "[]"), " ")
}
}
return result
}
func changedFiles(commitRange string) []string {
var cmd *exec.Cmd
var err error
var diffTree, localCached, local []byte
if commitRange != "" {
cmd = exec.Command("git", "diff-tree", "--relative", "--no-commit-id", "--name-only", "-r", commitRange)
diffTree, err = cmd.Output()
if err != nil {
die("Could not run git diff-tree: %v", err)
}
}
cmd = exec.Command("git", "diff", "--cached", "--name-only")
localCached, err = cmd.Output()
if err != nil {
die("Could not run git diff --cached --name-only: %v", err)
}
cmd = exec.Command("git", "diff", "--name-only")
local, err = cmd.Output()
if err != nil {
die("Could not run git diff --name-only: %v", err)
}
changed := string(diffTree) + string(localCached) + string(local)
files := strings.Split(changed, "\n")
var res []string
for _, f := range files {
f = strings.TrimSpace(f)
if f == "" {
continue
}
res = append(res, f)
}
return res
}