mirror of
https://github.com/iyear/tdl
synced 2025-01-08 11:57:55 +08:00
feat(migrate): support migrate data to another storage
This commit is contained in:
parent
6470e57ff5
commit
8d4ce974d6
@ -1,4 +1,4 @@
|
||||
package archive
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
44
app/migrate/migrate.go
Normal file
44
app/migrate/migrate.go
Normal file
@ -0,0 +1,44 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/fatih/color"
|
||||
"github.com/go-faster/errors"
|
||||
|
||||
"github.com/iyear/tdl/pkg/kv"
|
||||
)
|
||||
|
||||
func Migrate(ctx context.Context, to map[string]string) error {
|
||||
meta, err := kv.From(ctx).MigrateTo()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "read data")
|
||||
}
|
||||
|
||||
dest, err := kv.NewWithMap(to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create dest storage")
|
||||
}
|
||||
|
||||
var confirm bool
|
||||
if err = survey.AskOne(&survey.Confirm{
|
||||
Message: "It will overwrite the namespace data in the destination storage, continue?",
|
||||
Default: false,
|
||||
}, &confirm); err != nil {
|
||||
return errors.Wrap(err, "confirm")
|
||||
}
|
||||
if !confirm {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = dest.MigrateFrom(meta); err != nil {
|
||||
return errors.Wrap(err, "migrate from")
|
||||
}
|
||||
|
||||
color.Green("Migrate successfully.")
|
||||
for ns := range meta {
|
||||
color.Green(" - %s", ns)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package archive
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -2,11 +2,13 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/iyear/tdl/app/archive"
|
||||
"github.com/iyear/tdl/app/migrate"
|
||||
"github.com/iyear/tdl/pkg/kv"
|
||||
)
|
||||
|
||||
func NewBackup() *cobra.Command {
|
||||
@ -20,7 +22,7 @@ func NewBackup() *cobra.Command {
|
||||
dst = fmt.Sprintf("%s.backup.tdl", time.Now().Format("2006-01-02-15_04_05"))
|
||||
}
|
||||
|
||||
return archive.Backup(cmd.Context(), dst)
|
||||
return migrate.Backup(cmd.Context(), dst)
|
||||
},
|
||||
}
|
||||
|
||||
@ -36,7 +38,7 @@ func NewRecover() *cobra.Command {
|
||||
Use: "recover",
|
||||
Short: "Recover your data",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return archive.Recover(cmd.Context(), file)
|
||||
return migrate.Recover(cmd.Context(), file)
|
||||
},
|
||||
}
|
||||
|
||||
@ -50,3 +52,21 @@ func NewRecover() *cobra.Command {
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewMigrate() *cobra.Command {
|
||||
var to map[string]string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "Migrate your current data to another storage",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return migrate.Migrate(cmd.Context(), to)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringToStringVar(&to, "to", map[string]string{},
|
||||
fmt.Sprintf("destination storage options, format: type=driver,key1=value1,key2=value2. Available drivers: [%s]",
|
||||
strings.Join(kv.DriverNames(), ",")))
|
||||
|
||||
return cmd
|
||||
}
|
22
cmd/root.go
22
cmd/root.go
@ -21,8 +21,6 @@ import (
|
||||
)
|
||||
|
||||
func New() *cobra.Command {
|
||||
driverTypeKey := "type"
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "tdl",
|
||||
Short: "Telegram Downloader, but more than a downloader",
|
||||
@ -43,19 +41,7 @@ func New() *cobra.Command {
|
||||
zap.String("namespace", ns))
|
||||
}
|
||||
|
||||
// check storage flag
|
||||
storageOpts := viper.GetStringMapString(consts.FlagStorage)
|
||||
driver, err := kv.ParseDriver(storageOpts[driverTypeKey])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse driver")
|
||||
}
|
||||
delete(storageOpts, driverTypeKey)
|
||||
|
||||
opts := make(map[string]any)
|
||||
for k, v := range storageOpts {
|
||||
opts[k] = v
|
||||
}
|
||||
storage, err := kv.New(driver, opts)
|
||||
storage, err := kv.NewWithMap(viper.GetStringMapString(consts.FlagStorage))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create kv storage")
|
||||
}
|
||||
@ -72,11 +58,11 @@ func New() *cobra.Command {
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewVersion(), NewLogin(), NewDownload(), NewForward(),
|
||||
NewChat(), NewUpload(), NewBackup(), NewRecover(), NewGen())
|
||||
NewChat(), NewUpload(), NewBackup(), NewRecover(), NewMigrate(), NewGen())
|
||||
|
||||
cmd.PersistentFlags().StringToString(consts.FlagStorage, map[string]string{
|
||||
driverTypeKey: kv.DriverLegacy.String(),
|
||||
"path": consts.KVPath,
|
||||
kv.DriverTypeKey: kv.DriverLegacy.String(),
|
||||
"path": consts.KVPath,
|
||||
}, fmt.Sprintf("storage options, format: type=driver,key1=value1,key2=value2. Available drivers: [%s]",
|
||||
strings.Join(kv.DriverNames(), ",")))
|
||||
|
||||
|
17
pkg/kv/kv.go
17
pkg/kv/kv.go
@ -13,6 +13,8 @@ import (
|
||||
// ENUM(legacy, bolt, file)
|
||||
type Driver string
|
||||
|
||||
const DriverTypeKey = "type"
|
||||
|
||||
var ErrNotFound = errors.New("key not found")
|
||||
|
||||
type Meta map[string]map[string][]byte // namespace, key, value
|
||||
@ -46,6 +48,21 @@ func New(driver Driver, opts map[string]any) (Storage, error) {
|
||||
return nil, errors.Errorf("unsupported driver: %s", driver)
|
||||
}
|
||||
|
||||
func NewWithMap(o map[string]string) (Storage, error) {
|
||||
driver, err := ParseDriver(o[DriverTypeKey])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parse driver")
|
||||
}
|
||||
delete(o, DriverTypeKey)
|
||||
|
||||
opts := make(map[string]any)
|
||||
for k, v := range o {
|
||||
opts[k] = v
|
||||
}
|
||||
|
||||
return New(driver, opts)
|
||||
}
|
||||
|
||||
type ctxKey struct{}
|
||||
|
||||
func With(ctx context.Context, kv Storage) context.Context {
|
||||
|
Loading…
Reference in New Issue
Block a user