-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
110 lines (94 loc) · 2.9 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
package main
import (
"context"
"flag"
"fmt"
"io"
"os"
"os/signal"
"syscall"
"github.com/ejholmes/walk/internal/tty"
)
const (
// DefaultTarget is the name of the target that is used when no target
// is provided on the command line.
DefaultTarget = "all"
)
// Maps a named format to a function that renders the graph.
var printGraph = map[string]func(io.Writer, *Graph) error{
"dot": dot,
"plain": plain,
}
var isTTY bool
func init() {
isTTY = isTerminal(os.Stdout)
}
func main() {
flag.Usage = usage
var (
version = flag.Bool("version", false, "Print the version of walk and exit.")
verbose = flag.Bool("v", false, fmt.Sprintf("Show stdout from the Walkfile when executing the %s phase.", PhaseExec))
noprefix = flag.Bool("noprefix", false, "By default, the stdout/stderr output from the Walkfile is prefixed with the name of the target, followed by a tab character. This flag disables the prefixing. This can help with performance, or issues where you encounter \"too many open files\", since prefixing necessitates more file descriptors.")
concurrency = flag.Uint("j", 0, "Controls the number of targets that are executed in parallel. By default, targets are executed with the maximum level of parallelism that the graph allows. To limit the number of targets that are executed in parallel, set this to a value greater than 1. To execute targets serially, set this to 1.")
print = flag.String("p", "", "Prints the underlying DAG to stdout, using the provided format. Available formats are \"dot\" and \"plain\".")
)
flag.Parse()
if *version {
fmt.Fprintf(os.Stderr, "%s\n", Version)
os.Exit(0)
}
targets := flag.Args()
if len(targets) == 0 {
targets = []string{DefaultTarget}
}
plan := newPlan()
plan.NewTarget = NewTarget(TargetOptions{
Verbose: *verbose,
NoPrefix: *noprefix,
})
ctx, cancel := context.WithCancel(context.Background())
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
for {
<-c
cancel()
}
}()
must(plan.Plan(ctx, targets...))
if *print != "" {
fn, ok := printGraph[*print]
if !ok {
must(fmt.Errorf("invalid format provided: %s", *print))
}
must(fn(os.Stdout, plan.graph))
} else {
semaphore := NewSemaphore(*concurrency)
must(plan.Exec(ctx, semaphore))
}
}
func must(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", ansi("31", "error: %v", err))
os.Exit(1)
}
}
func isTerminal(w io.Writer) bool {
if w == nil {
return false
}
f, ok := w.(*os.File)
if !ok {
return false
}
return tty.IsTerminal(f.Fd())
}
func usage() {
fmt.Fprintf(os.Stderr, "walk - A fast, general purpose, graph based build and task execution utility.\n\n")
fmt.Fprintf(os.Stderr, "VERSION:\n")
fmt.Fprintf(os.Stderr, " %s\n\n", Version)
fmt.Fprintf(os.Stderr, "USAGE:\n")
fmt.Fprintf(os.Stderr, " walk [target...]\n\n")
fmt.Fprintf(os.Stderr, "OPTIONS:\n")
flag.PrintDefaults()
}