From b2f36ba7fb8a7c160f63698e3c64409b522fa618 Mon Sep 17 00:00:00 2001 From: Dominik Schulz Date: Tue, 26 May 2020 15:24:52 +0200 Subject: [PATCH] Cleanup repository root (#1390) RELEASE_NOTES=n/a Signed-off-by: Dominik Schulz --- .gitignore | 2 + app.go | 81 -------------- app_test.go | 15 --- commands.go | 54 ---------- commands_test.go | 125 ---------------------- context.go | 68 ------------ context_test.go | 28 ----- go.mod | 1 + go.sum | 2 + main.go | 172 ++++++++++++++++++++++++++++++ main_test.go | 139 ++++++++++++++++++++++++ commands_xc_test.go => xc_test.go | 0 12 files changed, 316 insertions(+), 371 deletions(-) delete mode 100644 app.go delete mode 100644 app_test.go delete mode 100644 commands.go delete mode 100644 commands_test.go delete mode 100644 context.go delete mode 100644 context_test.go rename commands_xc_test.go => xc_test.go (100%) diff --git a/.gitignore b/.gitignore index c17f2a2f33..5396ef8da2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ gopass +gopass-*-amd64 +gopass-full !pkg/gopass/ coverage.out coverage-all.* diff --git a/app.go b/app.go deleted file mode 100644 index 8479e31f67..0000000000 --- a/app.go +++ /dev/null @@ -1,81 +0,0 @@ -package main - -import ( - "context" - "os" - - ap "github.com/gopasspw/gopass/internal/action" - "github.com/gopasspw/gopass/internal/config" - "github.com/gopasspw/gopass/internal/out" - "github.com/gopasspw/gopass/internal/store/leaf" - "github.com/gopasspw/gopass/internal/termio" - - "github.com/blang/semver" - "github.com/urfave/cli/v2" -) - -func setupApp(ctx context.Context, sv semver.Version) (context.Context, *cli.App) { - // try to read config (if it exists) - cfg := config.LoadWithFallback() - - // set config values - ctx = initContext(ctx, cfg) - - // initialize action handlers - action, err := ap.New(ctx, cfg, sv) - if err != nil { - out.Error(ctx, "No gpg binary found: %s", err) - os.Exit(ap.ExitGPG) - } - - // set some action callbacks - if !cfg.Root.AutoImport { - ctx = leaf.WithImportFunc(ctx, termio.AskForKeyImport) - } - if !cfg.Root.NoConfirm { - ctx = leaf.WithRecipientFunc(ctx, action.ConfirmRecipients) - } - ctx = leaf.WithFsckFunc(ctx, termio.AskForConfirmation) - - app := cli.NewApp() - - app.Name = name - app.Version = sv.String() - app.Usage = "The standard unix password manager - rewritten in Go" - app.EnableBashCompletion = true - app.BashComplete = func(c *cli.Context) { - cli.DefaultAppComplete(c) - action.Complete(c) - } - - app.Action = func(c *cli.Context) error { - if err := action.Initialized(c); err != nil { - return err - } - - if c.Args().Present() { - return action.Show(c) - } - return action.List(c) - } - - app.Flags = []cli.Flag{ - &cli.BoolFlag{ - Name: "yes", - Usage: "Assume yes on all yes/no questions or use the default on all others", - }, - &cli.BoolFlag{ - Name: "clip", - Aliases: []string{"c"}, - Usage: "Copy the first line of the secret into the clipboard", - }, - &cli.BoolFlag{ - Name: "alsoclip", - Aliases: []string{"C"}, - Usage: "Copy the first line of the secret into the clipboard and show everything", - }, - } - - app.Commands = getCommands(ctx, action, app) - return ctx, app -} diff --git a/app_test.go b/app_test.go deleted file mode 100644 index 3cbed993a7..0000000000 --- a/app_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "context" - "testing" - - "github.com/blang/semver" - "github.com/stretchr/testify/assert" -) - -func TestSetupApp(t *testing.T) { - ctx := context.Background() - _, app := setupApp(ctx, semver.Version{}) - assert.NotNil(t, app) -} diff --git a/commands.go b/commands.go deleted file mode 100644 index 7513c0783f..0000000000 --- a/commands.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "context" - "sort" - - ap "github.com/gopasspw/gopass/internal/action" - "github.com/gopasspw/gopass/internal/action/binary" - "github.com/gopasspw/gopass/internal/action/create" - "github.com/gopasspw/gopass/internal/action/pwgen" - "github.com/gopasspw/gopass/internal/action/xc" - "github.com/urfave/cli/v2" -) - -func getCommands(ctx context.Context, action *ap.Action, app *cli.App) []*cli.Command { - cmds := []*cli.Command{ - { - Name: "completion", - Usage: "Bash and ZSH completion", - Description: "" + - "Source the output of this command with bash or zsh to get auto completion", - Subcommands: []*cli.Command{{ - Name: "bash", - Usage: "Source for auto completion in bash", - Action: action.CompletionBash, - }, { - Name: "zsh", - Usage: "Source for auto completion in zsh", - Action: func(c *cli.Context) error { - return action.CompletionZSH(c, app) - }, - }, { - Name: "fish", - Usage: "Source for auto completion in fish", - Action: func(c *cli.Context) error { - return action.CompletionFish(c, app) - }, - }, { - Name: "openbsdksh", - Usage: "Source for auto completion in OpenBSD's ksh", - Action: func(c *cli.Context) error { - return action.CompletionOpenBSDKsh(c, app) - }, - }}, - }, - } - cmds = append(cmds, action.GetCommands()...) - cmds = append(cmds, xc.GetCommands()...) - cmds = append(cmds, create.GetCommands(action, action.Store)...) - cmds = append(cmds, binary.GetCommands(action, action.Store)...) - cmds = append(cmds, pwgen.GetCommands()...) - sort.Slice(cmds, func(i, j int) bool { return cmds[i].Name < cmds[j].Name }) - return cmds -} diff --git a/commands_test.go b/commands_test.go deleted file mode 100644 index ff9c31509e..0000000000 --- a/commands_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package main - -import ( - "bytes" - "context" - "flag" - "os" - "testing" - - "github.com/atotto/clipboard" - "github.com/blang/semver" - "github.com/fatih/color" - "github.com/gopasspw/gopass/internal/action" - "github.com/gopasspw/gopass/internal/backend" - "github.com/gopasspw/gopass/internal/config" - "github.com/gopasspw/gopass/internal/gptest" - "github.com/gopasspw/gopass/internal/out" - "github.com/gopasspw/gopass/pkg/ctxutil" - "github.com/stretchr/testify/assert" - "github.com/urfave/cli/v2" -) - -// commandsWithError is a list of commands that return an error when -// invoked without arguments -var commandsWithError = map[string]struct{}{ - ".audit": {}, - ".audit.hibp": {}, - ".binary.cat": {}, - ".binary.copy": {}, - ".binary.move": {}, - ".binary.sum": {}, - ".clone": {}, - ".copy": {}, - ".create": {}, - ".delete": {}, - ".edit": {}, - ".env": {}, - ".find": {}, - ".generate": {}, - ".git.push": {}, - ".git.remote.add": {}, - ".git.remote.remove": {}, - ".grep": {}, - ".history": {}, - ".init": {}, - ".insert": {}, - ".mounts.add": {}, - ".mounts.remove": {}, - ".move": {}, - ".otp": {}, - ".recipients.add": {}, - ".recipients.remove": {}, - ".setup": {}, - ".show": {}, - ".templates.edit": {}, - ".templates.remove": {}, - ".templates.show": {}, - ".unclip": {}, -} - -func TestGetCommands(t *testing.T) { - u := gptest.NewUnitTester(t) - defer u.Remove() - - buf := &bytes.Buffer{} - out.Stdout = buf - color.NoColor = true - defer func() { - out.Stdout = os.Stdout - }() - - cfg := config.New() - cfg.Root.Path = backend.FromPath(u.StoreDir("")) - - clipboard.Unsupported = true - - ctx := context.Background() - ctx = ctxutil.WithAlwaysYes(ctx, true) - ctx = ctxutil.WithInteractive(ctx, false) - ctx = ctxutil.WithTerminal(ctx, false) - ctx = out.WithHidden(ctx, true) - ctx = backend.WithRCSBackendString(ctx, "noop") - ctx = backend.WithCryptoBackendString(ctx, "plain") - - act, err := action.New(ctx, cfg, semver.Version{}) - assert.NoError(t, err) - - app := cli.NewApp() - fs := flag.NewFlagSet("default", flag.ContinueOnError) - c := cli.NewContext(app, fs, nil) - c.Context = ctx - - commands := getCommands(ctx, act, app) - assert.Equal(t, 32, len(commands)) - - prefix := "" - testCommands(t, c, commands, prefix) -} - -func testCommands(t *testing.T, c *cli.Context, commands []*cli.Command, prefix string) { - for _, cmd := range commands { - if cmd.Name == "update" { - continue - } - if len(cmd.Subcommands) > 0 { - testCommands(t, c, cmd.Subcommands, prefix+"."+cmd.Name) - } - if cmd.Before != nil { - if err := cmd.Before(c); err != nil { - continue - } - } - if cmd.BashComplete != nil { - cmd.BashComplete(c) - } - if cmd.Action != nil { - fullName := prefix + "." + cmd.Name - if _, found := commandsWithError[fullName]; found { - assert.Error(t, cmd.Action(c), fullName) - continue - } - assert.NoError(t, cmd.Action(c), fullName) - } - } -} diff --git a/context.go b/context.go deleted file mode 100644 index 2008d36c6c..0000000000 --- a/context.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "context" - "os" - "runtime" - - "golang.org/x/crypto/ssh/terminal" - - "github.com/gopasspw/gopass/internal/backend/crypto/gpg" - "github.com/gopasspw/gopass/internal/config" - "github.com/gopasspw/gopass/internal/store/leaf" - "github.com/gopasspw/gopass/pkg/ctxutil" - - "github.com/fatih/color" -) - -func initContext(ctx context.Context, cfg *config.Config) context.Context { - // always trust - ctx = gpg.WithAlwaysTrust(ctx, true) - - // check recipients conflicts with always trust, make sure it's not enabled - // when always trust is - if gpg.IsAlwaysTrust(ctx) { - ctx = leaf.WithCheckRecipients(ctx, false) - } - - // debug flag - if gdb := os.Getenv("GOPASS_DEBUG"); gdb != "" { - ctx = ctxutil.WithDebug(ctx, true) - } - - // need this override for our integration tests - if nc := os.Getenv("GOPASS_NOCOLOR"); nc == "true" || ctxutil.IsNoColor(ctx) { - color.NoColor = true - ctx = ctxutil.WithColor(ctx, false) - } - - // support for no-color.org - if nc := os.Getenv("NO_COLOR"); nc != "" { - color.NoColor = true - ctx = ctxutil.WithColor(ctx, false) - } - - // only emit color codes when stdout is a terminal - if !terminal.IsTerminal(int(os.Stdout.Fd())) { - color.NoColor = true - ctx = ctxutil.WithColor(ctx, false) - ctx = ctxutil.WithTerminal(ctx, false) - ctx = ctxutil.WithInteractive(ctx, false) - } - - // reading from stdin? - if info, err := os.Stdin.Stat(); err == nil && info.Mode()&os.ModeCharDevice == 0 { - ctx = ctxutil.WithInteractive(ctx, false) - ctx = ctxutil.WithStdin(ctx, true) - } - - // disable colored output on windows since cmd.exe doesn't support ANSI color - // codes. Other terminal may do, but until we can figure that out better - // disable this for all terms on this platform - if runtime.GOOS == "windows" { - color.NoColor = true - ctx = ctxutil.WithColor(ctx, false) - } - - return ctx -} diff --git a/context_test.go b/context_test.go deleted file mode 100644 index 58c1a40f56..0000000000 --- a/context_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "context" - "os" - "testing" - - "github.com/gopasspw/gopass/internal/backend/crypto/gpg" - "github.com/gopasspw/gopass/internal/config" - "github.com/gopasspw/gopass/pkg/ctxutil" - "github.com/stretchr/testify/assert" -) - -func TestInitContext(t *testing.T) { - ctx := context.Background() - cfg := config.New() - - ctx = initContext(ctx, cfg) - assert.Equal(t, true, gpg.IsAlwaysTrust(ctx)) - - assert.NoError(t, os.Setenv("GOPASS_DEBUG", "true")) - ctx = initContext(ctx, cfg) - assert.Equal(t, true, ctxutil.IsDebug(ctx)) - - assert.NoError(t, os.Setenv("GOPASS_NOCOLOR", "true")) - ctx = initContext(ctx, cfg) - assert.Equal(t, false, ctxutil.IsColor(ctx)) -} diff --git a/go.mod b/go.mod index 54a00821d3..ed6e979ce4 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,7 @@ require ( github.com/schollz/closestmatch v0.0.0-20190308193919-1fbe626be92e github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 github.com/stretchr/testify v1.5.1 + github.com/urfave/cli v1.22.4 github.com/urfave/cli/v2 v2.2.0 golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 golang.org/x/net v0.0.0-20200421231249-e086a090c8fd diff --git a/go.sum b/go.sum index bd08f80595..92592e7f1a 100644 --- a/go.sum +++ b/go.sum @@ -92,6 +92,8 @@ github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086/go.mod h1:PLPIyL7i github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= +github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 h1:w8V9v0qVympSF6GjdjIyeqR7+EVhAF9CBQmkmW7Zw0w= diff --git a/main.go b/main.go index e3b13bad8b..8b2eff3a1b 100644 --- a/main.go +++ b/main.go @@ -8,18 +8,32 @@ import ( "os" "os/signal" "runtime" + "sort" "strings" "time" + "github.com/gopasspw/gopass/internal/action/binary" + "github.com/gopasspw/gopass/internal/action/create" + "github.com/gopasspw/gopass/internal/action/pwgen" + "github.com/gopasspw/gopass/internal/action/xc" _ "github.com/gopasspw/gopass/internal/backend/crypto" + "github.com/gopasspw/gopass/internal/backend/crypto/gpg" _ "github.com/gopasspw/gopass/internal/backend/rcs" _ "github.com/gopasspw/gopass/internal/backend/storage" + "github.com/gopasspw/gopass/pkg/ctxutil" "github.com/gopasspw/gopass/pkg/protect" + "golang.org/x/crypto/ssh/terminal" "github.com/blang/semver" "github.com/fatih/color" colorable "github.com/mattn/go-colorable" "github.com/urfave/cli/v2" + + ap "github.com/gopasspw/gopass/internal/action" + "github.com/gopasspw/gopass/internal/config" + "github.com/gopasspw/gopass/internal/out" + "github.com/gopasspw/gopass/internal/store/leaf" + "github.com/gopasspw/gopass/internal/termio" ) const ( @@ -69,6 +83,112 @@ func main() { } } +func setupApp(ctx context.Context, sv semver.Version) (context.Context, *cli.App) { + // try to read config (if it exists) + cfg := config.LoadWithFallback() + + // set config values + ctx = initContext(ctx, cfg) + + // initialize action handlers + action, err := ap.New(ctx, cfg, sv) + if err != nil { + out.Error(ctx, "No gpg binary found: %s", err) + os.Exit(ap.ExitGPG) + } + + // set some action callbacks + if !cfg.Root.AutoImport { + ctx = leaf.WithImportFunc(ctx, termio.AskForKeyImport) + } + if !cfg.Root.NoConfirm { + ctx = leaf.WithRecipientFunc(ctx, action.ConfirmRecipients) + } + ctx = leaf.WithFsckFunc(ctx, termio.AskForConfirmation) + + app := cli.NewApp() + + app.Name = name + app.Version = sv.String() + app.Usage = "The standard unix password manager - rewritten in Go" + app.EnableBashCompletion = true + app.BashComplete = func(c *cli.Context) { + cli.DefaultAppComplete(c) + action.Complete(c) + } + + app.Action = func(c *cli.Context) error { + if err := action.Initialized(c); err != nil { + return err + } + + if c.Args().Present() { + return action.Show(c) + } + return action.List(c) + } + + app.Flags = []cli.Flag{ + &cli.BoolFlag{ + Name: "yes", + Usage: "Assume yes on all yes/no questions or use the default on all others", + }, + &cli.BoolFlag{ + Name: "clip", + Aliases: []string{"c"}, + Usage: "Copy the first line of the secret into the clipboard", + }, + &cli.BoolFlag{ + Name: "alsoclip", + Aliases: []string{"C"}, + Usage: "Copy the first line of the secret into the clipboard and show everything", + }, + } + + app.Commands = getCommands(ctx, action, app) + return ctx, app +} + +func getCommands(ctx context.Context, action *ap.Action, app *cli.App) []*cli.Command { + cmds := []*cli.Command{ + { + Name: "completion", + Usage: "Bash and ZSH completion", + Description: "" + + "Source the output of this command with bash or zsh to get auto completion", + Subcommands: []*cli.Command{{ + Name: "bash", + Usage: "Source for auto completion in bash", + Action: action.CompletionBash, + }, { + Name: "zsh", + Usage: "Source for auto completion in zsh", + Action: func(c *cli.Context) error { + return action.CompletionZSH(c, app) + }, + }, { + Name: "fish", + Usage: "Source for auto completion in fish", + Action: func(c *cli.Context) error { + return action.CompletionFish(c, app) + }, + }, { + Name: "openbsdksh", + Usage: "Source for auto completion in OpenBSD's ksh", + Action: func(c *cli.Context) error { + return action.CompletionOpenBSDKsh(c, app) + }, + }}, + }, + } + cmds = append(cmds, action.GetCommands()...) + cmds = append(cmds, xc.GetCommands()...) + cmds = append(cmds, create.GetCommands(action, action.Store)...) + cmds = append(cmds, binary.GetCommands(action, action.Store)...) + cmds = append(cmds, pwgen.GetCommands()...) + sort.Slice(cmds, func(i, j int) bool { return cmds[i].Name < cmds[j].Name }) + return cmds +} func makeVersionPrinter(out io.Writer, sv semver.Version) func(c *cli.Context) { return func(c *cli.Context) { buildtime := "" @@ -127,3 +247,55 @@ func getVersion() semver.Version { Build: []string{"HEAD"}, } } + +func initContext(ctx context.Context, cfg *config.Config) context.Context { + // always trust + ctx = gpg.WithAlwaysTrust(ctx, true) + + // check recipients conflicts with always trust, make sure it's not enabled + // when always trust is + if gpg.IsAlwaysTrust(ctx) { + ctx = leaf.WithCheckRecipients(ctx, false) + } + + // debug flag + if gdb := os.Getenv("GOPASS_DEBUG"); gdb != "" { + ctx = ctxutil.WithDebug(ctx, true) + } + + // need this override for our integration tests + if nc := os.Getenv("GOPASS_NOCOLOR"); nc == "true" || ctxutil.IsNoColor(ctx) { + color.NoColor = true + ctx = ctxutil.WithColor(ctx, false) + } + + // support for no-color.org + if nc := os.Getenv("NO_COLOR"); nc != "" { + color.NoColor = true + ctx = ctxutil.WithColor(ctx, false) + } + + // only emit color codes when stdout is a terminal + if !terminal.IsTerminal(int(os.Stdout.Fd())) { + color.NoColor = true + ctx = ctxutil.WithColor(ctx, false) + ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithInteractive(ctx, false) + } + + // reading from stdin? + if info, err := os.Stdin.Stat(); err == nil && info.Mode()&os.ModeCharDevice == 0 { + ctx = ctxutil.WithInteractive(ctx, false) + ctx = ctxutil.WithStdin(ctx, true) + } + + // disable colored output on windows since cmd.exe doesn't support ANSI color + // codes. Other terminal may do, but until we can figure that out better + // disable this for all terms on this platform + if runtime.GOOS == "windows" { + color.NoColor = true + ctx = ctxutil.WithColor(ctx, false) + } + + return ctx +} diff --git a/main_test.go b/main_test.go index 9684467b5a..7cfdbe8f27 100644 --- a/main_test.go +++ b/main_test.go @@ -2,12 +2,25 @@ package main import ( "bytes" + "context" + "flag" "fmt" + "os" "runtime" "testing" + "github.com/atotto/clipboard" "github.com/blang/semver" + "github.com/fatih/color" + "github.com/gopasspw/gopass/internal/action" + "github.com/gopasspw/gopass/internal/backend" + "github.com/gopasspw/gopass/internal/backend/crypto/gpg" + "github.com/gopasspw/gopass/internal/config" + "github.com/gopasspw/gopass/internal/gptest" + "github.com/gopasspw/gopass/internal/out" + "github.com/gopasspw/gopass/pkg/ctxutil" "github.com/stretchr/testify/assert" + "github.com/urfave/cli/v2" ) func TestVersionPrinter(t *testing.T) { @@ -28,3 +41,129 @@ func TestGetVersion(t *testing.T) { t.Errorf("invalid version") } } + +func TestSetupApp(t *testing.T) { + ctx := context.Background() + _, app := setupApp(ctx, semver.Version{}) + assert.NotNil(t, app) +} + +// commandsWithError is a list of commands that return an error when +// invoked without arguments +var commandsWithError = map[string]struct{}{ + ".audit": {}, + ".audit.hibp": {}, + ".binary.cat": {}, + ".binary.copy": {}, + ".binary.move": {}, + ".binary.sum": {}, + ".clone": {}, + ".copy": {}, + ".create": {}, + ".delete": {}, + ".edit": {}, + ".env": {}, + ".find": {}, + ".generate": {}, + ".git.push": {}, + ".git.remote.add": {}, + ".git.remote.remove": {}, + ".grep": {}, + ".history": {}, + ".init": {}, + ".insert": {}, + ".mounts.add": {}, + ".mounts.remove": {}, + ".move": {}, + ".otp": {}, + ".recipients.add": {}, + ".recipients.remove": {}, + ".setup": {}, + ".show": {}, + ".templates.edit": {}, + ".templates.remove": {}, + ".templates.show": {}, + ".unclip": {}, +} + +func TestGetCommands(t *testing.T) { + u := gptest.NewUnitTester(t) + defer u.Remove() + + buf := &bytes.Buffer{} + out.Stdout = buf + color.NoColor = true + defer func() { + out.Stdout = os.Stdout + }() + + cfg := config.New() + cfg.Root.Path = backend.FromPath(u.StoreDir("")) + + clipboard.Unsupported = true + + ctx := context.Background() + ctx = ctxutil.WithAlwaysYes(ctx, true) + ctx = ctxutil.WithInteractive(ctx, false) + ctx = ctxutil.WithTerminal(ctx, false) + ctx = out.WithHidden(ctx, true) + ctx = backend.WithRCSBackendString(ctx, "noop") + ctx = backend.WithCryptoBackendString(ctx, "plain") + + act, err := action.New(ctx, cfg, semver.Version{}) + assert.NoError(t, err) + + app := cli.NewApp() + fs := flag.NewFlagSet("default", flag.ContinueOnError) + c := cli.NewContext(app, fs, nil) + c.Context = ctx + + commands := getCommands(ctx, act, app) + assert.Equal(t, 32, len(commands)) + + prefix := "" + testCommands(t, c, commands, prefix) +} + +func testCommands(t *testing.T, c *cli.Context, commands []*cli.Command, prefix string) { + for _, cmd := range commands { + if cmd.Name == "update" { + continue + } + if len(cmd.Subcommands) > 0 { + testCommands(t, c, cmd.Subcommands, prefix+"."+cmd.Name) + } + if cmd.Before != nil { + if err := cmd.Before(c); err != nil { + continue + } + } + if cmd.BashComplete != nil { + cmd.BashComplete(c) + } + if cmd.Action != nil { + fullName := prefix + "." + cmd.Name + if _, found := commandsWithError[fullName]; found { + assert.Error(t, cmd.Action(c), fullName) + continue + } + assert.NoError(t, cmd.Action(c), fullName) + } + } +} + +func TestInitContext(t *testing.T) { + ctx := context.Background() + cfg := config.New() + + ctx = initContext(ctx, cfg) + assert.Equal(t, true, gpg.IsAlwaysTrust(ctx)) + + assert.NoError(t, os.Setenv("GOPASS_DEBUG", "true")) + ctx = initContext(ctx, cfg) + assert.Equal(t, true, ctxutil.IsDebug(ctx)) + + assert.NoError(t, os.Setenv("GOPASS_NOCOLOR", "true")) + ctx = initContext(ctx, cfg) + assert.Equal(t, false, ctxutil.IsColor(ctx)) +} diff --git a/commands_xc_test.go b/xc_test.go similarity index 100% rename from commands_xc_test.go rename to xc_test.go