From c5e7cab4f3db6c0a2005c63582f27820d2fbc110 Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Tue, 7 Dec 2021 23:27:47 +0100 Subject: [PATCH] refactor: Decompose `move` func --- cmd/stbak/cmd/move.go | 162 +++++------------------------------------ pkg/operations/move.go | 115 ++++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 146 deletions(-) diff --git a/cmd/stbak/cmd/move.go b/cmd/stbak/cmd/move.go index 7e01bf9..5774f19 100644 --- a/cmd/stbak/cmd/move.go +++ b/cmd/stbak/cmd/move.go @@ -1,21 +1,9 @@ package cmd import ( - "archive/tar" - "context" - "strings" - - "github.com/pojntfx/stfs/internal/converters" - models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata" - "github.com/pojntfx/stfs/internal/encryption" - "github.com/pojntfx/stfs/internal/formatting" "github.com/pojntfx/stfs/internal/keys" - "github.com/pojntfx/stfs/internal/pax" - "github.com/pojntfx/stfs/internal/persisters" - "github.com/pojntfx/stfs/internal/signature" - "github.com/pojntfx/stfs/internal/tape" "github.com/pojntfx/stfs/pkg/config" - "github.com/pojntfx/stfs/pkg/recovery" + "github.com/pojntfx/stfs/pkg/operations" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/volatiletech/sqlboiler/v4/boil" @@ -65,145 +53,29 @@ var moveCmd = &cobra.Command{ return err } - return move( - viper.GetString(driveFlag), + return operations.Move( + config.StateConfig{ + Drive: viper.GetString(driveFlag), + Metadata: viper.GetString(metadataFlag), + }, + config.PipeConfig{ + Compression: viper.GetString(compressionFlag), + Encryption: viper.GetString(encryptionFlag), + Signature: viper.GetString(signatureFlag), + }, + config.CryptoConfig{ + Recipient: recipient, + Identity: identity, + Password: viper.GetString(passwordFlag), + }, + viper.GetInt(recordSizeFlag), - viper.GetString(metadataFlag), viper.GetString(fromFlag), viper.GetString(toFlag), - viper.GetString(encryptionFlag), - recipient, - viper.GetString(signatureFlag), - identity, ) }, } -func move( - drive string, - recordSize int, - metadata string, - src string, - dst string, - encryptionFormat string, - recipient interface{}, - signatureFormat string, - identity interface{}, -) error { - dirty := false - tw, isRegular, cleanup, err := tape.OpenTapeWriteOnly(drive, recordSize, false) - if err != nil { - return err - } - defer cleanup(&dirty) - - metadataPersister := persisters.NewMetadataPersister(metadata) - if err := metadataPersister.Open(); err != nil { - return err - } - - lastIndexedRecord, lastIndexedBlock, err := metadataPersister.GetLastIndexedRecordAndBlock(context.Background(), viper.GetInt(recordSizeFlag)) - if err != nil { - return err - } - - headersToMove := []*models.Header{} - dbhdr, err := metadataPersister.GetHeader(context.Background(), src) - if err != nil { - return err - } - headersToMove = append(headersToMove, dbhdr) - - // If the header refers to a directory, get it's children - if dbhdr.Typeflag == tar.TypeDir { - dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), src) - if err != nil { - return err - } - - headersToMove = append(headersToMove, dbhdrs...) - } - - if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { - return err - } - - // Append move headers to the tape or tar file - hdrs := []*tar.Header{} - for _, dbhdr := range headersToMove { - hdr, err := converters.DBHeaderToTarHeader(dbhdr) - if err != nil { - return err - } - - hdr.Size = 0 // Don't try to seek after the record - hdr.Name = strings.TrimSuffix(dst, "/") + strings.TrimPrefix(hdr.Name, strings.TrimSuffix(src, "/")) - hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1 - hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionUpdate - hdr.PAXRecords[pax.STFSRecordReplacesName] = dbhdr.Name - - if err := signature.SignHeader(hdr, isRegular, signatureFormat, identity); err != nil { - return err - } - - if err := encryption.EncryptHeader(hdr, encryptionFormat, recipient); err != nil { - return err - } - - if err := tw.WriteHeader(hdr); err != nil { - return err - } - - dirty = true - - if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, -1, -1, hdr)); err != nil { - return err - } - - hdrs = append(hdrs, hdr) - } - - return recovery.Index( - config.StateConfig{ - Drive: viper.GetString(driveFlag), - Metadata: viper.GetString(metadataFlag), - }, - config.PipeConfig{ - Compression: viper.GetString(compressionFlag), - Encryption: viper.GetString(encryptionFlag), - Signature: viper.GetString(signatureFlag), - }, - config.CryptoConfig{ - Recipient: recipient, - Identity: identity, - Password: viper.GetString(passwordFlag), - }, - - viper.GetInt(recordSizeFlag), - int(lastIndexedRecord), - int(lastIndexedBlock), - false, - - func(hdr *tar.Header, i int) error { - // Ignore the first header, which is the last header which we already indexed - if i == 0 { - return nil - } - - if len(hdrs) <= i-1 { - return errMissingTarHeader - } - - *hdr = *hdrs[i-1] - - return nil - }, - func(hdr *tar.Header, isRegular bool) error { - return nil // We sign above, no need to verify - }, - ) -} - func init() { moveCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record") moveCmd.PersistentFlags().StringP(fromFlag, "f", "", "Current path of the file or directory to move") diff --git a/pkg/operations/move.go b/pkg/operations/move.go index 5661674..fd96a57 100644 --- a/pkg/operations/move.go +++ b/pkg/operations/move.go @@ -1,7 +1,20 @@ package operations import ( + "archive/tar" + "context" + "strings" + + "github.com/pojntfx/stfs/internal/converters" + models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata" + "github.com/pojntfx/stfs/internal/encryption" + "github.com/pojntfx/stfs/internal/formatting" + "github.com/pojntfx/stfs/internal/pax" + "github.com/pojntfx/stfs/internal/persisters" + "github.com/pojntfx/stfs/internal/signature" + "github.com/pojntfx/stfs/internal/tape" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/recovery" ) func Move( @@ -13,5 +26,105 @@ func Move( from string, to string, ) error { - return nil + dirty := false + tw, isRegular, cleanup, err := tape.OpenTapeWriteOnly(state.Drive, recordSize, false) + if err != nil { + return err + } + defer cleanup(&dirty) + + metadataPersister := persisters.NewMetadataPersister(state.Metadata) + if err := metadataPersister.Open(); err != nil { + return err + } + + lastIndexedRecord, lastIndexedBlock, err := metadataPersister.GetLastIndexedRecordAndBlock(context.Background(), recordSize) + if err != nil { + return err + } + + headersToMove := []*models.Header{} + dbhdr, err := metadataPersister.GetHeader(context.Background(), from) + if err != nil { + return err + } + headersToMove = append(headersToMove, dbhdr) + + // If the header refers to a directory, get it's children + if dbhdr.Typeflag == tar.TypeDir { + dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), from) + if err != nil { + return err + } + + headersToMove = append(headersToMove, dbhdrs...) + } + + if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { + return err + } + + // Append move headers to the tape or tar file + hdrs := []*tar.Header{} + for _, dbhdr := range headersToMove { + hdr, err := converters.DBHeaderToTarHeader(dbhdr) + if err != nil { + return err + } + + hdr.Size = 0 // Don't try to seek after the record + hdr.Name = strings.TrimSuffix(to, "/") + strings.TrimPrefix(hdr.Name, strings.TrimSuffix(from, "/")) + hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1 + hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionUpdate + hdr.PAXRecords[pax.STFSRecordReplacesName] = dbhdr.Name + + if err := signature.SignHeader(hdr, isRegular, pipes.Signature, crypto.Identity); err != nil { + return err + } + + if err := encryption.EncryptHeader(hdr, pipes.Encryption, crypto.Recipient); err != nil { + return err + } + + if err := tw.WriteHeader(hdr); err != nil { + return err + } + + dirty = true + + if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, -1, -1, hdr)); err != nil { + return err + } + + hdrs = append(hdrs, hdr) + } + + return recovery.Index( + state, + pipes, + crypto, + + recordSize, + int(lastIndexedRecord), + int(lastIndexedBlock), + false, + + func(hdr *tar.Header, i int) error { + // Ignore the first header, which is the last header which we already indexed + if i == 0 { + return nil + } + + if len(hdrs) <= i-1 { + return config.ErrMissingTarHeader + } + + *hdr = *hdrs[i-1] + + return nil + }, + func(hdr *tar.Header, isRegular bool) error { + return nil // We sign above, no need to verify + }, + ) }