feat(db): abstract db ops need for dep

This commit is contained in:
jguer 2020-07-29 01:53:25 +02:00
parent 7f4c277ce7
commit ad9bc9ef8f
No known key found for this signature in database
GPG key ID: 6D6CC9BEA8556B35
7 changed files with 186 additions and 126 deletions

View file

@ -1014,7 +1014,7 @@ func buildInstallPkgbuilds(
for _, pkg := range base {
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, dep := range deps {
if _, errSatisfier := dp.LocalDB.PkgCache().FindSatisfier(dep); errSatisfier != nil {
if !dp.AlpmExecutor.LocalSatisfierExists(dep) {
satisfied = false
text.Warnln(gotext.Get("%s not satisfied, flushing install queue", dep))
break all
@ -1072,9 +1072,7 @@ func buildInstallPkgbuilds(
if cmdArgs.ExistsArg("needed") {
installed := true
for _, split := range base {
if alpmpkg := dp.LocalDB.Pkg(split.Name); alpmpkg == nil || alpmpkg.Version() != pkgVersion {
installed = false
}
installed = dp.AlpmExecutor.IsCorrectVersionInstalled(split.Name, pkgVersion)
}
if installed {

93
pkg/db/alpm.go Normal file
View file

@ -0,0 +1,93 @@
package db
import (
alpm "github.com/Jguer/go-alpm"
)
type AlpmExecutor struct {
Handle *alpm.Handle
LocalDB *alpm.DB
SyncDB alpm.DBList
}
func NewExecutor(handle *alpm.Handle) (*AlpmExecutor, error) {
localDB, err := handle.LocalDB()
if err != nil {
return nil, err
}
syncDB, err := handle.SyncDBs()
if err != nil {
return nil, err
}
return &AlpmExecutor{Handle: handle, LocalDB: localDB, SyncDB: syncDB}, nil
}
func (ae *AlpmExecutor) LocalSatisfierExists(pkgName string) bool {
if _, err := ae.LocalDB.PkgCache().FindSatisfier(pkgName); err != nil {
return false
}
return true
}
func (ae *AlpmExecutor) IsCorrectVersionInstalled(pkgName, versionRequired string) bool {
alpmPackage := ae.LocalDB.Pkg(pkgName)
if alpmPackage == nil {
return false
}
return alpmPackage.Version() == versionRequired
}
func (ae *AlpmExecutor) SyncSatisfier(pkgName string) RepoPackage {
foundPkg, err := ae.SyncDB.FindSatisfier(pkgName)
if err != nil {
return nil
}
return foundPkg
}
func (ae *AlpmExecutor) PackagesFromGroup(groupName string) []RepoPackage {
groupPackages := []RepoPackage{}
_ = ae.SyncDB.FindGroupPkgs(groupName).ForEach(func(pkg alpm.Package) error {
groupPackages = append(groupPackages, &pkg)
return nil
})
return groupPackages
}
func (ae *AlpmExecutor) LocalPackages() []RepoPackage {
localPackages := []RepoPackage{}
_ = ae.LocalDB.PkgCache().ForEach(func(pkg alpm.Package) error {
localPackages = append(localPackages, RepoPackage(&pkg))
return nil
})
return localPackages
}
func (ae *AlpmExecutor) PackageFromDB(pkgName, dbName string) RepoPackage {
singleDB, err := ae.Handle.SyncDBByName(dbName)
if err != nil {
return nil
}
foundPkg, err := singleDB.PkgCache().FindSatisfier(pkgName)
if err != nil {
return nil
}
return foundPkg
}
func (ae *AlpmExecutor) PackageDepends(pkg RepoPackage) []alpm.Depend {
alpmPackage := pkg.(*alpm.Package)
return alpmPackage.Depends().Slice()
}
func (ae *AlpmExecutor) PackageProvides(pkg RepoPackage) []alpm.Depend {
alpmPackage := pkg.(*alpm.Package)
return alpmPackage.Provides().Slice()
}
func (ae *AlpmExecutor) PackageConflicts(pkg RepoPackage) []alpm.Depend {
alpmPackage := pkg.(*alpm.Package)
return alpmPackage.Conflicts().Slice()
}

10
pkg/db/executor.go Normal file
View file

@ -0,0 +1,10 @@
package db
import alpm "github.com/Jguer/go-alpm"
type RepoPackage interface {
Base() string
Name() string
Version() string
DB() *alpm.DB
}

View file

@ -1,12 +1,12 @@
package dep
import (
"fmt"
"strings"
alpm "github.com/Jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
"github.com/Jguer/yay/v10/pkg/db"
"github.com/Jguer/yay/v10/pkg/text"
)
@ -121,19 +121,15 @@ func satisfiesAur(dep string, pkg *rpc.Pkg) bool {
return false
}
func satisfiesRepo(dep string, pkg *alpm.Package) bool {
func satisfiesRepo(dep string, pkg db.RepoPackage, ae *db.AlpmExecutor) bool {
if pkgSatisfies(pkg.Name(), pkg.Version(), dep) {
return true
}
if pkg.Provides().ForEach(func(provide alpm.Depend) error {
if provideSatisfies(provide.String(), dep) {
return fmt.Errorf("")
for _, provided := range ae.PackageProvides(pkg) {
if provideSatisfies(provided.String(), dep) {
return true
}
return nil
}) != nil {
return true
}
return false

View file

@ -6,7 +6,6 @@ import (
"strings"
"sync"
alpm "github.com/Jguer/go-alpm"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v10/pkg/stringset"
@ -29,28 +28,26 @@ func (dp *Pool) checkInnerConflict(name, conflict string, conflicts stringset.Ma
continue
}
if satisfiesRepo(conflict, pkg) {
if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
conflicts.Add(name, pkg.Name())
}
}
}
func (dp *Pool) checkForwardConflict(name, conflict string, conflicts stringset.MapStringSet) {
_ = dp.LocalDB.PkgCache().ForEach(func(pkg alpm.Package) error {
for _, pkg := range dp.AlpmExecutor.LocalPackages() {
if pkg.Name() == name || dp.hasPackage(pkg.Name()) {
return nil
continue
}
if satisfiesRepo(conflict, &pkg) {
if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
n := pkg.Name()
if n != conflict {
n += " (" + conflict + ")"
}
conflicts.Add(name, n)
}
return nil
})
}
}
func (dp *Pool) checkReverseConflict(name, conflict string, conflicts stringset.MapStringSet) {
@ -73,7 +70,7 @@ func (dp *Pool) checkReverseConflict(name, conflict string, conflicts stringset.
continue
}
if satisfiesRepo(conflict, pkg) {
if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
if name != conflict {
name += " (" + conflict + ")"
}
@ -91,10 +88,9 @@ func (dp *Pool) checkInnerConflicts(conflicts stringset.MapStringSet) {
}
for _, pkg := range dp.Repo {
_ = pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
}
}
}
@ -106,26 +102,21 @@ func (dp *Pool) checkForwardConflicts(conflicts stringset.MapStringSet) {
}
for _, pkg := range dp.Repo {
_ = pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
dp.checkForwardConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
}
}
}
func (dp *Pool) checkReverseConflicts(conflicts stringset.MapStringSet) {
_ = dp.LocalDB.PkgCache().ForEach(func(pkg alpm.Package) error {
for _, pkg := range dp.AlpmExecutor.LocalPackages() {
if dp.hasPackage(pkg.Name()) {
return nil
continue
}
_ = pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
return nil
})
}
}
}
func (dp *Pool) CheckConflicts(useAsk, noConfirm bool) (stringset.MapStringSet, error) {
@ -225,7 +216,7 @@ func (dp *Pool) _checkMissing(dep string, stack []string, missing *missing) {
missing.Good.Set(dep)
for _, deps := range [3][]string{aurPkg.Depends, aurPkg.MakeDepends, aurPkg.CheckDepends} {
for _, aurDep := range deps {
if _, err := dp.LocalDB.PkgCache().FindSatisfier(aurDep); err == nil {
if dp.AlpmExecutor.LocalSatisfierExists(aurDep) {
missing.Good.Set(aurDep)
continue
}
@ -240,15 +231,14 @@ func (dp *Pool) _checkMissing(dep string, stack []string, missing *missing) {
repoPkg := dp.findSatisfierRepo(dep)
if repoPkg != nil {
missing.Good.Set(dep)
_ = repoPkg.Depends().ForEach(func(repoDep alpm.Depend) error {
if _, err := dp.LocalDB.PkgCache().FindSatisfier(repoDep.String()); err == nil {
missing.Good.Set(repoDep.String())
return nil
for _, dep := range dp.AlpmExecutor.PackageDepends(repoPkg) {
if dp.AlpmExecutor.LocalSatisfierExists(dep.String()) {
missing.Good.Set(dep.String())
continue
}
dp._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing)
return nil
})
dp._checkMissing(dep.String(), append(stack, repoPkg.Name()), missing)
}
return
}

View file

@ -3,23 +3,23 @@ package dep
import (
"fmt"
alpm "github.com/Jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
"github.com/Jguer/yay/v10/pkg/db"
"github.com/Jguer/yay/v10/pkg/stringset"
"github.com/Jguer/yay/v10/pkg/text"
)
type Order struct {
Aur []Base
Repo []*alpm.Package
Repo []db.RepoPackage
Runtime stringset.StringSet
}
func makeOrder() *Order {
return &Order{
make([]Base, 0),
make([]*alpm.Package, 0),
make([]db.RepoPackage, 0),
make(stringset.StringSet),
}
}
@ -78,20 +78,18 @@ func (do *Order) orderPkgAur(pkg *rpc.Pkg, dp *Pool, runtime bool) {
do.Aur = append(do.Aur, Base{pkg})
}
func (do *Order) orderPkgRepo(pkg *alpm.Package, dp *Pool, runtime bool) {
func (do *Order) orderPkgRepo(pkg db.RepoPackage, dp *Pool, runtime bool) {
if runtime {
do.Runtime.Set(pkg.Name())
}
delete(dp.Repo, pkg.Name())
_ = pkg.Depends().ForEach(func(dep alpm.Depend) (err error) {
for _, dep := range dp.AlpmExecutor.PackageDepends(pkg) {
repoPkg := dp.findSatisfierRepo(dep.String())
if repoPkg != nil {
do.orderPkgRepo(repoPkg, dp, runtime)
}
return nil
})
}
do.Repo = append(do.Repo, pkg)
}

View file

@ -13,6 +13,7 @@ import (
"github.com/leonelquinteros/gotext"
rpc "github.com/mikkeloscar/aur"
"github.com/Jguer/yay/v10/pkg/db"
"github.com/Jguer/yay/v10/pkg/query"
"github.com/Jguer/yay/v10/pkg/settings"
"github.com/Jguer/yay/v10/pkg/stringset"
@ -27,11 +28,11 @@ type Target struct {
}
func ToTarget(pkg string) Target {
db, dep := text.SplitDBFromName(pkg)
name, mod, depVersion := splitDep(dep)
dbName, depString := text.SplitDBFromName(pkg)
name, mod, depVersion := splitDep(depString)
return Target{
DB: db,
DB: dbName,
Name: name,
Mod: mod,
Version: depVersion,
@ -51,44 +52,34 @@ func (t Target) String() string {
}
type Pool struct {
Targets []Target
Explicit stringset.StringSet
Repo map[string]*alpm.Package
Aur map[string]*rpc.Pkg
AurCache map[string]*rpc.Pkg
Groups []string
LocalDB *alpm.DB
SyncDB alpm.DBList
Warnings *query.AURWarnings
Targets []Target
Explicit stringset.StringSet
Repo map[string]db.RepoPackage
Aur map[string]*rpc.Pkg
AurCache map[string]*rpc.Pkg
Groups []string
AlpmExecutor *db.AlpmExecutor
Warnings *query.AURWarnings
}
func makePool(alpmHandle *alpm.Handle) (*Pool, error) {
localDB, err := alpmHandle.LocalDB()
if err != nil {
return nil, err
}
syncDB, err := alpmHandle.SyncDBs()
if err != nil {
return nil, err
}
func makePool(alpmHandle *alpm.Handle) *Pool {
ae, _ := db.NewExecutor(alpmHandle)
dp := &Pool{
make([]Target, 0),
make(stringset.StringSet),
make(map[string]*alpm.Package),
make(map[string]db.RepoPackage),
make(map[string]*rpc.Pkg),
make(map[string]*rpc.Pkg),
make([]string, 0),
localDB,
syncDB,
ae,
nil,
}
return dp, nil
return dp
}
// Includes db/ prefixes and group installs
func (dp *Pool) ResolveTargets(pkgs []string, alpmHandle *alpm.Handle,
func (dp *Pool) ResolveTargets(pkgs []string,
mode settings.TargetMode,
ignoreProviders, noConfirm, provides bool, rebuild string, splitN int) error {
// RPC requests are slow
@ -99,7 +90,6 @@ func (dp *Pool) ResolveTargets(pkgs []string, alpmHandle *alpm.Handle,
pkgs = query.RemoveInvalidTargets(pkgs, mode)
for _, pkg := range pkgs {
var err error
target := ToTarget(pkg)
// skip targets already satisfied
@ -111,8 +101,7 @@ func (dp *Pool) ResolveTargets(pkgs []string, alpmHandle *alpm.Handle,
continue
}
var foundPkg *alpm.Package
var singleDB *alpm.DB
var foundPkg db.RepoPackage
// aur/ prefix means we only check the aur
if target.DB == "aur" || mode == settings.ModeAUR {
@ -121,19 +110,15 @@ func (dp *Pool) ResolveTargets(pkgs []string, alpmHandle *alpm.Handle,
continue
}
// If there'ss a different priefix only look in that repo
// If there'ss a different prefix only look in that repo
if target.DB != "" {
singleDB, err = alpmHandle.SyncDBByName(target.DB)
if err != nil {
return err
}
foundPkg, err = singleDB.PkgCache().FindSatisfier(target.DepString())
// otherwise find it in any repo
foundPkg = dp.AlpmExecutor.PackageFromDB(target.DepString(), target.DB)
} else {
foundPkg, err = dp.SyncDB.FindSatisfier(target.DepString())
// otherwise find it in any repo
foundPkg = dp.AlpmExecutor.SyncSatisfier(target.DepString())
}
if err == nil {
if foundPkg != nil {
dp.Targets = append(dp.Targets, target)
dp.Explicit.Set(foundPkg.Name())
dp.ResolveRepoDependency(foundPkg)
@ -146,13 +131,12 @@ func (dp *Pool) ResolveTargets(pkgs []string, alpmHandle *alpm.Handle,
// the user specified a db but there's no easy way to do
// it without making alpm_lists so don't bother for now
// db/group is probably a rare use case
group := dp.SyncDB.FindGroupPkgs(target.Name)
if !group.Empty() {
groupPackages := dp.AlpmExecutor.PackagesFromGroup(target.Name)
if len(groupPackages) > 0 {
dp.Groups = append(dp.Groups, target.String())
_ = group.ForEach(func(pkg alpm.Package) error {
for _, pkg := range groupPackages {
dp.Explicit.Set(pkg.Name())
return nil
})
}
continue
}
}
@ -219,7 +203,7 @@ func (dp *Pool) findProvides(pkgs stringset.StringSet) error {
}
for pkg := range pkgs {
if dp.LocalDB.Pkg(pkg) != nil {
if dp.AlpmExecutor.LocalSatisfierExists(pkg) {
continue
}
wg.Add(1)
@ -319,16 +303,16 @@ func (dp *Pool) resolveAURPackages(pkgs stringset.StringSet,
continue
}
_, isInstalled := dp.LocalDB.PkgCache().FindSatisfier(dep) // has satisfier installed: skip
isInstalled := dp.AlpmExecutor.LocalSatisfierExists(dep)
hm := settings.HideMenus
settings.HideMenus = isInstalled == nil
repoPkg, inRepos := dp.SyncDB.FindSatisfier(dep) // has satisfier in repo: fetch it
settings.HideMenus = isInstalled
repoPkg := dp.AlpmExecutor.SyncSatisfier(dep) // has satisfier in repo: fetch it
settings.HideMenus = hm
if isInstalled == nil && (rebuild != "tree" || inRepos == nil) {
if isInstalled && (rebuild != "tree" || repoPkg != nil) {
continue
}
if inRepos == nil {
if repoPkg != nil {
dp.ResolveRepoDependency(repoPkg)
continue
}
@ -342,31 +326,25 @@ func (dp *Pool) resolveAURPackages(pkgs stringset.StringSet,
return err
}
func (dp *Pool) ResolveRepoDependency(pkg *alpm.Package) {
func (dp *Pool) ResolveRepoDependency(pkg db.RepoPackage) {
dp.Repo[pkg.Name()] = pkg
_ = pkg.Depends().ForEach(func(dep alpm.Depend) (err error) {
// have satisfier in dep tree: skip
for _, dep := range dp.AlpmExecutor.PackageDepends(pkg) {
if dp.hasSatisfier(dep.String()) {
return
continue
}
// has satisfier installed: skip
_, isInstalled := dp.LocalDB.PkgCache().FindSatisfier(dep.String())
if isInstalled == nil {
return
if dp.AlpmExecutor.LocalSatisfierExists(dep.String()) {
continue
}
// has satisfier in repo: fetch it
repoPkg, inRepos := dp.SyncDB.FindSatisfier(dep.String())
if inRepos != nil {
return
repoPkg := dp.AlpmExecutor.SyncSatisfier(dep.String())
if repoPkg != nil {
dp.ResolveRepoDependency(repoPkg)
}
dp.ResolveRepoDependency(repoPkg)
return nil
})
}
}
func GetPool(pkgs []string,
@ -375,13 +353,10 @@ func GetPool(pkgs []string,
mode settings.TargetMode,
ignoreProviders, noConfirm, provides bool,
rebuild string, splitN int) (*Pool, error) {
dp, err := makePool(alpmHandle)
if err != nil {
return nil, err
}
dp := makePool(alpmHandle)
dp.Warnings = warnings
err = dp.ResolveTargets(pkgs, alpmHandle, mode, ignoreProviders, noConfirm, provides, rebuild, splitN)
err := dp.ResolveTargets(pkgs, mode, ignoreProviders, noConfirm, provides, rebuild, splitN)
return dp, err
}
@ -411,7 +386,7 @@ func (dp *Pool) findSatisfierAurCache(dep string, ignoreProviders, noConfirm, pr
seen := make(stringset.StringSet)
providerSlice := makeProviders(depName)
if dp.LocalDB.Pkg(depName) != nil {
if dp.AlpmExecutor.LocalSatisfierExists(depName) {
if pkg, ok := dp.AurCache[dep]; ok && pkgSatisfies(pkg.Name, pkg.Version, dep) {
return pkg
}
@ -465,9 +440,9 @@ func (dp *Pool) findSatisfierAurCache(dep string, ignoreProviders, noConfirm, pr
return nil
}
func (dp *Pool) findSatisfierRepo(dep string) *alpm.Package {
func (dp *Pool) findSatisfierRepo(dep string) db.RepoPackage {
for _, pkg := range dp.Repo {
if satisfiesRepo(dep, pkg) {
if satisfiesRepo(dep, pkg, dp.AlpmExecutor) {
return pkg
}
}