1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
"github.com/juju/errors"
10
"github.com/juju/utils/set"
13
type layeredStorage []Storage
15
// NewLayeredStorage wraps multiple Storages such all of their metadata
16
// can be listed and fetched. The later entries in the list have lower
17
// precedence than the earlier ones. The first entry in the list is always
18
// used for mutating operations.
19
func NewLayeredStorage(s ...Storage) (Storage, error) {
21
return nil, errors.Errorf("expected multiple stores")
23
return layeredStorage(s), nil
26
// Add implements Storage.Add.
28
// This method operates on the first Storage passed to NewLayeredStorage.
29
func (s layeredStorage) Add(r io.Reader, m Metadata) error {
33
// Open implements Storage.Open.
35
// This method calls Open for each Storage passed to NewLayeredStorage in
36
// the order given, and returns the first result where the error does not
37
// satisfy errors.IsNotFound.
38
func (s layeredStorage) Open(v string) (Metadata, io.ReadCloser, error) {
43
m, rc, err = s.Open(v)
44
if !errors.IsNotFound(err) {
51
// Metadata implements Storage.Metadata.
53
// This method calls Metadata for each Storage passed to NewLayeredStorage in
54
// the order given, and returns the first result where the error does not
55
// satisfy errors.IsNotFound.
56
func (s layeredStorage) Metadata(v string) (Metadata, error) {
60
m, err = s.Metadata(v)
61
if !errors.IsNotFound(err) {
68
// AllMetadata implements Storage.AllMetadata.
70
// This method calls AllMetadata for each Storage passed to NewLayeredStorage
71
// in the order given, and accumulates the results. Any results from a Storage
72
// earlier in the list will take precedence over any others with the same
74
func (s layeredStorage) AllMetadata() ([]Metadata, error) {
75
seen := set.NewStrings()
78
sm, err := s.AllMetadata()
82
for _, m := range sm {
83
if seen.Contains(m.Version) {