diff --git a/docs/backends/age.md b/docs/backends/age.md index 531ac53947..b8408b94b6 100644 --- a/docs/backends/age.md +++ b/docs/backends/age.md @@ -19,8 +19,6 @@ gopass recipients add github:user This will automatically create a new age keypair and initilize the new store. -Existing stores can be migrated using `gopass convert --crypto age`. - ## Features * Encryption using `age` library, can be decrypted using the `age` CLI diff --git a/docs/commands/convert.md b/docs/commands/convert.md index ee9af697b4..e69de29bb2 100644 --- a/docs/commands/convert.md +++ b/docs/commands/convert.md @@ -1,24 +0,0 @@ -# `convert` command - -The `convert` command exists to migrate stores between different backend -implementations. - -Note: This command exists to enable a possible migration path. If we agree -on a single set of backend implementations the multiple backend support -might go away and this command as well. - -## Synopsis - -``` -$ gopass convert --store=foo --move=true --storage=gitfs --crypto=age -$ gopass convert --store=bar --move=false --storage=fs --crypto=plain -``` - -## Flags - -Flag | Description ----- | ----------- -`--store` | Substore to convert. -`--move` | Remove backup after converting? (default: `false`) -`--storage` | Target storage backend. -`--crypto` | Target crypto backend. diff --git a/internal/action/commands.go b/internal/action/commands.go index b852a99066..500933f629 100644 --- a/internal/action/commands.go +++ b/internal/action/commands.go @@ -151,33 +151,6 @@ func (s *Action) GetCommands() []*cli.Command { Action: s.Config, BashComplete: s.ConfigComplete, }, - { - Name: "convert", - Usage: "Convert a store to different backends", - Description: "Convert a store to a different set of backends", - Action: s.Convert, - Before: s.IsInitialized, - Hidden: true, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "store", - Usage: "Specify which store to convert", - }, - &cli.BoolFlag{ - Name: "move", - Value: true, - Usage: "Replace store?", - }, - &cli.StringFlag{ - Name: "crypto", - Usage: fmt.Sprintf("Which crypto backend? %v", backend.CryptoRegistry.BackendNames()), - }, - &cli.StringFlag{ - Name: "storage", - Usage: fmt.Sprintf("Which storage backend? %v", backend.StorageRegistry.BackendNames()), - }, - }, - }, { Name: "copy", Aliases: []string{"cp"}, diff --git a/internal/action/convert.go b/internal/action/convert.go deleted file mode 100644 index 0fe17efebd..0000000000 --- a/internal/action/convert.go +++ /dev/null @@ -1,91 +0,0 @@ -package action - -import ( - "fmt" - - "github.com/kpitt/gopass/internal/backend" - "github.com/kpitt/gopass/internal/backend/crypto/age" - "github.com/kpitt/gopass/internal/out" - "github.com/kpitt/gopass/pkg/ctxutil" - "github.com/kpitt/gopass/pkg/termio" - "github.com/urfave/cli/v2" -) - -// Convert converts a store to a different set of backends. -func (s *Action) Convert(c *cli.Context) error { - ctx := ctxutil.WithGlobalFlags(c) - ctx = age.WithOnlyNative(ctx, true) - - store := c.String("store") - move := c.Bool("move") - - sub, err := s.Store.GetSubStore(store) - if err != nil { - return fmt.Errorf("mount %q not found: %w", store, err) - } - - oldStorage := sub.Storage().Name() - - storage, err := backend.StorageRegistry.Backend(oldStorage) - if err != nil { - return fmt.Errorf("unknown storage backend %q: %w", oldStorage, err) - } - if sv := c.String("storage"); sv != "" { - var err error - storage, err = backend.StorageRegistry.Backend(sv) - if err != nil { - return fmt.Errorf("unknown storage backend %q: %w", sv, err) - } - } - - oldCrypto := sub.Crypto().Name() - - crypto, err := backend.CryptoRegistry.Backend(oldCrypto) - if err != nil { - return fmt.Errorf("unknown crypto backend %q: %w", oldCrypto, err) - } - if sv := c.String("crypto"); sv != "" { - var err error - crypto, err = backend.CryptoRegistry.Backend(sv) - if err != nil { - return fmt.Errorf("unknown crypto backend %q: %w", sv, err) - } - } - - if oldCrypto == crypto.String() && oldStorage == storage.String() { - out.Notice(ctx, "No conversion needed") - - return nil - } - - if oldCrypto != crypto.String() { - cbe, err := backend.NewCrypto(ctx, crypto) - if err != nil { - return err - } - - if err := s.initCheckPrivateKeys(ctx, cbe); err != nil { - return err - } - out.Printf(ctx, "Crypto %q has private keys", crypto.String()) - } - - out.Noticef(ctx, "Converting %q. Crypto: %q -> %q, Storage: %q -> %q", store, oldCrypto, crypto, oldStorage, storage) - ok, err := termio.AskForBool(ctx, "Continue?", false) - if err != nil { - return err - } - if !ok { - out.Notice(ctx, "Aborted") - - return nil - } - - if err := s.Store.Convert(ctx, store, crypto, storage, move); err != nil { - return fmt.Errorf("failed to convert %q: %w", store, err) - } - - out.OKf(ctx, "Successfully converted %q", store) - - return nil -} diff --git a/internal/store/leaf/convert.go b/internal/store/leaf/convert.go deleted file mode 100644 index 3457460d5e..0000000000 --- a/internal/store/leaf/convert.go +++ /dev/null @@ -1,147 +0,0 @@ -package leaf - -import ( - "context" - "fmt" - "os" - "path/filepath" - "sort" - "strings" - "time" - - "github.com/kpitt/gopass/internal/backend" - "github.com/kpitt/gopass/internal/cui" - "github.com/kpitt/gopass/internal/queue" - "github.com/kpitt/gopass/pkg/ctxutil" - "github.com/kpitt/gopass/pkg/debug" - "github.com/kpitt/gopass/pkg/fsutil" - "github.com/kpitt/gopass/pkg/termio" -) - -// Convert will convert an existing store to a new store with possibly -// different set of crypto and storage backends. Please note that it -// will happily convert to the same set of backends if requested. -func (s *Store) Convert(ctx context.Context, cryptoBe backend.CryptoBackend, storageBe backend.StorageBackend, move bool) error { - // use a temp queue so we can flush it before removing the old store - q := queue.New(ctx) - ctx = queue.WithQueue(ctx, q) - - // remove any previous attempts - if pDir := filepath.Join(filepath.Dir(s.path), filepath.Base(s.path)+"-autoconvert"); fsutil.IsDir(pDir) { - if err := os.RemoveAll(pDir); err != nil { - return fmt.Errorf("failed to remove previous attempt %q: %w", pDir, err) - } - } - - // create temp path - tmpPath := s.path + "-autoconvert" - if err := os.MkdirAll(tmpPath, 0o700); err != nil { - return err - } - - debug.Log("create temporary store path for conversion: %s", tmpPath) - - // init new store at temp path - st, err := backend.InitStorage(ctx, storageBe, tmpPath) - if err != nil { - return err - } - - debug.Log("initialized storage %s at %s", st, tmpPath) - - crypto, err := backend.NewCrypto(ctx, cryptoBe) - if err != nil { - return err - } - - debug.Log("initialized Crypto %s", crypto) - - tmpStore := &Store{ - alias: s.alias, - path: tmpPath, - crypto: crypto, - storage: st, - } - - // init new store - key, err := cui.AskForPrivateKey(ctx, crypto, "Please select a private key") - if err != nil { - return err - } - - if err := tmpStore.Init(ctx, tmpPath, key); err != nil { - return err - } - - // copy everything from old to temp, including all revisions - entries, err := s.List(ctx, "") - if err != nil { - return err - } - - bar := termio.NewProgressBar("Converting store", int64(len(entries))) - bar.Hidden = ctxutil.IsHidden(ctx) - if !ctxutil.IsTerminal(ctx) || ctxutil.IsHidden(ctx) { - bar = nil - } - - // Avoid network operations slowing down the bulk conversion. - // We will sync with the remote later. - ctx = ctxutil.WithNoNetwork(ctx, true) - for _, e := range entries { - e = strings.TrimPrefix(e, s.alias+Sep) - debug.Log("converting %s", e) - revs, err := s.ListRevisions(ctx, e) - if err != nil { - return err - } - sort.Sort(sort.Reverse(backend.Revisions(revs))) - - for _, r := range revs { - debug.Log("converting %s@%s", e, r.Hash) - sec, err := s.GetRevision(ctx, e, r.Hash) - if err != nil { - return err - } - - msg := fmt.Sprintf("%s\n%s\nCommitted as: %s\nDate: %s\nAuthor: %s <%s>", - r.Subject, - r.Body, - r.Hash, - r.Date.Format(time.RFC3339), - r.AuthorName, - r.AuthorEmail, - ) - ctx := ctxutil.WithCommitMessage(ctx, msg) - ctx = ctxutil.WithCommitTimestamp(ctx, r.Date) - if err := tmpStore.Set(ctx, e, sec); err != nil { - return err - } - } - bar.Inc() - } - bar.Done() - - // flush queue - _ = q.Close(ctx) - - if !move { - return nil - } - - // remove any previous backups - bDir := filepath.Join(filepath.Dir(s.path), filepath.Base(s.path)+"-backup") - if fsutil.IsDir(bDir) { - if err := os.RemoveAll(bDir); err != nil { - debug.Log("failed to remove previous backup %q: %s", bDir, err) - } - } - - // rename old to backup - if err := os.Rename(s.path, bDir); err != nil { - return err - } - - // rename temp to old - return os.Rename(tmpPath, s.path) -} diff --git a/internal/store/root/convert.go b/internal/store/root/convert.go deleted file mode 100644 index 34363e7380..0000000000 --- a/internal/store/root/convert.go +++ /dev/null @@ -1,34 +0,0 @@ -package root - -import ( - "context" - "fmt" - - "github.com/kpitt/gopass/internal/backend" - "github.com/kpitt/gopass/pkg/debug" -) - -// Convert will try to convert a given mount to a different set of -// backends. -func (r *Store) Convert(ctx context.Context, name string, cryptoBe backend.CryptoBackend, storageBe backend.StorageBackend, move bool) error { - sub, err := r.GetSubStore(name) - if err != nil { - return fmt.Errorf("mount not found: %w", err) - } - - debug.Log("converting %s to crypto: %s, rcs: %s, storage: %s", name, cryptoBe, storageBe) - - if err := sub.Convert(ctx, cryptoBe, storageBe, move); err != nil { - return fmt.Errorf("failed to convert %q: %w", name, err) - } - - if name == "" { - debug.Log("success. updating root path to %s", sub.Path()) - r.cfg.Path = sub.Path() - } else { - debug.Log("success. updating path for %s to %s", name, sub.Path()) - r.cfg.Mounts[name] = sub.Path() - } - - return r.cfg.Save() -} diff --git a/main_test.go b/main_test.go index 9ac49d77d0..44adc8a5fd 100644 --- a/main_test.go +++ b/main_test.go @@ -121,7 +121,7 @@ func TestGetCommands(t *testing.T) { //nolint:paralleltest c.Context = ctx commands := getCommands(act, app) - assert.Equal(t, 39, len(commands)) + assert.Equal(t, 38, len(commands)) prefix := "" testCommands(t, c, commands, prefix)