diff --git a/dep.go b/dep.go index b3fae560..d37aee44 100644 --- a/dep.go +++ b/dep.go @@ -8,6 +8,11 @@ import ( rpc "github.com/mikkeloscar/aur" ) +type missing struct { + Good stringSet + Missing map[string][][]string +} + type providers struct { lookfor string Pkgs []*rpc.Pkg @@ -40,6 +45,74 @@ 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 := "" diff --git a/depCheck.go b/depCheck.go index 0a3d26bb..169e4446 100644 --- a/depCheck.go +++ b/depCheck.go @@ -6,207 +6,10 @@ import ( "sync" alpm "github.com/jguer/go-alpm" + rpc "github.com/mikkeloscar/aur" ) -func (dp *depPool) checkInnerConflict(name string, conflict string, conflicts mapStringSet) { - for _, pkg := range dp.Aur { - if pkg.Name == name { - continue - } - - if satisfiesAur(conflict, pkg) { - conflicts.Add(name, pkg.Name) - } - } - - for _, pkg := range dp.Repo { - if pkg.Name() == name { - continue - } - - if satisfiesRepo(conflict, pkg) { - conflicts.Add(name, 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) - } - - return nil - }) -} - -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 + ")" - } - - conflicts.Add(pkg.Name, name) - } - } - - 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 (dp *depPool) checkInnerConflicts(conflicts mapStringSet) { - for _, pkg := range dp.Aur { - for _, conflict := range pkg.Conflicts { - dp.checkInnerConflict(pkg.Name, conflict, conflicts) - } - } - - for _, pkg := range dp.Repo { - pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { - dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts) - return nil - }) - } -} - -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 { - dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts) - return nil - }) - - return nil - }) -} - -func (dp *depPool) CheckConflicts() (mapStringSet, error) { - var wg sync.WaitGroup - innerConflicts := make(mapStringSet) - conflicts := make(mapStringSet) - wg.Add(2) - - fmt.Println(bold(cyan("::") + bold(" Checking for conflicts..."))) - go func() { - dp.checkForwardConflicts(conflicts) - dp.checkReverseConflicts(conflicts) - wg.Done() - }() - - fmt.Println(bold(cyan("::") + bold(" Checking for inner conflicts..."))) - go func() { - dp.checkInnerConflicts(innerConflicts) - wg.Done() - }() - - wg.Wait() - - if len(innerConflicts) != 0 { - fmt.Println() - fmt.Println(bold(red(arrow)), bold("Inner conflicts found:")) - - for name, pkgs := range innerConflicts { - str := red(bold(smallArrow)) + " " + name + ":" - for pkg := range pkgs { - str += " " + cyan(pkg) + "," - } - str = strings.TrimSuffix(str, ",") - - fmt.Println(str) - } - - } - - 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) - } - - } - - // 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) - } - } - - if len(conflicts) > 0 { - if !config.UseAsk { - if config.NoConfirm { - return nil, fmt.Errorf("Package conflicts can not be resolved with noconfirm, aborting") - } - - fmt.Println() - fmt.Println(bold(red(arrow)), bold("Conflicting packages will have to be confirmed manually")) - fmt.Println() - } - } - - return conflicts, nil -} - -type missing struct { - Good stringSet - Missing map[string][][]string -} - -func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { +func (ds *depSolver) _checkMissing(dep string, stack []string, missing *missing) { if missing.Good.get(dep) { return } @@ -221,33 +24,33 @@ func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { return } - aurPkg := dp.findSatisfierAur(dep) + 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 := dp.LocalDb.PkgCache().FindSatisfier(aurDep); err == nil { + if _, err := ds.LocalDb.PkgCache().FindSatisfier(aurDep); err == nil { missing.Good.set(aurDep) continue } - dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing) + ds._checkMissing(aurDep, append(stack, aurPkg.Name), missing) } } return } - repoPkg := dp.findSatisfierRepo(dep) + repoPkg := ds.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 { + if _, err := ds.LocalDb.PkgCache().FindSatisfier(repoDep.String()); err == nil { missing.Good.set(repoDep.String()) return nil } - dp._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing) + ds._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing) return nil }) @@ -257,14 +60,14 @@ func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { missing.Missing[dep] = [][]string{stack} } -func (dp *depPool) CheckMissing() error { +func (ds *depSolver) CheckMissing() error { missing := &missing{ make(stringSet), make(map[string][][]string), } - for _, target := range dp.Targets { - dp._checkMissing(target.DepString(), make([]string, 0), missing) + for _, target := range ds.Targets { + ds._checkMissing(target.DepString(), make([]string, 0), missing) } if len(missing.Missing) == 0 { @@ -293,3 +96,233 @@ func (dp *depPool) CheckMissing() error { 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()) { + return nil + } + + if satisfiesRepo(conflict, &pkg) { + n := pkg.Name() + conflicts.Add(name, n) + } + + return nil + }) +} + +func (ds *depSolver) checkReverseConflict(name string, conflict string, conflicts mapStringSet) { + for _, base := range ds.Aur { + for _, pkg := range base { + if pkg.Name == name { + continue + } + + if satisfiesAur(conflict, pkg) { + conflicts.Add(pkg.Name, name) + } + } + } + + for _, pkg := range ds.Repo { + if pkg.Name() == name { + continue + } + + if satisfiesRepo(conflict, pkg) { + 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) + } + } + } + + for _, pkg := range ds.Repo { + pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { + ds.checkForwardConflict(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()) { + return nil + } + + pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { + ds.checkReverseConflict(pkg.Name(), conflict.String(), conflicts) + return nil + }) + + return nil + }) +} + +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) { + var wg sync.WaitGroup + innerConflicts := make(mapStringSet) + conflicts := make(mapStringSet) + repoConflicts := make(mapStringSet) + wg.Add(3) + + fmt.Println(bold(cyan("::") + bold(" Checking for conflicts..."))) + go func() { + ds.checkForwardConflicts(conflicts) + ds.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) + wg.Done() + }() + + wg.Wait() + + formatConflicts := func(conflicts mapStringSet, inner bool, s string) { + if len(conflicts) != 0 { + fmt.Println() + if inner { + fmt.Println(bold(red(arrow)), bold("Inner conflicts found:")) + } else { + fmt.Println(bold(red(arrow)), bold("Package 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, ",") + + fmt.Println(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) + } + } + } + } + } + + repoStr := red(bold(smallArrow)) + " %s Conflicts with:" + formatConflicts(repoConflicts, true, repoStr) + + 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) + } + } + + if len(conflicts) > 0 { + if !config.UseAsk { + if config.NoConfirm { + return nil, fmt.Errorf("Package conflicts can not be resolved with noconfirm, aborting") + } + + fmt.Println() + fmt.Println(bold(red(arrow)), bold("Conflicting packages will have to be confirmed manually")) + fmt.Println() + } + } + + return conflicts, nil +} diff --git a/depOrder.go b/depOrder.go deleted file mode 100644 index e2d3f9a1..00000000 --- a/depOrder.go +++ /dev/null @@ -1,135 +0,0 @@ -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 -} diff --git a/depPool.go b/depPool.go deleted file mode 100644 index 231cecd9..00000000 --- a/depPool.go +++ /dev/null @@ -1,477 +0,0 @@ -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 -} diff --git a/depSolver.go b/depSolver.go new file mode 100644 index 00000000..100f296e --- /dev/null +++ b/depSolver.go @@ -0,0 +1,627 @@ +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 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 +} diff --git a/install.go b/install.go index 02793d82..083a0cdc 100644 --- a/install.go +++ b/install.go @@ -17,7 +17,6 @@ import ( func install(parser *arguments) error { var err error var incompatible stringSet - var do *depOrder var aurUp upSlice var repoUp upSlice @@ -110,17 +109,17 @@ func install(parser *arguments) error { targets := sliceToStringSet(parser.targets) - dp, err := getDepPool(requestTargets, warnings) + ds, err := getDepSolver(requestTargets, warnings) if err != nil { return err } - err = dp.CheckMissing() + err = ds.CheckMissing() if err != nil { return err } - if len(dp.Aur) == 0 { + if len(ds.Aur) == 0 { if !config.CombinedUpgrade { if parser.existsArg("u", "sysupgrade") { fmt.Println(" there is nothing to do") @@ -134,37 +133,32 @@ func install(parser *arguments) error { return show(passToPacman(parser)) } - if len(dp.Aur) > 0 && 0 == os.Geteuid() { + if len(ds.Aur) > 0 && 0 == os.Geteuid() { return fmt.Errorf(bold(red(arrow)) + " Refusing to install AUR Packages as root, Aborting.") } - conflicts, err := dp.CheckConflicts() + conflicts, err := ds.CheckConflicts() if err != nil { return err } - do = getDepOrder(dp) - if err != nil { - return err - } - - for _, pkg := range do.Repo { + for _, pkg := range ds.Repo { arguments.addTarget(pkg.DB().Name() + "/" + pkg.Name()) } - for _, pkg := range dp.Groups { + for _, pkg := range ds.Groups { arguments.addTarget(pkg) } - if len(do.Aur) == 0 && len(arguments.targets) == 0 && (!parser.existsArg("u", "sysupgrade") || mode == ModeAUR) { + if len(ds.Aur) == 0 && len(arguments.targets) == 0 && (!parser.existsArg("u", "sysupgrade") || mode == ModeAUR) { fmt.Println(" there is nothing to do") return nil } - do.Print() + ds.Print() fmt.Println() - if do.HasMake() { + if ds.HasMake() { if config.RemoveMake == "yes" { removeMake = true } else if config.RemoveMake == "no" { @@ -175,9 +169,9 @@ func install(parser *arguments) error { } if config.CleanMenu { - if anyExistInCache(do.Aur) { - askClean := pkgbuildNumberMenu(do.Aur, remoteNamesCache) - toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean) + if anyExistInCache(ds.Aur) { + askClean := pkgbuildNumberMenu(ds.Aur, remoteNamesCache) + toClean, err := cleanNumberMenu(ds.Aur, remoteNamesCache, askClean) if err != nil { return err } @@ -186,8 +180,8 @@ func install(parser *arguments) error { } } - toSkip := pkgbuildsToSkip(do.Aur, targets) - cloned, err := downloadPkgbuilds(do.Aur, toSkip, config.BuildDir) + toSkip := pkgbuildsToSkip(ds.Aur, targets) + cloned, err := downloadPkgbuilds(ds.Aur, toSkip, config.BuildDir) if err != nil { return err } @@ -196,8 +190,8 @@ func install(parser *arguments) error { var toEdit []Base if config.DiffMenu { - pkgbuildNumberMenu(do.Aur, remoteNamesCache) - toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache) + pkgbuildNumberMenu(ds.Aur, remoteNamesCache) + toDiff, err = diffNumberMenu(ds.Aur, remoteNamesCache) if err != nil { return err } @@ -220,19 +214,19 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - err = mergePkgbuilds(do.Aur) + err = mergePkgbuilds(ds.Aur) if err != nil { return err } - srcinfos, err = parseSrcinfoFiles(do.Aur, true) + srcinfos, err = parseSrcinfoFiles(ds.Aur, true) if err != nil { return err } if config.EditMenu { - pkgbuildNumberMenu(do.Aur, remoteNamesCache) - toEdit, err = editNumberMenu(do.Aur, remoteNamesCache) + pkgbuildNumberMenu(ds.Aur, remoteNamesCache) + toEdit, err = editNumberMenu(ds.Aur, remoteNamesCache) if err != nil { return err } @@ -255,13 +249,13 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - incompatible, err = getIncompatible(do.Aur, srcinfos) + incompatible, err = getIncompatible(ds.Aur, srcinfos) if err != nil { return err } if config.PGPFetch { - err = checkPgpKeys(do.Aur, srcinfos) + err = checkPgpKeys(ds.Aur, srcinfos) if err != nil { return err } @@ -282,15 +276,15 @@ func install(parser *arguments) error { expArguments := makeArguments() expArguments.addArg("D", "asexplicit") - for _, pkg := range do.Repo { - if !dp.Explicit.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) { + for _, pkg := range ds.Repo { + if !ds.Explicit.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) { depArguments.addTarget(pkg.Name()) continue } - if parser.existsArg("asdeps", "asdep") && dp.Explicit.get(pkg.Name()) { + if parser.existsArg("asdeps", "asdep") && ds.Explicit.get(pkg.Name()) { depArguments.addTarget(pkg.Name()) - } else if parser.existsArg("asexp", "asexplicit") && dp.Explicit.get(pkg.Name()) { + } else if parser.existsArg("asexp", "asexplicit") && ds.Explicit.get(pkg.Name()) { expArguments.addTarget(pkg.Name()) } } @@ -312,12 +306,12 @@ func install(parser *arguments) error { go updateCompletion(false) - err = downloadPkgbuildsSources(do.Aur, incompatible) + err = downloadPkgbuildsSources(ds.Aur, incompatible) if err != nil { return err } - err = buildInstallPkgbuilds(dp, do, srcinfos, parser, incompatible, conflicts) + err = buildInstallPkgbuilds(ds, srcinfos, parser, incompatible, conflicts) if err != nil { return err } @@ -326,7 +320,7 @@ func install(parser *arguments) error { removeArguments := makeArguments() removeArguments.addArg("R", "u") - for _, pkg := range do.getMake() { + for _, pkg := range ds.getMake() { removeArguments.addTarget(pkg) } @@ -341,7 +335,7 @@ func install(parser *arguments) error { } if config.CleanAfter { - cleanAfter(do.Aur) + cleanAfter(ds.Aur) } return nil @@ -900,8 +894,8 @@ func downloadPkgbuildsSources(bases []Base, incompatible stringSet) (err error) return } -func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { - for _, base := range do.Aur { +func buildInstallPkgbuilds(ds *depSolver, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { + for _, base := range ds.Aur { pkg := base.Pkgbase() dir := filepath.Join(config.BuildDir, pkg) built := true @@ -927,7 +921,7 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc isExplicit := false for _, b := range base { - isExplicit = isExplicit || dp.Explicit.get(b.Name) + isExplicit = isExplicit || ds.Explicit.get(b.Name) } if config.ReBuild == "no" || (config.ReBuild == "yes" && !isExplicit) { for _, split := range base { @@ -950,7 +944,7 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc if cmdArgs.existsArg("needed") { installed := true for _, split := range base { - if alpmpkg, err := dp.LocalDb.PkgByName(split.Name); err != nil || alpmpkg.Version() != version { + if alpmpkg, err := ds.LocalDb.PkgByName(split.Name); err != nil || alpmpkg.Version() != version { installed = false } } @@ -1034,11 +1028,11 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc } arguments.addTarget(pkgdest) - if !dp.Explicit.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) { + if !ds.Explicit.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) { depArguments.addTarget(split.Name) } - if dp.Explicit.get(split.Name) { + if ds.Explicit.get(split.Name) { if parser.existsArg("asdeps", "asdep") { depArguments.addTarget(split.Name) } else if parser.existsArg("asexplicit", "asexp") { diff --git a/print.go b/print.go index c47e52a4..9df7d609 100644 --- a/print.go +++ b/print.go @@ -189,76 +189,6 @@ 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