Merge pull request #866 from Morganamilo/revert-depsolver

Revert "Merge pull request #767 from Morganamilo/merge-dep-pool-order"
This commit is contained in:
J Guerreiro 2019-01-17 17:24:39 +00:00 committed by GitHub
commit 6354a4424e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 914 additions and 963 deletions

73
dep.go
View File

@ -8,11 +8,6 @@ import (
rpc "github.com/mikkeloscar/aur"
)
type missing struct {
Good stringSet
Missing map[string][][]string
}
type providers struct {
lookfor string
Pkgs []*rpc.Pkg
@ -45,74 +40,6 @@ func (q providers) Swap(i, j int) {
q.Pkgs[i], q.Pkgs[j] = q.Pkgs[j], q.Pkgs[i]
}
type Base []*rpc.Pkg
func (b Base) Pkgbase() string {
return b[0].PackageBase
}
func (b Base) Version() string {
return b[0].Version
}
func (b Base) URLPath() string {
return b[0].URLPath
}
func baseAppend(bases []Base, pkg *rpc.Pkg) []Base {
for i, base := range bases {
if base.Pkgbase() == pkg.PackageBase {
bases[i] = append(bases[i], pkg)
return bases
}
}
return append(bases, Base{pkg})
}
func baseFind(bases []Base, name string) *rpc.Pkg {
for _, base := range bases {
for _, pkg := range base {
if pkg.Name == name {
return pkg
}
}
}
return nil
}
type target struct {
Db string
Name string
Mod string
Version string
}
func toTarget(pkg string) target {
db, dep := splitDbFromName(pkg)
name, mod, version := splitDep(dep)
return target{
db,
name,
mod,
version,
}
}
func (t target) DepString() string {
return t.Name + t.Mod + t.Version
}
func (t target) String() string {
if t.Db != "" {
return t.Db + "/" + t.DepString()
}
return t.DepString()
}
func splitDep(dep string) (string, string, string) {
mod := ""

View File

@ -7,105 +7,41 @@ import (
"sync"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
)
func (ds *depSolver) _checkMissing(dep string, stack []string, missing *missing) {
if missing.Good.get(dep) {
return
}
if trees, ok := missing.Missing[dep]; ok {
for _, tree := range trees {
if stringSliceEqual(tree, stack) {
return
}
}
missing.Missing[dep] = append(missing.Missing[dep], stack)
return
}
aurPkg := ds.findSatisfierAur(dep)
if aurPkg != nil {
missing.Good.set(dep)
for _, deps := range [3][]string{aurPkg.Depends, aurPkg.MakeDepends, aurPkg.CheckDepends} {
for _, aurDep := range deps {
if _, err := ds.LocalDb.PkgCache().FindSatisfier(aurDep); err == nil {
missing.Good.set(aurDep)
continue
}
ds._checkMissing(aurDep, append(stack, aurPkg.Name), missing)
}
func (dp *depPool) checkInnerConflict(name string, conflict string, conflicts mapStringSet) {
for _, pkg := range dp.Aur {
if pkg.Name == name {
continue
}
return
if satisfiesAur(conflict, pkg) {
conflicts.Add(name, pkg.Name)
}
}
repoPkg := ds.findSatisfierRepo(dep)
if repoPkg != nil {
missing.Good.set(dep)
repoPkg.Depends().ForEach(func(repoDep alpm.Depend) error {
if _, err := ds.LocalDb.PkgCache().FindSatisfier(repoDep.String()); err == nil {
missing.Good.set(repoDep.String())
return nil
}
for _, pkg := range dp.Repo {
if pkg.Name() == name {
continue
}
ds._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing)
return nil
})
return
if satisfiesRepo(conflict, pkg) {
conflicts.Add(name, pkg.Name())
}
}
missing.Missing[dep] = [][]string{stack}
}
func (ds *depSolver) CheckMissing() error {
missing := &missing{
make(stringSet),
make(map[string][][]string),
}
for _, target := range ds.Targets {
ds._checkMissing(target.DepString(), make([]string, 0), missing)
}
if len(missing.Missing) == 0 {
return nil
}
fmt.Fprintln(os.Stderr, bold(red(arrow+" Error: "))+"Could not find all required packages:")
for dep, trees := range missing.Missing {
for _, tree := range trees {
fmt.Fprint(os.Stderr, " ", cyan(dep))
if len(tree) == 0 {
fmt.Fprint(os.Stderr, " (Target")
} else {
fmt.Fprint(os.Stderr, " (Wanted by: ")
for n := 0; n < len(tree)-1; n++ {
fmt.Fprint(os.Stderr, cyan(tree[n]), " -> ")
}
fmt.Fprint(os.Stderr, cyan(tree[len(tree)-1]))
}
fmt.Fprintln(os.Stderr, ")")
}
}
return fmt.Errorf("")
}
func (ds *depSolver) checkForwardConflict(name string, conflict string, conflicts mapStringSet) {
ds.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if pkg.Name() == name || ds.hasPackage(pkg.Name()) {
func (dp *depPool) checkForwardConflict(name string, conflict string, conflicts mapStringSet) {
dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if pkg.Name() == name || dp.hasPackage(pkg.Name()) {
return nil
}
if satisfiesRepo(conflict, &pkg) {
n := pkg.Name()
if n != conflict {
n += " (" + conflict + ")"
}
conflicts.Add(name, n)
}
@ -113,55 +49,74 @@ func (ds *depSolver) checkForwardConflict(name string, conflict string, conflict
})
}
func (ds *depSolver) checkReverseConflict(name string, conflict string, conflicts mapStringSet) {
for _, base := range ds.Aur {
for _, pkg := range base {
if pkg.Name == name {
continue
func (dp *depPool) checkReverseConflict(name string, conflict string, conflicts mapStringSet) {
for _, pkg := range dp.Aur {
if pkg.Name == name {
continue
}
if satisfiesAur(conflict, pkg) {
if name != conflict {
name += " (" + conflict + ")"
}
if satisfiesAur(conflict, pkg) {
conflicts.Add(pkg.Name, name)
}
conflicts.Add(pkg.Name, name)
}
}
for _, pkg := range ds.Repo {
for _, pkg := range dp.Repo {
if pkg.Name() == name {
continue
}
if satisfiesRepo(conflict, pkg) {
if name != conflict {
name += " (" + conflict + ")"
}
conflicts.Add(pkg.Name(), name)
}
}
}
func (ds *depSolver) checkForwardConflicts(conflicts mapStringSet) {
for _, base := range ds.Aur {
for _, pkg := range base {
for _, conflict := range pkg.Conflicts {
ds.checkForwardConflict(pkg.Name, conflict, conflicts)
}
func (dp *depPool) checkInnerConflicts(conflicts mapStringSet) {
for _, pkg := range dp.Aur {
for _, conflict := range pkg.Conflicts {
dp.checkInnerConflict(pkg.Name, conflict, conflicts)
}
}
for _, pkg := range ds.Repo {
for _, pkg := range dp.Repo {
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
ds.checkForwardConflict(pkg.Name(), conflict.String(), conflicts)
dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
}
}
func (ds *depSolver) checkReverseConflicts(conflicts mapStringSet) {
ds.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if ds.hasPackage(pkg.Name()) {
func (dp *depPool) checkForwardConflicts(conflicts mapStringSet) {
for _, pkg := range dp.Aur {
for _, conflict := range pkg.Conflicts {
dp.checkForwardConflict(pkg.Name, conflict, conflicts)
}
}
for _, pkg := range dp.Repo {
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
dp.checkForwardConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
}
}
func (dp *depPool) checkReverseConflicts(conflicts mapStringSet) {
dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if dp.hasPackage(pkg.Name()) {
return nil
}
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
ds.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
@ -169,147 +124,66 @@ func (ds *depSolver) checkReverseConflicts(conflicts mapStringSet) {
})
}
func (ds *depSolver) checkInnerRepoConflicts(conflicts mapStringSet) {
for _, pkg := range ds.Repo {
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
for _, innerpkg := range ds.Repo {
if pkg.Name() != innerpkg.Name() && satisfiesRepo(conflict.String(), innerpkg) {
conflicts.Add(pkg.Name(), innerpkg.Name())
}
}
return nil
})
}
}
func (ds *depSolver) checkInnerConflicts(conflicts mapStringSet) {
removed := make(stringSet)
//ds.checkInnerConflictRepoAur(conflicts)
for current, currbase := range ds.Aur {
for _, pkg := range currbase {
ds.checkInnerConflict(pkg, ds.Aur[:current], removed, conflicts)
}
}
}
// Check if anything conflicts with currpkg
// If so add the conflict with currpkg being removed by the conflicting pkg
func (ds *depSolver) checkInnerConflict(currpkg *rpc.Pkg, aur []Base, removed stringSet, conflicts mapStringSet) {
for _, base := range aur {
for _, pkg := range base {
for _, conflict := range pkg.Conflicts {
if !removed.get(pkg.Name) && satisfiesAur(conflict, currpkg) {
addInnerConflict(pkg.Name, currpkg.Name, removed, conflicts)
}
}
}
}
for _, pkg := range ds.Repo {
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
if !removed.get(pkg.Name()) && satisfiesAur(conflict.String(), currpkg) {
addInnerConflict(pkg.Name(), currpkg.Name, removed, conflicts)
}
return nil
})
}
for _, conflict := range currpkg.Conflicts {
for _, base := range aur {
for _, pkg := range base {
if !removed.get(pkg.Name) && satisfiesAur(conflict, pkg) {
addInnerConflict(pkg.Name, currpkg.Name, removed, conflicts)
}
}
}
for _, pkg := range ds.Repo {
if !removed.get(pkg.Name()) && satisfiesRepo(conflict, pkg) {
addInnerConflict(pkg.Name(), currpkg.Name, removed, conflicts)
}
}
}
}
func addInnerConflict(toRemove string, removedBy string, removed stringSet, conflicts mapStringSet) {
conflicts.Add(removedBy, toRemove)
removed.set(toRemove)
}
func (ds *depSolver) CheckConflicts() (mapStringSet, error) {
func (dp *depPool) CheckConflicts() (mapStringSet, error) {
var wg sync.WaitGroup
innerConflicts := make(mapStringSet)
conflicts := make(mapStringSet)
repoConflicts := make(mapStringSet)
wg.Add(3)
wg.Add(2)
fmt.Println(bold(cyan("::") + bold(" Checking for conflicts...")))
go func() {
ds.checkForwardConflicts(conflicts)
ds.checkReverseConflicts(conflicts)
dp.checkForwardConflicts(conflicts)
dp.checkReverseConflicts(conflicts)
wg.Done()
}()
fmt.Println(bold(cyan("::") + bold(" Checking for inner conflicts...")))
go func() {
ds.checkInnerConflicts(innerConflicts)
wg.Done()
}()
go func() {
ds.checkInnerRepoConflicts(repoConflicts)
dp.checkInnerConflicts(innerConflicts)
wg.Done()
}()
wg.Wait()
formatConflicts := func(conflicts mapStringSet, inner bool, s string) {
if len(conflicts) != 0 {
fmt.Fprintln(os.Stderr)
if inner {
fmt.Fprintln(os.Stderr, bold(red(arrow)), bold("Inner conflicts found:"))
} else {
fmt.Fprintln(os.Stderr, bold(red(arrow)), bold("Package conflicts found:"))
}
if len(innerConflicts) != 0 {
fmt.Println()
fmt.Println(bold(red(arrow)), bold("Inner conflicts found:"))
printConflict := func(name string, pkgs stringSet) {
str := fmt.Sprintf(s, cyan(name))
for pkg := range pkgs {
str += " " + cyan(pkg) + ","
}
str = strings.TrimSuffix(str, ",")
for name, pkgs := range innerConflicts {
str := red(bold(smallArrow)) + " " + name + ":"
for pkg := range pkgs {
str += " " + cyan(pkg) + ","
}
str = strings.TrimSuffix(str, ",")
fmt.Fprintln(os.Stderr, str)
}
for _, pkg := range ds.Repo {
if pkgs, ok := conflicts[pkg.Name()]; ok {
printConflict(pkg.Name(), pkgs)
}
}
for _, base := range ds.Aur {
for _, pkg := range base {
if pkgs, ok := conflicts[pkg.Name]; ok {
printConflict(pkg.Name, pkgs)
}
}
}
fmt.Println(str)
}
}
repoStr := red(bold(smallArrow)) + " %s Conflicts with:"
formatConflicts(repoConflicts, true, repoStr)
if len(conflicts) != 0 {
fmt.Println()
fmt.Println(bold(red(arrow)), bold("Package conflicts found:"))
for name, pkgs := range conflicts {
str := red(bold(smallArrow)) + " Installing " + cyan(name) + " will remove:"
for pkg := range pkgs {
str += " " + cyan(pkg) + ","
}
str = strings.TrimSuffix(str, ",")
fmt.Println(str)
}
if len(repoConflicts) > 0 {
return nil, fmt.Errorf("Unavoidable conflicts, aborting")
}
str := red(bold(smallArrow)) + " Installing %s will remove:"
formatConflicts(conflicts, false, str)
formatConflicts(innerConflicts, true, str)
for name, c := range innerConflicts {
for cs, _ := range c {
conflicts.Add(name, cs)
// Add the inner conflicts to the conflicts
// These are used to decide what to pass --ask to (if set) or don't pass --noconfirm to
// As we have no idea what the order is yet we add every inner conflict to the slice
for name, pkgs := range innerConflicts {
conflicts[name] = make(stringSet)
for pkg := range pkgs {
conflicts[pkg] = make(stringSet)
}
}
@ -327,3 +201,96 @@ func (ds *depSolver) CheckConflicts() (mapStringSet, error) {
return conflicts, nil
}
type missing struct {
Good stringSet
Missing map[string][][]string
}
func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) {
if missing.Good.get(dep) {
return
}
if trees, ok := missing.Missing[dep]; ok {
for _, tree := range trees {
if stringSliceEqual(tree, stack) {
return
}
}
missing.Missing[dep] = append(missing.Missing[dep], stack)
return
}
aurPkg := dp.findSatisfierAur(dep)
if aurPkg != nil {
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 {
missing.Good.set(aurDep)
continue
}
dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing)
}
}
return
}
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
}
dp._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing)
return nil
})
return
}
missing.Missing[dep] = [][]string{stack}
}
func (dp *depPool) CheckMissing() error {
missing := &missing{
make(stringSet),
make(map[string][][]string),
}
for _, target := range dp.Targets {
dp._checkMissing(target.DepString(), make([]string, 0), missing)
}
if len(missing.Missing) == 0 {
return nil
}
fmt.Println(bold(red(arrow+" Error: ")) + "Could not find all required packages:")
for dep, trees := range missing.Missing {
for _, tree := range trees {
fmt.Print(" ", cyan(dep))
if len(tree) == 0 {
fmt.Print(" (Target")
} else {
fmt.Print(" (Wanted by: ")
for n := 0; n < len(tree)-1; n++ {
fmt.Print(cyan(tree[n]), " -> ")
}
fmt.Print(cyan(tree[len(tree)-1]))
}
fmt.Println(")")
}
}
return fmt.Errorf("")
}

135
depOrder.go Normal file
View File

@ -0,0 +1,135 @@
package main
import (
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
)
type Base []*rpc.Pkg
func (b Base) Pkgbase() string {
return b[0].PackageBase
}
func (b Base) Version() string {
return b[0].Version
}
func (b Base) URLPath() string {
return b[0].URLPath
}
type depOrder struct {
Aur []Base
Repo []*alpm.Package
Runtime stringSet
}
func makeDepOrder() *depOrder {
return &depOrder{
make([]Base, 0),
make([]*alpm.Package, 0),
make(stringSet),
}
}
func getDepOrder(dp *depPool) *depOrder {
do := makeDepOrder()
for _, target := range dp.Targets {
dep := target.DepString()
aurPkg := dp.Aur[dep]
if aurPkg != nil && pkgSatisfies(aurPkg.Name, aurPkg.Version, dep) {
do.orderPkgAur(aurPkg, dp, true)
}
aurPkg = dp.findSatisfierAur(dep)
if aurPkg != nil {
do.orderPkgAur(aurPkg, dp, true)
}
repoPkg := dp.findSatisfierRepo(dep)
if repoPkg != nil {
do.orderPkgRepo(repoPkg, dp, true)
}
}
return do
}
func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) {
if runtime {
do.Runtime.set(pkg.Name)
}
delete(dp.Aur, pkg.Name)
for i, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, dep := range deps {
aurPkg := dp.findSatisfierAur(dep)
if aurPkg != nil {
do.orderPkgAur(aurPkg, dp, runtime && i == 0)
}
repoPkg := dp.findSatisfierRepo(dep)
if repoPkg != nil {
do.orderPkgRepo(repoPkg, dp, runtime && i == 0)
}
}
}
for i, base := range do.Aur {
if base.Pkgbase() == pkg.PackageBase {
do.Aur[i] = append(base, pkg)
return
}
}
do.Aur = append(do.Aur, Base{pkg})
}
func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) {
if runtime {
do.Runtime.set(pkg.Name())
}
delete(dp.Repo, pkg.Name())
pkg.Depends().ForEach(func(dep alpm.Depend) (err error) {
repoPkg := dp.findSatisfierRepo(dep.String())
if repoPkg != nil {
do.orderPkgRepo(repoPkg, dp, runtime)
}
return nil
})
do.Repo = append(do.Repo, pkg)
}
func (do *depOrder) HasMake() bool {
lenAur := 0
for _, base := range do.Aur {
lenAur += len(base)
}
return len(do.Runtime) != lenAur+len(do.Repo)
}
func (do *depOrder) getMake() []string {
makeOnly := make([]string, 0, len(do.Aur)+len(do.Repo)-len(do.Runtime))
for _, base := range do.Aur {
for _, pkg := range base {
if !do.Runtime.get(pkg.Name) {
makeOnly = append(makeOnly, pkg.Name)
}
}
}
for _, pkg := range do.Repo {
if !do.Runtime.get(pkg.Name()) {
makeOnly = append(makeOnly, pkg.Name())
}
}
return makeOnly
}

477
depPool.go Normal file
View File

@ -0,0 +1,477 @@
package main
import (
"sort"
"strings"
"sync"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
)
type target struct {
Db string
Name string
Mod string
Version string
}
func toTarget(pkg string) target {
db, dep := splitDbFromName(pkg)
name, mod, version := splitDep(dep)
return target{
db,
name,
mod,
version,
}
}
func (t target) DepString() string {
return t.Name + t.Mod + t.Version
}
func (t target) String() string {
if t.Db != "" {
return t.Db + "/" + t.DepString()
}
return t.DepString()
}
type depPool struct {
Targets []target
Explicit 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 *aurWarnings
}
func makeDepPool() (*depPool, error) {
localDb, err := alpmHandle.LocalDb()
if err != nil {
return nil, err
}
syncDb, err := alpmHandle.SyncDbs()
if err != nil {
return nil, err
}
dp := &depPool{
make([]target, 0),
make(stringSet),
make(map[string]*alpm.Package),
make(map[string]*rpc.Pkg),
make(map[string]*rpc.Pkg),
make([]string, 0),
localDb,
syncDb,
nil,
}
return dp, nil
}
// Includes db/ prefixes and group installs
func (dp *depPool) ResolveTargets(pkgs []string) error {
// RPC requests are slow
// Combine as many AUR package requests as possible into a single RPC
// call
aurTargets := make(stringSet)
pkgs = removeInvalidTargets(pkgs)
for _, pkg := range pkgs {
var err error
target := toTarget(pkg)
// skip targets already satisfied
// even if the user enters db/pkg and aur/pkg the latter will
// still get skipped even if it's from a different database to
// the one specified
// this is how pacman behaves
if dp.hasPackage(target.DepString()) {
continue
}
var foundPkg *alpm.Package
var singleDb *alpm.Db
// aur/ prefix means we only check the aur
if target.Db == "aur" || mode == modeAUR {
dp.Targets = append(dp.Targets, target)
aurTargets.set(target.DepString())
continue
}
// If there'ss a different priefix 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
} else {
foundPkg, err = dp.SyncDb.FindSatisfier(target.DepString())
}
if err == nil {
dp.Targets = append(dp.Targets, target)
dp.Explicit.set(foundPkg.Name())
dp.ResolveRepoDependency(foundPkg)
continue
} else {
//check for groups
//currently we don't resolve the packages in a group
//only check if the group exists
//would be better to check the groups from singleDb if
//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, err := dp.SyncDb.PkgCachebyGroup(target.Name)
if err == nil {
dp.Groups = append(dp.Groups, target.String())
group.ForEach(func(pkg alpm.Package) error {
dp.Explicit.set(pkg.Name())
return nil
})
continue
}
}
//if there was no db prefix check the aur
if target.Db == "" {
aurTargets.set(target.DepString())
}
dp.Targets = append(dp.Targets, target)
}
if len(aurTargets) > 0 && (mode == modeAny || mode == modeAUR) {
return dp.resolveAURPackages(aurTargets, true)
}
return nil
}
// Pseudo provides finder.
// Try to find provides by performing a search of the package name
// This effectively performs -Ss on each package
// then runs -Si on each result to cache the information.
//
// For example if you were to -S yay then yay -Ss would give:
// yay-git yay-bin yay realyog pacui pacui-git ruby-yard
// These packages will all be added to the cache in case they are needed later
// Ofcouse only the first three packages provide yay, the rest are just false
// positives.
//
// This method increases dependency resolve time
func (dp *depPool) findProvides(pkgs stringSet) error {
var mux sync.Mutex
var wg sync.WaitGroup
doSearch := func(pkg string) {
defer wg.Done()
var err error
var results []rpc.Pkg
// Hack for a bigger search result, if the user wants
// java-envronment we can search for just java instead and get
// more hits.
words := strings.Split(pkg, "-")
for i := range words {
results, err = rpc.SearchByNameDesc(strings.Join(words[:i+1], "-"))
if err == nil {
break
}
}
if err != nil {
return
}
for _, result := range results {
mux.Lock()
if _, ok := dp.AurCache[result.Name]; !ok {
pkgs.set(result.Name)
}
mux.Unlock()
}
}
for pkg := range pkgs {
if _, err := dp.LocalDb.PkgByName(pkg); err == nil {
continue
}
wg.Add(1)
go doSearch(pkg)
}
wg.Wait()
return nil
}
func (dp *depPool) cacheAURPackages(_pkgs stringSet) error {
pkgs := _pkgs.copy()
query := make([]string, 0)
for pkg := range pkgs {
if _, ok := dp.AurCache[pkg]; ok {
pkgs.remove(pkg)
}
}
if len(pkgs) == 0 {
return nil
}
if config.Provides {
err := dp.findProvides(pkgs)
if err != nil {
return err
}
}
for pkg := range pkgs {
if _, ok := dp.AurCache[pkg]; !ok {
name, _, _ := splitDep(pkg)
query = append(query, name)
}
}
info, err := aurInfo(query, dp.Warnings)
if err != nil {
return err
}
for _, pkg := range info {
// Dump everything in cache just in case we need it later
dp.AurCache[pkg.Name] = pkg
}
return nil
}
func (dp *depPool) resolveAURPackages(pkgs stringSet, explicit bool) error {
newPackages := make(stringSet)
newAURPackages := make(stringSet)
err := dp.cacheAURPackages(pkgs)
if err != nil {
return err
}
if len(pkgs) == 0 {
return nil
}
for name := range pkgs {
_, ok := dp.Aur[name]
if ok {
continue
}
pkg := dp.findSatisfierAurCache(name)
if pkg == nil {
continue
}
if explicit {
dp.Explicit.set(pkg.Name)
}
dp.Aur[pkg.Name] = pkg
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, dep := range deps {
newPackages.set(dep)
}
}
}
for dep := range newPackages {
if dp.hasSatisfier(dep) {
continue
}
_, isInstalled := dp.LocalDb.PkgCache().FindSatisfier(dep) //has satisfier installed: skip
hm := hideMenus
hideMenus = isInstalled == nil
repoPkg, inRepos := dp.SyncDb.FindSatisfier(dep) //has satisfier in repo: fetch it
hideMenus = hm
if isInstalled == nil && (config.ReBuild != "tree" || inRepos == nil) {
continue
}
if inRepos == nil {
dp.ResolveRepoDependency(repoPkg)
continue
}
//assume it's in the aur
//ditch the versioning because the RPC can't handle it
newAURPackages.set(dep)
}
err = dp.resolveAURPackages(newAURPackages, false)
return err
}
func (dp *depPool) ResolveRepoDependency(pkg *alpm.Package) {
dp.Repo[pkg.Name()] = pkg
pkg.Depends().ForEach(func(dep alpm.Depend) (err error) {
//have satisfier in dep tree: skip
if dp.hasSatisfier(dep.String()) {
return
}
//has satisfier installed: skip
_, isInstalled := dp.LocalDb.PkgCache().FindSatisfier(dep.String())
if isInstalled == nil {
return
}
//has satisfier in repo: fetch it
repoPkg, inRepos := dp.SyncDb.FindSatisfier(dep.String())
if inRepos != nil {
return
}
dp.ResolveRepoDependency(repoPkg)
return nil
})
}
func getDepPool(pkgs []string, warnings *aurWarnings) (*depPool, error) {
dp, err := makeDepPool()
if err != nil {
return nil, err
}
dp.Warnings = warnings
err = dp.ResolveTargets(pkgs)
return dp, err
}
func (dp *depPool) findSatisfierAur(dep string) *rpc.Pkg {
for _, pkg := range dp.Aur {
if satisfiesAur(dep, pkg) {
return pkg
}
}
return nil
}
// This is mostly used to promote packages from the cache
// to the Install list
// Provide a pacman style provider menu if there's more than one candidate
// This acts slightly differently from Pacman, It will give
// a menu even if a package with a matching name exists. I believe this
// method is better because most of the time you are choosing between
// foo and foo-git.
// Using Pacman's ways trying to install foo would never give you
// a menu.
// TODO: maybe intermix repo providers in the menu
func (dp *depPool) findSatisfierAurCache(dep string) *rpc.Pkg {
depName, _, _ := splitDep(dep)
seen := make(stringSet)
providers := makeProviders(depName)
if _, err := dp.LocalDb.PkgByName(depName); err == nil {
if pkg, ok := dp.AurCache[dep]; ok && pkgSatisfies(pkg.Name, pkg.Version, dep) {
return pkg
}
}
if cmdArgs.op == "Y" || cmdArgs.op == "yay" {
for _, pkg := range dp.AurCache {
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
for _, target := range dp.Targets {
if target.Name == pkg.Name {
return pkg
}
}
}
}
}
for _, pkg := range dp.AurCache {
if seen.get(pkg.Name) {
continue
}
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
providers.Pkgs = append(providers.Pkgs, pkg)
seen.set(pkg.Name)
continue
}
for _, provide := range pkg.Provides {
if provideSatisfies(provide, dep) {
providers.Pkgs = append(providers.Pkgs, pkg)
seen.set(pkg.Name)
continue
}
}
}
if providers.Len() == 1 {
return providers.Pkgs[0]
}
if providers.Len() > 1 {
sort.Sort(providers)
return providerMenu(dep, providers)
}
return nil
}
func (dp *depPool) findSatisfierRepo(dep string) *alpm.Package {
for _, pkg := range dp.Repo {
if satisfiesRepo(dep, pkg) {
return pkg
}
}
return nil
}
func (dp *depPool) hasSatisfier(dep string) bool {
return dp.findSatisfierRepo(dep) != nil || dp.findSatisfierAur(dep) != nil
}
func (dp *depPool) hasPackage(name string) bool {
for _, pkg := range dp.Repo {
if pkg.Name() == name {
return true
}
}
for _, pkg := range dp.Aur {
if pkg.Name == name {
return true
}
}
for _, pkg := range dp.Groups {
if pkg == name {
return true
}
}
return false
}

View File

@ -1,631 +0,0 @@
package main
import (
"sort"
"strings"
"sync"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
)
type depSolver struct {
Aur []Base
Repo []*alpm.Package
Runtime stringSet
Targets []target
Explicit stringSet
AurCache map[string]*rpc.Pkg
Groups []string
LocalDb *alpm.Db
SyncDb alpm.DbList
Seen stringSet
Warnings *aurWarnings
}
func makeDepSolver() (*depSolver, error) {
localDb, err := alpmHandle.LocalDb()
if err != nil {
return nil, err
}
syncDb, err := alpmHandle.SyncDbs()
if err != nil {
return nil, err
}
return &depSolver{
make([]Base, 0),
make([]*alpm.Package, 0),
make(stringSet),
make([]target, 0),
make(stringSet),
make(map[string]*rpc.Pkg),
make([]string, 0),
localDb,
syncDb,
make(stringSet),
nil,
}, nil
}
func getDepSolver(pkgs []string, warnings *aurWarnings) (*depSolver, error) {
ds, err := makeDepSolver()
if err != nil {
return nil, err
}
ds.Warnings = warnings
err = ds.resolveTargets(pkgs)
if err != nil {
return nil, err
}
ds.resolveRuntime()
return ds, err
}
// Includes db/ prefixes and group installs
func (ds *depSolver) resolveTargets(pkgs []string) error {
// RPC requests are slow
// Combine as many AUR package requests as possible into a single RPC
// call
aurTargets := make([]string, 0)
pkgs = removeInvalidTargets(pkgs)
for _, pkg := range pkgs {
var err error
target := toTarget(pkg)
// skip targets already satisfied
// even if the user enters db/pkg and aur/pkg the latter will
// still get skipped even if it's from a different database to
// the one specified
// this is how pacman behaves
if ds.hasPackage(target.DepString()) {
continue
}
var foundPkg *alpm.Package
var singleDb *alpm.Db
// aur/ prefix means we only check the aur
if target.Db == "aur" || mode == modeAUR {
ds.Targets = append(ds.Targets, target)
aurTargets = append(aurTargets, target.DepString())
continue
}
// If there'ss a different priefix 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
} else {
foundPkg, err = ds.SyncDb.FindSatisfier(target.DepString())
}
if err == nil {
ds.Targets = append(ds.Targets, target)
ds.Explicit.set(foundPkg.Name())
ds.ResolveRepoDependency(foundPkg)
continue
} else {
//check for groups
//currently we don't resolve the packages in a group
//only check if the group exists
//would be better to check the groups from singleDb if
//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, err := ds.SyncDb.PkgCachebyGroup(target.Name)
if err == nil {
ds.Groups = append(ds.Groups, target.String())
group.ForEach(func(pkg alpm.Package) error {
ds.Explicit.set(pkg.Name())
return nil
})
continue
}
}
//if there was no db prefix check the aur
if target.Db == "" {
aurTargets = append(aurTargets, target.DepString())
}
ds.Targets = append(ds.Targets, target)
}
if len(aurTargets) > 0 && (mode == modeAny || mode == modeAUR) {
return ds.resolveAURPackages(aurTargets, true)
}
return nil
}
func (ds *depSolver) hasPackage(name string) bool {
for _, pkg := range ds.Repo {
if pkg.Name() == name {
return true
}
}
for _, base := range ds.Aur {
for _, pkg := range base {
if pkg.Name == name {
return true
}
}
}
for _, pkg := range ds.Groups {
if pkg == name {
return true
}
}
return false
}
func (ds *depSolver) findSatisfierAur(dep string) *rpc.Pkg {
for _, base := range ds.Aur {
for _, pkg := range base {
if satisfiesAur(dep, pkg) {
return pkg
}
}
}
return nil
}
func (ds *depSolver) findSatisfierRepo(dep string) *alpm.Package {
for _, pkg := range ds.Repo {
if satisfiesRepo(dep, pkg) {
return pkg
}
}
return nil
}
func (ds *depSolver) hasSatisfier(dep string) bool {
return ds.findSatisfierRepo(dep) != nil || ds.findSatisfierAur(dep) != nil
}
func (ds *depSolver) ResolveRepoDependency(pkg *alpm.Package) {
if ds.Seen.get(pkg.Name()) {
return
}
ds.Repo = append(ds.Repo, pkg)
ds.Seen.set(pkg.Name())
pkg.Depends().ForEach(func(dep alpm.Depend) (err error) {
//have satisfier in dep tree: skip
if ds.hasSatisfier(dep.String()) {
return
}
//has satisfier installed: skip
_, isInstalled := ds.LocalDb.PkgCache().FindSatisfier(dep.String())
if isInstalled == nil {
return
}
//has satisfier in repo: fetch it
repoPkg, inRepos := ds.SyncDb.FindSatisfier(dep.String())
if inRepos != nil {
return
}
ds.ResolveRepoDependency(repoPkg)
return nil
})
}
// This is mostly used to promote packages from the cache
// to the Install list
// Provide a pacman style provider menu if there's more than one candidate
// This acts slightly differently from Pacman, It will give
// a menu even if a package with a matching name exists. I believe this
// method is better because most of the time you are choosing between
// foo and foo-git.
// Using Pacman's ways trying to install foo would never give you
// a menu.
// TODO: maybe intermix repo providers in the menu
func (ds *depSolver) findSatisfierAurCache(dep string) *rpc.Pkg {
depName, _, _ := splitDep(dep)
seen := make(stringSet)
providers := makeProviders(depName)
if _, err := ds.LocalDb.PkgByName(depName); err == nil {
if pkg, ok := ds.AurCache[dep]; ok && pkgSatisfies(pkg.Name, pkg.Version, dep) {
return pkg
}
}
if cmdArgs.op == "Y" || cmdArgs.op == "yay" {
for _, pkg := range ds.AurCache {
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
for _, target := range ds.Targets {
if target.Name == pkg.Name {
return pkg
}
}
}
}
}
for _, pkg := range ds.AurCache {
if seen.get(pkg.Name) {
continue
}
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
providers.Pkgs = append(providers.Pkgs, pkg)
seen.set(pkg.Name)
continue
}
for _, provide := range pkg.Provides {
if provideSatisfies(provide, dep) {
providers.Pkgs = append(providers.Pkgs, pkg)
seen.set(pkg.Name)
continue
}
}
}
if !config.Provides && providers.Len() >= 1 {
return providers.Pkgs[0]
}
if providers.Len() == 1 {
return providers.Pkgs[0]
}
if providers.Len() > 1 {
sort.Sort(providers)
return providerMenu(dep, providers)
}
return nil
}
func (ds *depSolver) cacheAURPackages(_pkgs []string) error {
pkgs := sliceToStringSet(_pkgs)
query := make([]string, 0)
for pkg := range pkgs {
if _, ok := ds.AurCache[pkg]; ok {
pkgs.remove(pkg)
}
}
if len(pkgs) == 0 {
return nil
}
if config.Provides {
err := ds.findProvides(pkgs)
if err != nil {
return err
}
}
for pkg := range pkgs {
if _, ok := ds.AurCache[pkg]; !ok {
name, _, _ := splitDep(pkg)
query = append(query, name)
}
}
info, err := aurInfo(query, ds.Warnings)
if err != nil {
return err
}
for _, pkg := range info {
// Dump everything in cache just in case we need it later
ds.AurCache[pkg.Name] = pkg
}
return nil
}
// Pseudo provides finder.
// Try to find provides by performing a search of the package name
// This effectively performs -Ss on each package
// then runs -Si on each result to cache the information.
//
// For example if you were to -S yay then yay -Ss would give:
// yay-git yay-bin yay realyog pacui pacui-git ruby-yard
// These packages will all be added to the cache in case they are needed later
// Ofcouse only the first three packages provide yay, the rest are just false
// positives.
//
// This method increases dependency resolve time
func (ds *depSolver) findProvides(pkgs stringSet) error {
var mux sync.Mutex
var wg sync.WaitGroup
doSearch := func(pkg string) {
defer wg.Done()
var err error
var results []rpc.Pkg
// Hack for a bigger search result, if the user wants
// java-envronment we can search for just java instead and get
// more hits.
words := strings.Split(pkg, "-")
for i := range words {
results, err = rpc.SearchByNameDesc(strings.Join(words[:i+1], "-"))
if err == nil {
break
}
}
if err != nil {
return
}
for _, result := range results {
mux.Lock()
if _, ok := ds.AurCache[result.Name]; !ok {
pkgs.set(result.Name)
}
mux.Unlock()
}
}
for pkg := range pkgs {
if _, err := ds.LocalDb.PkgByName(pkg); err == nil {
continue
}
wg.Add(1)
go doSearch(pkg)
}
wg.Wait()
return nil
}
func (ds *depSolver) resolveAURPackages(pkgs []string, explicit bool) error {
newPackages := make(stringSet)
newAURPackages := make([]string, 0)
toAdd := make([]*rpc.Pkg, 0)
if len(pkgs) == 0 {
return nil
}
err := ds.cacheAURPackages(pkgs)
if err != nil {
return err
}
for _, name := range pkgs {
if ds.Seen.get(name) {
continue
}
pkg := ds.findSatisfierAurCache(name)
if pkg == nil {
continue
}
if explicit {
ds.Explicit.set(pkg.Name)
}
ds.Seen.set(pkg.Name)
toAdd = append(toAdd, pkg)
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, dep := range deps {
newPackages.set(dep)
}
}
}
for dep := range newPackages {
if ds.hasSatisfier(dep) {
continue
}
_, isInstalled := ds.LocalDb.PkgCache().FindSatisfier(dep) //has satisfier installed: skip
hm := hideMenus
hideMenus = isInstalled == nil
repoPkg, inRepos := ds.SyncDb.FindSatisfier(dep) //has satisfier in repo: fetch it
hideMenus = hm
if isInstalled == nil && (config.ReBuild != "tree" || inRepos == nil) {
continue
}
if inRepos == nil {
ds.ResolveRepoDependency(repoPkg)
continue
}
//assume it's in the aur
//ditch the versioning because the RPC can't handle it
newAURPackages = append(newAURPackages, dep)
}
err = ds.resolveAURPackages(newAURPackages, false)
for _, pkg := range toAdd {
if !ds.hasPackage(pkg.Name) {
ds.Aur = baseAppend(ds.Aur, pkg)
}
}
return err
}
func (ds *depSolver) Print() {
repo := ""
repoMake := ""
aur := ""
aurMake := ""
repoLen := 0
repoMakeLen := 0
aurLen := 0
aurMakeLen := 0
for _, pkg := range ds.Repo {
if ds.Runtime.get(pkg.Name()) {
repo += " " + pkg.Name() + "-" + pkg.Version()
repoLen++
} else {
repoMake += " " + pkg.Name() + "-" + pkg.Version()
repoMakeLen++
}
}
for _, base := range ds.Aur {
pkg := base.Pkgbase()
pkgStr := " " + pkg + "-" + base[0].Version
pkgStrMake := pkgStr
push := false
pushMake := false
if len(base) > 1 || pkg != base[0].Name {
pkgStr += " ("
pkgStrMake += " ("
for _, split := range base {
if ds.Runtime.get(split.Name) {
pkgStr += split.Name + " "
aurLen++
push = true
} else {
pkgStrMake += split.Name + " "
aurMakeLen++
pushMake = true
}
}
pkgStr = pkgStr[:len(pkgStr)-1] + ")"
pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")"
} else if ds.Runtime.get(base[0].Name) {
aurLen++
push = true
} else {
aurMakeLen++
pushMake = true
}
if push {
aur += pkgStr
}
if pushMake {
aurMake += pkgStrMake
}
}
printDownloads("Repo", repoLen, repo)
printDownloads("Repo Make", repoMakeLen, repoMake)
printDownloads("Aur", aurLen, aur)
printDownloads("Aur Make", aurMakeLen, aurMake)
}
func (ds *depSolver) resolveRuntime() {
for _, pkg := range ds.Repo {
if ds.Explicit.get(pkg.Name()) {
ds.Runtime.set(pkg.Name())
ds.resolveRuntimeRepo(pkg)
}
}
for _, base := range ds.Aur {
for _, pkg := range base {
if ds.Explicit.get(pkg.Name) {
ds.Runtime.set(pkg.Name)
ds.resolveRuntimeAur(pkg)
}
}
}
}
func (ds *depSolver) resolveRuntimeRepo(pkg *alpm.Package) {
pkg.Depends().ForEach(func(dep alpm.Depend) (err error) {
for _, pkg := range ds.Repo {
if ds.Runtime.get(pkg.Name()) {
continue
}
if satisfiesRepo(dep.String(), pkg) {
ds.Runtime.set(pkg.Name())
ds.resolveRuntimeRepo(pkg)
}
}
return nil
})
}
func (ds *depSolver) resolveRuntimeAur(pkg *rpc.Pkg) {
for _, dep := range pkg.Depends {
for _, pkg := range ds.Repo {
if ds.Runtime.get(pkg.Name()) {
continue
}
if satisfiesRepo(dep, pkg) {
ds.Runtime.set(pkg.Name())
ds.resolveRuntimeRepo(pkg)
}
}
for _, base := range ds.Aur {
for _, pkg := range base {
if ds.Runtime.get(pkg.Name) {
continue
}
if satisfiesAur(dep, pkg) {
ds.Runtime.set(pkg.Name)
ds.resolveRuntimeAur(pkg)
}
}
}
}
}
func (ds *depSolver) HasMake() bool {
lenAur := 0
for _, base := range ds.Aur {
lenAur += len(base)
}
return len(ds.Runtime) != lenAur+len(ds.Repo)
}
func (ds *depSolver) getMake() []string {
makeOnly := make([]string, 0, len(ds.Aur)+len(ds.Repo)-len(ds.Runtime))
for _, base := range ds.Aur {
for _, pkg := range base {
if !ds.Runtime.get(pkg.Name) {
makeOnly = append(makeOnly, pkg.Name)
}
}
}
for _, pkg := range ds.Repo {
if !ds.Runtime.get(pkg.Name()) {
makeOnly = append(makeOnly, pkg.Name())
}
}
return makeOnly
}

