-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsys.go
178 lines (163 loc) · 4.47 KB
/
sys.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
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
168
169
170
171
172
173
174
175
176
177
178
package goutil
import (
"math"
"os"
"strconv"
"strings"
"syscall"
"github.com/tkdeng/goregex"
)
// SysFreeMemory returns the amount of memory available in megabytes
func SysFreeMemory() float64 {
in := &syscall.Sysinfo_t{}
err := syscall.Sysinfo(in)
if err != nil {
return 0
}
// If this is a 32-bit system, then these fields are
// uint32 instead of uint64.
// So we always convert to uint64 to match signature.
return math.Round(float64(uint64(in.Freeram)*uint64(in.Unit))/1024/1024*100) / 100
}
// FormatMemoryUsage converts bytes to megabytes
func FormatMemoryUsage(b uint64) float64 {
return math.Round(float64(b)/1024/1024*100) / 100
}
var regIsAlphaNumeric *regex.Regexp = regex.Comp(`^[A-Za-z0-9]+$`)
// MapArgs will convert a bash argument array ([]string) into a map (map[string]string)
//
// When @args is left blank with no values, it will default to os.Args[1:]
//
// -- Arg Conversions:
//
// "--Key=value" will convert to "key:value"
//
// "--boolKey" will convert to "boolKey:true"
//
// "-flags" will convert to "f:true, l:true, a:true, g:true, s:true" (only if its alphanumeric [A-Za-z0-9])
// if -flags is not alphanumeric (example: "-test.paniconexit0" "-test.timeout=10m0s") it will be treated as a --flag (--key=value --boolKey)
//
// keys that match a number ("--1" or "-1") will start with a "-" ("--1=value" -> "-1:value", "-1" -> -1:true)
// this prevents a number key from conflicting with an index key
//
// everything else is given a number value index starting with 0
//
// this method will not allow --args to have their values modified after they have already been set
func MapArgs(args ...[]string) map[string]string {
if len(args) == 0 {
args = append(args, os.Args[1:])
}
argMap := map[string]string{}
i := 0
for _, argList := range args {
for _, arg := range argList {
if strings.HasPrefix(arg, "--") {
arg = arg[2:]
if strings.ContainsRune(arg, '=') {
data := strings.SplitN(arg, "=", 2)
if _, err := strconv.Atoi(data[0]); err == nil {
if argMap["-"+data[0]] == "" {
argMap["-"+data[0]] = data[1]
}
} else {
if argMap[data[0]] == "" {
argMap[data[0]] = data[1]
}
}
} else {
if _, err := strconv.Atoi(arg); err == nil {
if argMap["-"+arg] == "" {
argMap["-"+arg] = "true"
}
} else {
if argMap[arg] == "" {
argMap[arg] = "true"
}
}
}
} else if strings.HasPrefix(arg, "-") {
arg = arg[1:]
if regIsAlphaNumeric.Match([]byte(arg)) {
flags := strings.Split(arg, "")
for _, flag := range flags {
if _, err := strconv.Atoi(flag); err == nil {
if argMap["-"+flag] == "" {
argMap["-"+flag] = "true"
}
} else {
if argMap[flag] == "" {
argMap[flag] = "true"
}
}
}
} else {
if strings.ContainsRune(arg, '=') {
data := strings.SplitN(arg, "=", 2)
if _, err := strconv.Atoi(data[0]); err == nil {
if argMap["-"+data[0]] == "" {
argMap["-"+data[0]] = data[1]
}
} else {
if argMap[data[0]] == "" {
argMap[data[0]] = data[1]
}
}
} else {
if _, err := strconv.Atoi(arg); err == nil {
if argMap["-"+arg] == "" {
argMap["-"+arg] = "true"
}
} else {
if argMap[arg] == "" {
argMap[arg] = "true"
}
}
}
}
} else {
argMap[strconv.Itoa(i)] = arg
i++
}
}
}
return argMap
}
// ArgsReader is a structured way to read os.args
//
// Note: you should call `args.New()` to get a populated list of arguments
type ArgsReader struct {
args map[string]string
nextInt int
}
// ReadArgs returns a list of `os.args` in a structured ArgsReader
func ReadArgs(args ...[]string) ArgsReader {
return ArgsReader{
args: MapArgs(args...),
nextInt: 0,
}
}
// Get returns a key value from os.args
//
// @def: default value if no arg is found
//
// @name: the name of the argument to search for
//
// @alt: optional list of fallback names to search for
// - note: if you pass an empty value or `*` into @alt,
// it will assume the next integer arg that has not been returned yet.
func (args *ArgsReader) Get(def string, name string, alt ...string) string {
if val, ok := args.args[name]; ok {
return val
}
for _, n := range alt {
if n == "" || n == "*" {
if val, ok := args.args[strconv.Itoa(args.nextInt)]; ok {
args.nextInt++
return val
}
} else if val, ok := args.args[n]; ok {
return val
}
}
return def
}