diff --git a/install.go b/install.go index b045c154..0ccf4326 100644 --- a/install.go +++ b/install.go @@ -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 { diff --git a/pkg/db/alpm.go b/pkg/db/alpm.go new file mode 100644 index 00000000..76cc8c60 --- /dev/null +++ b/pkg/db/alpm.go @@ -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() +} diff --git a/pkg/db/executor.go b/pkg/db/executor.go new file mode 100644 index 00000000..2a43f7fb --- /dev/null +++ b/pkg/db/executor.go @@ -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 +} diff --git a/pkg/dep/dep.go b/pkg/dep/dep.go index 61e016bb..25762343 100644 --- a/pkg/dep/dep.go +++ b/pkg/dep/dep.go @@ -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 diff --git a/pkg/dep/depCheck.go b/pkg/dep/depCheck.go index 4410bb0e..14071c04 100644 --- a/pkg/dep/depCheck.go +++ b/pkg/dep/depCheck.go @@ -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 } diff --git a/pkg/dep/depOrder.go b/pkg/dep/depOrder.go index c0a494ae..be3fff35 100644 --- a/pkg/dep/depOrder.go +++ b/pkg/dep/depOrder.go @@ -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) } diff --git a/pkg/dep/depPool.go b/pkg/dep/depPool.go index 75b731ee..0e669261 100644 --- a/pkg/dep/depPool.go +++ b/pkg/dep/depPool.go @@ -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 } }