From 8d74dc24e50025b3e3988567034fab003a49f3ed Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Mon, 21 Apr 2025 15:19:40 -0500 Subject: [PATCH 1/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20ezcache=20to=20o?= =?UTF-8?q?nly=20remember=20files=20for=20five=20minutes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- convids/logic.go | 32 ++++++++++++-------------------- go.mod | 3 ++- go.sum | 8 ++++++++ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/convids/logic.go b/convids/logic.go index 6d90c2b..8d82da2 100644 --- a/convids/logic.go +++ b/convids/logic.go @@ -10,7 +10,9 @@ import ( fp "path/filepath" "regexp" "strings" + "time" + "codeberg.org/danjones000/ezcache" "gopkg.in/yaml.v3" ) @@ -82,24 +84,6 @@ func processFile(input processInput) (processed bool, processError, cbError erro return } -type fileMap map[string][]os.DirEntry - -func (fm fileMap) GetFiles(path string) []os.DirEntry { - files, ok := fm[path] - if ok { - return files - } - fm.ReadPath(path) - return fm[path] -} - -func (fm fileMap) ReadPath(path string) { - if _, ok := fm[path]; ok { - return - } - fm[path], _ = os.ReadDir(path) -} - func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err error) { err = ensureExtRe(d.Config) if err != nil { @@ -109,8 +93,13 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e cb = DryRun(os.Stdout) } count := 0 - allFiles := fileMap{} + allFiles, cacheErr := ezcache.New(os.ReadDir, 5*time.Minute) + if cacheErr != nil { + return err + } + var files []os.DirEntry + var filesErr error if err != nil { return @@ -121,7 +110,10 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e } showstart: for _, source := range s.Sources { - files = allFiles.GetFiles(source) + files, filesErr = allFiles.Get(source) + if filesErr != nil { + return filesErr + } for _, file := range files { pIn := processInput{file, source, s, d.Config.extRe, d.Config.Skip, cb} processed, processErr, cbErr := processFile(pIn) diff --git a/go.mod b/go.mod index 83e42d4..7dca67b 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ module codeberg.org/danjones000/utils -go 1.23.1 +go 1.23.7 require ( + codeberg.org/danjones000/ezcache v0.5.2 github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbletea v1.1.1 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index c826619..8361db0 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +codeberg.org/danjones000/ezcache v0.5.2 h1:msWRwbLj+HHCU3dnFbsdedCRuhyPQCOFbT9EgjwN9KM= +codeberg.org/danjones000/ezcache v0.5.2/go.mod h1:wLTvTXfXxaEDUS9dOILqQmhAlB/9lUZCC2yB5CyGBfk= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= @@ -10,6 +12,8 @@ github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqo github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= +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= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -26,11 +30,15 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +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.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 7aae44048a806913983ec707c668e6fe35bf1168 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Thu, 24 Apr 2025 14:27:19 -0500 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=9B=A0=20golangci-lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .golangci.yaml | 39 ++++++++++++++++++++ Taskfile.yml | 26 ++----------- chill/chill.go | 24 +++++++----- cli/spin/spin.go | 10 ++--- cmd/test/main.go | 20 ++++++++++ convids/logic.go | 67 ++++++++++++++++++---------------- convids/methods.go | 35 +++++++++++------- internal/cli/convids/flags.go | 5 ++- internal/cli/convids/walker.go | 3 +- 9 files changed, 144 insertions(+), 85 deletions(-) create mode 100644 .golangci.yaml create mode 100644 cmd/test/main.go diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..766ec2a --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,39 @@ +linters: + enable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - unused + - copyloopvar + - dupl + - err113 + - errname + - exptostd + - fatcontext + - funlen + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - godox + - gosec + - perfsprint + - testifylint + +linters-settings: + testifylint: + enable-all: true + disable: + - require-error + gocognit: + min-complexity: 16 + gocyclo: + min-complexity: 15 + gocritic: + enable-all: true + settings: + hugeParam: + sizeThreshold: 255 diff --git a/Taskfile.yml b/Taskfile.yml index fce2e25..6f2562e 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -14,7 +14,7 @@ tasks: desc: fmt, vet, and build deps: - fmt - - analyze + - lint - build-all fmt: @@ -24,30 +24,12 @@ tasks: cmds: - go fmt ./... - vet: - desc: Vet go code + lint: + desc: Statically analyze code sources: - '**/*.go' cmds: - - go vet ./... - critic: - desc: Critique go code - sources: - - '**/*.go' - cmds: - - gocritic check ./... - staticcheck: - desc: Static check go code - sources: - - '**/*.go' - cmds: - - staticcheck ./... - analyze: - desc: Do static analysis - deps: - - vet - - critic - - staticcheck + - golangci-lint run cmd-build: internal: true diff --git a/chill/chill.go b/chill/chill.go index e18bf39..5e90044 100644 --- a/chill/chill.go +++ b/chill/chill.go @@ -42,16 +42,20 @@ func Chill(baseCtx context.Context) context.Context { return ret(ErrChilledOut) } - go func() { - for current >= MaxTemp && err == nil { - time.Sleep(Sleep) - current, err = getCurrentTemp() - } - if err == nil { - err = ErrChilledOut - } - cancel(err) - }() + go runChill(current, cancel) return ctx } + +func runChill(current int, cancel context.CancelCauseFunc) { + var err error + for current >= MaxTemp && err == nil { + time.Sleep(Sleep) + current, err = getCurrentTemp() + } + if err == nil { + err = ErrChilledOut + } + cancel(err) + +} diff --git a/cli/spin/spin.go b/cli/spin/spin.go index d5570fa..a3697a8 100644 --- a/cli/spin/spin.go +++ b/cli/spin/spin.go @@ -20,17 +20,17 @@ type errMsg error type textMessage string -func newModel(text string) model { +func newModel(text string) *model { s := spinner.New() s.Spinner = spinner.Dot - return model{spinner: s, text: text} + return &model{spinner: s, text: text} } -func (m model) Init() tea.Cmd { +func (m *model) Init() tea.Cmd { return m.spinner.Tick } -func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case errMsg: m.err = msg @@ -47,7 +47,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } } -func (m model) View() string { +func (m *model) View() string { if m.err != nil { return m.err.Error() } diff --git a/cmd/test/main.go b/cmd/test/main.go new file mode 100644 index 0000000..a58c715 --- /dev/null +++ b/cmd/test/main.go @@ -0,0 +1,20 @@ +package main + +import ( + e "codeberg.org/danjones000/utils/cli/err" + cli "codeberg.org/danjones000/utils/internal/cli/convids" + "fmt" + "os" +) + +func main() { + flags, err := cli.ParseFlags(os.Args[0], os.Args[1:]) + e.HandleErr(err) + if *cli.Help { + flags.Usage() + } + + fmt.Println("Help", *cli.Help) + fmt.Println("Loop", *cli.Loop) + fmt.Println("DryRun", *cli.DryRun) +} diff --git a/convids/logic.go b/convids/logic.go index 8d82da2..3786295 100644 --- a/convids/logic.go +++ b/convids/logic.go @@ -84,6 +84,35 @@ func processFile(input processInput) (processed bool, processError, cbError erro return } +func processSource(allFiles ezcache.Cache[string, []os.DirEntry], d *Data, s *Show, source string, stopOnError bool, cb ShowWalker) (count int, err error) { + files, filesErr := allFiles.Get(source) + if filesErr != nil { + return 0, filesErr + } + for _, file := range files { + pIn := processInput{file, source, s, d.Config.extRe, d.Config.Skip, cb} + processed, processErr, cbErr := processFile(pIn) + if processErr != nil { + return 0, processErr + } + if cbErr != nil && stopOnError { + return 0, cbErr + } + + if errors.Is(processErr, ErrSkipped) || (!processed && processErr == nil && cbErr == nil) { + continue + } + if cbErr == nil && processed { + count++ + } + if cbErr != nil { + err = cbErr + } + return + } + return +} + func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err error) { err = ensureExtRe(d.Config) if err != nil { @@ -98,9 +127,6 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e return err } - var files []os.DirEntry - var filesErr error - if err != nil { return } @@ -108,35 +134,13 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e if len(s.Sources) == 0 { s.Sources = []string{d.Config.Source} } - showstart: for _, source := range s.Sources { - files, filesErr = allFiles.Get(source) - if filesErr != nil { - return filesErr - } - for _, file := range files { - pIn := processInput{file, source, s, d.Config.extRe, d.Config.Skip, cb} - processed, processErr, cbErr := processFile(pIn) - if !processed && processErr == nil && cbErr == nil { - continue - } - if errors.Is(processErr, ErrSkipped) { - continue - } - if processErr != nil { - return processErr - } - if cbErr != nil && stopOnError { - return cbErr - } - if cbErr == nil && processed { - count++ - } - if cbErr != nil { - err = cbErr - } - break showstart + var c int + c, err = processSource(allFiles, d, s, source, stopOnError, cb) + if err != nil { + break } + count += c } } if err == nil && count < 1 { @@ -157,8 +161,9 @@ func GetShow(ctx context.Context) ShowWalker { return GetShowWithIO(ctx, os.Stdin, os.Stdout, os.Stderr) } -func GetShowWithIO(ctx context.Context, stdin io.Reader, stdout io.Writer, stderr io.Writer) ShowWalker { +func GetShowWithIO(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) ShowWalker { return func(s *Show, path string) error { + //nolint:gosec // I don't care if this is using user input cmd := exec.CommandContext(ctx, "get-shows", s.Folder, path) cmd.Stdin = stdin cmd.Stdout = stdout diff --git a/convids/methods.go b/convids/methods.go index e10a8a9..f71981a 100644 --- a/convids/methods.go +++ b/convids/methods.go @@ -62,21 +62,28 @@ func (d *Data) AllShows(outputGroup GroupPrinter) iter.Seq[*Show] { return } for _, groupName := range d.Config.Groups { - group := (*d.Shows)[groupName] - if group == nil || len(*group) < 1 { - continue - } - if outputGroup != nil { - outputGroup(groupName, *group) - } - for sh := range group.All() { - if sh == nil { - continue - } - if !yield(sh) { - return - } + if !d.yieldGroup(yield, outputGroup, groupName) { + return } } } } + +func (d *Data) yieldGroup(yield func(*Show) bool, outputGroup GroupPrinter, groupName string) bool { + group := (*d.Shows)[groupName] + if group == nil || len(*group) < 1 { + return true + } + if outputGroup != nil { + outputGroup(groupName, *group) + } + for sh := range group.All() { + if sh == nil { + continue + } + if !yield(sh) { + return false + } + } + return true +} diff --git a/internal/cli/convids/flags.go b/internal/cli/convids/flags.go index af2b2af..88b2e3f 100644 --- a/internal/cli/convids/flags.go +++ b/internal/cli/convids/flags.go @@ -32,7 +32,10 @@ func ParseFlags(name string, args []string) (*pflag.FlagSet, error) { } if *DryRun { - flags.Set("loop", "false") + err := flags.Set("loop", "false") + if err != nil { + return nil, err + } } return flags, nil diff --git a/internal/cli/convids/walker.go b/internal/cli/convids/walker.go index a7dc85c..b90b51f 100644 --- a/internal/cli/convids/walker.go +++ b/internal/cli/convids/walker.go @@ -2,7 +2,6 @@ package convids import ( "context" - "fmt" "io" "codeberg.org/danjones000/utils/chill" @@ -18,7 +17,7 @@ func GetWalker(ctx context.Context, dryRun bool, in io.Reader, out, errOut io.Wr gs := conutils.GetShowWithIO(ctx, in, out, errOut) return func(s *conutils.Show, path string) error { ct := chill.Chill(ctx) - msg := fmt.Sprintf("Waiting for CPU to cool, for %s", path) + msg := "Waiting for CPU to cool, for " + path sp := spin.Spin(ct, msg) err := sp.Wait() if err != nil {