-
-
Notifications
You must be signed in to change notification settings - Fork 24
/
gitmux.go
136 lines (106 loc) · 2.62 KB
/
gitmux.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
package main
import (
"context"
"flag"
"fmt"
"io"
"os"
"github.com/arl/gitstatus"
"gopkg.in/yaml.v3"
"github.com/arl/gitmux/json"
"github.com/arl/gitmux/tmux"
)
var version = "<<development version>>"
var _usage = `gitmux ` + version + `
Usage: gitmux [options] [dir]
gitmux prints the status of a Git working tree as a tmux format string.
If directory is not given, it default to the working directory.
Options:
-cfg cfgfile use cfgfile when printing git status.
-printcfg prints default configuration file.
-dbg outputs Git status as JSON and print errors.
-timeout DUR exits if still running after given duration (ex: 2s, 500ms).
-V prints gitmux version and exits.
`
func parseOptions() (ctx context.Context, cancel func(), dir string, dbg bool, cfg Config) {
var (
dbgOpt = flag.Bool("dbg", false, "")
cfgOpt = flag.String("cfg", "", "")
printCfgOpt = flag.Bool("printcfg", false, "")
versionOpt = flag.Bool("V", false, "")
timeoutOpt = flag.Duration("timeout", 0, "")
)
flag.Usage = func() {
fmt.Println(_usage)
}
flag.Parse()
dir = "."
if flag.NArg() > 0 {
dir = flag.Arg(0)
}
if *versionOpt {
fmt.Println(version)
os.Exit(0)
}
if *printCfgOpt {
os.Stdout.Write(cfgBytes)
os.Exit(0)
}
cfg = defaultCfg
if *cfgOpt != "" {
f, err := os.Open(*cfgOpt)
check(err, *dbgOpt)
dec := yaml.NewDecoder(f)
check(dec.Decode(&cfg), *dbgOpt)
}
if *timeoutOpt != 0 {
ctx, cancel = context.WithTimeout(context.Background(), *timeoutOpt)
} else {
ctx, cancel = context.WithCancel(context.Background())
}
return ctx, cancel, dir, *dbgOpt, cfg
}
func pushdir(dir string) (popdir func() error, err error) {
pwd := ""
if pwd, err = os.Getwd(); err != nil {
return nil, err
}
if err = os.Chdir(dir); err != nil {
return nil, err
}
return func() error { return os.Chdir(pwd) }, nil
}
func check(err error, dbg bool) {
if err == nil {
return
}
if dbg {
fmt.Fprintln(os.Stderr, "error:", err)
}
os.Exit(1)
}
func main() {
ctx, cancel, dir, dbg, cfg := parseOptions()
defer cancel()
// Handle directory change.
if dir != "." {
popDir, err := pushdir(dir)
check(err, dbg)
defer func() {
check(popDir(), dbg)
}()
}
// Retrieve git status.
st, err := gitstatus.NewWithContext(ctx)
check(err, dbg)
// Interface that writes a particular representation of a gitstatus.Status
type formater interface {
Format(io.Writer, *gitstatus.Status) error
}
// Set defauit formater.
var fmter formater = &tmux.Formater{Config: cfg.Tmux}
if dbg {
fmter = &json.Formater{}
}
check(fmter.Format(os.Stdout, st), dbg)
}