2017-08-02 19:24:03 +02:00
|
|
|
package main
|
|
|
|
|
2017-08-07 15:43:25 +02:00
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
alpm "github.com/jguer/go-alpm"
|
2018-01-20 23:37:10 +01:00
|
|
|
rpc "github.com/mikkeloscar/aur"
|
2017-08-07 15:43:25 +02:00
|
|
|
)
|
2017-08-04 11:26:53 +02:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
type depTree struct {
|
|
|
|
ToProcess []string
|
2018-01-20 23:37:10 +01:00
|
|
|
Repo map[string]*alpm.Package
|
|
|
|
Aur map[string]*rpc.Pkg
|
|
|
|
Missing stringSet
|
2018-01-17 22:48:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type depCatagories struct {
|
2018-01-20 23:37:10 +01:00
|
|
|
Repo []*alpm.Package
|
2018-01-17 22:48:23 +01:00
|
|
|
RepoMake []*alpm.Package
|
2018-01-20 23:37:10 +01:00
|
|
|
Aur []*rpc.Pkg
|
|
|
|
AurMake []*rpc.Pkg
|
2018-01-17 22:48:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func makeDepTree() *depTree {
|
|
|
|
dt := depTree{
|
|
|
|
make([]string, 0),
|
|
|
|
make(map[string]*alpm.Package),
|
|
|
|
make(map[string]*rpc.Pkg),
|
|
|
|
make(stringSet),
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
return &dt
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeDependCatagories() *depCatagories {
|
|
|
|
dc := depCatagories{
|
|
|
|
make([]*alpm.Package, 0),
|
|
|
|
make([]*alpm.Package, 0),
|
|
|
|
make([]*rpc.Pkg, 0),
|
|
|
|
make([]*rpc.Pkg, 0),
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
return &dc
|
|
|
|
}
|
|
|
|
|
|
|
|
func getNameFromDep(dep string) string {
|
|
|
|
return strings.FieldsFunc(dep, func(c rune) bool {
|
2017-08-02 19:24:03 +02:00
|
|
|
return c == '>' || c == '<' || c == '=' || c == ' '
|
2018-01-17 22:48:23 +01:00
|
|
|
})[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
func getDepCatagories(pkgs []string, dt *depTree) (*depCatagories, error) {
|
|
|
|
dc := makeDependCatagories()
|
|
|
|
|
|
|
|
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)
|
|
|
|
dc.Aur = append(dc.Aur, aurpkg)
|
|
|
|
delete(dt.Aur, dep)
|
|
|
|
}
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
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)
|
2018-01-20 23:37:10 +01:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
if isMake {
|
|
|
|
dc.RepoMake = append(dc.RepoMake, alpmpkg)
|
|
|
|
} else {
|
|
|
|
dc.Repo = append(dc.Repo, alpmpkg)
|
|
|
|
}
|
|
|
|
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func depCatagoriesRecursive(pkg *rpc.Pkg, dc *depCatagories, dt *depTree, isMake bool) {
|
|
|
|
for _, deps := range [2][]string{pkg.Depends, pkg.MakeDepends} {
|
|
|
|
for _, _dep := range deps {
|
|
|
|
dep := getNameFromDep(_dep)
|
2018-01-20 23:37:10 +01:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
aurpkg, exists := dt.Aur[dep]
|
|
|
|
if exists {
|
|
|
|
delete(dt.Aur, dep)
|
|
|
|
depCatagoriesRecursive(aurpkg, dc, dt, isMake)
|
|
|
|
|
|
|
|
if isMake {
|
|
|
|
dc.AurMake = append(dc.AurMake, aurpkg)
|
|
|
|
} else {
|
|
|
|
dc.Aur = append(dc.Aur, aurpkg)
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
2018-01-17 22:48:23 +01:00
|
|
|
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
2018-01-17 22:48:23 +01:00
|
|
|
|
|
|
|
alpmpkg, exists := dt.Repo[dep]
|
|
|
|
if exists {
|
|
|
|
delete(dt.Repo, dep)
|
|
|
|
repoDepCatagoriesRecursive(alpmpkg, dc, dt, isMake)
|
|
|
|
|
|
|
|
if isMake {
|
|
|
|
dc.RepoMake = append(dc.RepoMake, alpmpkg)
|
|
|
|
} else {
|
|
|
|
dc.Repo = append(dc.Repo, alpmpkg)
|
|
|
|
}
|
|
|
|
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
2018-01-17 22:48:23 +01:00
|
|
|
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
2018-01-17 22:48:23 +01:00
|
|
|
isMake = true
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
func getDepTree(pkgs []string) (*depTree, error) {
|
|
|
|
dt := makeDepTree()
|
|
|
|
|
2017-10-18 04:38:19 +02:00
|
|
|
localDb, err := alpmHandle.LocalDb()
|
2017-08-02 19:24:03 +02:00
|
|
|
if err != nil {
|
2018-01-17 22:48:23 +01:00
|
|
|
return dt, err
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
2018-01-17 22:48:23 +01:00
|
|
|
syncDb, err := alpmHandle.SyncDbs()
|
2017-08-02 19:24:03 +02:00
|
|
|
if err != nil {
|
2018-01-17 22:48:23 +01:00
|
|
|
return dt, err
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
|
2018-01-20 23:37:10 +01:00
|
|
|
for _, pkg := range pkgs {
|
2018-01-17 22:48:23 +01:00
|
|
|
//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
|
|
|
|
}//*/
|
2017-08-02 19:24:03 +02:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
//check the repos for a matching dep
|
|
|
|
repoPkg, inRepos := syncDb.FindSatisfier(pkg)
|
|
|
|
if inRepos == nil {
|
|
|
|
repoTreeRecursive(repoPkg, dt, localDb, syncDb)
|
2017-08-02 19:24:03 +02:00
|
|
|
continue
|
|
|
|
}
|
2018-01-20 23:37:10 +01:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
dt.ToProcess = append(dt.ToProcess, pkg)
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
if len(dt.ToProcess) > 0 {
|
|
|
|
err = depTreeRecursive(dt, localDb, syncDb, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dt, err
|
2017-08-02 19:24:03 +02:00
|
|
|
}
|
2017-08-07 15:43:25 +02:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
//takes a repo package
|
|
|
|
//gives all of the non installed deps
|
|
|
|
//does again on each sub dep
|
2018-01-20 23:37:10 +01:00
|
|
|
func repoTreeRecursive(pkg *alpm.Package, dt *depTree, localDb *alpm.Db, syncDb alpm.DbList) (err error) {
|
2018-01-17 22:48:23 +01:00
|
|
|
_, exists := dt.Repo[pkg.Name()]
|
|
|
|
if exists {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
dt.Repo[pkg.Name()] = pkg
|
|
|
|
|
|
|
|
(*pkg).Depends().ForEach(func(dep alpm.Depend) (err error) {
|
|
|
|
_, exists := dt.Repo[dep.Name]
|
|
|
|
if exists {
|
2017-08-07 15:43:25 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
_, isInstalled := localDb.PkgCache().FindSatisfier(dep.String())
|
|
|
|
if isInstalled == nil {
|
|
|
|
return
|
2018-01-20 23:37:10 +01:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
repoPkg, inRepos := syncDb.FindSatisfier(dep.String())
|
|
|
|
if inRepos == nil {
|
|
|
|
repoTreeRecursive(repoPkg, dt, localDb, syncDb)
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
dt.Missing.set(dep.String())
|
2017-08-07 15:43:25 +02:00
|
|
|
}
|
2018-01-17 22:48:23 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2017-08-07 15:43:25 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
//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]
|
|
|
|
|
|
|
|
//didnt 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
|
|
|
|
}
|
2018-01-20 23:37:10 +01:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
_, exists = dt.Repo[dep]
|
|
|
|
//we have it cached so skip
|
|
|
|
if exists {
|
|
|
|
continue
|
|
|
|
}
|
2018-01-20 23:37:10 +01:00
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
_, exists = dt.Missing[dep]
|
|
|
|
//we know it doesnt 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 failes add it to next search
|
|
|
|
nextProcess = append(nextProcess, versionedDep)
|
|
|
|
}
|
2017-08-07 15:43:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-17 22:48:23 +01:00
|
|
|
dt.ToProcess = nextProcess
|
|
|
|
depTreeRecursive(dt, localDb, syncDb, true)
|
2018-01-20 23:37:10 +01:00
|
|
|
|
2017-08-07 15:43:25 +02:00
|
|
|
return
|
|
|
|
}
|