diff options
| author | 2026-03-04 08:26:56 +0800 | |
|---|---|---|
| committer | 2026-03-04 08:59:53 +0800 | |
| commit | ab7501be34032fb9e5c48726a68ae90a917af9eb (patch) | |
| tree | 20d005647569befea8133e953c3270e8fd2a2a5b /refstore/chain | |
| parent | *: gofumpt (diff) | |
| signature | No signature | |
*: Lint
Diffstat (limited to 'refstore/chain')
| -rw-r--r-- | refstore/chain/chain.go | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/refstore/chain/chain.go b/refstore/chain/chain.go index 633bac25..9e04aeec 100644 --- a/refstore/chain/chain.go +++ b/refstore/chain/chain.go @@ -28,15 +28,19 @@ func (chain *Chain) Resolve(name string) (ref.Ref, error) { if backend == nil { continue } + resolved, err := backend.Resolve(name) if err == nil { return resolved, nil } + if errors.Is(err, refstore.ErrReferenceNotFound) { continue } + return nil, fmt.Errorf("refstore: backend %d resolve: %w", i, err) } + return nil, refstore.ErrReferenceNotFound } @@ -46,11 +50,13 @@ func (chain *Chain) Resolve(name string) (ref.Ref, error) { // references to cross backends in the chain. func (chain *Chain) ResolveFully(name string) (ref.Detached, error) { cur := name + seen := map[string]struct{}{} for { if _, ok := seen[cur]; ok { return ref.Detached{}, fmt.Errorf("refstore: symbolic reference cycle at %q", cur) } + seen[cur] = struct{}{} resolved, err := chain.Resolve(cur) @@ -65,6 +71,7 @@ func (chain *Chain) ResolveFully(name string) (ref.Detached, error) { if resolved.Target == "" { return ref.Detached{}, fmt.Errorf("refstore: symbolic reference %q has empty target", resolved.Name()) } + cur = resolved.Target default: return ref.Detached{}, fmt.Errorf("refstore: unsupported reference type %T", resolved) @@ -77,25 +84,31 @@ func (chain *Chain) ResolveFully(name string) (ref.Detached, error) { // First-seen wins, so earlier backends have precedence. func (chain *Chain) List(pattern string) ([]ref.Ref, error) { var refs []ref.Ref + seen := map[string]struct{}{} for i, backend := range chain.backends { if backend == nil { continue } + listed, err := backend.List(pattern) if err != nil { return nil, fmt.Errorf("refstore: backend %d list: %w", i, err) } + for _, entry := range listed { if entry == nil { continue } + name := entry.Name() if _, ok := seen[name]; ok { continue } + seen[name] = struct{}{} + refs = append(refs, entry) } } @@ -109,34 +122,44 @@ func (chain *Chain) Shorten(name string) (string, error) { if err != nil { return "", err } + names := make([]string, 0, len(refs)) found := false + for _, entry := range refs { if entry == nil { continue } + full := entry.Name() + names = append(names, full) if full == name { found = true } } + if !found { return "", refstore.ErrReferenceNotFound } + return refstore.ShortenName(name, names), nil } // Close closes all backends and joins close errors. func (chain *Chain) Close() error { var errs []error + for _, backend := range chain.backends { if backend == nil { continue } - if err := backend.Close(); err != nil { + + err := backend.Close() + if err != nil { errs = append(errs, err) } } + return errors.Join(errs...) } |
