diff --git a/.gitignore b/.gitignore deleted file mode 100644 index c525b60..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -.task/ diff --git a/.golangci.yaml b/.golangci.yaml deleted file mode 100644 index 3f33683..0000000 --- a/.golangci.yaml +++ /dev/null @@ -1,39 +0,0 @@ -version: "2" - -linters: - enable: - - errcheck - - govet - - ineffassign - - staticcheck - - unused - - copyloopvar - - dupl - - err113 - - errname - - exptostd - - fatcontext - - funlen - - gocognit - - goconst - - gocritic - - gocyclo - - godot - - godox - - gosec - - perfsprint - - testifylint - 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/AGENTS.md b/AGENTS.md deleted file mode 100644 index 33ff925..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,45 +0,0 @@ -# Agent Guidelines for waiterr - -This document outlines the conventions and commands for agents operating within the `waiterr` Go project. - -## Build/Lint/Test Commands - -- **Lint:** `task lint` -- **Test All:** `task test` -- **Test Single File:** `go test -run ` (e.g., `go test -run TestNewHappy ./ezcache_test.go`) -- **Format:** `task fmt` - -## Code Style Guidelines - -- **Module**: `codeberg.org/danjones000/waiterr` -- **Go version**: 1.24.9 -- **Imports:** Group standard library imports separately from third-party imports. -- **Formatting:** Adhere to `go fmt` standards. -- **Naming Conventions:** - - Variables: `camelCase` - - Functions/Methods: `CamelCase` (exported), `camelCase` (unexported) - - Packages: `lowercase` -- **Error Handling:** Return errors explicitly. Check errors immediately after a function call that returns an error. -- **Linter Rules:** Refer to `.golangci.yaml` for detailed linting rules. -- **Testing**: - - Use `github.com/nalgeon/be` - - Tests should be in a separate package, such as waiterr_test - -## Git Commit Guidelines -- **Format**: Prepend commit messages with a gitmoji emoji (see https://gitmoji.dev) -- **Style**: Write detailed commit messages that explain what changed and why -- **Examples**: `✨ Add JSON export functionality for log entries`, `🐛 Fix date parsing for RFC3339 timestamps`, `📝 Update README with configuration examples` - -## Git Flow Workflow -- **Main branches**: `stable` (production-ready), `develop` (integration branch) -- **Development**: Always commit new features/fixes to `develop` branch or appropriate feature branches -- **Branch prefixes**: - - `feat/feature-name` - New features, merge to `develop` when complete - - `bug/bug-name` - Bug fixes (non-urgent), merge to `develop` when complete - - `rel/version` - Release preparation branches, merge to `stable` and then **also** merge `stable` back to `develop` - - `hot/version` - Hotfixes for production issues follow same merge rules as releases -- **Version tags**: Prefix all version tags with `v` (e.g., `v1.0.2`, `v0.0.6`) -- **Releases**: Update CHANGELOG.md with a summary of changes for each new version -- **Never commit directly to** `stable` branch (only merge from `rel/` or `hot/` branches) -- After merging to `stable`, always merge it back to `develop` -- **Before starting work**: Ensure you're on `develop` branch or create an appropriate feature branch from it diff --git a/Taskfile.yml b/Taskfile.yml deleted file mode 100644 index 049fc9a..0000000 --- a/Taskfile.yml +++ /dev/null @@ -1,55 +0,0 @@ -version: '3' - -tasks: - default: - cmds: - - task: fmt - - task: test - - task: lint - - fmt: - desc: Format go code - sources: - - '**/*.go' - cmds: - - go fmt ./... - - go mod tidy - - lint: - desc: Do static analysis - sources: - - '**/*.go' - cmds: - - golangci-lint run - - test: - desc: Run unit tests - deps: [fmt] - sources: - - '**/*.go' - generates: - - build/cover.out - cmds: - - go test -race -cover -coverprofile build/cover.out ./... - - coverage-report: - desc: Build coverage report - deps: [test] - sources: - - build/cover.out - generates: - - build/cover.html - cmds: - - go tool cover -html=build/cover.out -o build/cover.html - - serve-report: - desc: Serve the coverage report - deps: [coverage-report] - cmds: - - ip addr list | grep inet - - python3 -m http.server -d build 3434 - - serve-docs: - desc: Serve the current docs - cmds: - - godoc -http=0.0.0.0:3434 -play diff --git a/go.mod b/go.mod deleted file mode 100644 index 6d6bf2f..0000000 --- a/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module codeberg.org/danjones000/waiterr - -go 1.24.9 - -require github.com/nalgeon/be v0.3.0 diff --git a/go.sum b/go.sum deleted file mode 100644 index bd32e32..0000000 --- a/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/nalgeon/be v0.3.0 h1:QsPANqEtcOD5qT2S3KAtIkDBBn8SXUf/Lb5Bi/z4UqM= -github.com/nalgeon/be v0.3.0/go.mod h1:PMwMuBLopwKJkSHnr2qHyLcZYUTqNejN7A8RAqNWO3E= diff --git a/waiterr.go b/waiterr.go deleted file mode 100644 index 3da73bf..0000000 --- a/waiterr.go +++ /dev/null @@ -1,58 +0,0 @@ -package waiterr - -import ( - "errors" - "sync" -) - -// WaitErr wraps a sync.WaitGroup with error handling. -type WaitErr struct { - wg sync.WaitGroup - errs []error - mut sync.RWMutex -} - -// Go runs f in its own goroutine. When f returns, its error is stored, and returned -// with we.Wait() -func (we *WaitErr) Go(f func() error) { - wrap := func() { - err := f() - we.mut.Lock() - defer we.mut.Unlock() - we.errs = append(we.errs, err) - } - we.wg.Go(wrap) -} - -// WaitForError waits for the first error to be returned by one of our go routines, and immediately returns -// with that error. If all functions return successfully, a nil is returned. -func (we *WaitErr) WaitForError() error { - // Implement this - // If we already have an error, return it immediately without waiting - // If no error has yet been returned, wait for the very first error and return it - return nil -} - -// Wait for all current goroutines to finish. Return an error that combines all errors returned -// in the group so far (if any). -func (we *WaitErr) Wait() error { - we.wg.Wait() - we.mut.RLock() - defer we.mut.RUnlock() - return errors.Join(we.errs...) -} - -// Unwrap returns all non-nil errors returned by our functions. -// If we.errs is empty, or all errors are nil, just return nil. -func (we *WaitErr) Unwrap() []error { - errs := make([]error, 0, len(we.errs)) - for _, e := range we.errs { - if e != nil { - errs = append(errs, e) - } - } - if len(errs) == 0 { - return nil - } - return errs -} diff --git a/waiterr_test.go b/waiterr_test.go deleted file mode 100644 index 293f7dc..0000000 --- a/waiterr_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package waiterr_test - -import ( - "errors" - "testing" - - "github.com/nalgeon/be" - - "codeberg.org/danjones000/waiterr" -) - -func TestGo(t *testing.T) { - we := new(waiterr.WaitErr) - err := errors.New("uh-oh") - var run bool - we.Go(func() error { - run = true - return err - }) - - be.Err(t, we.Wait(), err) - be.True(t, run) -} - -func TestWait(t *testing.T) { - we := new(waiterr.WaitErr) - er1 := errors.New("uh-oh") - er2 := errors.New("oops") - we.Go(func() error { return er1 }) - we.Go(func() error { return nil }) - we.Go(func() error { return er2 }) - - err := we.Wait() - be.Err(t, err, er1, er2) - if ers, ok := err.(interface{ Unwrap() []error }); ok { - all := ers.Unwrap() - be.Equal(t, len(all), 2) - be.True(t, all[0] == er1 || all[0] == er2) - be.True(t, all[1] == er2 || all[1] == er1) - } else { - t.Fatal("Returned error should have Unwrap method") - } -} - -func TestWaitForError(t *testing.T) { - we := new(waiterr.WaitErr) - er1 := errors.New("uh-oh") - er2 := errors.New("oops") - we.Go(func() error { return nil }) - we.Go(func() error { return er1 }) - we.Go(func() error { return er2 }) - - err := we.WaitForError() - // Due to how goroutines run, it is possible that either of those return first. This is an acceptable limitation - be.True(t, err == er1 || err == er2) -} - -func TestWaitForErrorNoErr(t *testing.T) { - we := new(waiterr.WaitErr) - we.Go(func() error { return nil }) - we.Go(func() error { return nil }) - we.Go(func() error { return nil }) - - err := we.WaitForError() - be.Err(t, err, nil) -}