From da35bf4bcf719c568dbf7c42d8948b4649b2253f Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 9 Oct 2024 15:08:37 -0500 Subject: [PATCH 01/11] =?UTF-8?q?=E2=9C=85=20Fix=20TestMkdirErr=20on=20Dar?= =?UTF-8?q?win?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/append_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/append_test.go b/files/append_test.go index 0976363..03f0253 100644 --- a/files/append_test.go +++ b/files/append_test.go @@ -211,7 +211,7 @@ func (s *AppendTestSuite) TestConfLoadErr() { func (s *AppendTestSuite) TestMkdirErr() { // Don't run this test as root - config.Overrides["input.path"] = "/root/my-logs-test" + config.Overrides["input.path"] = "/var/my-logs-test" defer func(path string) { config.Overrides["input.path"] = path }(s.dir) From 85671a076cf0c4c530c25424548a98d26c0b72dd Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 9 Oct 2024 15:13:34 -0500 Subject: [PATCH 02/11] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20Makefile=20so?= =?UTF-8?q?=20it=20doesn't=20re-run=20test=20and=20fmt=20when=20it=20doesn?= =?UTF-8?q?'t=20need=20to?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 35491dc..c65ce26 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,8 @@ test: ## Test application and generate coverage report $(MAKE) clean $(MAKE) $(COVEROUT) -$(COVEROUT): $(SOURCES) fmt +$(COVEROUT): $(SOURCES) + $(MAKE) fmt go test ./... -race -cover -coverprofile $@ $(COVERHTML): $(COVEROUT) @@ -33,7 +34,7 @@ $(COVERHTML): $(COVEROUT) report: $(COVERHTML) ## Generate a coverage report .PHONY: open-report -open-report: report ## Open the coverage report in the default browser +open-report: $(COVERHTML) ## Open the coverage report in the default browser xdg-open $(COVERHTML) .PHONY: build From fba5551bb3e0b5a2b7f914e3e4e1ee6c75a2155e Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 9 Oct 2024 15:14:37 -0500 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=94=A8=20Fix=20make=20open-report?= =?UTF-8?q?=20for=20Darwin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c65ce26..a3d8581 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,12 @@ OUT=my-log GOBIN=$(shell go env GOBIN) COVEROUT=cover.out COVERHTML=cover.html +OPEN=xdg-open +OS=$(shell uname -s) + +ifeq ($(OS),Darwin) +OPEN=open +endif .PHONY: help help: ## Show help for documented recipes @@ -35,7 +41,7 @@ report: $(COVERHTML) ## Generate a coverage report .PHONY: open-report open-report: $(COVERHTML) ## Open the coverage report in the default browser - xdg-open $(COVERHTML) + $(OPEN) $< .PHONY: build build: $(OUT) ## Builds the application From a8cbfd087f1b4fb39cc83f2d4dcbd08487ffdaab Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Thu, 31 Oct 2024 14:31:16 -0500 Subject: [PATCH 04/11] =?UTF-8?q?=E2=9C=A8=20Allow=20value=20prefixed=20wi?= =?UTF-8?q?th=20bang=20to=20skip=20parsing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/parse.go | 4 ++++ tools/parse_test.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tools/parse.go b/tools/parse.go index e69c476..d82517b 100644 --- a/tools/parse.go +++ b/tools/parse.go @@ -17,6 +17,10 @@ func ParseString(in string) any { return s } + if strings.HasPrefix(s, "!") { + return strings.TrimPrefix(s, "!") + } + yesno := regexp.MustCompile("^(y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$") yes := regexp.MustCompile("^(y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON)$") null := regexp.MustCompile("^(~|null|Null|NULL|none|None|NONE|nil|Nil|NIL)$") diff --git a/tools/parse_test.go b/tools/parse_test.go index 826af9b..9ff0e2e 100644 --- a/tools/parse_test.go +++ b/tools/parse_test.go @@ -38,6 +38,10 @@ func TestParse(t *testing.T) { {"on-value", "on", true}, {"no-value", "no", false}, {"off-value", "off", false}, + {"skip-parsing-num", "!42", "42"}, + {"skip-parsing-bool", "!false", "false"}, + {"skip-parsing-time", "!" + when.Format(time.RFC3339), when.Format(time.RFC3339)}, + {"skip-parsing-duration", "!15 mins", "15 mins"}, } for _, tt := range tests { From 0b2e17806664da282e91529256a44594003092bd Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Thu, 31 Oct 2024 15:09:42 -0500 Subject: [PATCH 05/11] =?UTF-8?q?=F0=9F=90=9B=20Only=20trim=20bang=20on=20?= =?UTF-8?q?out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/parse.go | 2 +- tools/parse_test.go | 8 ++++---- tools/write_buffer.go | 7 +++++++ tools/write_buffer_test.go | 8 ++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/tools/parse.go b/tools/parse.go index d82517b..fdeefd3 100644 --- a/tools/parse.go +++ b/tools/parse.go @@ -18,7 +18,7 @@ func ParseString(in string) any { } if strings.HasPrefix(s, "!") { - return strings.TrimPrefix(s, "!") + return s } yesno := regexp.MustCompile("^(y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$") diff --git a/tools/parse_test.go b/tools/parse_test.go index 9ff0e2e..72fc50d 100644 --- a/tools/parse_test.go +++ b/tools/parse_test.go @@ -38,10 +38,10 @@ func TestParse(t *testing.T) { {"on-value", "on", true}, {"no-value", "no", false}, {"off-value", "off", false}, - {"skip-parsing-num", "!42", "42"}, - {"skip-parsing-bool", "!false", "false"}, - {"skip-parsing-time", "!" + when.Format(time.RFC3339), when.Format(time.RFC3339)}, - {"skip-parsing-duration", "!15 mins", "15 mins"}, + {"skip-parsing-num", "!42", "!42"}, + {"skip-parsing-bool", "!false", "!false"}, + {"skip-parsing-time", "!" + when.Format(time.RFC3339), "!" + when.Format(time.RFC3339)}, + {"skip-parsing-duration", "!15 mins", "!15 mins"}, } for _, tt := range tests { diff --git a/tools/write_buffer.go b/tools/write_buffer.go index 8ae9386..b9626bc 100644 --- a/tools/write_buffer.go +++ b/tools/write_buffer.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strconv" + "strings" "time" ) @@ -27,6 +28,9 @@ func WriteValue(buff *bytes.Buffer, val any) (n int, err error) { return buff.Write(o) } case string: + if strings.HasPrefix(v, "!") { + return buff.WriteString(strings.TrimPrefix(v, "!")) + } return buff.WriteString(v) case int: return buff.WriteString(strconv.Itoa(v)) @@ -39,6 +43,9 @@ func WriteValue(buff *bytes.Buffer, val any) (n int, err error) { case json.RawMessage: return buff.Write(v) case []byte: + if v[0] == '!' { + return buff.Write(v[1:]) + } return buff.Write(v) case byte: err = buff.WriteByte(v) diff --git a/tools/write_buffer_test.go b/tools/write_buffer_test.go index aa7e203..8d3ab1f 100644 --- a/tools/write_buffer_test.go +++ b/tools/write_buffer_test.go @@ -33,6 +33,14 @@ func TestWriteBuffer(t *testing.T) { {"slice", []any{1, 2, "foo"}, `[1,2,"foo"]`, nil}, {"map", map[string]any{"baz": 42, "foo": "bar"}, `{"baz":42,"foo":"bar"}`, nil}, {"struct", struct{}{}, "", errors.New("Unsupported type struct {}")}, + {"skip-bang-num", "!42", "42", nil}, + {"skip-bang-bool", "!false", "false", nil}, + {"skip-bang-time", "!" + when.Format(time.RFC3339), when.Format(time.RFC3339), nil}, + {"skip-bang-duration", "!15 mins", "15 mins", nil}, + {"skip-bang-bytes-num", []byte("!42"), "42", nil}, + {"skip-bang-bytes-bool", []byte("!false"), "false", nil}, + {"skip-bang-bytes-time", []byte("!" + when.Format(time.RFC3339)), when.Format(time.RFC3339), nil}, + {"skip-bang-bytes-duration", []byte("!15 mins"), "15 mins", nil}, } for _, tt := range tests { From c0007c291dcc999fd5a6cf3b99f2119b7d95ad29 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 5 Nov 2025 15:50:00 -0600 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=93=9D=20Add=20AGENTS.md=20with=20c?= =?UTF-8?q?omprehensive=20guidelines=20for=20coding=20agents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2f54c9d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,33 @@ +# Agent Guidelines for my-log + +## Build/Test/Lint Commands +- Build: `make build` or `go build -o my-log` +- Test all: `make test` (runs fmt + test with race + coverage) +- Test single: `go test ./path/to/package -run TestName` +- Format: `make fmt` or `go fmt ./...` +- Coverage report: `make report` (generates cover.html) + +## Code Style +- **Module**: `codeberg.org/danjones000/my-log` +- **Go version**: 1.21.5 +- **Imports**: Standard library first, then external packages, then local packages. Use short aliases for common imports (e.g., `fp` for `path/filepath`, `mapst` for `mitchellh/mapstructure`) +- **Formatting**: Always run `go fmt` before commits (included in test target) +- **Types**: Use explicit types (e.g., `int64`, `float64`). Convert numbers appropriately when unmarshaling JSON +- **Naming**: PascalCase for exported, camelCase for unexported. Use descriptive names +- **Error handling**: Return wrapped errors with context. Define custom errors in models/errors.go. Use `ErrorIs` for error checking +- **Testing**: Use testify/assert. Table-driven tests with helper functions. Test both marshal/unmarshal for encoding types +- **Concurrency**: Use channels and goroutines with WaitGroups for parallel processing (see entry.go patterns) +- **Comments**: Include license header on cmd files. Document exported functions and types + +## 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` + +## Project Structure +- `cmd/`: Cobra commands (root, drop, config) +- `models/`: Core types (Entry, Log, Meta) with marshal/unmarshal implementations +- `config/`: TOML-based configuration with env overrides +- `formatters/`: Output formatters (plain, json, null) +- `files/`: File operations (append) +- `tools/`: Utilities (date parsing, string parsing, write buffers) From ad7eba9b03621dc1cc3ea592808400742b555d68 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 5 Nov 2025 16:00:55 -0600 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=9A=9A=20Refactor=20project=20struc?= =?UTF-8?q?ture=20to=20follow=20standard=20Go=20layout=20conventions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- AGENTS.md | 3 ++- Makefile | 2 +- main.go => cmd/my-log/main.go | 2 +- {cmd => internal/cmd}/config.go | 0 {cmd => internal/cmd}/drop.go | 0 {cmd => internal/cmd}/root.go | 0 7 files changed, 5 insertions(+), 4 deletions(-) rename main.go => cmd/my-log/main.go (93%) rename {cmd => internal/cmd}/config.go (100%) rename {cmd => internal/cmd}/drop.go (100%) rename {cmd => internal/cmd}/root.go (100%) diff --git a/.gitignore b/.gitignore index 3a550dc..5a806ae 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,6 @@ Temporary Items *.icloud # End of https://www.toptal.com/developers/gitignore/api/go,linux,emacs,macos -my-log +/my-log cover.html cmd/test.go diff --git a/AGENTS.md b/AGENTS.md index 2f54c9d..50a1aca 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,7 +25,8 @@ - **Examples**: `✨ Add JSON export functionality for log entries`, `🐛 Fix date parsing for RFC3339 timestamps`, `📝 Update README with configuration examples` ## Project Structure -- `cmd/`: Cobra commands (root, drop, config) +- `cmd/my-log/`: Main application entrypoint +- `internal/cmd/`: Cobra commands (root, drop, config) - `models/`: Core types (Entry, Log, Meta) with marshal/unmarshal implementations - `config/`: TOML-based configuration with env overrides - `formatters/`: Output formatters (plain, json, null) diff --git a/Makefile b/Makefile index a3d8581..aaf684f 100644 --- a/Makefile +++ b/Makefile @@ -47,4 +47,4 @@ open-report: $(COVERHTML) ## Open the coverage report in the default browser build: $(OUT) ## Builds the application $(OUT): $(SOURCES) fmt - go build -o $@ + go build -o $@ ./cmd/my-log diff --git a/main.go b/cmd/my-log/main.go similarity index 93% rename from main.go rename to cmd/my-log/main.go index a23ee3c..c7f2435 100644 --- a/main.go +++ b/cmd/my-log/main.go @@ -16,7 +16,7 @@ along with this program. If not, see . */ package main -import "codeberg.org/danjones000/my-log/cmd" +import "codeberg.org/danjones000/my-log/internal/cmd" func main() { cmd.Execute() diff --git a/cmd/config.go b/internal/cmd/config.go similarity index 100% rename from cmd/config.go rename to internal/cmd/config.go diff --git a/cmd/drop.go b/internal/cmd/drop.go similarity index 100% rename from cmd/drop.go rename to internal/cmd/drop.go diff --git a/cmd/root.go b/internal/cmd/root.go similarity index 100% rename from cmd/root.go rename to internal/cmd/root.go From f0ee52b3ef5be10d43dedc18fe0a53f9107fffe9 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 5 Nov 2025 16:21:14 -0600 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=93=9D=20Add=20Git=20Flow=20Workflo?= =?UTF-8?q?w=20guidelines=20to=20AGENTS.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 50a1aca..e2e6343 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,6 +24,18 @@ - **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 + - `hot/version` - Hotfixes for production issues, merge to **both** `stable` and `develop` + - `rel/version` - Release preparation branches +- **Version tags**: Prefix all version tags with `v` (e.g., `v1.0.2`, `v0.0.6`) +- **Never commit directly to**: `stable` branch (only merge from `rel/` or `hot/` branches) +- **Before starting work**: Ensure you're on `develop` branch or create an appropriate feature branch from it + ## Project Structure - `cmd/my-log/`: Main application entrypoint - `internal/cmd/`: Cobra commands (root, drop, config) From a0e81c108205e5f0e06ed38033609524078c6c00 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Sat, 11 Oct 2025 17:28:15 -0500 Subject: [PATCH 09/11] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Only=20compile=20reg?= =?UTF-8?q?exes=20once?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/parse.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/parse.go b/tools/parse.go index fdeefd3..618737e 100644 --- a/tools/parse.go +++ b/tools/parse.go @@ -11,6 +11,10 @@ func ParseBytes(in []byte) any { return ParseString(string(in)) } +var yesno = regexp.MustCompile("^(y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$") +var yes = regexp.MustCompile("^(y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON)$") +var null = regexp.MustCompile("^(~|null|Null|NULL|none|None|NONE|nil|Nil|NIL)$") + func ParseString(in string) any { s := strings.TrimSpace(in) if s == "" { @@ -21,9 +25,6 @@ func ParseString(in string) any { return s } - yesno := regexp.MustCompile("^(y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$") - yes := regexp.MustCompile("^(y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON)$") - null := regexp.MustCompile("^(~|null|Null|NULL|none|None|NONE|nil|Nil|NIL)$") var j json.RawMessage if null.MatchString(s) { return nil From 193eb43c9370a8d5c8479e98a522f2e950423428 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 5 Nov 2025 16:34:04 -0600 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=93=9D=20Add=20CHANGELOG=20update?= =?UTF-8?q?=20requirement=20to=20Git=20Flow=20Workflow=20guidelines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AGENTS.md b/AGENTS.md index e2e6343..c10b6e7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,6 +33,7 @@ - `hot/version` - Hotfixes for production issues, merge to **both** `stable` and `develop` - `rel/version` - Release preparation branches - **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) - **Before starting work**: Ensure you're on `develop` branch or create an appropriate feature branch from it From 27c3f54e71e5765a57de52ab28ec07dd662781f2 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Wed, 5 Nov 2025 16:35:59 -0600 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=93=9D=20Update=20CHANGELOG=20for?= =?UTF-8?q?=20v0.0.7=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90a3f53..46990e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [0.0.7] - 2025-11-05 + +- 🚚 Refactor project structure to follow standard Go layout (cmd/my-log/ and internal/cmd/) +- 📝 Add AGENTS.md with comprehensive guidelines for coding agents +- ⚡️ Performance improvement: compile regexes only once +- ✨ Add support for bang prefix to skip value parsing +- 🐛 Fix bang trimming in output +- 🔨 Fix Makefile for Darwin compatibility +- ✏️ Fix Makefile to avoid unnecessary reruns +- ✅ Fix TestMkdirErr on Darwin + ## [0.0.6] - 2024-10-07 - Update external dependency: go-dateparser