-
Notifications
You must be signed in to change notification settings - Fork 0
/
gitstat.go
139 lines (113 loc) · 2.74 KB
/
gitstat.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
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"sync"
"time"
"github.com/MichaelTJones/walk"
"github.com/briandowns/spinner"
)
var (
mutex = sync.Mutex{}
spinSet = []string{"| ", "/ ", "- ", "\\ "}
spin = spinner.New(spinSet, 100*time.Millisecond)
repodirs = make(sort.StringSlice, 0)
startdir = "."
help = flag.Bool("?", false, "show usage and options (this help)")
alwaysshow = flag.Bool("a", false, "show directory name, even if there is no status")
ignored = flag.Bool("i", false, "show ignored files by adding the '--ignored' option")
long = flag.Bool("l", false, "show normal 'git status'")
)
// init, makes sure we have a start directory
func init() {
flag.Usage = usage
flag.Parse()
if *help {
usage()
os.Exit(0)
}
var dir = flag.Arg(0)
if dir != "" {
startdir = dir
}
}
// usage
func usage() {
fmt.Printf("\nGITSTAT (C) Copyright 2017 Erlend Johannessen\n")
fmt.Printf("Finds all git repositories below the given path, and for each repository runs \"git status -s\".\n")
fmt.Printf("Usage: gitstat [options] [dirname] \n")
flag.PrintDefaults()
fmt.Printf("\n")
}
// foreachEntry is called for each entry in the given directory
func foreachEntry(entryName string, f os.FileInfo, err error) error {
if f == nil || !f.IsDir() || f.Name() != ".git" {
return nil
}
// Getting the repo dir
var dir = strings.Replace(entryName, string(os.PathSeparator)+".git", string(os.PathSeparator), 1)
// edge case for current directory
if dir == ".git" {
dir = ""
}
var dirpath, patherr = filepath.Abs(ensureDir(dir))
if patherr != nil {
return nil
}
mutex.Lock()
repodirs = append(repodirs, dirpath)
mutex.Unlock()
return nil
}
// ensureDir makes sure that the given directory is not empty
// if empty it is the current directory
func ensureDir(dir string) string {
if dir == "" {
return "."
}
return dir
}
// printStatus runs "git status -s" for the given directory
func printStatus(workdir string) {
var gitdir = workdir + string(os.PathSeparator) + ".git"
var args = []string{
"--git-dir=" + gitdir,
"--work-tree=" + ensureDir(workdir),
"status",
}
if !*long {
args = append(args, "-s")
}
if *ignored {
args = append(args, "--ignored")
}
var cmd = exec.Command("git", args...)
var r, w, _ = os.Pipe()
cmd.Stdout = w
cmd.Stderr = os.Stderr
cmd.Run()
w.Close()
var status, _ = ioutil.ReadAll(r)
if *alwaysshow || len(bytes.TrimSpace(status)) > 0 {
fmt.Printf("----- %s -----\n", workdir)
fmt.Printf("%v", string(status))
}
}
// main
func main() {
spin.Start()
walk.Walk(startdir, foreachEntry)
spin.Restart()
spin.Stop()
sort.Sort(repodirs)
for _, wdir := range repodirs {
printStatus(wdir)
}
}