forked from jfrog/jfrog-cli-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
conversionlayer.go
209 lines (192 loc) · 5.43 KB
/
conversionlayer.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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package components
import (
"errors"
"fmt"
"github.com/jfrog/jfrog-cli-core/v2/docs/common"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/urfave/cli"
"strings"
)
func ConvertApp(jfrogApp App) (*cli.App, error) {
var err error
app := cli.NewApp()
app.Name = jfrogApp.Name
app.Description = jfrogApp.Description
app.Version = jfrogApp.Version
app.Commands, err = convertCommands(jfrogApp)
if err != nil {
return nil, err
}
// Defaults:
app.EnableBashCompletion = true
return app, nil
}
func convertCommands(jfrogApp App) ([]cli.Command, error) {
var converted []cli.Command
for _, cmd := range jfrogApp.Commands {
cur, err := convertCommand(cmd, jfrogApp.Name)
if err != nil {
return converted, err
}
converted = append(converted, cur)
}
return converted, nil
}
func convertCommand(cmd Command, appName string) (cli.Command, error) {
convertedFlags, err := convertFlags(cmd)
if err != nil {
return cli.Command{}, err
}
return cli.Command{
Name: cmd.Name,
Flags: convertedFlags,
Aliases: cmd.Aliases,
Description: cmd.Description,
HelpName: common.CreateUsage(appName+" "+cmd.Name, cmd.Description, []string{createCommandUsage(cmd, appName)}),
UsageText: createArgumentsSummary(cmd),
ArgsUsage: createEnvVarsSummary(cmd),
BashComplete: common.CreateBashCompletionFunc(),
SkipFlagParsing: cmd.SkipFlagParsing,
// Passing any other interface than 'cli.ActionFunc' will fail the command.
Action: getActionFunc(cmd),
}, nil
}
func createCommandUsage(cmd Command, appName string) string {
usage := fmt.Sprintf(coreutils.GetCliExecutableName()+" %s %s", appName, cmd.Name)
if len(cmd.Flags) > 0 {
usage += " [command options]"
}
for _, argument := range cmd.Arguments {
usage += fmt.Sprintf(" <%s>", argument.Name)
}
return usage
}
func createArgumentsSummary(cmd Command) string {
summary := ""
for i, argument := range cmd.Arguments {
if i > 0 {
summary += "\n"
}
summary += "\t" + argument.Name + "\n\t\t" + argument.Description + "\n"
}
return summary
}
func createEnvVarsSummary(cmd Command) string {
var envVarsSummary []string
for i, env := range cmd.EnvVars {
summary := ""
if i > 0 {
summary += "\n"
}
summary = "\t" + env.Name + "\n"
if env.Default != "" {
summary += "\t\t[Default: " + env.Default + "]\n"
}
summary += "\t\t" + env.Description
envVarsSummary = append(envVarsSummary, summary)
}
return strings.Join(envVarsSummary[:], "\n\n")
}
func convertFlags(cmd Command) ([]cli.Flag, error) {
var convertedFlags []cli.Flag
for _, flag := range cmd.Flags {
converted, err := convertByType(flag)
if err != nil {
return convertedFlags, err
}
if converted != nil {
convertedFlags = append(convertedFlags, converted)
}
}
return convertedFlags, nil
}
func convertByType(flag Flag) (cli.Flag, error) {
if f, ok := flag.(StringFlag); ok {
return convertStringFlag(f), nil
}
if f, ok := flag.(BoolFlag); ok {
return convertBoolFlag(f), nil
}
return nil, errors.New(fmt.Sprintf("Flag '%s' does not match any known flag type.", flag.GetName()))
}
func convertStringFlag(f StringFlag) cli.Flag {
stringFlag := cli.StringFlag{
Name: f.Name,
Usage: f.Description + "` `",
}
// If default is set, add its value and return.
if f.DefaultValue != "" {
stringFlag.Usage = fmt.Sprintf("[Default: %s] %s", f.DefaultValue, stringFlag.Usage)
return stringFlag
}
// Otherwise, mark as mandatory/optional accordingly.
if f.Mandatory {
stringFlag.Usage = "[Mandatory] " + stringFlag.Usage
} else {
stringFlag.Usage = "[Optional] " + stringFlag.Usage
}
return stringFlag
}
func convertBoolFlag(f BoolFlag) cli.Flag {
if f.DefaultValue {
return cli.BoolTFlag{
Name: f.Name,
Usage: "[Default: true] " + f.Description + "` `",
}
}
return cli.BoolFlag{
Name: f.Name,
Usage: "[Default: false] " + f.Description + "` `",
}
}
// Wrap the base's ActionFunc with our own, while retrieving needed information from the Context.
func getActionFunc(cmd Command) cli.ActionFunc {
return func(baseContext *cli.Context) error {
pluginContext := &Context{}
pluginContext.Arguments = baseContext.Args()
err := fillFlagMaps(pluginContext, baseContext, cmd.Flags)
if err != nil {
return err
}
return cmd.Action(pluginContext)
}
}
func fillFlagMaps(c *Context, baseContext *cli.Context, originalFlags []Flag) error {
c.stringFlags = make(map[string]string)
c.boolFlags = make(map[string]bool)
// Loop over all plugin's known flags.
for _, flag := range originalFlags {
if stringFlag, ok := flag.(StringFlag); ok {
finalValue, err := getValueForStringFlag(stringFlag, baseContext.String(stringFlag.Name))
if err != nil {
return err
}
c.stringFlags[stringFlag.Name] = finalValue
continue
}
if boolFlag, ok := flag.(BoolFlag); ok {
c.boolFlags[boolFlag.Name] = getValueForBoolFlag(boolFlag, baseContext)
}
}
return nil
}
func getValueForStringFlag(f StringFlag, receivedValue string) (finalValue string, err error) {
if receivedValue != "" {
return receivedValue, nil
}
// Empty but has a default value defined.
if f.DefaultValue != "" {
return f.DefaultValue, nil
}
// Empty but mandatory.
if f.Mandatory {
return "", errors.New("Mandatory flag '" + f.Name + "' is missing")
}
return "", nil
}
func getValueForBoolFlag(f BoolFlag, baseContext *cli.Context) bool {
if f.DefaultValue {
return baseContext.BoolT(f.Name)
}
return baseContext.Bool(f.Name)
}