123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- package dep
- import (
- "errors"
- "fmt"
- "os"
- "strings"
- "sync"
- "github.com/leonelquinteros/gotext"
- "github.com/Jguer/yay/v12/pkg/stringset"
- "github.com/Jguer/yay/v12/pkg/text"
- )
- func (dp *Pool) checkInnerConflict(name, conflict string, conflicts stringset.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, dp.AlpmExecutor) {
- conflicts.Add(name, pkg.Name())
- }
- }
- }
- func (dp *Pool) checkForwardConflict(name, conflict string, conflicts stringset.MapStringSet) {
- for _, pkg := range dp.AlpmExecutor.LocalPackages() {
- if pkg.Name() == name || dp.hasPackage(pkg.Name()) {
- continue
- }
- if satisfiesRepo(conflict, pkg, dp.AlpmExecutor) {
- n := pkg.Name()
- if n != conflict {
- n += " (" + conflict + ")"
- }
- conflicts.Add(name, n)
- }
- }
- }
- func (dp *Pool) checkReverseConflict(name, conflict string, conflicts stringset.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, dp.AlpmExecutor) {
- if name != conflict {
- name += " (" + conflict + ")"
- }
- conflicts.Add(pkg.Name(), name)
- }
- }
- }
- func (dp *Pool) checkInnerConflicts(conflicts stringset.MapStringSet) {
- for _, pkg := range dp.Aur {
- for _, conflict := range pkg.Conflicts {
- dp.checkInnerConflict(pkg.Name, conflict, conflicts)
- }
- }
- for _, pkg := range dp.Repo {
- for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
- dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts)
- }
- }
- }
- func (dp *Pool) checkForwardConflicts(conflicts stringset.MapStringSet) {
- for _, pkg := range dp.Aur {
- for _, conflict := range pkg.Conflicts {
- dp.checkForwardConflict(pkg.Name, conflict, conflicts)
- }
- }
- for _, pkg := range dp.Repo {
- for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
- dp.checkForwardConflict(pkg.Name(), conflict.String(), conflicts)
- }
- }
- }
- func (dp *Pool) checkReverseConflicts(conflicts stringset.MapStringSet) {
- for _, pkg := range dp.AlpmExecutor.LocalPackages() {
- if dp.hasPackage(pkg.Name()) {
- continue
- }
- for _, conflict := range dp.AlpmExecutor.PackageConflicts(pkg) {
- dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
- }
- }
- }
- func (dp *Pool) CheckConflicts(useAsk, noConfirm, noDeps bool) (stringset.MapStringSet, error) {
- conflicts := make(stringset.MapStringSet)
- if noDeps {
- return conflicts, nil
- }
- var wg sync.WaitGroup
- innerConflicts := make(stringset.MapStringSet)
- wg.Add(2)
- text.OperationInfoln(gotext.Get("Checking for conflicts..."))
- go func() {
- dp.checkForwardConflicts(conflicts)
- dp.checkReverseConflicts(conflicts)
- wg.Done()
- }()
- text.OperationInfoln(gotext.Get("Checking for inner conflicts..."))
- go func() {
- dp.checkInnerConflicts(innerConflicts)
- wg.Done()
- }()
- wg.Wait()
- if len(innerConflicts) != 0 {
- text.Errorln(gotext.Get("Inner conflicts found:"))
- for name, pkgs := range innerConflicts {
- str := text.SprintError(name + ":")
- for pkg := range pkgs {
- str += " " + text.Cyan(pkg) + ","
- }
- str = strings.TrimSuffix(str, ",")
- fmt.Println(str)
- }
- }
- if len(conflicts) != 0 {
- text.Errorln(gotext.Get("Package conflicts found:"))
- for name, pkgs := range conflicts {
- str := text.SprintError(gotext.Get("Installing %s will remove:", text.Cyan(name)))
- for pkg := range pkgs {
- str += " " + text.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.StringSet)
- for pkg := range pkgs {
- conflicts[pkg] = make(stringset.StringSet)
- }
- }
- if len(conflicts) > 0 {
- if !useAsk {
- if noConfirm {
- return nil, errors.New(gotext.Get("package conflicts can not be resolved with noconfirm, aborting"))
- }
- text.Errorln(gotext.Get("Conflicting packages will have to be confirmed manually"))
- }
- }
- return conflicts, nil
- }
- type missing struct {
- Good stringset.StringSet
- Missing map[string][][]string
- }
- func (dp *Pool) _checkMissing(dep string, stack []string, missing *missing, noDeps, noCheckDeps bool) {
- 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
- }
- if aurPkg := dp.findSatisfierAur(dep); aurPkg != nil {
- missing.Good.Set(dep)
- combinedDepList := ComputeCombinedDepList(aurPkg, noDeps, noCheckDeps)
- for _, aurDep := range combinedDepList {
- if dp.AlpmExecutor.LocalSatisfierExists(aurDep) {
- missing.Good.Set(aurDep)
- continue
- }
- dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing, noDeps, noCheckDeps)
- }
- return
- }
- if repoPkg := dp.findSatisfierRepo(dep); repoPkg != nil {
- missing.Good.Set(dep)
- if noDeps {
- return
- }
- for _, dep := range dp.AlpmExecutor.PackageDepends(repoPkg) {
- if dp.AlpmExecutor.LocalSatisfierExists(dep.String()) {
- missing.Good.Set(dep.String())
- continue
- }
- dp._checkMissing(dep.String(), append(stack, repoPkg.Name()), missing, noDeps, noCheckDeps)
- }
- return
- }
- missing.Missing[dep] = [][]string{stack}
- }
- func stringSliceEqual(a, b []string) bool {
- if a == nil && b == nil {
- return true
- }
- if a == nil || b == nil {
- return false
- }
- if len(a) != len(b) {
- return false
- }
- for i := 0; i < len(a); i++ {
- if a[i] != b[i] {
- return false
- }
- }
- return true
- }
- func (dp *Pool) CheckMissing(noDeps, noCheckDeps bool) error {
- missing := &missing{
- make(stringset.StringSet),
- make(map[string][][]string),
- }
- for _, target := range dp.Targets {
- dp._checkMissing(target.DepString(), make([]string, 0), missing, noDeps, noCheckDeps)
- }
- if len(missing.Missing) == 0 {
- return nil
- }
- text.Errorln(gotext.Get("could not find all required packages:"))
- for dep, trees := range missing.Missing {
- for _, tree := range trees {
- fmt.Fprintf(os.Stderr, "\t%s", text.Cyan(dep))
- if len(tree) == 0 {
- fmt.Fprint(os.Stderr, gotext.Get(" (Target"))
- } else {
- fmt.Fprint(os.Stderr, gotext.Get(" (Wanted by: "))
- for n := 0; n < len(tree)-1; n++ {
- fmt.Fprint(os.Stderr, text.Cyan(tree[n]), " -> ")
- }
- fmt.Fprint(os.Stderr, text.Cyan(tree[len(tree)-1]))
- }
- fmt.Fprintln(os.Stderr, ")")
- }
- }
- return fmt.Errorf("")
- }
|