mirror of
https://github.com/Jguer/yay
synced 2024-09-19 08:01:32 +00:00
b2d3eb5c49
This is a rewrite of the dependency system, It aims to be cleaner written, with a better idea of what is needed from the start, meaning less new code being hacked on for things that were not thought about. This version also aims to use as many small functions as possible, for cleaner code and better testing. Added dep.go: general dependency functions Added depPool.go: Replacement of depTree, dependencies were never ordered so a tree did not really make sense. Instead the term pool makes more sense. Added depOrder.go: Replacement of depCatagories, This simply orders the dependencies, dependencies are still catagorized as repo and AUR but I believe this to be a better name Added depCheck.go: Replaces conflicts.go and also contains the missing dependency code This version is mostly the same as the old version with a few improvments: Missing packages will print the full dependency tree Versioned dependency checking errors should be fixed Make depends should be calculated properly Experimental AUR provide searcher This code has been added along side the old code for testing and is not currently used by the install process. Once the install process is moved to use this code, the old code will be removed.
265 lines
5.4 KiB
Go
265 lines
5.4 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 {
|
|
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 {
|
|
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
|
|
dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
|
|
return nil
|
|
})
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (dp *depPool) CheckConflicts() 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 fmt.Errorf("Unresolvable package conflicts, aborting")
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type missing struct {
|
|
Good stringSet
|
|
Missing map[string][][]string
|
|
}
|
|
|
|
func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) {
|
|
if _, err := dp.LocalDb.PkgCache().FindSatisfier(dep); err == nil {
|
|
missing.Good.set(dep)
|
|
return
|
|
}
|
|
|
|
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 {
|
|
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 {
|
|
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), " (Tree: ")
|
|
|
|
if len(tree) == 0 {
|
|
fmt.Print(cyan("Target "))
|
|
} else {
|
|
for _, pkg := range tree {
|
|
fmt.Print(cyan(pkg), " -> ")
|
|
}
|
|
}
|
|
|
|
fmt.Println(")")
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("")
|
|
}
|