feat: Add support for deleting directories
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user