From 16a3bf0d91631ac81194806b33a04a58b319a49a Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 23 Dec 2023 20:03:29 -0300 Subject: [PATCH] cli: read cli arguments and not only stdin, migrate to urfave/cli/v3 --- .gitignore | 1 + cmd/eventstore/del.go | 27 ++++++++++++++++++++++----- cmd/eventstore/helpers.go | 30 +++++++++++++++++------------- cmd/eventstore/main.go | 13 +++++++------ cmd/eventstore/put.go | 20 +++++++++++++------- cmd/eventstore/query-or-put.go | 21 +++++++++++---------- cmd/eventstore/query.go | 21 ++++++++++++++------- go.mod | 4 +--- go.sum | 8 ++------ 9 files changed, 88 insertions(+), 57 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7992fce --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +eventstore diff --git a/cmd/eventstore/del.go b/cmd/eventstore/del.go index 0af823b..016e760 100644 --- a/cmd/eventstore/del.go +++ b/cmd/eventstore/del.go @@ -1,21 +1,38 @@ package main import ( + "context" "fmt" + "os" - "github.com/urfave/cli/v2" + "github.com/nbd-wtf/go-nostr" + "github.com/urfave/cli/v3" ) var del = &cli.Command{ Name: "del", Usage: "deletes an event", Description: ``, - Action: func(c *cli.Context) error { - for line := range getStdinLinesOrBlank() { - fmt.Println(line) + Action: func(ctx context.Context, c *cli.Command) error { + hasError := false + for line := range getStdinLinesOrFirstArgument(c) { + f := nostr.Filter{IDs: []string{line}} + ch, err := db.QueryEvents(ctx, f) + if err != nil { + fmt.Fprintf(os.Stderr, "error querying for %s: %s", f, err) + hasError = true + } + for evt := range ch { + if err := db.DeleteEvent(ctx, evt); err != nil { + fmt.Fprintf(os.Stderr, "error deleting") + hasError = true + } + } } - exitIfLineProcessingError(c) + if hasError { + os.Exit(123) + } return nil }, } diff --git a/cmd/eventstore/helpers.go b/cmd/eventstore/helpers.go index 9576fdf..2dc3d4a 100644 --- a/cmd/eventstore/helpers.go +++ b/cmd/eventstore/helpers.go @@ -3,13 +3,12 @@ package main import ( "bufio" "bytes" - "context" "fmt" "io" "os" "strings" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) const ( @@ -68,6 +67,22 @@ func isPiped() bool { return stat.Mode()&os.ModeCharDevice == 0 } +func getStdinLinesOrFirstArgument(c *cli.Command) chan string { + // try the first argument + target := c.Args().First() + if target != "" { + single := make(chan string, 1) + single <- target + close(single) + return single + } + + // try the stdin + multi := make(chan string) + writeStdinLinesOrNothing(multi) + return multi +} + func getStdinLinesOrBlank() chan string { multi := make(chan string) if hasStdinLines := writeStdinLinesOrNothing(multi); !hasStdinLines { @@ -96,14 +111,3 @@ func writeStdinLinesOrNothing(ch chan string) (hasStdinLines bool) { return false } } - -func lineProcessingError(c *cli.Context, msg string, args ...any) { - c.Context = context.WithValue(c.Context, LINE_PROCESSING_ERROR, true) - fmt.Fprintf(os.Stderr, msg, args...) -} - -func exitIfLineProcessingError(c *cli.Context) { - if val := c.Context.Value(LINE_PROCESSING_ERROR); val != nil && val.(bool) { - os.Exit(123) - } -} diff --git a/cmd/eventstore/main.go b/cmd/eventstore/main.go index 1b2fc90..63aa8c4 100644 --- a/cmd/eventstore/main.go +++ b/cmd/eventstore/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "os" "strings" @@ -12,17 +13,17 @@ import ( "github.com/fiatjaf/eventstore/mysql" "github.com/fiatjaf/eventstore/postgresql" "github.com/fiatjaf/eventstore/sqlite3" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) var db eventstore.Store -var app = &cli.App{ +var app = &cli.Command{ Name: "eventstore", Usage: "a CLI for all the eventstore backends", UsageText: "eventstore -d ./data/sqlite ...", Flags: []cli.Flag{ - &cli.PathFlag{ + &cli.StringFlag{ Name: "store", Aliases: []string{"d"}, Usage: "path to the database file or directory or database connection uri", @@ -34,8 +35,8 @@ var app = &cli.App{ Usage: "store type ('sqlite', 'lmdb', 'badger', 'postgres', 'mysql', 'elasticsearch')", }, }, - Before: func(c *cli.Context) error { - path := c.Path("store") + Before: func(ctx context.Context, c *cli.Command) error { + path := c.String("store") typ := c.String("type") if typ != "" { // bypass automatic detection @@ -95,7 +96,7 @@ var app = &cli.App{ } func main() { - if err := app.Run(os.Args); err != nil { + if err := app.Run(context.Background(), os.Args); err != nil { fmt.Println(err) os.Exit(1) } diff --git a/cmd/eventstore/put.go b/cmd/eventstore/put.go index 0010704..9b396a6 100644 --- a/cmd/eventstore/put.go +++ b/cmd/eventstore/put.go @@ -1,35 +1,41 @@ package main import ( + "context" "fmt" "os" "github.com/mailru/easyjson" "github.com/nbd-wtf/go-nostr" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) var put = &cli.Command{ Name: "put", Usage: "saves an event to an eventstore", Description: ``, - Action: func(c *cli.Context) error { - for line := range getStdinLinesOrBlank() { + Action: func(ctx context.Context, c *cli.Command) error { + hasError := false + for line := range getStdinLinesOrFirstArgument(c) { var event nostr.Event if err := easyjson.Unmarshal([]byte(line), &event); err != nil { - lineProcessingError(c, "invalid event '%s' received from stdin: %s", line, err) + fmt.Fprintf(os.Stderr, "invalid event '%s' received from stdin: %s", line, err) + hasError = true continue } - if err := db.SaveEvent(c.Context, &event); err != nil { - lineProcessingError(c, "failed to save event '%s': %s", line, err) + if err := db.SaveEvent(ctx, &event); err != nil { + fmt.Fprintf(os.Stderr, "failed to save event '%s': %s", line, err) + hasError = true continue } fmt.Fprintf(os.Stderr, "saved %s", event.ID) } - exitIfLineProcessingError(c) + if hasError { + os.Exit(123) + } return nil }, } diff --git a/cmd/eventstore/query-or-put.go b/cmd/eventstore/query-or-put.go index 9d356d3..6307196 100644 --- a/cmd/eventstore/query-or-put.go +++ b/cmd/eventstore/query-or-put.go @@ -1,18 +1,19 @@ package main import ( + "context" "encoding/json" "fmt" "os" "github.com/nbd-wtf/go-nostr" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) var queryOrPut = &cli.Command{ Hidden: true, Name: "query-or-put", - Action: func(c *cli.Context) error { + Action: func(ctx context.Context, c *cli.Command) error { line := getStdin() ee := &nostr.EventEnvelope{} @@ -21,33 +22,33 @@ var queryOrPut = &cli.Command{ f := &nostr.Filter{} if json.Unmarshal([]byte(line), ee) == nil && ee.Event.ID != "" { e = &ee.Event - return doPut(c, line, e) + return doPut(ctx, line, e) } if json.Unmarshal([]byte(line), e) == nil && e.ID != "" { - return doPut(c, line, e) + return doPut(ctx, line, e) } if json.Unmarshal([]byte(line), re) == nil && len(re.Filters) > 0 { f = &re.Filters[0] - return doQuery(c, f) + return doQuery(ctx, f) } if json.Unmarshal([]byte(line), f) == nil && len(f.String()) > 2 { - return doQuery(c, f) + return doQuery(ctx, f) } return fmt.Errorf("couldn't parse input '%s'", line) }, } -func doPut(c *cli.Context, line string, e *nostr.Event) error { - if err := db.SaveEvent(c.Context, e); err != nil { +func doPut(ctx context.Context, line string, e *nostr.Event) error { + if err := db.SaveEvent(ctx, e); err != nil { return fmt.Errorf("failed to save event '%s': %s", line, err) } fmt.Fprintf(os.Stderr, "saved %s", e.ID) return nil } -func doQuery(c *cli.Context, f *nostr.Filter) error { - ch, err := db.QueryEvents(c.Context, *f) +func doQuery(ctx context.Context, f *nostr.Filter) error { + ch, err := db.QueryEvents(ctx, *f) if err != nil { return fmt.Errorf("error querying: %w", err) } diff --git a/cmd/eventstore/query.go b/cmd/eventstore/query.go index deadcca..e05696e 100644 --- a/cmd/eventstore/query.go +++ b/cmd/eventstore/query.go @@ -1,28 +1,33 @@ package main import ( + "context" "fmt" + "os" "github.com/mailru/easyjson" "github.com/nbd-wtf/go-nostr" - "github.com/urfave/cli/v2" + "github.com/urfave/cli/v3" ) var query = &cli.Command{ Name: "query", Usage: "queries an eventstore for events", Description: ``, - Action: func(c *cli.Context) error { - for line := range getStdinLinesOrBlank() { + Action: func(ctx context.Context, c *cli.Command) error { + hasError := false + for line := range getStdinLinesOrFirstArgument(c) { filter := nostr.Filter{} if err := easyjson.Unmarshal([]byte(line), &filter); err != nil { - lineProcessingError(c, "invalid filter '%s' received from stdin: %s", line, err) + fmt.Fprintf(os.Stderr, "invalid filter '%s' received from stdin: %s", line, err) + hasError = true continue } - ch, err := db.QueryEvents(c.Context, filter) + ch, err := db.QueryEvents(ctx, filter) if err != nil { - lineProcessingError(c, "error querying: %w", err) + fmt.Fprintf(os.Stderr, "error querying: %s", err) + hasError = true continue } @@ -31,7 +36,9 @@ var query = &cli.Command{ } } - exitIfLineProcessingError(c) + if hasError { + os.Exit(123) + } return nil }, } diff --git a/go.mod b/go.mod index d347cdf..960f223 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.18 github.com/nbd-wtf/go-nostr v0.27.3 github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v3 v3.0.0-alpha7 golang.org/x/exp v0.0.0-20231006140011-7918f672742d ) @@ -22,7 +22,6 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -46,7 +45,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect diff --git a/go.sum b/go.sum index bbda27b..1b1236a 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -125,8 +123,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -143,8 +139,8 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v3 v3.0.0-alpha7 h1:dj+WjtBA2StTinGwue+o2oyFFvo8aQ/AGb5MYvUqk/8= +github.com/urfave/cli/v3 v3.0.0-alpha7/go.mod h1:0kK/RUFHyh+yIKSfWxwheGndfnrvYSmYFVeKCh03ZUc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=