-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjock.go
More file actions
167 lines (137 loc) · 4.09 KB
/
jock.go
File metadata and controls
167 lines (137 loc) · 4.09 KB
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
159
160
161
162
163
164
165
166
167
package main
import (
"fmt"
"github.com/spf13/viper"
"os"
)
func main() {
readConfig()
invocation := getInvocationDetails()
run(invocation)
}
// Takes in the invocation details and applies run logic to it.
func run(invocation *InvocationDetails) {
if invocation.version {
displayVersion()
}
if invocation.help || len(invocation.plugin) == 0 {
displayHelp()
}
runPlugin(invocation)
}
/**********************************************
Invocation
**********************************************/
type FolderConfig struct {
Location string `mapstructure:"location"`
Plugins map[string]interface{} `mapstructure:"plugins"`
}
// Holds the processed details of the jock invocation for logic to be applied later.
type InvocationDetails struct {
version bool
help bool
folders map[string]FolderConfig
plugin string
pluginArgs []string
}
// Loops over the arguments supplied to jock and returns a pointer to the populated invocation details.
func getInvocationDetails() *InvocationDetails {
args := os.Args[1:]
invocation := &InvocationDetails{
folders: make(map[string]FolderConfig),
}
for i := 0; i < len(args); i++ {
switch args[i] {
case "--help", "-h":
invocation.help = true
break
case "--version", "-v":
invocation.version = true
break
case "--folder", "-f":
i++
invocation.folders[args[i]] = getFolderConfig(args[i])
break
default:
setPluginDetails(invocation, args[i:])
return invocation
}
}
return invocation
}
// Takes in a pointer to the invocation details and populates the relevant fields from the plugin argument slice.
func setPluginDetails(c *InvocationDetails, pluginArgs []string) {
c.plugin = pluginArgs[0]
if len(pluginArgs) > 1 {
c.pluginArgs = pluginArgs[1:]
}
}
/**********************************************
JockPlugin
**********************************************/
// Will run the plugin.
func runPlugin(invocation *InvocationDetails) {
fmt.Printf("Plugin: %s\n", invocation.plugin)
fmt.Printf("Plugin Args: %s\n", invocation.pluginArgs)
fmt.Printf("Folders: %s\n", invocation.folders)
for k, v := range invocation.folders {
fmt.Printf("%s config for %s: %s\n", invocation.plugin, k, v.Plugins[invocation.plugin])
}
}
/**********************************************
Print
**********************************************/
// Will display the version of jock-cli and exit.
func displayVersion() {
fmt.Println("0.0.0")
os.Exit(0)
}
// Displays help information for jock, including example usage and a description of available options and flags.
func displayHelp() {
fmt.Println("Usage:")
fmt.Println(" jock [JOCK_ARGS] [PLUGIN] [PLUGIN_COMMAND] [PLUGIN_COMMAND_ARGS]")
fmt.Println(" e.g. jock -f user-serv git clone --recurse-submodules")
fmt.Println("")
fmt.Println("Jock Arguments:")
fmt.Println(" --version, -v Print version and exit")
fmt.Println(" --help, -h Print this help text and exit")
fmt.Println(" --folder, -f Define one or more folders to run the plugin command on")
os.Exit(0)
}
/**********************************************
Config
**********************************************/
// Reads the config file from ~/.jockrc
func readConfig() {
viper.SetConfigName(".jockrc")
viper.SetConfigType("yaml")
viper.AddConfigPath("$HOME")
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; ignore error if desired
fmt.Println(err)
} else {
// Config file was found but another error was produced
fmt.Println(err)
}
}
}
const FOLDERS = "folders"
// Checks that the config contains the specified folder, and returns marshalled FolderConfig if so.
func getFolderConfig(name string) FolderConfig {
folder := FolderConfig{}
if !viper.InConfig(FOLDERS) {
fmt.Print("Config does not contain folders")
os.Exit(1)
}
if !viper.Sub(FOLDERS).InConfig(name) {
fmt.Printf("Config folders do not contain [%s]", name)
os.Exit(1)
}
err := viper.Sub(FOLDERS).UnmarshalKey(name, &folder)
if err != nil {
fmt.Printf("Unable to decode into config struct, %v", err)
os.Exit(1)
}
return folder
}