-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathroot.go
More file actions
164 lines (131 loc) · 4.19 KB
/
root.go
File metadata and controls
164 lines (131 loc) · 4.19 KB
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
package cmd
import (
"fmt"
"os"
"path/filepath"
"github.com/charmbracelet/log"
"github.com/numtide/treefmt/v2/build"
"github.com/numtide/treefmt/v2/cmd/format"
_init "github.com/numtide/treefmt/v2/cmd/init"
"github.com/numtide/treefmt/v2/config"
"github.com/numtide/treefmt/v2/stats"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func NewRoot() (*cobra.Command, *stats.Stats) {
var (
treefmtInit bool
configFile string
)
// create a viper instance for reading in config
v, err := config.NewViper()
if err != nil {
cobra.CheckErr(fmt.Errorf("failed to create viper instance: %w", err))
}
// create a new stats instance
statz := stats.New()
// create out root command
cmd := &cobra.Command{
Use: build.Name + " <paths...>",
Short: "The formatter multiplexer",
Version: build.Version,
RunE: func(cmd *cobra.Command, args []string) error {
return runE(v, &statz, cmd, args)
},
}
// update version template
cmd.SetVersionTemplate("treefmt {{.Version}}")
fs := cmd.Flags()
// add our config flags to the command's flag set
config.SetFlags(fs)
// xor tree-root and tree-root-file flags
cmd.MarkFlagsMutuallyExclusive("tree-root", "tree-root-file")
cmd.HelpTemplate()
// add a couple of special flags which don't have a corresponding entry in treefmt.toml
fs.StringVar(
&configFile, "config-file", "",
"Load the config file from the given path (defaults to searching upwards for treefmt.toml or "+
".treefmt.toml).",
)
fs.BoolVarP(
&treefmtInit, "init", "i", false,
"Create a treefmt.toml file in the current directory.",
)
// bind our command's flags to viper
if err := v.BindPFlags(fs); err != nil {
cobra.CheckErr(fmt.Errorf("failed to bind global config to viper: %w", err))
}
// bind prj_root to the tree-root flag, allowing viper to handle environment override for us
// conforms with https://github.com/numtide/prj-spec/blob/main/PRJ_SPEC.md
cobra.CheckErr(v.BindPFlag("prj_root", fs.Lookup("tree-root")))
return cmd, &statz
}
func runE(v *viper.Viper, statz *stats.Stats, cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
// change working directory if required
workingDir, err := filepath.Abs(v.GetString("working-dir"))
if err != nil {
return fmt.Errorf("failed to get absolute path for working directory: %w", err)
} else if err = os.Chdir(workingDir); err != nil {
return fmt.Errorf("failed to change working directory: %w", err)
}
// check if we are running the init command
if init, err := flags.GetBool("init"); err != nil {
return fmt.Errorf("failed to read init flag: %w", err)
} else if init {
err := _init.Run()
if err != nil {
return fmt.Errorf("failed to run init command: %w", err)
}
return nil
}
// otherwise attempt to load the config file
// use the path specified by the flag
configFile, err := flags.GetString("config-file")
if err != nil {
return fmt.Errorf("failed to read config-file flag: %w", err)
}
// fallback to env
if configFile == "" {
configFile = os.Getenv("TREEFMT_CONFIG")
}
filenames := []string{"treefmt.toml", ".treefmt.toml"}
// look in PRJ_ROOT if set
if prjRoot := os.Getenv("PRJ_ROOT"); configFile == "" && prjRoot != "" {
configFile, _ = config.Find(prjRoot, filenames...)
}
// search up from the working directory
if configFile == "" {
configFile, _, err = config.FindUp(workingDir, filenames...)
}
// error out if we couldn't find the config file
if err != nil {
cmd.SilenceUsage = true
return fmt.Errorf("failed to find treefmt config file: %w", err)
}
log.Debugf("using config file: %s", configFile)
// read in the config
v.SetConfigFile(configFile)
if err := v.ReadInConfig(); err != nil {
cobra.CheckErr(fmt.Errorf("failed to read config file '%s': %w", configFile, err))
}
// configure logging
log.SetOutput(os.Stderr)
log.SetReportTimestamp(false)
if v.GetBool("quiet") {
// if quiet, we only log errors
log.SetLevel(log.ErrorLevel)
} else {
// otherwise, the verbose flag controls the log level
switch v.GetInt("verbose") {
case 0:
log.SetLevel(log.WarnLevel)
case 1:
log.SetLevel(log.InfoLevel)
default:
log.SetLevel(log.DebugLevel)
}
}
// format
return format.Run(v, statz, cmd, args) //nolint:wrapcheck
}