Переглянути джерело

feat(db): abstract db ops need for dep

jguer 4 роки тому
батько
коміт
ad9bc9ef8f
7 змінених файлів з 186 додано та 126 видалено
  1. 2 4
      install.go
  2. 93 0
      pkg/db/alpm.go
  3. 10 0
      pkg/db/executor.go
  4. 5 9
      pkg/dep/dep.go
  5. 22 32
      pkg/dep/depCheck.go
  6. 6 8
      pkg/dep/depOrder.go
  7. 48 73
      pkg/dep/depPool.go

+ 2 - 4
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 {

+ 93 - 0
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()
+}

+ 10 - 0
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
+}

+ 5 - 9
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

+ 22 - 32
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
 	}

+ 6 - 8
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)
 }

+ 48 - 73
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
 		}
 	}