Compare commits

..

3 Commits

Author SHA1 Message Date
5d9924ff58 replace exitOnError with a deferred exit function.
this ensures the closer() cleanup function is always called.
2026-02-15 11:08:25 +00:00
00acafa290 fix docstring 2026-02-15 10:51:59 +00:00
f97d241f64 add linter exclusion for test files
set thresholds for issues
2026-02-15 09:54:12 +00:00
2 changed files with 48 additions and 17 deletions

View File

@ -67,6 +67,7 @@ linters:
- name: unused-parameter - name: unused-parameter
- name: var-declaration - name: var-declaration
- name: blank-imports - name: blank-imports
- name: range
# Disabled rules (can be enabled if needed) # Disabled rules (can be enabled if needed)
# - name: line-length-limit # - name: line-length-limit
@ -81,6 +82,17 @@ linters:
- G104 # Duplicated errcheck checks - G104 # Duplicated errcheck checks
- G115 # integer overflow conversion int -> uint32 - G115 # integer overflow conversion int -> uint32
exclusions:
warn-unused: false
rules:
# Exclude some linters from running on tests files.
- path: _test\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
# Formatters configuration # Formatters configuration
formatters: formatters:
# Enable specific formatters # Enable specific formatters
@ -106,5 +118,8 @@ formatters:
extra-rules: true # Enable additional formatting rules extra-rules: true # Enable additional formatting rules
issues: issues:
max-same-issues: 0 # Limit the number of same issues reported to avoid spam
max-issues-per-linter: 0 max-same-issues: 50
# Limit the number of issues per linter to keep output manageable
max-issues-per-linter: 100

View File

@ -47,12 +47,28 @@ func (f *Flags) String() string {
) )
} }
func exitOnError(err error) { func main() {
fmt.Fprintf(os.Stderr, "Error: %s\n", err) var exitCode int
os.Exit(1)
// Defer exit with the final exit code
defer func() {
if exitCode != 0 {
os.Exit(exitCode)
}
}()
closer, err := run()
if closer != nil {
defer closer()
}
if err != nil {
log.Error(err)
exitCode = 1
}
} }
func main() { // run contains the main application logic and returns a closer function and any error.
func run() (func(), error) {
var flags Flags var flags Flags
// VBAN specific flags // VBAN specific flags
@ -66,7 +82,7 @@ func main() {
configDir, err := os.UserConfigDir() configDir, err := os.UserConfigDir()
if err != nil { if err != nil {
exitOnError(fmt.Errorf("failed to get user config directory: %w", err)) return nil, fmt.Errorf("failed to get user config directory: %w", err)
} }
defaultConfigPath := filepath.Join(configDir, "vbantxt", "config.toml") defaultConfigPath := filepath.Join(configDir, "vbantxt", "config.toml")
@ -98,7 +114,7 @@ func main() {
fmt.Fprintf(os.Stderr, "%s\n", ffhelp.Flags(fs, "vbantxt [flags] <vban commands>")) fmt.Fprintf(os.Stderr, "%s\n", ffhelp.Flags(fs, "vbantxt [flags] <vban commands>"))
os.Exit(0) os.Exit(0)
case err != nil: case err != nil:
exitOnError(fmt.Errorf("failed to parse flags: %w", err)) return nil, fmt.Errorf("failed to parse flags: %w", err)
} }
if flags.Version { if flags.Version {
@ -108,7 +124,7 @@ func main() {
level, err := log.ParseLevel(flags.Loglevel) level, err := log.ParseLevel(flags.Loglevel)
if err != nil { if err != nil {
exitOnError(fmt.Errorf("invalid log level: %s", flags.Loglevel)) return nil, fmt.Errorf("invalid log level %q", flags.Loglevel)
} }
log.SetLevel(level) log.SetLevel(level)
@ -116,16 +132,18 @@ func main() {
client, closer, err := createClient(&flags) client, closer, err := createClient(&flags)
if err != nil { if err != nil {
exitOnError(err) return nil, fmt.Errorf("failed to create VBAN client: %w", err)
} }
defer closer()
commands := fs.GetArgs() commands := fs.GetArgs()
if len(commands) == 0 { if len(commands) == 0 {
exitOnError(errors.New("no VBAN commands provided")) return closer, errors.New(
"no VBAN commands provided; please provide at least one command as an argument",
)
} }
sendCommands(client, commands) sendCommands(client, commands)
return closer, nil
} }
// versionFromBuild retrieves the version information from the build metadata. // versionFromBuild retrieves the version information from the build metadata.
@ -133,7 +151,7 @@ func versionFromBuild() string {
if version == "" { if version == "" {
info, ok := debug.ReadBuildInfo() info, ok := debug.ReadBuildInfo()
if !ok { if !ok {
exitOnError(errors.New("failed to read build info")) return "(unable to read build info)"
} }
version = strings.Split(info.Main.Version, "-")[0] version = strings.Split(info.Main.Version, "-")[0]
} }
@ -162,13 +180,11 @@ func createClient(flags *Flags) (*vbantxt.VbanTxt, func(), error) {
return client, closer, err return client, closer, err
} }
// sendCommands sends a list of commands to the VBAN client. // sendCommands sends the provided VBAN commands using the client and logs any errors that occur.
func sendCommands(client *vbantxt.VbanTxt, commands []string) { func sendCommands(client *vbantxt.VbanTxt, commands []string) {
for _, cmd := range commands { for _, cmd := range commands {
err := client.Send(cmd) if err := client.Send(cmd); err != nil {
if err != nil {
log.Errorf("Failed to send command '%s': %v", cmd, err) log.Errorf("Failed to send command '%s': %v", cmd, err)
continue
} }
} }
} }