7 Commits

Author SHA1 Message Date
a149ce347b simplify del/reset commands by using readWriteTruncater interface.
remove the type assertions

update the tests:
the tests now check output as well as file contents separately.
2026-04-07 01:22:56 +01:00
github-actions[bot]
c2eab8576e chore: auto-update Go modules 2026-04-06 00:39:25 +00:00
f1312fb781 move versionFromBuild 2026-03-30 18:49:09 +01:00
github-actions[bot]
aa6c6a0fd3 chore: auto-update Go modules 2026-03-30 00:38:58 +00:00
b956f58f5e use CommandPath to catch completion subcommands 2026-03-29 22:55:58 +01:00
bfa3314ad3 also skip for help (if called as command and not flag) 2026-03-29 22:41:25 +01:00
92e84ca582 skip pre/post hooks for completion command 2026-03-29 22:39:24 +01:00
12 changed files with 161 additions and 158 deletions

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@
*.dll
*.so
*.dylib
bin/
# Test binary, built with `go test -c`
*.test

View File

@@ -7,43 +7,50 @@ import (
func TestRunAddCommand(t *testing.T) {
tests := []struct {
name string
existing string
args []string
expectedOutput string
name string
existing string
args []string
expectedOut string
expectedContent string
}{
{
name: "Add new patterns",
existing: "",
args: []string{"*.log", "temp/"},
expectedOutput: "Added pattern '*.log' to the exclude file.\nAdded pattern 'temp/' to the exclude file.\n",
name: "Add new patterns",
existing: "",
args: []string{"*.log", "temp/"},
expectedOut: "Added pattern '*.log' to the exclude file.\nAdded pattern 'temp/' to the exclude file.\n",
expectedContent: "*.log\ntemp/\n",
},
{
name: "Add duplicate patterns",
existing: "*.log\ntemp/\n",
args: []string{"*.log", "temp/"},
expectedOutput: "Pattern '*.log' already exists in the exclude file. Skipping.\nPattern 'temp/' already exists in the exclude file. Skipping.\n",
name: "Add duplicate patterns",
existing: "*.log\ntemp/\n",
args: []string{"*.log", "temp/"},
expectedOut: "Pattern '*.log' already exists in the exclude file. Skipping.\nPattern 'temp/' already exists in the exclude file. Skipping.\n",
expectedContent: "",
},
{
name: "Add mix of new and duplicate patterns",
existing: "*.log\n",
args: []string{"*.log", "temp/"},
expectedOutput: "Pattern '*.log' already exists in the exclude file. Skipping.\nAdded pattern 'temp/' to the exclude file.\n",
name: "Add mix of new and duplicate patterns",
existing: "*.log\n",
args: []string{"*.log", "temp/"},
expectedOut: "Pattern '*.log' already exists in the exclude file. Skipping.\nAdded pattern 'temp/' to the exclude file.\n",
expectedContent: "temp/\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
var out bytes.Buffer
f := bytes.NewBufferString(tt.existing)
err := runAddCommand(&buf, f, tt.args)
err := runAddCommand(&out, f, tt.args)
if err != nil {
t.Fatalf("runAddCommand returned an error: %v", err)
}
if buf.String() != tt.expectedOutput {
t.Errorf("Expected output:\n%s\nGot:\n%s", tt.expectedOutput, buf.String())
if out.String() != tt.expectedOut {
t.Errorf("Expected output:\n%s\nGot:\n%s", tt.expectedOut, out.String())
}
if f.String() != tt.expectedContent {
t.Errorf("Expected file content:\n%s\nGot:\n%s", tt.expectedContent, f.String())
}
})
}

View File

@@ -32,13 +32,8 @@ func init() {
}
// runDelCommand deletes the specified pattern from the exclude file and writes the updated content back
// It handles both file and in-memory buffer cases for testing
func runDelCommand(out io.Writer, f any, pattern string) error {
r, ok := f.(io.Reader)
if !ok {
return fmt.Errorf("provided file does not support Reader")
}
existingPatterns, err := readExistingPatterns(r)
func runDelCommand(out io.Writer, f readWriteTruncater, pattern string) error {
existingPatterns, err := readExistingPatterns(f)
if err != nil {
return fmt.Errorf("error reading existing patterns: %v", err)
}
@@ -55,29 +50,18 @@ func runDelCommand(out io.Writer, f any, pattern string) error {
}
}
var w io.Writer
if t, ok := f.(truncater); ok {
if err := t.Truncate(0); err != nil {
return fmt.Errorf("error truncating exclude file: %w", err)
}
if s, ok := f.(io.Seeker); ok {
if _, err := s.Seek(0, 0); err != nil {
return fmt.Errorf("error seeking to the beginning of exclude file: %w", err)
}
}
w, _ = f.(io.Writer)
} else if buf, ok := f.(interface{ Reset() }); ok {
buf.Reset()
w, _ = f.(io.Writer)
} else {
return fmt.Errorf("provided file does not support writing")
if err := f.Truncate(0); err != nil {
return fmt.Errorf("error truncating exclude file: %w", err)
}
if _, err := f.Seek(0, 0); err != nil {
return fmt.Errorf("error seeking to the beginning of exclude file: %w", err)
}
if err := writeDefaultExcludeContent(w); err != nil {
if err := writeDefaultExcludeContent(f); err != nil {
return fmt.Errorf("error writing default exclude content: %w", err)
}
for _, p := range updatedPatterns {
if _, err := fmt.Fprintln(w, p); err != nil {
if _, err := fmt.Fprintln(f, p); err != nil {
return fmt.Errorf("error writing updated patterns to exclude file: %v", err)
}
}

View File

@@ -10,40 +10,43 @@ func TestRunDelCommand(t *testing.T) {
name string
initialContent string
patternToDelete string
expectedOutput string
expectedOut string
expectedContent string
}{
{
name: "Delete existing pattern",
initialContent: defaultExcludeFileContent + "node_modules\n.DS_Store\n",
patternToDelete: "node_modules",
expectedOutput: defaultExcludeFileContent + ".DS_Store\n" + "Deleted pattern 'node_modules' from the exclude file.\n",
expectedOut: "Deleted pattern 'node_modules' from the exclude file.\n",
expectedContent: defaultExcludeFileContent + ".DS_Store\n",
},
{
name: "Delete non-existing pattern",
initialContent: defaultExcludeFileContent + "node_modules\n.DS_Store\n",
patternToDelete: "dist",
expectedOutput: "Pattern 'dist' not found in the exclude file. Nothing to delete.\n",
expectedOut: "Pattern 'dist' not found in the exclude file. Nothing to delete.\n",
expectedContent: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
buf.WriteString(tt.initialContent)
var out bytes.Buffer
var f seekBuffer
f.WriteString(tt.initialContent)
err := runDelCommand(&buf, &buf, tt.patternToDelete)
err := runDelCommand(&out, &f, tt.patternToDelete)
if err != nil {
t.Fatalf("runDelCommand returned an error: %v", err)
}
if buf.String() != tt.expectedOutput {
t.Errorf(
"Expected output and content:\n%s\nGot:\n%s",
tt.expectedOutput,
buf.String(),
)
if out.String() != tt.expectedOut {
t.Errorf("Expected output:\n%s\nGot:\n%s", tt.expectedOut, out.String())
}
if f.String() != tt.expectedContent {
t.Errorf("Expected file content:\n%s\nGot:\n%s", tt.expectedContent, f.String())
}
})
}
}

View File

@@ -27,33 +27,15 @@ func init() {
RootCmd.AddCommand(resetCmd)
}
// Truncate and seek to beginning
type truncater interface{ Truncate(size int64) error }
// resetAndWriteExcludeFile truncates and resets the file, then writes the default content
func resetAndWriteExcludeFile(out io.Writer, f any) error {
// Try to assert to io.ReadWriteSeeker for file operations
rws, ok := f.(io.ReadWriteSeeker)
if !ok {
// If not a file, try as io.Writer (for test buffers)
if w, ok := f.(io.Writer); ok {
return writeDefaultExcludeContent(w)
}
return fmt.Errorf("provided file does not support ReadWriteSeeker or Writer")
}
t, ok := f.(truncater)
if !ok {
return fmt.Errorf("provided file does not support Truncate")
}
if err := t.Truncate(0); err != nil {
func resetAndWriteExcludeFile(out io.Writer, f readWriteTruncater) error {
if err := f.Truncate(0); err != nil {
return fmt.Errorf("error truncating exclude file: %w", err)
}
if _, err := rws.Seek(0, 0); err != nil {
if _, err := f.Seek(0, 0); err != nil {
return fmt.Errorf("error seeking to the beginning of exclude file: %w", err)
}
err := writeDefaultExcludeContent(rws)
if err != nil {
if err := writeDefaultExcludeContent(f); err != nil {
return fmt.Errorf("error writing default exclude content: %w", err)
}
fmt.Fprintf(out, "Exclude file reset successfully.\n")

View File

@@ -2,27 +2,23 @@ package cmd
import (
"bytes"
"io"
"testing"
)
func TestRunResetCommand(t *testing.T) {
var buf bytes.Buffer
var out bytes.Buffer
var f seekBuffer
if err := resetAndWriteExcludeFile(&buf, &buf); err != nil {
if err := resetAndWriteExcludeFile(&out, &f); err != nil {
t.Fatalf("resetAndWriteExcludeFile failed: %v", err)
}
resetContent, err := io.ReadAll(&buf)
if err != nil {
t.Fatalf("failed to read from temp file: %v", err)
}
if string(resetContent) != defaultExcludeFileContent {
if f.String() != defaultExcludeFileContent {
t.Errorf(
"unexpected content after reset:\nGot:\n%s\nExpected:\n%s",
string(resetContent),
f.String(),
defaultExcludeFileContent,
)
}
}

View File

@@ -28,6 +28,11 @@ It allows you to add, list, and delete patterns from the exclude file easily.
This tool is particularly useful for developers who want to keep their repository clean
by excluding certain files or directories from version control.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if strings.HasPrefix(cmd.CommandPath(), "exclude completion") ||
strings.HasPrefix(cmd.CommandPath(), "exclude help") {
return nil
}
if _, err := os.Stat(".git"); os.IsNotExist(err) {
return fmt.Errorf("this command must be run in a Git repository")
}
@@ -42,6 +47,11 @@ by excluding certain files or directories from version control.`,
return nil
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
if strings.HasPrefix(cmd.CommandPath(), "exclude completion") ||
strings.HasPrefix(cmd.CommandPath(), "exclude help") {
return nil
}
if ctx, ok := ContextObjectFromContext(cmd.Context()); ok {
defer ctx.File.Close()
} else {

18
cmd/testhelpers_test.go Normal file
View File

@@ -0,0 +1,18 @@
package cmd
import "bytes"
// seekBuffer wraps bytes.Buffer to satisfy the readWriteTruncater interface,
// allowing it to be used in place of *os.File in tests.
type seekBuffer struct {
bytes.Buffer
}
func (s *seekBuffer) Seek(offset int64, whence int) (int64, error) {
return 0, nil
}
func (s *seekBuffer) Truncate(size int64) error {
s.Buffer.Reset()
return nil
}

View File

@@ -7,6 +7,13 @@ import (
"strings"
)
// readWriteTruncater is the interface satisfied by *os.File that allows
// reading, writing, seeking, and truncating — the operations needed to rewrite the exclude file.
type readWriteTruncater interface {
io.ReadWriteSeeker
Truncate(size int64) error
}
// readExistingPatterns reads the existing patterns from the exclude file, ignoring comments and empty lines
func readExistingPatterns(f io.Reader) ([]string, error) {
var patterns []string

41
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/onyx-and-iris/exclude
go 1.24.3
go 1.25.0
require (
github.com/charmbracelet/fang v1.0.0
@@ -9,38 +9,37 @@ require (
)
require (
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106193318-19329a3e8410 // indirect
github.com/charmbracelet/colorprofile v0.3.3 // indirect
github.com/charmbracelet/ultraviolet v0.0.0-20251106190538-99ea45596692 // indirect
github.com/charmbracelet/x/ansi v0.11.0 // indirect
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444 // indirect
charm.land/lipgloss/v2 v2.0.2 // indirect
github.com/charmbracelet/colorprofile v0.4.3 // indirect
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b // indirect
github.com/charmbracelet/x/ansi v0.11.6 // indirect
github.com/charmbracelet/x/exp/charmtone v0.0.0-20260330094520-2dce04b6f8a4 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/charmbracelet/x/termios v0.1.1 // indirect
github.com/charmbracelet/x/windows v0.2.2 // indirect
github.com/clipperhouse/displaywidth v0.4.1 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
github.com/mattn/go-runewidth v0.0.22 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/mango v0.1.0 // indirect
github.com/muesli/mango-cobra v1.2.0 // indirect
github.com/muesli/mango-pflag v0.1.0 // indirect
github.com/muesli/mango v0.2.0 // indirect
github.com/muesli/mango-cobra v1.3.0 // indirect
github.com/muesli/mango-pflag v0.2.0 // indirect
github.com/muesli/roff v0.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pelletier/go-toml/v2 v2.3.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
)

80
go.sum
View File

@@ -1,17 +1,17 @@
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106193318-19329a3e8410 h1:D9PbaszZYpB4nj+d6HTWr1onlmlyuGVNfL9gAi8iB3k=
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106193318-19329a3e8410/go.mod h1:1qZyvvVCenJO2M1ac2mX0yyiIZJoZmDM4DG4s0udJkU=
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
github.com/charmbracelet/colorprofile v0.3.3 h1:DjJzJtLP6/NZ8p7Cgjno0CKGr7wwRJGxWUwh2IyhfAI=
github.com/charmbracelet/colorprofile v0.3.3/go.mod h1:nB1FugsAbzq284eJcjfah2nhdSLppN2NqvfotkfRYP4=
charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs=
charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM=
github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
github.com/charmbracelet/fang v1.0.0 h1:jESBY40agJOlLYnnv9jE0mLqDGTxEk0hkOnx7YGyRlQ=
github.com/charmbracelet/fang v1.0.0/go.mod h1:P5/DNb9DddQ0Z0dbc0P3ol4/ix5Po7Ofr2KMBfAqoCo=
github.com/charmbracelet/ultraviolet v0.0.0-20251106190538-99ea45596692 h1:r/3jQZ1LjWW6ybp8HHfhrKrwHIWiJhUuY7wwYIWZulQ=
github.com/charmbracelet/ultraviolet v0.0.0-20251106190538-99ea45596692/go.mod h1:Y8B4DzWeTb0ama8l3+KyopZtkE8fZjwRQ3aEAPEXHE0=
github.com/charmbracelet/x/ansi v0.11.0 h1:uuIVK7GIplwX6UBIz8S2TF8nkr7xRlygSsBRjSJqIvA=
github.com/charmbracelet/x/ansi v0.11.0/go.mod h1:uQt8bOrq/xgXjlGcFMc8U2WYbnxyjrKhnvTQluvfCaE=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444 h1:IJDiTgVE56gkAGfq0lBEloWgkXMk4hl/bmuPoicI4R0=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0=
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b h1:ASDO9RT6SNKTQN87jO2bRfxHFJq8cgeYdFzivY2gCeM=
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b/go.mod h1:Vo8TffMf0q7Uho/n8e6XpBZvOWtd3g39yX+9P5rRutA=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20260330094520-2dce04b6f8a4 h1:pIj18ZCZO4WOVj7jwjLoUb1lC7rS/I8oC3fZWXugNaY=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20260330094520-2dce04b6f8a4/go.mod h1:nsExn0DGyX0lh9LwLHTn2Gg+hafdzfSXnC+QmEJTZFY=
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA=
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
@@ -20,12 +20,10 @@ github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
github.com/clipperhouse/displaywidth v0.4.1 h1:uVw9V8UDfnggg3K2U84VWY1YLQ/x2aKSCtkRyYozfoU=
github.com/clipperhouse/displaywidth v0.4.1/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -33,8 +31,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -43,22 +41,22 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.22 h1:76lXsPn6FyHtTY+jt2fTTvsMUCZq1k0qwRsAMuxzKAk=
github.com/mattn/go-runewidth v0.0.22/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=
github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg=
github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA=
github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg=
github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=
github.com/muesli/mango v0.2.0 h1:iNNc0c5VLQ6fsMgAqGQofByNUBH2Q2nEbD6TaI+5yyQ=
github.com/muesli/mango v0.2.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=
github.com/muesli/mango-cobra v1.3.0 h1:vQy5GvPg3ndOSpduxutqFoINhWk3vD5K2dXo5E8pqec=
github.com/muesli/mango-cobra v1.3.0/go.mod h1:Cj1ZrBu3806Qw7UjxnAUgE+7tllUBj1NCLQDwwGx19E=
github.com/muesli/mango-pflag v0.2.0 h1:QViokgKDZQCzKhYe1zH8D+UlPJzBSGoP9yx0hBG0t5k=
github.com/muesli/mango-pflag v0.2.0/go.mod h1:X9LT1p/pbGA1wjvEbtwnixujKErkP0jVmrxwrw3fL0Y=
github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
@@ -66,10 +64,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
@@ -91,12 +87,12 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

12
main.go
View File

@@ -12,12 +12,6 @@ import (
var version string // Version of the CLI, set during build time
func main() {
if err := fang.Execute(context.Background(), cmd.RootCmd, fang.WithVersion(versionFromBuild())); err != nil {
os.Exit(1)
}
}
func versionFromBuild() string {
if version != "" {
return version
@@ -29,3 +23,9 @@ func versionFromBuild() string {
}
return strings.Split(info.Main.Version, "-")[0]
}
func main() {
if err := fang.Execute(context.Background(), cmd.RootCmd, fang.WithVersion(versionFromBuild())); err != nil {
os.Exit(1)
}
}