Add explicit force replacement workflow

This commit is contained in:
2026-05-31 17:29:20 +00:00
parent 7a174ce5f1
commit 48169dc8b4
28 changed files with 811 additions and 53 deletions

View File

@@ -242,33 +242,87 @@ func (b *Backend) DeleteManagedBundle(ctx context.Context, bundlePath string, ma
return err
}
for _, target := range targets {
key, err := b.objectKey(target, false)
if err := b.deleteObject(ctx, storage.OpDeleteManagedBundle, target, opts); err != nil {
return err
}
}
return nil
}
func (b *Backend) DeletePrefix(ctx context.Context, logicalPrefix string, opts storage.DeleteOptions) error {
if err := ctx.Err(); err != nil {
return err
}
if err := storage.ValidatePrefix(logicalPrefix); err != nil {
return err
}
found := false
if logicalPrefix != "" {
key, err := b.objectKey(logicalPrefix, false)
if err != nil {
return err
}
if key == b.prefix {
return storage.NewError(storage.OpDeleteManagedBundle, BackendName, target, storage.ErrInvalidPath, nil)
}
if !opts.IgnoreMissing {
_, err := b.client.HeadObject(ctx, &awss3.HeadObjectInput{
Bucket: aws.String(b.bucket),
Key: aws.String(key),
})
if err != nil {
return b.translateError(storage.OpDeleteManagedBundle, target, err)
_, err = b.client.HeadObject(ctx, &awss3.HeadObjectInput{
Bucket: aws.String(b.bucket),
Key: aws.String(key),
})
if err == nil {
found = true
if err := b.deleteObject(ctx, storage.OpDeletePrefix, logicalPrefix, storage.DeleteOptions{IgnoreMissing: false}); err != nil {
return err
}
} else if !isNotFound(err) {
return b.translateError(storage.OpDeletePrefix, logicalPrefix, err)
}
_, err = b.client.DeleteObject(ctx, &awss3.DeleteObjectInput{
}
var entries []storage.Entry
if err := b.walkObjects(ctx, logicalPrefix, storage.WalkOptions{Recursive: true}, func(entry storage.Entry) error {
if entry.Type == storage.EntryTypeFile {
entries = append(entries, entry)
}
return nil
}); err != nil {
return err
}
for _, entry := range entries {
found = true
if err := b.deleteObject(ctx, storage.OpDeletePrefix, entry.Path, storage.DeleteOptions{IgnoreMissing: true}); err != nil {
return err
}
}
if !found && !opts.IgnoreMissing {
return storage.NewError(storage.OpDeletePrefix, BackendName, logicalPrefix, storage.ErrNotFound, nil)
}
return nil
}
func (b *Backend) deleteObject(ctx context.Context, op, logicalPath string, opts storage.DeleteOptions) error {
key, err := b.objectKey(logicalPath, false)
if err != nil {
return err
}
if key == b.prefix {
return storage.NewError(op, BackendName, logicalPath, storage.ErrInvalidPath, nil)
}
if !opts.IgnoreMissing {
_, err := b.client.HeadObject(ctx, &awss3.HeadObjectInput{
Bucket: aws.String(b.bucket),
Key: aws.String(key),
})
if err != nil {
if opts.IgnoreMissing && isNotFound(err) {
continue
}
return b.translateError(storage.OpDeleteManagedBundle, target, err)
return b.translateError(op, logicalPath, err)
}
}
_, err = b.client.DeleteObject(ctx, &awss3.DeleteObjectInput{
Bucket: aws.String(b.bucket),
Key: aws.String(key),
})
if err != nil {
if opts.IgnoreMissing && isNotFound(err) {
return nil
}
return b.translateError(op, logicalPath, err)
}
return nil
}