Two output-style fixes plus a quiet-mode correction.
Banner: a manual scan of os.Args in CLIEntry decides whether to suppress
the banner (--quiet/-q/--cron), then prints it before cobra parses any
arguments. This makes the banner appear even when cobra rejects bad args
("requires at least 2 arg(s)") and on --help — paths that previously
skipped PersistentPreRun entirely. The cobra-side hook plumbing (sync.Once,
PersistentPreRun, custom HelpFunc) is removed.
Errors: rootCmd.SilenceErrors = true so cobra no longer prints its own
"Error: <msg>" line. Any error returned from Execute() goes through
ui.New(os.Stderr).Error(...), giving the documented "🛑 ERROR: <msg>"
format. A new helper cli.ReportError() formats errors from goroutine
paths that can't return through cobra's normal return chain; every
CLI command's fx-goroutine error path now calls it alongside the
existing structured log.Error so both channels record the failure.
Quiet mode: previously --quiet/--cron swapped Vaultik.UI to io.Discard,
which silenced Warning and Error messages too — contradicting the
documented "suppresses non-error output" semantics. ui.Writer now has
a SetQuiet flag that drops Begin/Complete/Info/Notice/Detail/Progress/
Banner only; Warning and Error always emit.
Also folds in restore.go cleanups the audit flagged: the hardcoded
"WARNING:" prefix on the failed-files block now uses ui.Warning +
ui.Detail, the post-restore "Restored N files" line uses ui.Complete,
and the "No files found to restore" branch emits both log.Warn and
ui.Warning so structured logs continue to capture it under --verbose.
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
package cli
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"sneak.berlin/go/vaultik/internal/globals"
|
|
"sneak.berlin/go/vaultik/internal/ui"
|
|
)
|
|
|
|
// CLIEntry is the main entry point for the CLI application.
|
|
// It prints the startup banner (unless a quiet flag is present in os.Args),
|
|
// executes the root cobra command, and routes any returned error through
|
|
// the ui.Writer so the user sees a properly formatted "🛑 ERROR:" line.
|
|
func CLIEntry() {
|
|
if !bannerSuppressedInArgs(os.Args[1:]) {
|
|
short := globals.Commit
|
|
if len(short) > 12 {
|
|
short = short[:12]
|
|
}
|
|
writeStartupBanner(ui.New(os.Stdout), time.Now().UTC(), short)
|
|
}
|
|
|
|
rootCmd := NewRootCommand()
|
|
rootCmd.SilenceErrors = true
|
|
|
|
if err := rootCmd.Execute(); err != nil {
|
|
ReportError("%s", err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// ReportError emits a user-facing error to stderr in the standard
|
|
// 🛑 ERROR: format. Use it from goroutine error paths (where returning
|
|
// an error to cobra isn't an option) and anywhere else a CLI command
|
|
// must surface a failure outside the normal RunE return path.
|
|
func ReportError(format string, args ...any) {
|
|
ui.New(os.Stderr).Error(format, args...)
|
|
}
|
|
|
|
// bannerSuppressedInArgs reports whether any of args is a flag that
|
|
// should suppress the startup banner (--quiet/-q/--cron). Stops at the
|
|
// "--" argument terminator. Recognizes both long forms and short -q,
|
|
// including combined short flags like "-qv".
|
|
func bannerSuppressedInArgs(args []string) bool {
|
|
for _, a := range args {
|
|
if a == "--" {
|
|
return false
|
|
}
|
|
switch a {
|
|
case "--quiet", "-q", "--cron":
|
|
return true
|
|
}
|
|
if strings.HasPrefix(a, "--quiet=") || strings.HasPrefix(a, "--cron=") {
|
|
return true
|
|
}
|
|
// Combined short flags like -qv or -vq.
|
|
if len(a) > 1 && a[0] == '-' && a[1] != '-' {
|
|
for _, c := range a[1:] {
|
|
if c == 'q' {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|