From 8924b9de91cc2938395519309101def70d9d18db Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Tue, 23 Nov 2021 12:17:24 +0100 Subject: [PATCH] feat: Add support for deleting directories --- cmd/stbak/cmd/remove.go | 49 +++++++++++++++++++++++++++----------- pkg/persisters/metadata.go | 27 +++++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/cmd/stbak/cmd/remove.go b/cmd/stbak/cmd/remove.go index 915fde9..8a144d7 100644 --- a/cmd/stbak/cmd/remove.go +++ b/cmd/stbak/cmd/remove.go @@ -9,6 +9,7 @@ import ( "github.com/pojntfx/stfs/pkg/controllers" "github.com/pojntfx/stfs/pkg/converters" "github.com/pojntfx/stfs/pkg/counters" + models "github.com/pojntfx/stfs/pkg/db/sqlite/models/metadata" "github.com/pojntfx/stfs/pkg/formatting" "github.com/pojntfx/stfs/pkg/pax" "github.com/pojntfx/stfs/pkg/persisters" @@ -100,32 +101,52 @@ var removeCmd = &cobra.Command{ return err } - dbhdr, err := metadataPersister.DeleteHeader(context.Background(), viper.GetString(nameFlag), false) + headersToDelete := []*models.Header{} + dbhdr, err := metadataPersister.GetHeader(context.Background(), viper.GetString(nameFlag)) if err != nil { return err } + headersToDelete = append(headersToDelete, dbhdr) - hdr, err := converters.DBHeaderToTarHeader(dbhdr) - if err != nil { - return err + // If the header refers to a directory, get it's children + if dbhdr.Typeflag == tar.TypeDir { + dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), viper.GetString(nameFlag)) + if err != nil { + return err + } + + headersToDelete = append(headersToDelete, dbhdrs...) } - hdr.Size = 0 // Don't try to seek after the record - hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1 - hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionDelete - - if err := tw.WriteHeader(hdr); err != nil { - return err + // Remove the headers from the index + if err := metadataPersister.DeleteHeaders(context.Background(), headersToDelete); err != nil { + return nil } - dirty = true - if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { return err } - if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil { - return err + // Append deletion headers to the tape/tar file + for _, dbhdr := range headersToDelete { + hdr, err := converters.DBHeaderToTarHeader(dbhdr) + if err != nil { + return err + } + + hdr.Size = 0 // Don't try to seek after the record + hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1 + hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionDelete + + if err := tw.WriteHeader(hdr); err != nil { + return err + } + + dirty = true + + if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil { + return err + } } return nil diff --git a/pkg/persisters/metadata.go b/pkg/persisters/metadata.go index 3bb4db2..309decf 100644 --- a/pkg/persisters/metadata.go +++ b/pkg/persisters/metadata.go @@ -7,12 +7,14 @@ import ( "context" "database/sql" "fmt" + "strings" "github.com/pojntfx/stfs/pkg/db/sqlite/migrations/metadata" models "github.com/pojntfx/stfs/pkg/db/sqlite/models/metadata" migrate "github.com/rubenv/sql-migrate" "github.com/volatiletech/sqlboiler/v4/boil" "github.com/volatiletech/sqlboiler/v4/queries" + "github.com/volatiletech/sqlboiler/v4/queries/qm" ) type MetadataPersister struct { @@ -56,6 +58,16 @@ func (p *MetadataPersister) GetHeaders(ctx context.Context) (models.HeaderSlice, return models.Headers().All(ctx, p.db) } +func (p *MetadataPersister) GetHeader(ctx context.Context, name string) (*models.Header, error) { + return models.FindHeader(ctx, p.db, name) +} + +func (p *MetadataPersister) GetHeaderChildren(ctx context.Context, name string) (models.HeaderSlice, error) { + return models.Headers( + qm.Where(models.HeaderColumns.Name+" like ?", strings.TrimSuffix(name, "/")+"/%"), // Prevent double trailing slashes + ).All(ctx, p.db) +} + func (p *MetadataPersister) DeleteHeader(ctx context.Context, name string, ignoreNotExists bool) (*models.Header, error) { hdr, err := models.FindHeader(ctx, p.db, name) if err != nil { @@ -73,6 +85,21 @@ func (p *MetadataPersister) DeleteHeader(ctx context.Context, name string, ignor return hdr, nil } +func (p *MetadataPersister) DeleteHeaders(ctx context.Context, hdrs models.HeaderSlice) error { + tx, err := p.db.BeginTx(ctx, nil) + if err != nil { + return err + } + + for _, hdr := range hdrs { + if _, err := hdr.Delete(ctx, tx); err != nil { + return err + } + } + + return tx.Commit() +} + func (p *MetadataPersister) GetLastIndexedRecordAndBlock(ctx context.Context, recordSize int) (int64, int64, error) { var header models.Header if err := queries.Raw(