-
Notifications
You must be signed in to change notification settings - Fork 2
/
init_command.go
90 lines (81 loc) · 2.04 KB
/
init_command.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
package main
import (
"fmt"
"os"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
"gopkg.in/yaml.v3"
)
type InitCommand struct {
cli.Command
}
func newInitCommand() *InitCommand {
c := &InitCommand{}
c.Command = cli.Command{
Name: "init",
Usage: "Initializes a config file",
Description: `If CONFIG-FILE is "-" the YAML will be printed to stdout.
If empty, it will be written to "config.yaml".`,
Action: c.Action,
ArgsUsage: "[CONFIG-FILE]",
}
return c
}
func (c *InitCommand) Action(ctx *cli.Context) error {
configFilePath := "config.yaml"
if ctx.NArg() >= 1 {
configFilePath = ctx.Args().First()
}
flags := allAltSrcFlags(ctx)
values := map[string]any{}
for _, flag := range flags {
values[flag.Names()[0]] = getValueFor(flag)
}
b, err := yaml.Marshal(values)
if err != nil {
return fmt.Errorf("cannot serialize flags to yaml: %w", err)
}
if configFilePath == "-" {
fmt.Println(string(b))
return nil
}
if _, statErr := os.Stat(configFilePath); statErr != nil && os.IsNotExist(statErr) {
return os.WriteFile(configFilePath, b, 0644)
}
return fmt.Errorf("target file %q exists already", configFilePath)
}
func getValueFor(flag cli.Flag) any {
if f, ok := flag.(*altsrc.StringFlag); ok {
return f.Value
}
if f, ok := flag.(*altsrc.BoolFlag); ok {
return f.Value
}
if f, ok := flag.(*altsrc.DurationFlag); ok {
return f.Value
}
if f, ok := flag.(*altsrc.IntFlag); ok {
return f.Value
}
panic(fmt.Errorf("unknown flag type: %v", flag))
}
func allAltSrcFlags(ctx *cli.Context) []cli.Flag {
flagMap := map[string]cli.Flag{}
for _, flag := range ctx.App.Flags {
if f, isAltSrcFlag := flag.(altsrc.FlagInputSourceExtension); isAltSrcFlag {
flagMap[flag.Names()[0]] = f
}
}
for _, subcommand := range ctx.App.Commands {
for _, flag := range subcommand.Flags {
if f, isAltSrcFlag := flag.(altsrc.FlagInputSourceExtension); isAltSrcFlag {
flagMap[flag.Names()[0]] = f
}
}
}
flags := make([]cli.Flag, 0)
for _, flag := range flagMap {
flags = append(flags, flag)
}
return flags
}