forked from canonical/snapd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsnapref.go
138 lines (119 loc) · 3.05 KB
/
snapref.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package naming
// A SnapRef references a snap by name and/or id.
type SnapRef interface {
SnapName() string
ID() string
}
// Snap references a snap by name only.
type Snap string
func (s Snap) SnapName() string {
return string(s)
}
func (s Snap) ID() string {
return ""
}
type snapRef struct {
name string
id string
}
// NewSnapRef returns a reference to the snap with given name and id.
func NewSnapRef(name, id string) SnapRef {
return &snapRef{name: name, id: id}
}
func (r *snapRef) SnapName() string {
return r.name
}
func (r *snapRef) ID() string {
return r.id
}
// SameSnap returns whether the two arguments refer to the same snap.
// If ids are not available for both it will fallback to names.
func SameSnap(snapRef1, snapRef2 SnapRef) bool {
id1 := snapRef1.ID()
id2 := snapRef2.ID()
if id1 != "" && id2 != "" {
return id1 == id2
}
return snapRef1.SnapName() == snapRef2.SnapName()
}
// SnapSet can hold a set of references to snaps.
type SnapSet struct {
byID map[string]SnapRef
byName map[string]SnapRef
n int
}
// NewSnapSet builds a snap set with the given references.
func NewSnapSet(refs []SnapRef) *SnapSet {
sz := len(refs) + 2
s := &SnapSet{
byID: make(map[string]SnapRef, sz),
byName: make(map[string]SnapRef, sz),
}
for _, r := range refs {
s.Add(r)
}
return s
}
// Empty returns whether the snap set is empty.
func (s *SnapSet) Empty() bool {
return s.n == 0
}
// Size returns the number of snaps in the snap set.
func (s *SnapSet) Size() int {
return s.n
}
// Lookup finds the reference in the set matching the given one if any.
func (s *SnapSet) Lookup(which SnapRef) SnapRef {
whichID := which.ID()
name := which.SnapName()
if whichID != "" {
if ref := s.byID[whichID]; ref != nil {
return ref
}
}
ref := s.byName[name]
if ref == nil || (ref.ID() != "" && whichID != "") {
return nil
}
return ref
}
// Contains returns whether the set has a matching reference already.
func (s *SnapSet) Contains(ref SnapRef) bool {
return s.Lookup(ref) != nil
}
// Add adds one reference to the set.
// Already added ids or names will be ignored. The assumption is that
// a SnapSet is populated with distinct snaps.
func (s *SnapSet) Add(ref SnapRef) {
if s.Contains(ref) {
// nothing to do
return
}
inc := 0
if id := ref.ID(); id != "" {
s.byID[id] = ref
inc = 1
}
if name := ref.SnapName(); name != "" {
s.byName[name] = ref
inc = 1
}
s.n += inc
}