-
Notifications
You must be signed in to change notification settings - Fork 2
/
indexer.go
72 lines (64 loc) · 1.9 KB
/
indexer.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
package packman
import "sync"
// Indexer is the interface our actual implementations must satisfy to be
// considered package indexers.
type Indexer interface {
Index(Package) error
Remove(Package) error
Query(string) (Package, error)
}
// Package represents a package to be indexed, removed and querried.
type Package struct {
Name string
Deps []*Package
}
// PackageIndexer implements the Indexer capabilities of adding, removing and
// querying for a package.
type PackageIndexer struct {
dict map[string]*Package
*sync.Mutex
}
// NewIndexer returns an implementation of our indexer.
func NewIndexer(initialDict map[string]*Package) PackageIndexer {
pi := PackageIndexer{initialDict, &sync.Mutex{}}
if pi.dict == nil {
pi.dict = make(map[string]*Package, 0)
}
return pi
}
// Index indexes a package. If the package is already indexed, we update its dependencies.
// If any of the package's dependencies are unknown, we return an error.
func (pi *PackageIndexer) Index(p *Package) error {
// check dependency exists
for _, d := range p.Deps {
_, err := pi.Query(d.Name)
if _, ok := err.(PackageNotFoundError); ok {
return UnknownDependentError{p.Name, d.Name}
}
}
// add/update package
pi.dict[p.Name] = p
return nil
}
// Remove removes a package from the index if no other package depends on it.
// Returns a PackageHasDependentsError if any other package depends on it.
func (pi *PackageIndexer) Remove(p *Package) error {
// ensure package is not depended upon by another
for _, pkg := range pi.dict {
for _, dep := range pkg.Deps {
if p.Name == dep.Name {
return PackageHasDependentsError{p.Name}
}
}
}
// we're free to remove it at this point
delete(pi.dict, p.Name)
return nil
}
// Query searches index for a package.
func (pi *PackageIndexer) Query(name string) (*Package, error) {
if p, ok := pi.dict[name]; ok {
return p, nil
}
return nil, PackageNotFoundError{name}
}