123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- 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
- RepoMake []*alpm.Package
- Aur []*rpc.Pkg
- AurMake []*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([]*alpm.Package, 0),
- make([]*rpc.Pkg, 0),
- make([]*rpc.Pkg, 0),
- }
- return &dc
- }
- func getNameFromDep(dep string) string {
- return strings.FieldsFunc(dep, func(c rune) bool {
- return c == '>' || c == '<' || c == '=' || c == ' '
- })[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)
- }
- }
- 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.RepoMake = append(dc.RepoMake, alpmpkg)
- } else {
- dc.Repo = append(dc.Repo, alpmpkg)
- }
- }
- 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)
- 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)
- }
- }
- 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)
- }
- }
- }
- 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
- }
|