diff --git a/cmd/stbak/cmd/index.go b/cmd/stbak/cmd/index.go index a47fc59..ae3ac0e 100644 --- a/cmd/stbak/cmd/index.go +++ b/cmd/stbak/cmd/index.go @@ -286,6 +286,11 @@ func indexHeader(record, block int64, hdr *tar.Header, metadataPersister *persis return err } } + case pax.STFSReplacesName: + // Move header; does not update metadata + if err := metadataPersister.MoveHeader(context.Background(), hdr.PAXRecords[pax.STFSReplacesName], hdr.Name); err != nil { + return err + } default: return pax.ErrUnsupportedAction } diff --git a/pkg/pax/stfs.go b/pkg/pax/stfs.go index e2af9ea..4321a38 100644 --- a/pkg/pax/stfs.go +++ b/pkg/pax/stfs.go @@ -13,6 +13,8 @@ const ( STFSReplacesContent = "STFS.ReplacesContent" STFSReplacesContentTrue = "true" STFSReplacesContentFalse = "false" + + STFSReplacesName = "STFS.ReplacesName" ) var ( diff --git a/pkg/persisters/metadata.go b/pkg/persisters/metadata.go index ad466bb..3ff1c64 100644 --- a/pkg/persisters/metadata.go +++ b/pkg/persisters/metadata.go @@ -56,11 +56,15 @@ func (p *MetadataPersister) UpsertHeader(ctx context.Context, dbhdr *models.Head func (p *MetadataPersister) UpdateHeaderMetadata(ctx context.Context, dbhdr *models.Header) error { currentHdr, err := models.FindHeader(ctx, p.db, dbhdr.Name, models.HeaderColumns.Name, models.HeaderColumns.Record, models.HeaderColumns.Block) + if err == sql.ErrNoRows { + return nil // We may have renamed the header in a later, but indexed record/block, so we can skip this + } + if err != nil { return err } - // Update everything but the record & block + // Update everything but the name, record & block dbhdr.Record = currentHdr.Record dbhdr.Block = currentHdr.Block @@ -71,6 +75,28 @@ func (p *MetadataPersister) UpdateHeaderMetadata(ctx context.Context, dbhdr *mod return nil } +func (p *MetadataPersister) MoveHeader(ctx context.Context, oldName string, newName string) error { + dbhdr, err := models.FindHeader(ctx, p.db, oldName, models.HeaderColumns.Name) + if err == sql.ErrNoRows { + return nil // We may have renamed the header in a later, but indexed record/block, so we can skip this + } + + if err != nil { + return err + } + + // Update the name + dbhdr.Name = newName + + if _, err := dbhdr.Update(ctx, p.db, boil.Infer()); err != nil { + return err + } + + // TODO: Update children's names too + + return nil +} + func (p *MetadataPersister) GetHeaders(ctx context.Context) (models.HeaderSlice, error) { return models.Headers().All(ctx, p.db) }