mirror of
https://github.com/Jguer/yay.git
synced 2024-11-06 17:17:22 +01:00
a04dd94282
To know what AUR packages need updating a rpc request is needed for all packages. The dep tree is designed to cache everything to minimize the amount of rpc requests. The downside of this is the dep tree ends up with all sorts of packages in cache that it doesn't need. Then the deptree tries to resolve deps for all of thoes packages. By spliting the sysupgrade from the dep tree this stops this from happening, it uses one more rpc request but also may lower the amount of total rpc requests needed lated on. This fixes a couple of tiny bugs such as triggering providers prompts and printing AUR out of date messages for packages that are not going to be installed. This also fixes another display bug where repo packages from -Su would not apear when printing the packages to be installed under [Repo].
341 lines
7.6 KiB
Go
341 lines
7.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
|
|
alpm "github.com/jguer/go-alpm"
|
|
rpc "github.com/mikkeloscar/aur"
|
|
pkgb "github.com/mikkeloscar/gopkgbuild"
|
|
)
|
|
|
|
// upgrade type describes a system upgrade.
|
|
type upgrade struct {
|
|
Name string
|
|
Repository string
|
|
LocalVersion string
|
|
RemoteVersion string
|
|
}
|
|
|
|
// upSlice is a slice of Upgrades
|
|
type upSlice []upgrade
|
|
|
|
func (u upSlice) Len() int { return len(u) }
|
|
func (u upSlice) Swap(i, j int) { u[i], u[j] = u[j], u[i] }
|
|
|
|
func (u upSlice) Less(i, j int) bool {
|
|
if u[i].Repository == u[j].Repository {
|
|
iRunes := []rune(u[i].Name)
|
|
jRunes := []rune(u[j].Name)
|
|
return lessRunes(iRunes, jRunes)
|
|
}
|
|
|
|
syncDb, err := alpmHandle.SyncDbs()
|
|
if err != nil {
|
|
iRunes := []rune(u[i].Repository)
|
|
jRunes := []rune(u[j].Repository)
|
|
return lessRunes(iRunes, jRunes)
|
|
}
|
|
|
|
less := false
|
|
found := syncDb.ForEach(func(db alpm.Db) error {
|
|
if db.Name() == u[i].Repository {
|
|
less = true
|
|
} else if db.Name() == u[j].Repository {
|
|
less = false
|
|
} else {
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("")
|
|
})
|
|
|
|
if found != nil {
|
|
return less
|
|
} else {
|
|
iRunes := []rune(u[i].Repository)
|
|
jRunes := []rune(u[j].Repository)
|
|
return lessRunes(iRunes, jRunes)
|
|
}
|
|
|
|
}
|
|
|
|
func getVersionDiff(oldVersion, newversion string) (left, right string) {
|
|
old, errOld := pkgb.NewCompleteVersion(oldVersion)
|
|
new, errNew := pkgb.NewCompleteVersion(newversion)
|
|
|
|
if errOld != nil {
|
|
left = red("Invalid Version")
|
|
}
|
|
if errNew != nil {
|
|
right = red("Invalid Version")
|
|
}
|
|
|
|
if errOld == nil && errNew == nil {
|
|
if old.Version == new.Version {
|
|
left = string(old.Version) + "-" + red(string(old.Pkgrel))
|
|
right = string(new.Version) + "-" + green(string(new.Pkgrel))
|
|
} else {
|
|
left = red(string(old.Version)) + "-" + string(old.Pkgrel)
|
|
right = bold(green(string(new.Version))) + "-" + string(new.Pkgrel)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// upList returns lists of packages to upgrade from each source.
|
|
func upList() (aurUp upSlice, repoUp upSlice, err error) {
|
|
local, remote, _, remoteNames, err := filterPackages()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
var wg sync.WaitGroup
|
|
var develUp upSlice
|
|
|
|
var repoErr error
|
|
var aurErr error
|
|
var develErr error
|
|
|
|
fmt.Println(bold(cyan("::") + " Searching databases for updates..."))
|
|
wg.Add(1)
|
|
go func() {
|
|
repoUp, repoErr = upRepo(local)
|
|
wg.Done()
|
|
}()
|
|
|
|
fmt.Println(bold(cyan("::") + " Searching AUR for updates..."))
|
|
wg.Add(1)
|
|
go func() {
|
|
aurUp, aurErr = upAUR(remote, remoteNames)
|
|
wg.Done()
|
|
}()
|
|
|
|
if config.Devel {
|
|
fmt.Println(bold(cyan("::") + " Checking development packages..."))
|
|
wg.Add(1)
|
|
go func() {
|
|
develUp, develErr = upDevel(remote)
|
|
wg.Done()
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
errs := make([]string, 0)
|
|
for _, e := range []error{repoErr, aurErr, develErr} {
|
|
if e != nil {
|
|
errs = append(errs, e.Error())
|
|
}
|
|
}
|
|
|
|
if len(errs) > 0 {
|
|
err = fmt.Errorf("%s", strings.Join(errs, "\n"))
|
|
return nil, nil, err
|
|
}
|
|
|
|
if develUp != nil {
|
|
names := make(stringSet)
|
|
for _, up := range develUp {
|
|
names.set(up.Name)
|
|
}
|
|
for _, up := range aurUp {
|
|
if !names.get(up.Name) {
|
|
develUp = append(develUp, up)
|
|
}
|
|
}
|
|
|
|
aurUp = develUp
|
|
}
|
|
|
|
return aurUp, repoUp, err
|
|
}
|
|
|
|
func upDevel(remote []alpm.Package) (toUpgrade upSlice, err error) {
|
|
toUpdate := make([]alpm.Package, 0, 0)
|
|
toRemove := make([]string, 0, 0)
|
|
|
|
var mux1 sync.Mutex
|
|
var mux2 sync.Mutex
|
|
var wg sync.WaitGroup
|
|
|
|
checkUpdate := func(vcsName string, e shaInfos) {
|
|
defer wg.Done()
|
|
|
|
if e.needsUpdate() {
|
|
for _, pkg := range remote {
|
|
if pkg.Name() == vcsName {
|
|
mux1.Lock()
|
|
toUpdate = append(toUpdate, pkg)
|
|
mux1.Unlock()
|
|
return
|
|
}
|
|
}
|
|
|
|
mux2.Lock()
|
|
toRemove = append(toRemove, vcsName)
|
|
mux2.Unlock()
|
|
}
|
|
}
|
|
|
|
for vcsName, e := range savedInfo {
|
|
wg.Add(1)
|
|
go checkUpdate(vcsName, e)
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
for _, pkg := range toUpdate {
|
|
if pkg.ShouldIgnore() {
|
|
left, right := getVersionDiff(pkg.Version(), "latest-commit")
|
|
fmt.Print(magenta("Warning: "))
|
|
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", cyan(pkg.Name()), left, right)
|
|
} else {
|
|
toUpgrade = append(toUpgrade, upgrade{pkg.Name(), "devel", pkg.Version(), "latest-commit"})
|
|
}
|
|
}
|
|
|
|
removeVCSPackage(toRemove)
|
|
return
|
|
}
|
|
|
|
// upAUR gathers foreign packages and checks if they have new versions.
|
|
// Output: Upgrade type package list.
|
|
func upAUR(remote []alpm.Package, remoteNames []string) (upSlice, error) {
|
|
toUpgrade := make(upSlice, 0)
|
|
_pkgdata, err := aurInfo(remoteNames)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pkgdata := make(map[string]*rpc.Pkg)
|
|
for _, pkg := range _pkgdata {
|
|
pkgdata[pkg.Name] = pkg
|
|
}
|
|
|
|
for _, pkg := range remote {
|
|
aurPkg, ok := pkgdata[pkg.Name()]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if (config.TimeUpdate && (int64(aurPkg.LastModified) > pkg.BuildDate().Unix())) ||
|
|
(alpm.VerCmp(pkg.Version(), aurPkg.Version) < 0) {
|
|
if pkg.ShouldIgnore() {
|
|
left, right := getVersionDiff(pkg.Version(), aurPkg.Version)
|
|
fmt.Print(magenta("Warning: "))
|
|
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", cyan(pkg.Name()), left, right)
|
|
} else {
|
|
toUpgrade = append(toUpgrade, upgrade{aurPkg.Name, "aur", pkg.Version(), aurPkg.Version})
|
|
}
|
|
}
|
|
}
|
|
|
|
return toUpgrade, nil
|
|
}
|
|
|
|
// upRepo gathers local packages and checks if they have new versions.
|
|
// Output: Upgrade type package list.
|
|
func upRepo(local []alpm.Package) (upSlice, error) {
|
|
dbList, err := alpmHandle.SyncDbs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
slice := upSlice{}
|
|
|
|
for _, pkg := range local {
|
|
newPkg := pkg.NewVersion(dbList)
|
|
if newPkg != nil {
|
|
if pkg.ShouldIgnore() {
|
|
left, right := getVersionDiff(pkg.Version(), newPkg.Version())
|
|
fmt.Print(magenta("Warning: "))
|
|
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", cyan(pkg.Name()), left, right)
|
|
} else {
|
|
slice = append(slice, upgrade{pkg.Name(), newPkg.DB().Name(), pkg.Version(), newPkg.Version()})
|
|
}
|
|
}
|
|
}
|
|
return slice, nil
|
|
}
|
|
|
|
// upgradePkgs handles updating the cache and installing updates.
|
|
func upgradePkgs(aurUp, repoUp upSlice) (stringSet, stringSet, error) {
|
|
ignore := make(stringSet)
|
|
aurNames := make(stringSet)
|
|
|
|
if len(aurUp)+len(repoUp) == 0 {
|
|
return ignore, aurNames, nil
|
|
}
|
|
|
|
sort.Sort(repoUp)
|
|
sort.Sort(aurUp)
|
|
fmt.Println(bold(blue("::")), len(aurUp)+len(repoUp), bold("Packages to upgrade."))
|
|
repoUp.Print(len(aurUp) + 1)
|
|
aurUp.Print(1)
|
|
|
|
if config.NoConfirm {
|
|
for _, up := range aurUp {
|
|
aurNames.set(up.Name)
|
|
}
|
|
return ignore, aurNames, nil
|
|
}
|
|
|
|
fmt.Println(bold(green(arrow + " Packages to not upgrade (eg: 1 2 3, 1-3, ^4 or repo name)")))
|
|
fmt.Print(bold(green(arrow + " ")))
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
numberBuf, overflow, err := reader.ReadLine()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if overflow {
|
|
return nil, nil, fmt.Errorf("Input too long")
|
|
}
|
|
|
|
//upgrade menu asks you which packages to NOT upgrade so in this case
|
|
//include and exclude are kind of swaped
|
|
//include, exclude, other := parseNumberMenu(string(numberBuf))
|
|
include, exclude, otherInclude, otherExclude := parseNumberMenu(string(numberBuf))
|
|
|
|
isInclude := len(exclude) == 0 && len(otherExclude) == 0
|
|
|
|
for i, pkg := range repoUp {
|
|
if isInclude && otherInclude.get(pkg.Repository) {
|
|
ignore.set(pkg.Name)
|
|
}
|
|
|
|
if isInclude && !include.get(len(repoUp)-i+len(aurUp)) {
|
|
continue
|
|
}
|
|
|
|
if !isInclude && (exclude.get(len(repoUp)-i+len(aurUp)) || otherExclude.get(pkg.Repository)) {
|
|
continue
|
|
}
|
|
|
|
ignore.set(pkg.Name)
|
|
}
|
|
|
|
for i, pkg := range aurUp {
|
|
if isInclude && otherInclude.get(pkg.Repository) {
|
|
continue
|
|
}
|
|
|
|
if isInclude && !include.get(len(aurUp)-i) {
|
|
aurNames.set(pkg.Name)
|
|
}
|
|
|
|
if !isInclude && (exclude.get(len(aurUp)-i) || otherExclude.get(pkg.Repository)) {
|
|
aurNames.set(pkg.Name)
|
|
}
|
|
}
|
|
|
|
return ignore, aurNames, err
|
|
}
|