-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
cli_context.go
102 lines (92 loc) Β· 2.93 KB
/
cli_context.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
package config
import (
"reflect"
"time"
"github.com/urfave/cli"
"github.com/photoprism/photoprism/pkg/txt"
)
// ApplyCliContext applies the values of the cli context based on the "flag" annotations.
func ApplyCliContext(c interface{}, ctx *cli.Context) error {
v := reflect.ValueOf(c).Elem()
// Iterate through all config fields.
for i := 0; i < v.NumField(); i++ {
fieldValue := v.Field(i)
tagValue := v.Type().Field(i).Tag.Get("flag")
// Assign value to field with "flag" tag.
if tagValue != "" && tagValue != "-" {
switch t := fieldValue.Interface().(type) {
case time.Duration:
var s string
// Get duration string.
if ctx.IsSet(tagValue) {
s = ctx.String(tagValue)
} else if ctx.GlobalIsSet(tagValue) || fieldValue.Interface().(time.Duration) == 0 {
s = ctx.GlobalString(tagValue)
}
// Parse duration string.
if s == "" {
// Omit.
} else if sec := txt.UInt(s); sec > 0 {
fieldValue.Set(reflect.ValueOf(time.Duration(sec) * time.Second))
} else if d, err := time.ParseDuration(s); err == nil {
fieldValue.Set(reflect.ValueOf(d))
}
case float64:
// Only if explicitly set or current value is empty (use default).
if ctx.IsSet(tagValue) {
f := ctx.Float64(tagValue)
fieldValue.SetFloat(f)
} else if ctx.GlobalIsSet(tagValue) || fieldValue.Float() == 0 {
f := ctx.GlobalFloat64(tagValue)
fieldValue.SetFloat(f)
}
case int, int64:
// Only if explicitly set or current value is empty (use default).
if ctx.IsSet(tagValue) {
f := ctx.Int64(tagValue)
fieldValue.SetInt(f)
} else if ctx.GlobalIsSet(tagValue) || fieldValue.Int() == 0 {
f := ctx.GlobalInt64(tagValue)
fieldValue.SetInt(f)
}
case uint, uint64:
// Only if explicitly set or current value is empty (use default).
if ctx.IsSet(tagValue) {
f := ctx.Uint64(tagValue)
fieldValue.SetUint(f)
} else if ctx.GlobalIsSet(tagValue) || fieldValue.Uint() == 0 {
f := ctx.GlobalUint64(tagValue)
fieldValue.SetUint(f)
}
case string:
// Only if explicitly set or current value is empty (use default)
if ctx.IsSet(tagValue) {
f := ctx.String(tagValue)
fieldValue.SetString(f)
} else if ctx.GlobalIsSet(tagValue) || fieldValue.String() == "" {
f := ctx.GlobalString(tagValue)
fieldValue.SetString(f)
}
case []string:
if ctx.IsSet(tagValue) {
f := reflect.ValueOf(ctx.StringSlice(tagValue))
fieldValue.Set(f)
} else if ctx.GlobalIsSet(tagValue) || fieldValue.Len() == 0 {
f := reflect.ValueOf(ctx.GlobalStringSlice(tagValue))
fieldValue.Set(f)
}
case bool:
if ctx.IsSet(tagValue) {
f := ctx.Bool(tagValue)
fieldValue.SetBool(f)
} else if ctx.GlobalIsSet(tagValue) {
f := ctx.GlobalBool(tagValue)
fieldValue.SetBool(f)
}
default:
log.Warnf("cannot assign value of type %s from cli flag %s", t, tagValue)
}
}
}
return nil
}