-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvcstool.go
158 lines (142 loc) · 3.08 KB
/
vcstool.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
155
156
157
158
package main
import (
"flag"
"fmt"
"github.com./wsxiaoys/terminal/color"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)
var git_cmds = map[string]string{
"pull": "git pull",
"diff": "git diff",
"status": "git status",
"push": "git push",
}
var hg_cmds = map[string]string{
"pull": "hg pull -u",
"diff": "hg diff",
"status": "hg status",
"push": "hg push",
}
var svn_cmds = map[string]string{
"pull": "svn up",
"diff": "svn diff",
"status": "svn status",
"push": "",
}
var vcs_color = map[string]string{
"git": "g",
"hg": "b",
"svn": "r",
}
var quit chan int = make(chan int)
var count int
var verb string
var (
sequential = flag.Bool("s", false, "serializes vcs calls")
)
func execute(path string, vcs string, vcs_verb string) {
if vcs_verb == "" {
return
}
a := func(wd string, vcs string, vcs_verb string, seq bool) {
msg := "=== @{!" + vcs_color[vcs] + "} "
msg += filepath.Base(path)
msg += "@| (@!" + vcs + "@|) ==="
var cmd exec.Cmd
cmd.Dir = wd
cmd.Args = strings.Split(vcs_verb, " ")
path, err := exec.LookPath(cmd.Args[0])
if err != nil {
path = cmd.Args[0]
}
cmd.Path = path
out, err := cmd.CombinedOutput()
if err != nil {
br := color.Colorize("!r")
rst := color.Colorize("|")
fmt.Printf(color.Sprint(msg)+"\n%s\n%s%s%s\n\n", out, br, err, rst)
} else {
fmt.Printf(color.Sprint(msg)+"\n%s\n", out)
}
if !seq {
quit <- 0
}
}
if *sequential {
a(path, vcs, vcs_verb, *sequential)
} else {
count += 1
go a(path, vcs, vcs_verb, *sequential)
}
}
func visit(path string, f os.FileInfo, err error) error {
if f == nil || !f.IsDir() {
return nil
}
entries, err := ioutil.ReadDir(path)
if err != nil {
log.Fatal("Failed to list the directory '", path, "': ", err)
}
for _, entry := range entries {
switch {
case entry.IsDir() && entry.Name() == ".git":
execute(path, "git", git_cmds[verb])
return filepath.SkipDir
case entry.IsDir() && entry.Name() == ".hg":
execute(path, "hg", hg_cmds[verb])
return filepath.SkipDir
case entry.IsDir() && entry.Name() == ".svn":
execute(path, "svn", svn_cmds[verb])
return filepath.SkipDir
}
}
return nil
}
func main() {
// Parse the command line arguments
flag.Parse()
// Make sure we got a verb
if flag.NArg() == 0 {
log.Fatal("No verb specified")
}
// I dentify the verb
cmd := flag.Arg(0)
switch {
case cmd == "pull":
verb = "pull"
case cmd == "diff":
verb = "diff"
case cmd == "status", cmd == "stat", cmd == "st":
verb = "status"
case cmd == "push":
verb = "push"
default:
log.Fatal("Invalid verb specified: ", cmd)
}
// Determine the working path
path, err := os.Getwd()
if err != nil {
log.Fatal("Failed to get the current working directory.")
}
// Use the given directory if specified
if flag.NArg() == 2 {
path = flag.Arg(1)
}
// If there are more arguments, error
if flag.NArg() > 2 {
log.Fatal("Too many arugments")
}
// Walk the directory
count = 0
fmt.Println("Walking: ", path)
filepath.Walk(path, visit)
// Wait for everything to finish
for i := 0; i < count; i++ {
<-quit
}
}