Adds EXTRAORDINARILY Installable implementation
We want the simplest satisfiability solver we can have, but one that chases transitive dependencies. This one only checks the requested packages exist in the availability database.
This commit is contained in:
parent
b869bd250c
commit
14a456f006
93
available.go
93
available.go
@ -1,8 +1,10 @@
|
||||
package pm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -28,10 +30,52 @@ func (v Versions) Len() int { return len(v) }
|
||||
func (v Versions) Swap(a, b int) { v[a], v[b] = v[b], v[a] }
|
||||
func (v Versions) Less(a, b int) bool { return v[a] < v[b] }
|
||||
|
||||
type label struct {
|
||||
n Name
|
||||
v Version
|
||||
}
|
||||
|
||||
type labels []label
|
||||
|
||||
// TODO (sm): make this semver sort?
|
||||
func (n labels) Len() int { return len(n) }
|
||||
func (n labels) Swap(a, b int) { n[a], n[b] = n[b], n[a] }
|
||||
func (n labels) Less(a, b int) bool {
|
||||
if n[a].n != n[b].n {
|
||||
return n[a].n < n[b].n
|
||||
}
|
||||
return n[a].v < n[b].v
|
||||
}
|
||||
|
||||
// Available is the structure used to represent the collection of all packages
|
||||
// that can be installed.
|
||||
type Available map[Name]map[Version]Meta
|
||||
|
||||
// Get returns the meta stored at a[n][v] or an error explaining why it could
|
||||
// not be Get.
|
||||
func (a Available) Get(n Name, v Version) (Meta, error) {
|
||||
if _, ok := a[n]; !ok {
|
||||
return Meta{}, errors.Errorf("could not find package named %q", n)
|
||||
}
|
||||
|
||||
if v == "" {
|
||||
if len(a[n]) == 0 {
|
||||
return Meta{}, errors.Errorf("no configured versions for %q", n)
|
||||
}
|
||||
vers := Versions{}
|
||||
for ver := range a[n] {
|
||||
vers = append(vers, ver)
|
||||
}
|
||||
sort.Sort(vers)
|
||||
v = vers[len(vers)-1]
|
||||
}
|
||||
|
||||
if _, ok := a[n][v]; !ok {
|
||||
return Meta{}, errors.Errorf("could not find %v@%v in database", n, v)
|
||||
}
|
||||
return a[n][v], nil
|
||||
}
|
||||
|
||||
// Add inserts m into a.
|
||||
func (a Available) Add(m Meta) error {
|
||||
if _, err := m.Valid(); err != nil {
|
||||
@ -92,3 +136,52 @@ func (a Available) Traverse() <-chan Meta {
|
||||
}()
|
||||
return r
|
||||
}
|
||||
|
||||
func labelForString(s string) (label, error) {
|
||||
r := label{}
|
||||
c := strings.Count(s, "@")
|
||||
switch c {
|
||||
case 0:
|
||||
r.n = Name(s)
|
||||
case 1:
|
||||
sp := strings.Split(s, "@")
|
||||
r.n, r.v = Name(sp[0]), Version(sp[1])
|
||||
default:
|
||||
return r, fmt.Errorf("unexpected number of '@' found, got %v, want 1", c)
|
||||
}
|
||||
if r.n == "" {
|
||||
return r, fmt.Errorf("name cannot be empty")
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Installable calculates if the packages requested in "in" can be installed.
|
||||
func (a Available) Installable(in []string) (Metas, error) {
|
||||
ls := labels{}
|
||||
for _, i := range in {
|
||||
l, err := labelForString(i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing name/version")
|
||||
}
|
||||
ls = append(ls, l)
|
||||
}
|
||||
|
||||
seen := map[Name]bool{}
|
||||
for _, l := range ls {
|
||||
if _, ok := seen[l.n]; ok {
|
||||
return nil, fmt.Errorf("can only ask to install %q once", l.n)
|
||||
}
|
||||
seen[l.n] = true
|
||||
}
|
||||
|
||||
ms := Metas{}
|
||||
for _, l := range ls {
|
||||
m, err := a.Get(l.n, l.v)
|
||||
if err != nil {
|
||||
return ms, errors.Wrapf(err, "getting %v", l)
|
||||
}
|
||||
ms = append(ms, m)
|
||||
}
|
||||
|
||||
return ms, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user