mirror of
https://github.com/Jguer/yay.git
synced 2025-08-19 13:41:18 +02:00
The depTree holds info on all packages by name ready for the depCatagories to catagorize and order them. To make things easier when a repo package was added to the deptree it was also aliased to all of its provides. So to find a package in the deptree you could search for its provides instead of it's name and still find it. The depCatagories is meant to filter out unneeded packages such as the aliases but as it turns out if a package depends on a package and something it provides then that alias is no longer unneeded and will end up in the depCatagories. Because these are just alias provieds still points to the original package so you end up with the package name displaed to the user twice when printing dependencies. This commit just comments out the aliasing. It should have no effect on package finding because where it used to seach by alias to find the package it should instead fail then try to preform a lookup itself using findSatisfyer and find the package. This is probably a little less efficient than before but the database is already on disk so there should be no real perfomance difference.
325 lines
6.8 KiB
Go
325 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
alpm "github.com/jguer/go-alpm"
|
|
rpc "github.com/mikkeloscar/aur"
|
|
"strings"
|
|
)
|
|
|
|
type depTree struct {
|
|
ToProcess stringSet
|
|
Repo map[string]*alpm.Package
|
|
Aur map[string]*rpc.Pkg
|
|
Missing stringSet
|
|
}
|
|
|
|
type depCatagories struct {
|
|
Repo []*alpm.Package
|
|
Aur []*rpc.Pkg
|
|
MakeOnly stringSet
|
|
Bases map[string][]*rpc.Pkg
|
|
}
|
|
|
|
func makeDepTree() *depTree {
|
|
dt := depTree{
|
|
make(stringSet),
|
|
make(map[string]*alpm.Package),
|
|
make(map[string]*rpc.Pkg),
|
|
make(stringSet),
|
|
}
|
|
|
|
return &dt
|
|
}
|
|
|
|
func makeDependCatagories() *depCatagories {
|
|
dc := depCatagories{
|
|
make([]*alpm.Package, 0),
|
|
make([]*rpc.Pkg, 0),
|
|
make(stringSet),
|
|
make(map[string][]*rpc.Pkg),
|
|
}
|
|
|
|
return &dc
|
|
}
|
|
|
|
func getNameFromDep(dep string) string {
|
|
return strings.FieldsFunc(dep, func(c rune) bool {
|
|
return c == '>' || c == '<' || c == '='
|
|
})[0]
|
|
}
|
|
|
|
func getDepCatagories(pkgs []string, dt *depTree) (*depCatagories, error) {
|
|
dc := makeDependCatagories()
|
|
seen := make(stringSet)
|
|
|
|
for _, pkg := range pkgs {
|
|
dep := getNameFromDep(pkg)
|
|
alpmpkg, exists := dt.Repo[dep]
|
|
if exists {
|
|
repoDepCatagoriesRecursive(alpmpkg, dc, dt, false)
|
|
dc.Repo = append(dc.Repo, alpmpkg)
|
|
delete(dt.Repo, dep)
|
|
}
|
|
|
|
aurpkg, exists := dt.Aur[dep]
|
|
if exists {
|
|
depCatagoriesRecursive(aurpkg, dc, dt, false, seen)
|
|
if !seen.get(aurpkg.PackageBase) {
|
|
dc.Aur = append(dc.Aur, aurpkg)
|
|
seen.set(aurpkg.PackageBase)
|
|
}
|
|
|
|
_, ok := dc.Bases[aurpkg.PackageBase]
|
|
if !ok {
|
|
dc.Bases[aurpkg.PackageBase] = make([]*rpc.Pkg, 0)
|
|
}
|
|
dc.Bases[aurpkg.PackageBase] = append(dc.Bases[aurpkg.PackageBase], aurpkg)
|
|
delete(dt.Aur, dep)
|
|
}
|
|
}
|
|
|
|
for _, base := range dc.Bases {
|
|
for _, pkg := range base {
|
|
for _, dep := range pkg.Depends {
|
|
dc.MakeOnly.remove(dep)
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, pkg := range dc.Repo {
|
|
pkg.Depends().ForEach(func(_dep alpm.Depend) error {
|
|
dep := _dep.Name
|
|
dc.MakeOnly.remove(dep)
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
return dc, nil
|
|
}
|
|
|
|
func repoDepCatagoriesRecursive(pkg *alpm.Package, dc *depCatagories, dt *depTree, isMake bool) {
|
|
pkg.Depends().ForEach(func(_dep alpm.Depend) error {
|
|
dep := _dep.Name
|
|
alpmpkg, exists := dt.Repo[dep]
|
|
if exists {
|
|
delete(dt.Repo, dep)
|
|
repoDepCatagoriesRecursive(alpmpkg, dc, dt, isMake)
|
|
|
|
if isMake {
|
|
dc.MakeOnly.set(alpmpkg.Name())
|
|
}
|
|
|
|
dc.Repo = append(dc.Repo, alpmpkg)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func depCatagoriesRecursive(pkg *rpc.Pkg, dc *depCatagories, dt *depTree, isMake bool, seen stringSet) {
|
|
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
|
|
for _, _dep := range deps {
|
|
dep := getNameFromDep(_dep)
|
|
|
|
aurpkg, exists := dt.Aur[dep]
|
|
if exists {
|
|
_, ok := dc.Bases[aurpkg.PackageBase]
|
|
if !ok {
|
|
dc.Bases[aurpkg.PackageBase] = make([]*rpc.Pkg, 0)
|
|
}
|
|
dc.Bases[aurpkg.PackageBase] = append(dc.Bases[aurpkg.PackageBase], aurpkg)
|
|
|
|
delete(dt.Aur, dep)
|
|
depCatagoriesRecursive(aurpkg, dc, dt, isMake, seen)
|
|
|
|
if !seen.get(aurpkg.PackageBase) {
|
|
dc.Aur = append(dc.Aur, aurpkg)
|
|
seen.set(aurpkg.PackageBase)
|
|
}
|
|
|
|
if isMake {
|
|
dc.MakeOnly.set(aurpkg.Name)
|
|
}
|
|
}
|
|
|
|
alpmpkg, exists := dt.Repo[dep]
|
|
if exists {
|
|
delete(dt.Repo, dep)
|
|
repoDepCatagoriesRecursive(alpmpkg, dc, dt, isMake)
|
|
|
|
if isMake {
|
|
dc.MakeOnly.set(alpmpkg.Name())
|
|
}
|
|
|
|
dc.Repo = append(dc.Repo, alpmpkg)
|
|
}
|
|
|
|
}
|
|
isMake = true
|
|
}
|
|
}
|
|
|
|
func getDepTree(pkgs []string) (*depTree, error) {
|
|
dt := makeDepTree()
|
|
|
|
localDb, err := alpmHandle.LocalDb()
|
|
if err != nil {
|
|
return dt, err
|
|
}
|
|
syncDb, err := alpmHandle.SyncDbs()
|
|
if err != nil {
|
|
return dt, err
|
|
}
|
|
|
|
for _, pkg := range pkgs {
|
|
//if they explicitly asked for it still look for installed pkgs
|
|
/*installedPkg, isInstalled := localDb.PkgCache().FindSatisfier(pkg)
|
|
if isInstalled == nil {
|
|
dt.Repo[installedPkg.Name()] = installedPkg
|
|
continue
|
|
}//*/
|
|
|
|
//check the repos for a matching dep
|
|
repoPkg, inRepos := syncDb.FindSatisfier(pkg)
|
|
if inRepos == nil {
|
|
repoTreeRecursive(repoPkg, dt, localDb, syncDb)
|
|
continue
|
|
}
|
|
|
|
dt.ToProcess.set(pkg)
|
|
}
|
|
|
|
err = depTreeRecursive(dt, localDb, syncDb, false)
|
|
|
|
return dt, err
|
|
}
|
|
|
|
//takes a repo package
|
|
//gives all of the non installed deps
|
|
//does again on each sub dep
|
|
func repoTreeRecursive(pkg *alpm.Package, dt *depTree, localDb *alpm.Db, syncDb alpm.DbList) (err error) {
|
|
_, exists := dt.Repo[pkg.Name()]
|
|
if exists {
|
|
return
|
|
}
|
|
|
|
dt.Repo[pkg.Name()] = pkg
|
|
/*(*pkg).Provides().ForEach(func(dep alpm.Depend) (err error) {
|
|
dt.Repo[dep.Name] = pkg
|
|
return nil
|
|
})*/
|
|
|
|
(*pkg).Depends().ForEach(func(dep alpm.Depend) (err error) {
|
|
_, exists := dt.Repo[dep.Name]
|
|
if exists {
|
|
return
|
|
}
|
|
|
|
_, isInstalled := localDb.PkgCache().FindSatisfier(dep.String())
|
|
if isInstalled == nil {
|
|
return
|
|
}
|
|
|
|
repoPkg, inRepos := syncDb.FindSatisfier(dep.String())
|
|
if inRepos == nil {
|
|
repoTreeRecursive(repoPkg, dt, localDb, syncDb)
|
|
return
|
|
}
|
|
|
|
dt.Missing.set(dep.String())
|
|
|
|
return
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
func depTreeRecursive(dt *depTree, localDb *alpm.Db, syncDb alpm.DbList, isMake bool) (err error) {
|
|
if len(dt.ToProcess) == 0 {
|
|
return
|
|
}
|
|
|
|
nextProcess := make(stringSet)
|
|
currentProcess := make(stringSet)
|
|
//strip version conditions
|
|
for dep := range dt.ToProcess {
|
|
currentProcess.set(getNameFromDep(dep))
|
|
}
|
|
|
|
//assume toprocess only contains aur stuff we have not seen
|
|
info, err := aurInfo(currentProcess.toSlice())
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
//cache the results
|
|
for _, pkg := range info {
|
|
//copying to p fixes a bug
|
|
//would rather not copy but cant find another way to fix
|
|
p := pkg
|
|
dt.Aur[pkg.Name] = &p
|
|
|
|
}
|
|
|
|
//loop through to process and check if we now have
|
|
//each packaged cached
|
|
//if its not cached we assume its missing
|
|
for pkgName := range currentProcess {
|
|
pkg, exists := dt.Aur[pkgName]
|
|
|
|
//did not get it in the request
|
|
if !exists {
|
|
dt.Missing.set(pkgName)
|
|
continue
|
|
}
|
|
|
|
//for each dep and makedep
|
|
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
|
|
for _, versionedDep := range deps {
|
|
dep := getNameFromDep(versionedDep)
|
|
|
|
_, exists = dt.Aur[dep]
|
|
//we have it cached so skip
|
|
if exists {
|
|
continue
|
|
}
|
|
|
|
_, exists = dt.Repo[dep]
|
|
//we have it cached so skip
|
|
if exists {
|
|
continue
|
|
}
|
|
|
|
_, exists = dt.Missing[dep]
|
|
//we know it does not resolve so skip
|
|
if exists {
|
|
continue
|
|
}
|
|
|
|
//check if already installed
|
|
_, isInstalled := localDb.PkgCache().FindSatisfier(versionedDep)
|
|
if isInstalled == nil {
|
|
continue
|
|
}
|
|
|
|
//check the repos for a matching dep
|
|
repoPkg, inRepos := syncDb.FindSatisfier(versionedDep)
|
|
if inRepos == nil {
|
|
repoTreeRecursive(repoPkg, dt, localDb, syncDb)
|
|
continue
|
|
}
|
|
|
|
//if all else fails add it to next search
|
|
nextProcess.set(versionedDep)
|
|
}
|
|
}
|
|
}
|
|
|
|
dt.ToProcess = nextProcess
|
|
depTreeRecursive(dt, localDb, syncDb, true)
|
|
|
|
return
|
|
}
|