yay/pkg/dep/dep.go
2020-08-16 23:41:55 +02:00

136 lines
2.4 KiB
Go

package dep
import (
"strings"
alpm "github.com/Jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
"github.com/Jguer/yay/v10/pkg/db"
"github.com/Jguer/yay/v10/pkg/text"
)
type providers struct {
lookfor string
Pkgs []*rpc.Pkg
}
func makeProviders(name string) providers {
return providers{
name,
make([]*rpc.Pkg, 0),
}
}
func (q providers) Len() int {
return len(q.Pkgs)
}
func (q providers) Less(i, j int) bool {
if q.lookfor == q.Pkgs[i].Name {
return true
}
if q.lookfor == q.Pkgs[j].Name {
return false
}
return text.LessRunes([]rune(q.Pkgs[i].Name), []rune(q.Pkgs[j].Name))
}
func (q providers) Swap(i, j int) {
q.Pkgs[i], q.Pkgs[j] = q.Pkgs[j], q.Pkgs[i]
}
func splitDep(dep string) (pkg, mod, ver string) {
split := strings.FieldsFunc(dep, func(c rune) bool {
match := c == '>' || c == '<' || c == '='
if match {
mod += string(c)
}
return match
})
if len(split) == 0 {
return "", "", ""
}
if len(split) == 1 {
return split[0], "", ""
}
return split[0], mod, split[1]
}
func pkgSatisfies(name, version, dep string) bool {
depName, depMod, depVersion := splitDep(dep)
if depName != name {
return false
}
return verSatisfies(version, depMod, depVersion)
}
func provideSatisfies(provide, dep string) bool {
depName, depMod, depVersion := splitDep(dep)
provideName, provideMod, provideVersion := splitDep(provide)
if provideName != depName {
return false
}
// Unversioned provieds can not satisfy a versioned dep
if provideMod == "" && depMod != "" {
return false
}
return verSatisfies(provideVersion, depMod, depVersion)
}
func verSatisfies(ver1, mod, ver2 string) bool {
switch mod {
case "=":
return alpm.VerCmp(ver1, ver2) == 0
case "<":
return alpm.VerCmp(ver1, ver2) < 0
case "<=":
return alpm.VerCmp(ver1, ver2) <= 0
case ">":
return alpm.VerCmp(ver1, ver2) > 0
case ">=":
return alpm.VerCmp(ver1, ver2) >= 0
}
return true
}
func satisfiesAur(dep string, pkg *rpc.Pkg) bool {
if pkgSatisfies(pkg.Name, pkg.Version, dep) {
return true
}
for _, provide := range pkg.Provides {
if provideSatisfies(provide, dep) {
return true
}
}
return false
}
func satisfiesRepo(dep string, pkg db.RepoPackage, ae *db.AlpmExecutor) bool {
if pkgSatisfies(pkg.Name(), pkg.Version(), dep) {
return true
}
for _, provided := range ae.PackageProvides(pkg) {
if provideSatisfies(provided.String(), dep) {
return true
}
}
return false
}