Skip to content

Commit

Permalink
Support stdout / stdin for backup and restore
Browse files Browse the repository at this point in the history
This adds support for passing a single dash character as the filename
to the backup command, resulting in it using stdin.  It also changes
the restore command to default to reading from stdin if no filename is
given.

Fixes: #284
  • Loading branch information
bison committed Aug 17, 2023
1 parent e4815f1 commit 8a75805
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 12 deletions.
26 changes: 20 additions & 6 deletions internal/cmd/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,30 @@ var backupCmd = &cobra.Command{
RunE: backupCmdFunc,
}

func backupCmdFunc(cmd *cobra.Command, args []string) error {
filename := args[0]
func createBackupFile(filename string) (*os.File, error) {
if filename == "-" {
log.Trace().Str("filename", "- (stdout)").Send()
return os.Stdout, nil
}

log.Trace().Str("filename", filename).Send()

if _, err := os.Stat(filename); err == nil {
return fmt.Errorf("backup file already exists: %s", filename)
return nil, fmt.Errorf("backup file already exists: %s", filename)
}

f, err := os.Create(filename)
if err != nil {
return fmt.Errorf("unable to create backup file: %w", err)
return nil, fmt.Errorf("unable to create backup file: %w", err)
}

return f, nil
}

func backupCmdFunc(cmd *cobra.Command, args []string) error {
f, err := createBackupFile(args[0])
if err != nil {
return err
}

client, err := client.NewClient(cmd)
Expand Down Expand Up @@ -116,8 +128,10 @@ func backupCmdFunc(cmd *cobra.Command, args []string) error {
return fmt.Errorf("error closing backup encoder: %w", err)
}

if err := f.Sync(); err != nil {
return fmt.Errorf("error syncing backup file: %w", err)
if f != os.Stdout {
if err := f.Sync(); err != nil {
return fmt.Errorf("error syncing backup file: %w", err)
}
}

if err := f.Close(); err != nil {
Expand Down
30 changes: 24 additions & 6 deletions internal/cmd/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,49 @@ func registerRestoreCmd(rootCmd *cobra.Command) {
var restoreCmd = &cobra.Command{
Use: "restore <filename>",
Short: "Restore a permission system from a file",
Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
RunE: restoreCmdFunc,
}

func restoreCmdFunc(cmd *cobra.Command, args []string) error {
filename := args[0]
func openRestoreFile(filename string) (*os.File, int64, error) {
if filename == "" {
log.Trace().Str("filename", "(stdin)").Send()
return os.Stdin, -1, nil
}

log.Trace().Str("filename", filename).Send()

stats, err := os.Stat(filename)
if err != nil {
return fmt.Errorf("unable to stat restore file: %w", err)
return nil, 0, fmt.Errorf("unable to stat restore file: %w", err)
}

f, err := os.Open(filename)
if err != nil {
return fmt.Errorf("unable to open restore file: %w", err)
return nil, 0, fmt.Errorf("unable to open restore file: %w", err)
}

return f, stats.Size(), nil
}

func restoreCmdFunc(cmd *cobra.Command, args []string) error {
filename := "" // Default to stdin.

if len(args) > 0 {
filename = args[0]
}

f, fSize, err := openRestoreFile(filename)
if err != nil {
return err
}

printZTOnly := cobrautil.MustGetBool(cmd, "print-zedtoken-only")

var hasProgressbar bool
var restoreReader io.Reader = f
if isatty.IsTerminal(os.Stderr.Fd()) && !printZTOnly {
bar := progressbar.DefaultBytes(stats.Size(), "restoring")
bar := progressbar.DefaultBytes(fSize, "restoring")
restoreReader = io.TeeReader(f, bar)
hasProgressbar = true
}
Expand Down

0 comments on commit 8a75805

Please sign in to comment.