mirror of
https://github.com/Jguer/yay.git
synced 2024-11-06 17:17:22 +01:00
b8f2ac0ab3
This should not make any real difference as pkgnames and pkgvers should not contain whitespace. But there was a problem where a packagepkg connected two deps by quoting them. depends=('make qt5-tools') Because we split on spaces this caused yay to generate an error saying it couldn't find 'make' when instead it should say it cant find 'make qt5tools' which was a little confusing. This commit should fix the misleading error.
324 lines
6.8 KiB
Go
324 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
|
|
alpm "github.com/jguer/go-alpm"
|
|
rpc "github.com/mikkeloscar/aur"
|
|
)
|
|
|
|
type depTree struct {
|
|
ToProcess []string
|
|
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([]string, 0),
|
|
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 [2][]string{pkg.Depends, pkg.MakeDepends} {
|
|
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 = append(dt.ToProcess, pkg)
|
|
}
|
|
|
|
if len(dt.ToProcess) > 0 {
|
|
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) {
|
|
nextProcess := make([]string, 0)
|
|
currentProcess := make([]string, 0, len(dt.ToProcess))
|
|
|
|
//strip version conditions
|
|
for _, dep := range dt.ToProcess {
|
|
currentProcess = append(currentProcess, getNameFromDep(dep))
|
|
}
|
|
|
|
//assume toprocess only contains aur stuff we have not seen
|
|
info, err := rpc.Info(currentProcess)
|
|
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 k, pkgName := range currentProcess {
|
|
pkg, exists := dt.Aur[pkgName]
|
|
|
|
//did not get it in the request
|
|
if !exists {
|
|
dt.Missing.set(dt.ToProcess[k])
|
|
continue
|
|
}
|
|
|
|
//for reach dep and makedep
|
|
for _, deps := range [2][]string{pkg.Depends, pkg.MakeDepends} {
|
|
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 = append(nextProcess, versionedDep)
|
|
}
|
|
}
|
|
}
|
|
|
|
dt.ToProcess = nextProcess
|
|
depTreeRecursive(dt, localDb, syncDb, true)
|
|
|
|
return
|
|
}
|