mirror of
https://github.com/Jguer/yay.git
synced 2024-11-06 17:17:22 +01:00
ea5a94e0f8
--ask is no longer used when installing AUR packages, instead pass no confirm when we know there are no conflicts and wait for manual confirmation when there are. This means that when there are no conflicts there should be no change in behaviour and the user will not need to intervene at all. The old behaviour can still be used with --useask.
281 lines
5.9 KiB
Go
281 lines
5.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
alpm "github.com/jguer/go-alpm"
|
|
// gopkg "github.com/mikkeloscar/gopkgbuild"
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
return nil, fmt.Errorf("Unresolvable package conflicts, aborting")
|
|
}
|
|
|
|
if len(conflicts) != 0 {
|
|
fmt.Println()
|
|
fmt.Println(bold(red(arrow)), bold("Package conflicts found:"))
|
|
|
|
if !config.UseAsk {
|
|
fmt.Println(bold(red(arrow)), bold("You will have to confirm these when installing"))
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
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("")
|
|
}
|