diff options
Diffstat (limited to 'object/store/packed/quarantine_promote.go')
| -rw-r--r-- | object/store/packed/quarantine_promote.go | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/object/store/packed/quarantine_promote.go b/object/store/packed/quarantine_promote.go new file mode 100644 index 00000000..a4eb426d --- /dev/null +++ b/object/store/packed/quarantine_promote.go @@ -0,0 +1,89 @@ +package packed + +import ( + "errors" + "fmt" + "io/fs" + "os" + "slices" + "strings" +) + +// Promote publishes all finalized pack artifacts in the quarantine into the +// parent packed store and invalidates the receiver. +func (quarantine *packQuarantine) Promote() error { + closeErr := quarantine.Close() + promoteErr := promotePackQuarantine(quarantine.parent.root, quarantine.tempName, quarantine.tempRoot) + tempRootErr := quarantine.tempRoot.Close() + removeErr := quarantine.parent.root.RemoveAll(quarantine.tempName) + + if closeErr != nil { + return closeErr + } + + if tempRootErr != nil { + return tempRootErr + } + + if promoteErr != nil { + return promoteErr + } + + return removeErr +} + +func promotePackQuarantine(parent *os.Root, tempName string, tempRoot *os.Root) error { + entries, err := fs.ReadDir(tempRoot.FS(), ".") + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return err + } + + slices.SortFunc(entries, func(left, right fs.DirEntry) int { + return packPromotionPriority(left.Name()) - packPromotionPriority(right.Name()) + }) + + for _, entry := range entries { + if entry.IsDir() { + return fmt.Errorf("packed: quarantine contains unexpected directory %q", entry.Name()) + } + + err := promotePackQuarantineFile(parent, tempName, entry.Name()) + if err != nil { + return err + } + } + + return nil +} + +func promotePackQuarantineFile(parent *os.Root, tempName, name string) error { + src := tempName + "/" + name + + err := parent.Link(src, name) + if err == nil { + _ = parent.Remove(src) + + return nil + } + + if errors.Is(err, fs.ErrExist) { + _ = parent.Remove(src) + + return nil + } + + return fmt.Errorf("packed: promote quarantine %q -> %q: %w", src, name, err) +} + +func packPromotionPriority(name string) int { + switch { + case strings.HasPrefix(name, "pack-") && strings.HasSuffix(name, ".pack"): + return 1 + case strings.HasPrefix(name, "pack-") && strings.HasSuffix(name, ".rev"): + return 2 + case strings.HasPrefix(name, "pack-") && strings.HasSuffix(name, ".idx"): + return 3 + default: + return 0 + } +} |
