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

@@ -292,6 +292,82 @@ func (b *Backend) DeleteManagedBundle(ctx context.Context, bundlePath string, ma
return nil
}
func (b *Backend) DeletePrefix(ctx context.Context, prefix string, opts storage.DeleteOptions) error {
if err := ctx.Err(); err != nil {
return err
}
if err := storage.ValidatePrefix(prefix); err != nil {
return err
}
var entries []storage.Entry
if prefix != "" {
entry, err := b.Stat(ctx, prefix)
if err != nil {
if opts.IgnoreMissing && storage.IsNotFound(err) {
return nil
}
return err
}
if entry.Type != storage.EntryTypeDirectory {
return b.deleteEntry(ctx, entry, opts)
}
entries = append(entries, entry)
}
if err := b.Walk(ctx, prefix, storage.WalkOptions{Recursive: true}, func(entry storage.Entry) error {
entries = append(entries, entry)
return nil
}); err != nil {
return err
}
if prefix != "" && len(entries) == 1 {
if err := b.deleteEntry(ctx, entries[0], opts); err != nil {
return err
}
if opts.PruneEmptyDirs {
b.pruneEmptyParents(parentOf(prefix))
}
return nil
}
sort.Slice(entries, func(i, j int) bool {
return strings.Count(entries[i].Path, "/") > strings.Count(entries[j].Path, "/")
})
for _, entry := range entries {
if entry.Path == "" {
continue
}
if err := b.deleteEntry(ctx, entry, storage.DeleteOptions{IgnoreMissing: true}); err != nil {
return err
}
}
if opts.PruneEmptyDirs {
b.pruneEmptyParents(parentOf(prefix))
}
return nil
}
func (b *Backend) deleteEntry(ctx context.Context, entry storage.Entry, opts storage.DeleteOptions) error {
if err := ctx.Err(); err != nil {
return err
}
nativePath, err := b.nativePath(entry.Path, false)
if err != nil {
return err
}
var removeErr error
if entry.Type == storage.EntryTypeDirectory {
removeErr = b.client.RemoveDirectory(nativePath)
} else {
removeErr = b.client.Remove(nativePath)
}
if removeErr != nil {
if opts.IgnoreMissing && isNotExist(removeErr) {
return nil
}
return b.translateError(storage.OpDeletePrefix, entry.Path, removeErr)
}
return nil
}
func (b *Backend) walkDirectory(ctx context.Context, logicalPrefix, nativePrefix string, opts storage.WalkOptions, emit func(storage.Entry) error) error {
entries, err := b.client.ReadDir(nativePrefix)
if err != nil {