diff --git a/pkg/package/database.go b/pkg/package/database.go index 1af3d49b..9e76085a 100644 --- a/pkg/package/database.go +++ b/pkg/package/database.go @@ -33,6 +33,7 @@ type PackageSet interface { GetPackage(ID string) (Package, error) Clean() error FindPackage(Package) (Package, error) + FindPackages(p Package) ([]Package, error) UpdatePackage(p Package) error GetAllPackages(packages chan Package) error RemovePackage(Package) error diff --git a/pkg/package/database_boltdb.go b/pkg/package/database_boltdb.go index 72b5b160..bf90524e 100644 --- a/pkg/package/database_boltdb.go +++ b/pkg/package/database_boltdb.go @@ -22,6 +22,7 @@ import ( "sync" "time" + version "github.com/hashicorp/go-version" "github.com/pkg/errors" storm "github.com/asdine/storm" @@ -293,3 +294,27 @@ func (db *BoltDatabase) FindPackageCandidate(p Package) (Package, error) { return required, err } + +// FindPackages return the list of the packages beloging to cat/name (any versions) +// FIXME: Optimize, see inmemorydb +func (db *BoltDatabase) FindPackages(p Package) ([]Package, error) { + var versionsInWorld []Package + for _, w := range db.World() { + if w.GetName() != p.GetName() || w.GetCategory() != p.GetCategory() { + continue + } + + v, err := version.NewVersion(w.GetVersion()) + if err != nil { + return nil, err + } + constraints, err := version.NewConstraint(p.GetVersion()) + if err != nil { + return nil, err + } + if constraints.Check(v) { + versionsInWorld = append(versionsInWorld, w) + } + } + return versionsInWorld, nil +} diff --git a/pkg/package/database_mem.go b/pkg/package/database_mem.go index 452cb6ae..49f98dbe 100644 --- a/pkg/package/database_mem.go +++ b/pkg/package/database_mem.go @@ -18,28 +18,35 @@ package pkg import ( "encoding/base64" "encoding/json" - "errors" "sync" + + version "github.com/hashicorp/go-version" + "github.com/pkg/errors" ) var DBInMemoryInstance = &InMemoryDatabase{ - Mutex: &sync.Mutex{}, - FileDatabase: map[string][]string{}, - Database: map[string]string{}} + Mutex: &sync.Mutex{}, + FileDatabase: map[string][]string{}, + Database: map[string]string{}, + CacheNoVersion: map[string]map[string]interface{}{}, +} type InMemoryDatabase struct { *sync.Mutex - Database map[string]string - FileDatabase map[string][]string + Database map[string]string + FileDatabase map[string][]string + CacheNoVersion map[string]map[string]interface{} } func NewInMemoryDatabase(singleton bool) PackageDatabase { // In memoryDB is a singleton if !singleton { return &InMemoryDatabase{ - Mutex: &sync.Mutex{}, - FileDatabase: map[string][]string{}, - Database: map[string]string{}} + Mutex: &sync.Mutex{}, + FileDatabase: map[string][]string{}, + Database: map[string]string{}, + CacheNoVersion: map[string]map[string]interface{}{}, + } } return DBInMemoryInstance } @@ -131,6 +138,16 @@ func (db *InMemoryDatabase) CreatePackage(p Package) (string, error) { if err != nil { return "", err } + + // Create extra cache between package -> []versions + db.Lock() + defer db.Unlock() + _, ok = db.CacheNoVersion[p.GetPackageName()] + if !ok { + db.CacheNoVersion[p.GetPackageName()] = make(map[string]interface{}) + } + db.CacheNoVersion[p.GetPackageName()][p.GetVersion()] = nil + return ID, nil } @@ -153,6 +170,33 @@ func (db *InMemoryDatabase) FindPackage(p Package) (Package, error) { return db.GetPackage(p.GetFingerPrint()) } +// FindPackages return the list of the packages beloging to cat/name (any versions) +func (db *InMemoryDatabase) FindPackages(p Package) ([]Package, error) { + versions, ok := db.CacheNoVersion[p.GetPackageName()] + if !ok { + return nil, errors.New("No versions found for package") + } + var versionsInWorld []Package + for ve, _ := range versions { + v, err := version.NewVersion(ve) + if err != nil { + return nil, err + } + constraints, err := version.NewConstraint(p.GetVersion()) + if err != nil { + return nil, err + } + if constraints.Check(v) { + w, err := db.FindPackage(&DefaultPackage{Name: p.GetName(), Category: p.GetCategory(), Version: ve}) + if err != nil { + return nil, errors.Wrap(err, "Cache mismatch - this shouldn't happen") + } + versionsInWorld = append(versionsInWorld, w) + } + } + return versionsInWorld, nil +} + func (db *InMemoryDatabase) UpdatePackage(p Package) error { _, enc, err := db.encodePackage(p)