-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuild.go
142 lines (113 loc) · 3.93 KB
/
build.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
// +build ignore
package main
import (
"flag"
"fmt"
"os"
"path"
"strings"
"github.com/karlmutch/duat"
"github.com/karlmutch/duat/version"
"github.com/karlmutch/errors" // Forked copy of https://github.com/jjeffery/errors
"github.com/karlmutch/stack" // Forked copy of https://github.com/go-stack/stack
"github.com/mgutz/logxi" // Using a forked copy of this package results in build issues
"github.com/karlmutch/envflag" // Forked copy of https://github.com/GoBike/envflag
)
var (
logger = logxi.New("build.go")
verbose = flag.Bool("v", false, "When enabled will print internal logging for this tool")
recursive = flag.Bool("r", true, "When enabled this tool will visit any sub directories that contain main functions and build in each")
userDirs = flag.String("dirs", "cmd", "A comma seperated list of root directories that will be used a starting points looking for Go code, this will default to the current working directory")
)
func usage() {
fmt.Fprintln(os.Stderr, path.Base(os.Args[0]))
fmt.Fprintln(os.Stderr, "usage: ", os.Args[0], "[options] build tool (build.go) ", version.GitHash, " ", version.BuildTime)
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "Arguments")
fmt.Fprintln(os.Stderr, "")
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "Environment Variables:")
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "options can also be extracted from environment variables by changing dashes '-' to underscores and using upper case.")
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "log levels are handled by the LOGXI env variables, these are documented at https://github.com/mgutz/logxi")
}
func init() {
flag.Usage = usage
}
func main() {
// This code is run in the same fashion as a script and should be co-located
// with the component that is being built
// Parse the CLI flags
if !flag.Parsed() {
envflag.Parse()
}
if *verbose {
logger.SetLevel(logxi.LevelDebug)
}
// First assume that the directory supplied is a code directory
rootDirs := strings.Split(*userDirs, ",")
dirs := []string{}
err := errors.New("")
// If this is a recursive build scan all inner directories looking for go code
// and build it if there is code found
//
if *recursive {
for _, dir := range rootDirs {
// Will auto skip any vendor directories found
found, err := duat.FindGoDirs(dir)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(-1)
}
dirs = append(dirs, found...)
}
} else {
dirs = rootDirs
}
logger.Debug(fmt.Sprintf("%v", dirs))
// Take the discovered directories and build them
//
outputs := []string{}
localOut := []string{}
for _, dir := range dirs {
if localOut, err = runBuild(dir, "README.md"); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(-2)
}
outputs = append(outputs, localOut...)
}
for _, output := range outputs {
fmt.Fprintln(os.Stdout, output)
}
}
// runBuild is used to restore the current working directory after the build itself
// has switch directories
//
func runBuild(dir string, verFn string) (outputs []string, err errors.Error) {
logger.Info(fmt.Sprintf("building in %s", dir))
cwd, errGo := os.Getwd()
if errGo != nil {
return outputs, errors.Wrap(errGo).With("stack", stack.Trace().TrimRuntime())
}
outputs, err = build(dir, verFn)
if errGo = os.Chdir(cwd); errGo != nil {
logger.Warn("The original directory could not be restored after the build completed")
if err == nil {
err = errors.Wrap(errGo).With("stack", stack.Trace().TrimRuntime())
}
}
return outputs, err
}
// build performs the default build for the component within the directory specified
//
func build(dir string, verFn string) (outputs []string, err errors.Error) {
outputs = []string{}
// Gather information about the current environment. also changes directory to the working area
md, err := duat.NewMetaData(dir, verFn)
if err != nil {
return outputs, err
}
return md.GoBuild()
}