-
Notifications
You must be signed in to change notification settings - Fork 27
/
main.go
142 lines (122 loc) · 3 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
/*
Command git-hound is a Git plugin that helps prevent sensitive data from being committed
into a repository by sniffing potential commits against regular expressions
*/
package main
import (
"flag"
"fmt"
"github.com/fatih/color"
"io/ioutil"
"os"
"sourcegraph.com/sourcegraph/go-diff/diff"
)
var (
version = "1.0.0"
showVersion = flag.Bool("v", false, "Show version")
noColor = flag.Bool("no-color", false, "Disable color output")
config = flag.String("config", ".githound.yml", "Hound config file")
bin = flag.String("bin", "git", "Executable binary to use for git command")
)
func main() {
defer func() {
if r := recover(); r != nil {
color.Red(fmt.Sprintf("error: %s\n", r))
os.Exit(1)
}
}()
flag.Parse()
if *showVersion {
fmt.Printf("%s\n", version)
os.Exit(0)
}
if *noColor {
color.NoColor = true
}
hound := &Hound{config: *config}
git := &Command{bin: *bin}
if ok := hound.New(); !ok {
color.Red("No config file detected")
os.Exit(1)
}
var (
runnable bool
out string
)
switch flag.Arg(0) {
case "commit":
out, _ = git.Exec("diff", "-U0", "--staged")
runnable = true
case "sniff":
stat, _ := os.Stdin.Stat()
// Check if anything was piped to STDIN
if (stat.Mode() & os.ModeCharDevice) == 0 {
stdin, _ := ioutil.ReadAll(os.Stdin)
out = string(stdin)
} else {
commit := flag.Arg(1)
if commit == "" {
// NOTE: This let's us get a diff containing the entire repo codebase by
// utilizing a magic commit hash. In reality, it's not magical,
// it's simply the result of sha1("tree 0\0").
commit = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
}
out, _ = git.Exec("diff", commit, "--staged")
}
default:
fmt.Print("Usage:\n git-hound commit [...]\n git-hound sniff [commit]\n")
os.Exit(0)
}
fileDiffs, err := diff.ParseMultiFileDiff([]byte(out))
if err != nil {
color.Red(fmt.Sprintf("%s\n", err))
os.Exit(1)
}
severeSmellCount := 0
hunkCount := 0
smells := make(chan smell)
done := make(chan bool)
for _, fileDiff := range fileDiffs {
fileName := fileDiff.NewName
hunks := fileDiff.Hunks
for _, hunk := range hunks {
go func(hunk *diff.Hunk) {
defer func() {
if r := recover(); r != nil {
color.Red(fmt.Sprintf("%s\n", r))
os.Exit(1)
}
}()
hound.Sniff(fileName, hunk, smells, done)
}(hunk)
hunkCount++
}
}
for c := 0; c < hunkCount; {
select {
case s := <-smells:
if s.severity > 1 {
severeSmellCount++
}
switch s.severity {
case 1:
color.Yellow(fmt.Sprintf("warning: %s\n", s.String()))
case 2:
color.Red(fmt.Sprintf("failure: %s\n", s.String()))
default:
color.Red(fmt.Sprintf("error: unknown severity given - %d\n", s.severity))
}
case <-done:
c++
}
}
if severeSmellCount > 0 {
fmt.Printf("%d severe smell(s) detected - please fix them before you can commit\n", severeSmellCount)
os.Exit(1)
}
if runnable {
out, code := git.Exec(flag.Args()...)
fmt.Print(out)
os.Exit(code)
}
}