Skip to content

Commit 592b701

Browse files
committed
Switching to urfave/cli/v3
1 parent 703bee0 commit 592b701

File tree

121 files changed

+6939
-19041
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+6939
-19041
lines changed

cmd/s2k/main.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
56
"os"
67
"path/filepath"
78
"runtime"
89
"runtime/debug"
910
"time"
1011

11-
cli "github.com/urfave/cli/v2"
12+
cli "github.com/urfave/cli/v3"
1213
"go.uber.org/zap"
1314

1415
"sync2kindle/config"
@@ -18,19 +19,21 @@ import (
1819
"sync2kindle/sync"
1920
)
2021

21-
func beforeAppRun(ctx *cli.Context) (err error) {
22-
if ctx.NArg() == 0 {
23-
return nil
22+
func beforeAppRun(ctx context.Context, cmd *cli.Command) (context.Context, error) {
23+
var err error
24+
25+
if cmd.NArg() == 0 {
26+
return ctx, nil
2427
}
25-
env := ctx.Generic(state.FlagName).(*state.LocalEnv)
28+
env := ctx.Value(state.EnvValue).(*state.LocalEnv)
2629

27-
configFile := ctx.String("config")
30+
configFile := cmd.String("config")
2831
if env.Cfg, err = config.LoadConfiguration(configFile); err != nil {
29-
return fmt.Errorf("unable to prepare configuration: %w", err)
32+
return ctx, fmt.Errorf("unable to prepare configuration: %w", err)
3033
}
31-
if ctx.Bool("debug") {
34+
if cmd.Bool("debug") {
3235
if env.Rpt, err = env.Cfg.Reporting.Prepare(); err != nil {
33-
return fmt.Errorf("unable to prepare debug reporter: %w", err)
36+
return ctx, fmt.Errorf("unable to prepare debug reporter: %w", err)
3437
}
3538
// save complete processed configuration if external configuration was provided
3639
if len(configFile) > 0 {
@@ -41,48 +44,48 @@ func beforeAppRun(ctx *cli.Context) (err error) {
4144
}
4245
}
4346
if env.Log, err = env.Cfg.Logging.Prepare(env.Rpt); err != nil {
44-
return fmt.Errorf("unable to prepare logs: %w", err)
47+
return ctx, fmt.Errorf("unable to prepare logs: %w", err)
4548
}
4649
env.RestoreStdLog = zap.RedirectStdLog(env.Log)
4750

4851
env.Log.Debug("Program started", zap.Strings("args", os.Args), zap.String("ver", misc.GetVersion()+" ("+runtime.Version()+") : "+misc.GetGitHash()))
4952
if env.Rpt != nil {
5053
env.Log.Info("Creating debug report", zap.String("location", env.Rpt.Name()))
5154
}
52-
return nil
55+
return ctx, nil
5356
}
5457

55-
func afterAppRun(ctx *cli.Context) error {
56-
env := ctx.Generic(state.FlagName).(*state.LocalEnv)
58+
func afterAppRun(ctx context.Context, cmd *cli.Command) error {
59+
env := ctx.Value(state.EnvValue).(*state.LocalEnv)
5760
if env.Log != nil {
58-
env.Log.Debug("Program ended", zap.Duration("elapsed", time.Since(env.Start)), zap.Strings("parsed args", ctx.Args().Slice()))
61+
env.Log.Debug("Program ended", zap.Duration("elapsed", time.Since(env.Start)), zap.Strings("parsed args", cmd.Args().Slice()))
5962
}
6063
return nil
6164
}
6265

63-
func beforeCmdRun(ctx *cli.Context) (err error) {
64-
env := ctx.Generic(state.FlagName).(*state.LocalEnv)
66+
func beforeCmdRun(ctx context.Context, cmd *cli.Command) (context.Context, error) {
67+
env := ctx.Value(state.EnvValue).(*state.LocalEnv)
6568

66-
configFile := ctx.String("config")
69+
configFile := cmd.String("config")
6770
if len(configFile) == 0 && env.Log != nil {
6871
env.Log.Info("Using defaults (no configuration file)")
6972
}
70-
return nil
73+
return ctx, nil
7174
}
7275

7376
func main() {
7477

7578
env := state.NewLocalEnv()
79+
ctx := context.WithValue(context.Background(), state.EnvValue, env)
7680

77-
app := &cli.App{
81+
app := &cli.Command{
7882
Name: "s2k",
7983
Usage: "synchronizing local books with supported kindle device over MTP protocol, USBMS mount or using e-mail",
8084
Version: misc.GetVersion() + " (" + runtime.Version() + ") : " + misc.GetGitHash(),
8185
HideHelpCommand: true,
8286
Before: beforeAppRun,
8387
After: afterAppRun,
8488
Flags: []cli.Flag{
85-
&cli.GenericFlag{Name: state.FlagName, Hidden: true, Value: env},
8689
&cli.StringFlag{Name: "config", Aliases: []string{"c"}, DefaultText: "", Usage: "load configuration from `FILE` (YAML)"},
8790
&cli.BoolFlag{Name: "debug", Aliases: []string{"d"}, Usage: "changes program behavior to help troubleshooting"},
8891
},
@@ -175,7 +178,7 @@ To see actual "active" configuration use dry-run mode.
175178
},
176179
}
177180

178-
err := app.Run(os.Args)
181+
err := app.Run(ctx, os.Args)
179182
if err != nil {
180183
if env.Log != nil {
181184
env.Log.Error("Command ended with error", zap.Error(err))
@@ -215,14 +218,14 @@ To see actual "active" configuration use dry-run mode.
215218
}
216219
}
217220

218-
func outputConfiguration(ctx *cli.Context) error {
221+
func outputConfiguration(ctx context.Context, cmd *cli.Command) error {
219222

220-
env := ctx.Generic(state.FlagName).(*state.LocalEnv)
221-
if ctx.Args().Len() > 1 {
222-
env.Log.Warn("Malformed command line, too many destinations", zap.Strings("ignoring", ctx.Args().Slice()[1:]))
223+
env := ctx.Value(state.EnvValue).(*state.LocalEnv)
224+
if cmd.Args().Len() > 1 {
225+
env.Log.Warn("Malformed command line, too many destinations", zap.Strings("ignoring", cmd.Args().Slice()[1:]))
223226
}
224227

225-
fname := ctx.Args().Get(0)
228+
fname := cmd.Args().Get(0)
226229

227230
var (
228231
err error
@@ -240,7 +243,7 @@ func outputConfiguration(ctx *cli.Context) error {
240243

241244
}
242245

243-
if ctx.Bool("dry-run") {
246+
if cmd.Bool("dry-run") {
244247
state = "active"
245248
data, err = config.Dump(env.Cfg)
246249
} else {

go.mod

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/go-playground/validator/v10 v10.27.0
1313
github.com/gosimple/slug v1.15.0
1414
github.com/rupor-github/gencfg v1.0.6
15-
github.com/urfave/cli/v2 v2.27.7
15+
github.com/urfave/cli/v3 v3.3.8
1616
go.uber.org/zap v1.27.0
1717
golang.org/x/sys v0.34.0
1818
golang.org/x/term v0.33.0
@@ -23,7 +23,6 @@ require (
2323

2424
require (
2525
github.com/BurntSushi/toml v1.5.0 // indirect
26-
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
2726
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
2827
github.com/go-playground/locales v0.14.1 // indirect
2928
github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -34,9 +33,6 @@ require (
3433
github.com/mattn/go-isatty v0.0.20 // indirect
3534
github.com/ncruces/go-strftime v0.1.9 // indirect
3635
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
37-
github.com/russross/blackfriday/v2 v2.1.0 // indirect
38-
github.com/stretchr/testify v1.10.0 // indirect
39-
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
4036
go.uber.org/multierr v1.11.0 // indirect
4137
golang.org/x/crypto v0.40.0 // indirect
4238
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect

go.sum

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg
22
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
33
github.com/amazon-ion/ion-go v1.5.0 h1:fxsAyFda8N9HsM2xYbQSxJ3Qi/oLn0xzLoiXWG3bseg=
44
github.com/amazon-ion/ion-go v1.5.0/go.mod h1:3ZEje8i20TiIPVZlN+KE3B2ppZ1B8d9F/KaT7Dtec+k=
5-
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
6-
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
75
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
86
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
97
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -52,16 +50,12 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
5250
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
5351
github.com/rupor-github/gencfg v1.0.6 h1:J5EkicCQoGlc2edndCKsg5DwkQh1YSj8Q3iBMgOZwOw=
5452
github.com/rupor-github/gencfg v1.0.6/go.mod h1:ghRCdE6g3BAtgbQgoolAxWbP4hKaA37FLEACIxX6Ayw=
55-
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
56-
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
5753
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
5854
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
5955
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
6056
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
61-
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
62-
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
63-
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
64-
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
57+
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
58+
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
6559
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
6660
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
6761
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=

history/run.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
package history
22

33
import (
4+
"context"
45
"fmt"
56
"os"
67
"path/filepath"
78

8-
cli "github.com/urfave/cli/v2"
9+
cli "github.com/urfave/cli/v3"
910
"go.uber.org/zap"
1011
"zombiezen.com/go/sqlite"
1112
"zombiezen.com/go/sqlite/sqlitex"
1213

1314
"sync2kindle/state"
1415
)
1516

16-
func RunList(ctx *cli.Context) error {
17-
env := ctx.Generic(state.FlagName).(*state.LocalEnv)
17+
func RunList(ctx context.Context, cmd *cli.Command) error {
18+
env := ctx.Value(state.EnvValue).(*state.LocalEnv)
1819
log := env.Log.Named(driverName)
1920

2021
entries, err := os.ReadDir(env.Cfg.HistoryPath)

state/env.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ func NewLocalEnv() *LocalEnv {
2323
return &LocalEnv{Start: time.Now()}
2424
}
2525

26-
// In "github.com/urfave/cli" the only way I found to share state between "app" and "command" without global variables
27-
// is to use hidden GenericFlag. To implement the mechanics we need following code...
26+
type LocalEnvKeyType string
27+
2828
const (
29-
FlagName = "$-localenv-$"
29+
EnvValue LocalEnvKeyType = "$-localenv-$"
3030
)
3131

3232
// Set implements cli's flag interface

sync/run.go

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package sync
22

33
import (
4+
"context"
45
"errors"
56
"fmt"
67
"os"
78
"path/filepath"
89
"strings"
910
"time"
1011

11-
cli "github.com/urfave/cli/v2"
12+
cli "github.com/urfave/cli/v3"
1213
"go.uber.org/zap"
1314

1415
"sync2kindle/common"
@@ -21,20 +22,20 @@ import (
2122
"sync2kindle/usbms"
2223
)
2324

24-
func RunUSB(ctx *cli.Context) error {
25-
return Sync(ctx, common.ProtocolUSB)
25+
func RunUSB(ctx context.Context, cmd *cli.Command) error {
26+
return sync(ctx, cmd, common.ProtocolUSB)
2627
}
2728

28-
func RunMTP(ctx *cli.Context) error {
29-
return Sync(ctx, common.ProtocolMTP)
29+
func RunMTP(ctx context.Context, cmd *cli.Command) error {
30+
return sync(ctx, cmd, common.ProtocolMTP)
3031
}
3132

32-
func RunMail(ctx *cli.Context) error {
33-
return Sync(ctx, common.ProtocolMail)
33+
func RunMail(ctx context.Context, cmd *cli.Command) error {
34+
return sync(ctx, cmd, common.ProtocolMail)
3435
}
3536

36-
func Sync(ctx *cli.Context, protocol common.SupportedProtocols) error {
37-
env := ctx.Generic(state.FlagName).(*state.LocalEnv)
37+
func sync(ctx context.Context, cmd *cli.Command, protocol common.SupportedProtocols) error {
38+
env := ctx.Value(state.EnvValue).(*state.LocalEnv)
3839
log := env.Log.Named("sync")
3940

4041
if protocol == common.ProtocolMail {
@@ -92,7 +93,7 @@ func Sync(ctx *cli.Context, protocol common.SupportedProtocols) error {
9293

9394
// Target: device
9495

95-
dev, err := connectDevice(ctx, protocol, env)
96+
dev, err := connectDevice(cmd, protocol, env)
9697
if err != nil {
9798
return fmt.Errorf("unable to connect to device: %w", err)
9899
}
@@ -131,7 +132,7 @@ func Sync(ctx *cli.Context, protocol common.SupportedProtocols) error {
131132

132133
// See if anything needs to be done
133134

134-
actions, localBooks, err := PrepareActions(src, dev, hst, env.Cfg, ctx.Bool("ignore-device-removals"), protocol == common.ProtocolMail, log)
135+
actions, localBooks, err := PrepareActions(src, dev, hst, env.Cfg, cmd.Bool("ignore-device-removals"), protocol == common.ProtocolMail, log)
135136
if err != nil {
136137
return fmt.Errorf("unable to prepare sync actions: %w", err)
137138
}
@@ -141,7 +142,7 @@ func Sync(ctx *cli.Context, protocol common.SupportedProtocols) error {
141142

142143
// do the work
143144

144-
dryRun := ctx.Bool("dry-run")
145+
dryRun := cmd.Bool("dry-run")
145146
for _, action := range actions {
146147
if err := action(dryRun, log); err != nil {
147148
return fmt.Errorf("action failed: %w", err)
@@ -159,18 +160,18 @@ func Sync(ctx *cli.Context, protocol common.SupportedProtocols) error {
159160
return nil
160161
}
161162

162-
func connectDevice(ctx *cli.Context, protocol common.SupportedProtocols, env *state.LocalEnv) (driver, error) {
163+
func connectDevice(cmd *cli.Command, protocol common.SupportedProtocols, env *state.LocalEnv) (driver, error) {
163164
switch protocol {
164165
case common.ProtocolUSB:
165166
return usbms.Connect(
166167
strings.Join([]string{env.Cfg.TargetPath, common.ThumbnailFolder}, string(filepath.ListSeparator)),
167-
env.Cfg.DeviceSerial, ctx.Bool("unmount") && !ctx.Bool("dry-run"), env.Log.Named("sync"))
168+
env.Cfg.DeviceSerial, cmd.Bool("unmount") && !cmd.Bool("dry-run"), env.Log.Named("sync"))
168169
case common.ProtocolMTP:
169170
return mtp.Connect(
170171
strings.Join([]string{env.Cfg.TargetPath, common.ThumbnailFolder}, string(filepath.ListSeparator)),
171-
env.Cfg.DeviceSerial, ctx.Bool("debug"), env.Log.Named("sync"))
172+
env.Cfg.DeviceSerial, cmd.Bool("debug"), env.Log.Named("sync"))
172173
case common.ProtocolMail:
173-
debug := ctx.Bool("debug")
174+
debug := cmd.Bool("debug")
174175
if debug {
175176
mailDir, err := os.MkdirTemp("", "s2k-m-")
176177
if err != nil {

vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)