View File

@ -17,6 +17,7 @@ import (
func install(parser *arguments) error {
var err error
var incompatible stringSet
var do *depOrder
var aurUp upSlice
var repoUp upSlice
@ -109,17 +110,17 @@ func install(parser *arguments) error {
targets := sliceToStringSet(parser.targets)
ds, err := getDepSolver(requestTargets, warnings)
dp, err := getDepPool(requestTargets, warnings)
if err != nil {
return err
}
err = ds.CheckMissing()
err = dp.CheckMissing()
if err != nil {
return err
}
if len(ds.Aur) == 0 {
if len(dp.Aur) == 0 {
if !config.CombinedUpgrade {
if parser.existsArg("u", "sysupgrade") {
fmt.Println(" there is nothing to do")
@ -133,32 +134,37 @@ func install(parser *arguments) error {
return show(passToPacman(parser))
}
if len(ds.Aur) > 0 && 0 == os.Geteuid() {
if len(dp.Aur) > 0 && 0 == os.Geteuid() {
return fmt.Errorf(bold(red(arrow)) + " Refusing to install AUR Packages as root, Aborting.")
}
conflicts, err := ds.CheckConflicts()
conflicts, err := dp.CheckConflicts()
if err != nil {
return err
}
for _, pkg := range ds.Repo {
do = getDepOrder(dp)
if err != nil {
return err
}
for _, pkg := range do.Repo {
arguments.addTarget(pkg.DB().Name() + "/" + pkg.Name())
}
for _, pkg := range ds.Groups {
for _, pkg := range dp.Groups {
arguments.addTarget(pkg)
}
if len(ds.Aur) == 0 && len(arguments.targets) == 0 && (!parser.existsArg("u", "sysupgrade") || mode == modeAUR) {
if len(do.Aur) == 0 && len(arguments.targets) == 0 && (!parser.existsArg("u", "sysupgrade") || mode == modeAUR) {
fmt.Println(" there is nothing to do")
return nil
}
ds.Print()
do.Print()
fmt.Println()
if ds.HasMake() {
if do.HasMake() {
if config.RemoveMake == "yes" {
removeMake = true
} else if config.RemoveMake == "no" {
@ -169,9 +175,9 @@ func install(parser *arguments) error {
}
if config.CleanMenu {
if anyExistInCache(ds.Aur) {
askClean := pkgbuildNumberMenu(ds.Aur, remoteNamesCache)
toClean, err := cleanNumberMenu(ds.Aur, remoteNamesCache, askClean)
if anyExistInCache(do.Aur) {
askClean := pkgbuildNumberMenu(do.Aur, remoteNamesCache)
toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean)
if err != nil {
return err
}
@ -180,8 +186,8 @@ func install(parser *arguments) error {
}
}
toSkip := pkgbuildsToSkip(ds.Aur, targets)
cloned, err := downloadPkgbuilds(ds.Aur, toSkip, config.BuildDir)
toSkip := pkgbuildsToSkip(do.Aur, targets)
cloned, err := downloadPkgbuilds(do.Aur, toSkip, config.BuildDir)
if err != nil {
return err
}
@ -190,8 +196,8 @@ func install(parser *arguments) error {
var toEdit []Base
if config.DiffMenu {
pkgbuildNumberMenu(ds.Aur, remoteNamesCache)
toDiff, err = diffNumberMenu(ds.Aur, remoteNamesCache)
pkgbuildNumberMenu(do.Aur, remoteNamesCache)
toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache)
if err != nil {
return err
}
@ -214,19 +220,19 @@ func install(parser *arguments) error {
config.NoConfirm = oldValue
}
err = mergePkgbuilds(ds.Aur)
err = mergePkgbuilds(do.Aur)
if err != nil {
return err
}
srcinfos, err = parseSrcinfoFiles(ds.Aur, true)
srcinfos, err = parseSrcinfoFiles(do.Aur, true)
if err != nil {
return err
}
if config.EditMenu {
pkgbuildNumberMenu(ds.Aur, remoteNamesCache)
toEdit, err = editNumberMenu(ds.Aur, remoteNamesCache)
pkgbuildNumberMenu(do.Aur, remoteNamesCache)
toEdit, err = editNumberMenu(do.Aur, remoteNamesCache)
if err != nil {
return err
}
@ -249,13 +255,13 @@ func install(parser *arguments) error {
config.NoConfirm = oldValue
}
incompatible, err = getIncompatible(ds.Aur, srcinfos)
incompatible, err = getIncompatible(do.Aur, srcinfos)
if err != nil {
return err
}
if config.PGPFetch {
err = checkPgpKeys(ds.Aur, srcinfos)
err = checkPgpKeys(do.Aur, srcinfos)
if err != nil {
return err
}
@ -276,15 +282,15 @@ func install(parser *arguments) error {
expArguments := makeArguments()
expArguments.addArg("D", "asexplicit")
for _, pkg := range ds.Repo {
if !ds.Explicit.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) {
for _, pkg := range do.Repo {
if !dp.Explicit.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) {
depArguments.addTarget(pkg.Name())
continue
}
if parser.existsArg("asdeps", "asdep") && ds.Explicit.get(pkg.Name()) {
if parser.existsArg("asdeps", "asdep") && dp.Explicit.get(pkg.Name()) {
depArguments.addTarget(pkg.Name())
} else if parser.existsArg("asexp", "asexplicit") && ds.Explicit.get(pkg.Name()) {
} else if parser.existsArg("asexp", "asexplicit") && dp.Explicit.get(pkg.Name()) {
expArguments.addTarget(pkg.Name())
}
}
@ -306,12 +312,12 @@ func install(parser *arguments) error {
go updateCompletion(false)
err = downloadPkgbuildsSources(ds.Aur, incompatible)
err = downloadPkgbuildsSources(do.Aur, incompatible)
if err != nil {
return err
}
err = buildInstallPkgbuilds(ds, srcinfos, parser, incompatible, conflicts)
err = buildInstallPkgbuilds(dp, do, srcinfos, parser, incompatible, conflicts)
if err != nil {
return err
}
@ -320,7 +326,7 @@ func install(parser *arguments) error {
removeArguments := makeArguments()
removeArguments.addArg("R", "u")
for _, pkg := range ds.getMake() {
for _, pkg := range do.getMake() {
removeArguments.addTarget(pkg)
}
@ -335,7 +341,7 @@ func install(parser *arguments) error {
}
if config.CleanAfter {
cleanAfter(ds.Aur)
cleanAfter(do.Aur)
}
return nil
@ -894,8 +900,8 @@ func downloadPkgbuildsSources(bases []Base, incompatible stringSet) (err error)
return
}
func buildInstallPkgbuilds(ds *depSolver, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error {
for _, base := range ds.Aur {
func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error {
for _, base := range do.Aur {
pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
built := true
@ -921,7 +927,7 @@ func buildInstallPkgbuilds(ds *depSolver, srcinfos map[string]*gosrc.Srcinfo, pa
isExplicit := false
for _, b := range base {
isExplicit = isExplicit || ds.Explicit.get(b.Name)
isExplicit = isExplicit || dp.Explicit.get(b.Name)
}
if config.ReBuild == "no" || (config.ReBuild == "yes" && !isExplicit) {
for _, split := range base {
@ -944,7 +950,7 @@ func buildInstallPkgbuilds(ds *depSolver, srcinfos map[string]*gosrc.Srcinfo, pa
if cmdArgs.existsArg("needed") {
installed := true
for _, split := range base {
if alpmpkg, err := ds.LocalDb.PkgByName(split.Name); err != nil || alpmpkg.Version() != version {
if alpmpkg, err := dp.LocalDb.PkgByName(split.Name); err != nil || alpmpkg.Version() != version {
installed = false
}
}
@ -1028,11 +1034,11 @@ func buildInstallPkgbuilds(ds *depSolver, srcinfos map[string]*gosrc.Srcinfo, pa
}
arguments.addTarget(pkgdest)
if !ds.Explicit.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) {
if !dp.Explicit.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) {
depArguments.addTarget(split.Name)
}
if ds.Explicit.get(split.Name) {
if dp.Explicit.get(split.Name) {
if parser.existsArg("asdeps", "asdep") {
depArguments.addTarget(split.Name)
} else if parser.existsArg("asexplicit", "asexp") {

View File

@ -189,6 +189,76 @@ func (u upSlice) print() {
}
}
// printDownloadsFromRepo prints repository packages to be downloaded
func (do *depOrder) Print() {
repo := ""
repoMake := ""
aur := ""
aurMake := ""
repoLen := 0
repoMakeLen := 0
aurLen := 0
aurMakeLen := 0
for _, pkg := range do.Repo {
if do.Runtime.get(pkg.Name()) {
repo += " " + pkg.Name() + "-" + pkg.Version()
repoLen++
} else {
repoMake += " " + pkg.Name() + "-" + pkg.Version()
repoMakeLen++
}
}
for _, base := range do.Aur {
pkg := base.Pkgbase()
pkgStr := " " + pkg + "-" + base[0].Version
pkgStrMake := pkgStr
push := false
pushMake := false
if len(base) > 1 || pkg != base[0].Name {
pkgStr += " ("
pkgStrMake += " ("
for _, split := range base {
if do.Runtime.get(split.Name) {
pkgStr += split.Name + " "
aurLen++
push = true
} else {
pkgStrMake += split.Name + " "
aurMakeLen++
pushMake = true
}
}
pkgStr = pkgStr[:len(pkgStr)-1] + ")"
pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")"
} else if do.Runtime.get(base[0].Name) {
aurLen++
push = true
} else {
aurMakeLen++
pushMake = true
}
if push {
aur += pkgStr
}
if pushMake {
aurMake += pkgStrMake
}
}
printDownloads("Repo", repoLen, repo)
printDownloads("Repo Make", repoMakeLen, repoMake)
printDownloads("Aur", aurLen, aur)
printDownloads("Aur Make", aurMakeLen, aurMake)
}
func printDownloads(repoName string, length int, packages string) {
if length < 1 {
return