-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroot.go
More file actions
139 lines (118 loc) · 3.48 KB
/
Copy pathroot.go
File metadata and controls
139 lines (118 loc) · 3.48 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
// Package cli builds the mvn command tree on top of the maven library.
package cli
import (
"fmt"
"os"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
"github.com/tamnd/maven-cli/maven"
)
// Build metadata, set via -ldflags at release time.
var (
Version = "dev"
Commit = "none"
Date = "unknown"
)
// exit codes.
const (
exitError = 1
exitUsage = 2
exitNoData = 3
)
// ExitError carries a process exit code up to main.
type ExitError struct {
Code int
Err error
}
func (e *ExitError) Error() string {
if e.Err != nil {
return e.Err.Error()
}
return fmt.Sprintf("exit %d", e.Code)
}
func (e *ExitError) Unwrap() error { return e.Err }
func codeError(code int, err error) error { return &ExitError{Code: code, Err: err} }
// App holds shared state threaded through every command.
type App struct {
client *maven.Client
cfg maven.Config
output string
fields []string
noHeader bool
template string
limit int
quiet bool
}
// Root builds the root command and its subtree.
func Root() *cobra.Command {
app := &App{cfg: maven.DefaultConfig()}
root := &cobra.Command{
Use: "maven",
Short: "Search Maven Central artifacts",
Long: `maven searches Maven Central through the Solr search API.
No API key is required. It returns records as table, JSON, JSONL, CSV, TSV, or URLs.
maven is an independent tool and is not affiliated with Maven Central or Sonatype.`,
SilenceUsage: true,
SilenceErrors: true,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
return app.setup()
},
}
pf := root.PersistentFlags()
pf.StringVarP(&app.output, "output", "o", "auto", "output: table|json|jsonl|csv|tsv|url|raw (auto=table on TTY, jsonl piped)")
pf.StringSliceVar(&app.fields, "fields", nil, "comma-separated columns to include")
pf.BoolVar(&app.noHeader, "no-header", false, "omit the header row in table/csv/tsv")
pf.StringVar(&app.template, "template", "", "Go text/template applied per record")
pf.IntVarP(&app.limit, "limit", "n", 0, "limit number of records (0 = command default)")
pf.BoolVarP(&app.quiet, "quiet", "q", false, "suppress progress on stderr")
pf.DurationVar(&app.cfg.Rate, "delay", app.cfg.Rate, "minimum spacing between requests")
pf.DurationVar(&app.cfg.Timeout, "timeout", app.cfg.Timeout, "per-request timeout")
pf.IntVar(&app.cfg.Retries, "retries", app.cfg.Retries, "retry attempts on 429/5xx")
pf.StringVar(&app.cfg.UserAgent, "user-agent", app.cfg.UserAgent, "User-Agent sent with each request")
root.AddCommand(
app.searchCmd(),
app.artifactCmd(),
app.versionsCmd(),
newVersionCmd(),
)
return root
}
func (a *App) setup() error {
if a.output == "" || a.output == "auto" {
if isatty.IsTerminal(os.Stdout.Fd()) {
a.output = string(FormatTable)
} else {
a.output = string(FormatJSONL)
}
}
if !Format(a.output).Valid() {
return codeError(exitUsage, fmt.Errorf("unknown output format %q", a.output))
}
a.client = maven.NewClient(a.cfg)
return nil
}
func (a *App) render(records any) error {
r := NewRenderer(os.Stdout, Format(a.output), a.fields, a.noHeader, a.template)
return r.Render(records)
}
func (a *App) renderOrEmpty(records any, n int) error {
if err := a.render(records); err != nil {
return err
}
if n == 0 {
return codeError(exitNoData, nil)
}
return nil
}
func (a *App) progressf(format string, args ...any) {
if a.quiet {
return
}
_, _ = fmt.Fprintf(os.Stderr, format+"\n", args...)
}
func (a *App) effectiveLimit(def int) int {
if a.limit > 0 {
return a.limit
}
return def
}