...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package command
17
18 import (
19 "os/exec"
20 "reflect"
21 "strings"
22
23 "github.com/pkg/errors"
24 )
25
26
27
28
29
30 const ExecTag = "exec"
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 const SubCommandTag = "sub_command"
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 const ParaTag = "para"
63
64
65
66
67
68
69
70
71
72
73 type Exec struct {
74 active bool
75 }
76
77 func NewExec() Exec {
78 return Exec{active: true}
79 }
80
81 func ToCommand(i interface{}) (*exec.Cmd, error) {
82 path, args, err := Marshal(i)
83 if err != nil {
84 return nil, err
85 }
86 return exec.Command(path, args...), nil
87 }
88
89 func Marshal(i interface{}) (string, []string, error) {
90 value := reflect.ValueOf(i)
91 return marshal(value)
92 }
93
94 func marshal(value reflect.Value) (string, []string, error) {
95
96 if path, ok := SearchKey(value); ok {
97
98
99 if path == "" {
100 return "", nil, nil
101 }
102 args := make([]string, 0)
103 for i := 0; i < value.NumField(); i++ {
104 if _, ok := value.Type().Field(i).Tag.Lookup(SubCommandTag); ok {
105 subPath, subArgs, err := marshal(value.Field(i))
106 if err != nil {
107 return "", nil, err
108 }
109 if subPath != "" {
110 args = append(args, subPath)
111 }
112 args = append(args, subArgs...)
113 }
114 if paraName, ok := value.Type().Field(i).Tag.Lookup(ParaTag); ok {
115 if value.Type().Field(i).Type.Name() == "string" {
116 if value.Field(i).String() != "" {
117 if paraName != "" {
118 args = append(args, paraName)
119 }
120 args = append(args, value.Field(i).String())
121 }
122 } else if value.Field(i).Kind() == reflect.Slice {
123 if slicePara, ok := value.Field(i).Interface().([]string); ok {
124 if strings.Join(slicePara, "") != "" {
125 if paraName != "" {
126 args = append(args, paraName)
127 }
128 args = append(args, slicePara...)
129 }
130 } else {
131 return "", nil, errors.Errorf("invalid parameter slice type %s :parameter slice must be string slice", value.Field(i).String())
132 }
133 } else {
134 return "", nil, errors.Errorf("invalid parameter type %s : parameter must be string or string slice", value.Type().Field(i).Type.Name())
135 }
136 }
137 }
138 return path, args, nil
139 }
140 return "", nil, nil
141 }
142
143 func SearchKey(value reflect.Value) (string, bool) {
144 for i := 0; i < value.NumField(); i++ {
145 if path, ok := value.Type().Field(i).Tag.Lookup(ExecTag); ok {
146 if value.Field(i).Field(0).Bool() {
147 return path, ok
148 }
149 }
150 }
151 return "", false
152 }
153