1
0
mirror of https://github.com/Jguer/yay.git synced 2025-08-08 15:47:08 +02:00

Merge pull request #164 from Morganamilo/warnings

Improvements to install algorithm
This commit is contained in:
Morgana 2018-02-27 02:57:11 +00:00 committed by GitHub
commit 005635b4ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 427 additions and 348 deletions

20
cmd.go
View File

@ -448,16 +448,7 @@ func handleYay() (err error) {
}
func handleGetpkgbuild() (err error) {
for pkg := range cmdArgs.targets {
err = getPkgbuild(pkg)
if err != nil {
//we print the error instead of returning it
//seems as we can handle multiple errors without stoping
//theres no easy way around this right now
fmt.Println(pkg+":", err)
}
}
err = getPkgbuilds(cmdArgs.formatTargets())
return
}
@ -497,10 +488,10 @@ func handleSync() (err error) {
err = syncSearch(targets)
} else if cmdArgs.existsArg("c", "clean") {
err = passToPacman(cmdArgs)
} else if cmdArgs.existsArg("u", "sysupgrade") {
err = upgradePkgs(make([]string, 0))
} else if cmdArgs.existsArg("i", "info") {
err = syncInfo(targets)
} else if cmdArgs.existsArg("u", "sysupgrade") {
err = install(cmdArgs)
} else if len(cmdArgs.targets) > 0 {
err = install(cmdArgs)
}
@ -602,9 +593,8 @@ func numberMenu(pkgS []string, flags []string) (err error) {
aurQ.printSearch(numpq + 1)
}
fmt.Println(greenFg("Type the numbers or ranges (e.g. 1-10) you want to install. " +
"Separate each one of them with a space."))
fmt.Print("Numbers: ")
fmt.Println(boldGreenFg(arrow) + boldGreenFg(" Packages to not upgrade (eg: 1 2 3, 1-3 or ^4)"))
fmt.Print(boldGreenFg(arrow + " "))
reader := bufio.NewReader(os.Stdin)
numberBuf, overflow, err := reader.ReadLine()
if err != nil || overflow {

View File

@ -1,14 +1,13 @@
package main
import (
"strings"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
"strings"
)
type depTree struct {
ToProcess []string
ToProcess stringSet
Repo map[string]*alpm.Package
Aur map[string]*rpc.Pkg
Missing stringSet
@ -23,7 +22,7 @@ type depCatagories struct {
func makeDepTree() *depTree {
dt := depTree{
make([]string, 0),
make(stringSet),
make(map[string]*alpm.Package),
make(map[string]*rpc.Pkg),
make(stringSet),
@ -119,7 +118,7 @@ func repoDepCatagoriesRecursive(pkg *alpm.Package, dc *depCatagories, dt *depTre
}
func depCatagoriesRecursive(pkg *rpc.Pkg, dc *depCatagories, dt *depTree, isMake bool, seen stringSet) {
for _, deps := range [2][]string{pkg.Depends, pkg.MakeDepends} {
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, _dep := range deps {
dep := getNameFromDep(_dep)
@ -188,12 +187,10 @@ func getDepTree(pkgs []string) (*depTree, error) {
continue
}
dt.ToProcess = append(dt.ToProcess, pkg)
dt.ToProcess.set(pkg)
}
if len(dt.ToProcess) > 0 {
err = depTreeRecursive(dt, localDb, syncDb, false)
}
err = depTreeRecursive(dt, localDb, syncDb, false)
return dt, err
}
@ -239,16 +236,20 @@ func repoTreeRecursive(pkg *alpm.Package, dt *depTree, localDb *alpm.Db, syncDb
}
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))
if len(dt.ToProcess) == 0 {
return
}
nextProcess := make(stringSet)
currentProcess := make(stringSet)
//strip version conditions
for _, dep := range dt.ToProcess {
currentProcess = append(currentProcess, getNameFromDep(dep))
for dep := range dt.ToProcess {
currentProcess.set(getNameFromDep(dep))
}
//assume toprocess only contains aur stuff we have not seen
info, err := rpc.Info(currentProcess)
info, err := aurInfo(currentProcess.toSlice())
if err != nil {
return
}
@ -265,17 +266,17 @@ func depTreeRecursive(dt *depTree, localDb *alpm.Db, syncDb alpm.DbList, isMake
//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 {
for pkgName := range currentProcess {
pkg, exists := dt.Aur[pkgName]
//did not get it in the request
if !exists {
dt.Missing.set(dt.ToProcess[k])
dt.Missing.set(pkgName)
continue
}
//for reach dep and makedep
for _, deps := range [2][]string{pkg.Depends, pkg.MakeDepends} {
//for each dep and makedep
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, versionedDep := range deps {
dep := getNameFromDep(versionedDep)
@ -311,7 +312,7 @@ func depTreeRecursive(dt *depTree, localDb *alpm.Db, syncDb alpm.DbList, isMake
}
//if all else fails add it to next search
nextProcess = append(nextProcess, versionedDep)
nextProcess.set(versionedDep)
}
}
}

View File

@ -7,8 +7,6 @@ import (
"os"
"os/exec"
"strings"
rpc "github.com/mikkeloscar/aur"
)
func downloadFile(path string, url string) (err error) {
@ -63,60 +61,71 @@ func downloadAndUnpack(url string, path string, trim bool) (err error) {
return
}
func getPkgbuild(pkg string) (err error) {
func getPkgbuilds(pkgs []string) error {
//possibleAurs := make([]string, 0, 0)
wd, err := os.Getwd()
if err != nil {
return
return err
}
wd = wd + "/"
err = getPkgbuildfromABS(pkg, wd)
if err == nil {
return
missing, err := getPkgbuildsfromABS(pkgs, wd)
if err != nil {
return err
}
err = getPkgbuildfromAUR(pkg, wd)
return
err = getPkgbuildsfromAUR(missing, wd)
return err
}
// GetPkgbuild downloads pkgbuild from the ABS.
func getPkgbuildfromABS(pkgN string, path string) (err error) {
func getPkgbuildsfromABS(pkgs []string, path string) (missing []string, err error) {
dbList, err := alpmHandle.SyncDbs()
if err != nil {
return
}
for _, db := range dbList.Slice() {
pkg, err := db.PkgByName(pkgN)
if err == nil {
var url string
if db.Name() == "core" || db.Name() == "extra" {
url = "https://projects.archlinux.org/svntogit/packages.git/snapshot/packages/" + pkg.Base() + ".tar.gz"
} else if db.Name() == "community" {
url = "https://projects.archlinux.org/svntogit/community.git/snapshot/community-packages/" + pkg.Base() + ".tar.gz"
} else {
return fmt.Errorf("Not in standard repositories")
nextPkg:
for _, pkgN := range pkgs {
for _, db := range dbList.Slice() {
pkg, err := db.PkgByName(pkgN)
if err == nil {
var url string
if db.Name() == "core" || db.Name() == "extra" {
url = "https://projects.archlinux.org/svntogit/packages.git/snapshot/packages/" + pkg.Base() + ".tar.gz"
} else if db.Name() == "community" {
url = "https://projects.archlinux.org/svntogit/community.git/snapshot/community-packages/" + pkg.Base() + ".tar.gz"
} else {
fmt.Println(pkgN + " not in standard repositories")
}
errD := downloadAndUnpack(url, path, true)
if errD != nil {
fmt.Println(boldYellowFg(pkg.Name()), boldGreenFg(errD.Error()))
}
fmt.Println(boldGreenFg(arrow), boldGreenFg("Downloaded"), boldYellowFg(pkg.Name()), boldGreenFg("from ABS"))
continue nextPkg
}
fmt.Println(boldGreenFg(arrow), boldYellowFg(pkgN), boldGreenFg("found in ABS."))
errD := downloadAndUnpack(url, path, true)
return errD
}
missing = append(missing, pkgN)
}
return fmt.Errorf("package not found")
return
}
// GetPkgbuild downloads pkgbuild from the AUR.
func getPkgbuildfromAUR(pkgN string, dir string) (err error) {
aq, err := rpc.Info([]string{pkgN})
func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) {
aq, err := aurInfo(pkgs)
if err != nil {
return err
}
if len(aq) == 0 {
return fmt.Errorf("no results")
for _, pkg := range aq {
downloadAndUnpack(baseURL+aq[0].URLPath, dir, false)
fmt.Println(boldGreenFg(arrow), boldGreenFg("Downloaded"), boldYellowFg(pkg.Name), boldGreenFg("from AUR"))
}
fmt.Println(boldGreenFg(arrow), boldYellowFg(pkgN), boldGreenFg("found in AUR."))
downloadAndUnpack(baseURL+aq[0].URLPath, dir, false)
return
}

View File

@ -5,8 +5,8 @@ import (
"io/ioutil"
"os"
"os/exec"
"strings"
"strconv"
"strings"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
@ -15,87 +15,136 @@ import (
// Install handles package installs
func install(parser *arguments) error {
aurs, repos, missing, err := packageSlices(parser.targets.toSlice())
srcinfos := make(map[string]*gopkg.PKGBUILD)
removeMake := false
aur, repo, err := packageSlices(parser.targets.toSlice())
if err != nil {
return err
}
if len(missing) > 0 {
fmt.Println(missing)
fmt.Println("Could not find all Targets")
srcinfos := make(map[string]*gopkg.PKGBUILD)
var dc *depCatagories
//fmt.Println(greenFg(arrow), greenFg("Resolving Dependencies"))
requestTargets := append(aur, repo...)
//remotenames: names of all non repo packages on the system
_, _, _, remoteNames, err := filterPackages()
if err != nil {
return err
}
//cache as a stringset. maybe make it return a string set in the first
//place
remoteNamesCache := make(stringSet)
for _, name := range remoteNames {
remoteNamesCache.set(name)
}
//if we are doing -u also request every non repo package on the system
if parser.existsArg("u", "sysupgrade") {
requestTargets = append(requestTargets, remoteNames...)
}
if len(aur) > 0 || parser.existsArg("u", "sysupgrade") && len(remoteNames) > 0 {
fmt.Println(boldCyanFg("::"), boldFg("Querying AUR..."))
}
dt, err := getDepTree(requestTargets)
if err != nil {
return err
}
//only error if direct targets or deps are missing
for missingName := range dt.Missing {
if !remoteNamesCache.get(missingName) {
return fmt.Errorf(boldRedFgBlackBg(arrow+" Error: ") +
blackBg("Could not find all required package"))
}
}
//create the arguments to pass for the repo install
arguments := parser.copy()
arguments.delArg("u", "sysupgrade")
arguments.delArg("y", "refresh")
arguments.op = "S"
arguments.targets = make(stringSet)
arguments.addTarget(repos...)
if len(repos) != 0 {
err := passToPacman(arguments)
if parser.existsArg("u", "sysupgrade") {
repoUp, aurUp, err := upgradePkgs(dt)
if err != nil {
fmt.Println("Error installing repo packages.")
return err
}
fmt.Println()
for pkg := range aurUp {
parser.addTarget(pkg)
}
for pkg := range repoUp {
arguments.addTarget(pkg)
}
//discard stuff thats
//not a target and
//not an upgrade and
//is installed
for pkg := range dt.Aur {
if !parser.targets.get(pkg) && remoteNamesCache.get(pkg) {
delete(dt.Aur, pkg)
}
}
}
if len(aurs) != 0 {
//todo mamakeke pretty
fmt.Println(greenFg(arrow), greenFg("Resolving Dependencies"))
hasAur := len(dt.Aur) != 0
dc, err = getDepCatagories(parser.formatTargets(), dt)
if err != nil {
return err
}
dt, err := getDepTree(aurs)
if err != nil {
return err
}
for _, pkg := range dc.Repo {
arguments.addTarget(pkg.Name())
}
if len(dt.Missing) > 0 {
fmt.Println(dt.Missing)
return fmt.Errorf("Could not find all Deps")
}
for _, pkg := range repo {
arguments.addTarget(pkg)
}
dc, err := getDepCatagories(aurs, dt)
if err != nil {
return err
}
for _, pkg := range dc.Aur {
if pkg.Maintainer == "" {
fmt.Println(boldRedFgBlackBg(arrow+" Warning:"),
blackBg(pkg.Name+"-"+pkg.Version+" is orphaned"))
}
}
//printDownloadsFromRepo("Repo", dc.Repo)
//printDownloadsFromRepo("Repo Make", dc.RepoMake)
//printDownloadsFromAur("AUR", dc.Aur)
//printDownloadsFromAur("AUR Make", dc.AurMake)
//fmt.Println(dc.MakeOnly)
//fmt.Println(dc.AurSet)
if len(dc.Aur) == 0 && len(arguments.targets) == 0 {
fmt.Println("There is nothing to do")
return nil
}
if hasAur {
printDepCatagories(dc)
fmt.Println()
}
if !arguments.existsArg("gendb") {
if !parser.existsArg("gendb") && len(arguments.targets) > 0 {
err := passToPacman(arguments)
if err != nil {
return fmt.Errorf("Error installing repo packages.")
}
}
if hasAur {
if !parser.existsArg("gendb") {
err = checkForConflicts(dc)
if err != nil {
return err
}
}
askCleanBuilds(dc.Aur, dc.Bases)
fmt.Println()
if !continueTask("Proceed with install?", "nN") {
return fmt.Errorf("Aborting due to user")
if len(dc.MakeOnly) > 0 {
if !continueTask("Remove make dependencies after install?", "yY") {
removeMake = true
}
}
// if !continueTask("Proceed with download?", "nN") {
// return fmt.Errorf("Aborting due to user")
// }
askCleanBuilds(dc.Aur, dc.Bases)
if !continueTask("Proceed with Download?", "nN") {
return fmt.Errorf("Aborting due to user")
}
err = dowloadPkgBuilds(dc.Aur, dc.Bases)
if err != nil {
@ -107,41 +156,35 @@ func install(parser *arguments) error {
return err
}
if len(dc.Repo) > 0 {
arguments := parser.copy()
arguments.delArg("u", "sysupgrade")
arguments.delArg("y", "refresh")
arguments.op = "S"
arguments.targets = make(stringSet)
arguments.addArg("needed", "asdeps")
for _, pkg := range dc.Repo {
arguments.addTarget(pkg.Name())
}
if !continueTask("Proceed with install?", "nN") {
return fmt.Errorf("Aborting due to user")
}
oldConfirm := config.NoConfirm
config.NoConfirm = true
passToPacman(arguments)
config.NoConfirm = oldConfirm
//conflicts have been checked so answer y for them
ask, _ := strconv.Atoi(cmdArgs.globals["ask"])
uask := alpm.Question(ask) | alpm.QuestionConflictPkg
cmdArgs.globals["ask"] = fmt.Sprint(uask)
//this downloads the package build sources but also causes
//a version bumb for vsc packages
//that should not edit the sources so we should be safe to skip
//it and parse the srcinfo at the current version
if arguments.existsArg("gendb") {
err = parsesrcinfosFile(dc.Aur, srcinfos, dc.Bases)
if err != nil {
return err
}
}
if arguments.existsArg("gendb") {
fmt.Println("GenDB finished. No packages were installed")
fmt.Println(boldGreenFg(arrow + " GenDB finished. No packages were installed"))
return nil
}
// if !continueTask("Proceed with install?", "nN") {
// return fmt.Errorf("Aborting due to user")
// }
err = downloadPkgBuildsSources(dc.Aur)
if err != nil {
return err
}
err = parsesrcinfos(dc.Aur, srcinfos)
err = parsesrcinfosGenerate(dc.Aur, srcinfos, dc.Bases)
if err != nil {
return err
}
@ -152,7 +195,7 @@ func install(parser *arguments) error {
}
if len(dc.MakeOnly) > 0 {
if continueTask("Remove make dependencies?", "yY") {
if !removeMake {
return nil
}
@ -236,21 +279,13 @@ func checkForConflicts(dc *depCatagories) error {
fmt.Println(
redFg("Package conflicts found:"))
for name, pkgs := range toRemove {
str := yellowFg("\t" + name) + " Replaces"
str := "\tInstalling " + yellowFg(name) + " will remove"
for pkg := range pkgs {
str += " " + yellowFg(pkg)
}
fmt.Println(str)
}
if !continueTask("Continue with install?", "nN") {
return fmt.Errorf("Aborting due to user")
}
ask, _ := strconv.Atoi(cmdArgs.globals["ask"])
uask := alpm.Question(ask) | alpm.QuestionConflictPkg
cmdArgs.globals["ask"] = fmt.Sprint(uask)
}
return nil
@ -279,10 +314,44 @@ func askEditPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error {
return nil
}
func parsesrcinfos(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) error {
for _, pkg := range pkgs {
func updateVSCdb(pkgbuild *gopkg.PKGBUILD) {
for _, pkgsource := range pkgbuild.Source {
owner, repo := parseSource(pkgsource)
if owner != "" && repo != "" {
err := branchInfo(pkgbuild.Pkgbase, owner, repo)
if err != nil {
fmt.Println(err)
}
}
}
}
func parsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) error {
for k, pkg := range pkgs {
dir := config.BuildDir + pkg.PackageBase + "/"
str := boldCyanFg("::") + boldFg(" Parsing SRCINFO (%d/%d): %s\n")
fmt.Printf(str, k+1, len(pkgs), formatPkgbase(pkg, bases))
pkgbuild, err := gopkg.ParseSRCINFO(dir + ".SRCINFO")
if err != nil {
return fmt.Errorf("%s: %s", pkg.Name, err)
}
srcinfos[pkg.PackageBase] = pkgbuild
updateVSCdb(pkgbuild)
}
return nil
}
func parsesrcinfosGenerate(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) error {
for k, pkg := range pkgs {
dir := config.BuildDir + pkg.PackageBase + "/"
str := boldCyanFg("::") + boldFg(" Parsing SRCINFO (%d/%d): %s\n")
fmt.Printf(str, k+1, len(pkgs), formatPkgbase(pkg, bases))
cmd := exec.Command(config.MakepkgBin, "--printsrcinfo")
cmd.Stderr = os.Stderr
cmd.Dir = dir
@ -298,33 +367,18 @@ func parsesrcinfos(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) error {
}
srcinfos[pkg.PackageBase] = pkgbuild
for _, pkgsource := range pkgbuild.Source {
owner, repo := parseSource(pkgsource)
if owner != "" && repo != "" {
err = branchInfo(pkg.Name, owner, repo)
if err != nil {
return err
}
}
}
updateVSCdb(pkgbuild)
}
return nil
}
func dowloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) (err error) {
for _, pkg := range pkgs {
for k, pkg := range pkgs {
//todo make pretty
str := "Downloading: " + pkg.PackageBase + "-" + pkg.Version
if len(bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name {
str += " ("
for _, split := range bases[pkg.PackageBase] {
str += split.Name + " "
}
str = str[:len(str)-1] + ")"
}
fmt.Println(str)
str := boldCyanFg("::") + boldFg(" Downloading (%d/%d): %s\n")
fmt.Printf(str, k+1, len(pkgs), formatPkgbase(pkg, bases))
err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir, false)
if err != nil {
@ -340,7 +394,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg) (err error) {
dir := config.BuildDir + pkg.PackageBase + "/"
err = passToMakepkg(dir, "--nobuild", "--nocheck", "--noprepare", "--nodeps")
if err != nil {
return
return fmt.Errorf("Error downloading sources: %s", pkg)
}
}
@ -373,9 +427,9 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD,
fmt.Println(boldRedFgBlackBg(arrow+" Warning:"),
blackBg(pkg.Name+"-"+pkg.Version+" Already made -- skipping build"))
} else {
err := passToMakepkg(dir, "-Cscf", "--noconfirm")
err := passToMakepkg(dir, "-Ccf", "--noconfirm")
if err != nil {
return err
return fmt.Errorf("Error making: %s", pkg.Name)
}
}

View File

@ -94,6 +94,21 @@ func (s repoQuery) printSearch() {
}
}
func formatPkgbase(pkg *rpc.Pkg, bases map[string][]*rpc.Pkg) string {
str := pkg.PackageBase
if len(bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name {
str2 := " ("
for _, split := range bases[pkg.PackageBase] {
str2 += split.Name + " "
}
str2 = str2[:len(str2)-1] + ")"
str += str2
}
return str
}
// printDownloadsFromRepo prints repository packages to be downloaded
func printDepCatagories(dc *depCatagories) {
repo := ""
@ -201,6 +216,7 @@ func PrintInfo(a *rpc.Pkg) {
fmt.Println(boldWhiteFg("Licenses :"), strings.Join(a.License, " "))
fmt.Println(boldWhiteFg("Depends On :"), strings.Join(a.Depends, " "))
fmt.Println(boldWhiteFg("Make Deps :"), strings.Join(a.MakeDepends, " "))
fmt.Println(boldWhiteFg("Check Deps :"), strings.Join(a.CheckDepends, " "))
fmt.Println(boldWhiteFg("Optional Deps :"), strings.Join(a.OptDepends, " "))
fmt.Println(boldWhiteFg("Conflicts With :"), strings.Join(a.Conflicts, " "))
fmt.Println(boldWhiteFg("Maintainer :"), a.Maintainer)
@ -256,53 +272,7 @@ func localStatistics() error {
biggestPackages()
fmt.Println(boldCyanFg("==========================================="))
var q aurQuery
var j int
for i := len(remoteNames); i != 0; i = j {
j = i - config.RequestSplitN
if j < 0 {
j = 0
}
qtemp, err := rpc.Info(remoteNames[j:i])
q = append(q, qtemp...)
if err != nil {
return err
}
}
var outcast []string
for _, s := range remoteNames {
found := false
for _, i := range q {
if s == i.Name {
found = true
break
}
}
if !found {
outcast = append(outcast, s)
}
}
if err != nil {
return err
}
for _, res := range q {
if res.Maintainer == "" {
fmt.Println(boldRedFgBlackBg(arrow+"Warning:"),
boldYellowFgBlackBg(res.Name), whiteFgBlackBg("is orphaned"))
}
if res.OutOfDate != 0 {
fmt.Println(boldRedFgBlackBg(arrow+"Warning:"),
boldYellowFgBlackBg(res.Name), whiteFgBlackBg("is out-of-date in AUR"))
}
}
for _, res := range outcast {
fmt.Println(boldRedFgBlackBg(arrow+"Warning:"),
boldYellowFgBlackBg(res), whiteFgBlackBg("is not available in AUR"))
}
aurInfo(remoteNames)
return nil
}
@ -318,14 +288,18 @@ func printMissing(missing stringSet) {
//todo make it less hacky
func printNumberOfUpdates() error {
//todo
old := os.Stdout // keep backup of the real stdout
os.Stdout = nil
aurUp, repoUp, err := upList()
_, _, localNames, remoteNames, err := filterPackages()
dt, _ := getDepTree(append(localNames, remoteNames...))
aurUp, repoUp, err := upList(dt)
os.Stdout = old // restoring the real stdout
if err != nil {
return err
}
fmt.Println(len(aurUp) + len(repoUp))
return nil
}
@ -333,7 +307,10 @@ func printNumberOfUpdates() error {
func printUpdateList() error {
old := os.Stdout // keep backup of the real stdout
os.Stdout = nil
aurUp, repoUp, err := upList()
_, _, localNames, remoteNames, err := filterPackages()
dt, _ := getDepTree(append(localNames, remoteNames...))
aurUp, repoUp, err := upList(dt)
os.Stdout = old // restoring the real stdout
if err != nil {
return err

144
query.go
View File

@ -4,6 +4,7 @@ import (
"fmt"
"sort"
"strings"
"sync"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
@ -153,16 +154,23 @@ func syncSearch(pkgS []string) (err error) {
// SyncInfo serves as a pacman -Si for repo packages and AUR packages.
func syncInfo(pkgS []string) (err error) {
aurS, repoS, missing, err := packageSlices(pkgS)
var info []rpc.Pkg
aurS, repoS, err := packageSlices(pkgS)
if err != nil {
return
}
if len(aurS) != 0 {
info, err = aurInfo(aurS)
if err != nil {
fmt.Println(err)
}
}
//repo always goes first
if len(repoS) != 0 {
arguments := cmdArgs.copy()
arguments.delTarget(aurS...)
arguments.delTarget(missing...)
err = passToPacman(arguments)
if err != nil {
@ -171,20 +179,11 @@ func syncInfo(pkgS []string) (err error) {
}
if len(aurS) != 0 {
q, err := rpc.Info(aurS)
if err != nil {
fmt.Println(err)
}
for _, aurP := range q {
PrintInfo(&aurP)
for _, pkg := range info {
PrintInfo(&pkg)
}
}
//todo
//if len(missing) != 0 {
// printMissing(missing)
//}
return
}
@ -239,8 +238,7 @@ func queryRepo(pkgInputN []string) (s repoQuery, n int, err error) {
}
// PackageSlices separates an input slice into aur and repo slices
func packageSlices(toCheck []string) (aur []string, repo []string, missing []string, err error) {
possibleAur := make([]string, 0)
func packageSlices(toCheck []string) (aur []string, repo []string, err error) {
dbList, err := alpmHandle.SyncDbs()
if err != nil {
return
@ -263,30 +261,10 @@ func packageSlices(toCheck []string) (aur []string, repo []string, missing []str
if found {
repo = append(repo, pkg)
} else {
possibleAur = append(possibleAur, pkg)
aur = append(aur, pkg)
}
}
if len(possibleAur) == 0 {
return
}
info, err := rpc.Info(possibleAur)
if err != nil {
fmt.Println(err)
}
outer:
for _, pkg := range possibleAur {
for _, rpcpkg := range info {
if rpcpkg.Name == pkg {
aur = append(aur, pkg)
continue outer
}
}
missing = append(missing, pkg)
}
return
}
@ -380,3 +358,97 @@ big:
}
return
}
func min(a, b int) int {
if a < b {
return a
}
return a
}
func aurInfo(names []string) ([]rpc.Pkg, error) {
info := make([]rpc.Pkg, 0, len(names))
seen := make(map[string]int)
var mux sync.Mutex
var wg sync.WaitGroup
var err error
missing := make([]string, 0, len(names))
orphans := make([]string, 0, len(names))
outOfDate := make([]string, 0, len(names))
makeRequest := func(n, max int) {
tempInfo, requestErr := rpc.Info(names[n:max])
if err != nil {
return
}
if requestErr != nil {
//return info, err
err = requestErr
return
}
mux.Lock()
info = append(info, tempInfo...)
mux.Unlock()
wg.Done()
}
for n := 0; n < len(names); n += config.RequestSplitN {
max := min(len(names), n+config.RequestSplitN)
wg.Add(1)
go makeRequest(n, max)
}
wg.Wait()
if err != nil {
return info, err
}
for k, pkg := range info {
seen[pkg.Name] = k
}
for _, name := range names {
i, ok := seen[name]
if !ok {
missing = append(missing, name)
continue
}
pkg := info[i]
if pkg.Maintainer == "" {
orphans = append(orphans, name)
}
if pkg.OutOfDate != 0 {
outOfDate = append(outOfDate, name)
}
}
if len(missing) > 0 {
fmt.Print(boldRedFgBlackBg(arrow + " Missing AUR Packages:"))
for _, name := range missing {
fmt.Print(" " + boldYellowFgBlackBg(name))
}
fmt.Println()
}
if len(orphans) > 0 {
fmt.Print(boldRedFgBlackBg(arrow + " Orphaned AUR Packages:"))
for _, name := range orphans {
fmt.Print(" " + boldYellowFgBlackBg(name))
}
fmt.Println()
}
if len(outOfDate) > 0 {
fmt.Print(boldRedFgBlackBg(arrow + " Out Of Date AUR Packages:"))
for _, name := range outOfDate {
fmt.Print(" " + boldYellowFgBlackBg(name))
}
fmt.Println()
}
return info, nil
}

View File

@ -10,7 +10,6 @@ import (
"unicode"
alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
pkgb "github.com/mikkeloscar/gopkgbuild"
)
@ -57,12 +56,34 @@ func (u upSlice) Less(i, j int) bool {
return false
}
func getVersionDiff(oldVersion, newversion string) (left, right string) {
old, errOld := pkgb.NewCompleteVersion(oldVersion)
new, errNew := pkgb.NewCompleteVersion(newversion)
if errOld != nil {
left = redFg("Invalid Version")
}
if errNew != nil {
right = redFg("Invalid Version")
}
if errOld == nil && errNew == nil {
if old.Version == new.Version {
left = string(old.Version) + "-" + redFg(string(old.Pkgrel))
right = string(new.Version) + "-" + greenFg(string(new.Pkgrel))
} else {
left = redFg(string(old.Version)) + "-" + string(old.Pkgrel)
right = boldGreenFg(string(new.Version)) + "-" + string(new.Pkgrel)
}
}
return
}
// Print prints the details of the packages to upgrade.
func (u upSlice) Print(start int) {
for k, i := range u {
old, errOld := pkgb.NewCompleteVersion(i.LocalVersion)
new, errNew := pkgb.NewCompleteVersion(i.RemoteVersion)
var left, right string
left, right := getVersionDiff(i.LocalVersion, i.RemoteVersion)
f := func(name string) (output string) {
if alpmConf.Options&alpm.ConfColor == 0 {
@ -77,26 +98,6 @@ func (u upSlice) Print(start int) {
fmt.Print(yellowFg(fmt.Sprintf("%2d ", len(u)+start-k-1)))
fmt.Print(f(i.Repository), "/", boldWhiteFg(i.Name))
if errOld != nil {
left = redFg("Invalid Version")
} else {
if old.Version == new.Version {
left = string(old.Version) + "-" + redFg(string(old.Pkgrel))
} else {
left = redFg(string(old.Version)) + "-" + string(old.Pkgrel)
}
}
if errNew != nil {
right = redFg("Invalid Version")
} else {
if old.Version == new.Version {
right = string(new.Version) + "-" + greenFg(string(new.Pkgrel))
} else {
right = boldGreenFg(string(new.Version)) + "-" + string(new.Pkgrel)
}
}
w := 70 - len(i.Repository) - len(i.Name) + len(left)
fmt.Printf(fmt.Sprintf("%%%ds", w),
fmt.Sprintf("%s -> %s\n", left, right))
@ -104,7 +105,7 @@ func (u upSlice) Print(start int) {
}
// upList returns lists of packages to upgrade from each source.
func upList() (aurUp upSlice, repoUp upSlice, err error) {
func upList(dt *depTree) (aurUp upSlice, repoUp upSlice, err error) {
local, remote, _, remoteNames, err := filterPackages()
if err != nil {
return
@ -123,7 +124,7 @@ func upList() (aurUp upSlice, repoUp upSlice, err error) {
fmt.Println(boldCyanFg("::"), boldFg("Searching AUR for updates..."))
go func() {
aurUpList, err := upAUR(remote, remoteNames)
aurUpList, err := upAUR(remote, remoteNames, dt)
errC <- err
aurC <- aurUpList
}()
@ -168,7 +169,7 @@ func upDevel(remote []alpm.Package, packageC chan upgrade, done chan bool) {
fmt.Print(yellowFg("Warning: "))
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", pkg.Name(), pkg.Version(), "git")
} else {
packageC <- upgrade{e.Package, "devel", e.SHA[0:6], "git"}
packageC <- upgrade{e.Package, "devel", pkg.Version(), "commit-" + e.SHA[0:6]}
}
} else {
removeVCSPackage([]string{e.Package})
@ -180,8 +181,7 @@ func upDevel(remote []alpm.Package, packageC chan upgrade, done chan bool) {
// upAUR gathers foreign packages and checks if they have new versions.
// Output: Upgrade type package list.
func upAUR(remote []alpm.Package, remoteNames []string) (toUpgrade upSlice, err error) {
var j int
func upAUR(remote []alpm.Package, remoteNames []string, dt *depTree) (toUpgrade upSlice, err error) {
var routines int
var routineDone int
@ -194,48 +194,32 @@ func upAUR(remote []alpm.Package, remoteNames []string) (toUpgrade upSlice, err
fmt.Println(boldCyanFg("::"), boldFg("Checking development packages..."))
}
for i := len(remote); i != 0; i = j {
//Split requests so AUR RPC doesn't get mad at us.
j = i - config.RequestSplitN
if j < 0 {
j = 0
}
routines++
go func(local []alpm.Package, remote []string) {
qtemp, err := rpc.Info(remote)
if err != nil {
fmt.Println(err)
done <- true
return
routines++
go func(remote []alpm.Package, remoteNames []string, dt *depTree) {
for _, pkg := range remote {
aurPkg, ok := dt.Aur[pkg.Name()]
if !ok {
continue
}
// For each item in query: Search equivalent in foreign.
// We assume they're ordered and are returned ordered
// and will only be missing if they don't exist in AUR.
max := len(qtemp) - 1
var missing, x int
for i := range local {
x = i - missing
if x > max {
break
} else if qtemp[x].Name == local[i].Name() {
if (config.TimeUpdate && (int64(qtemp[x].LastModified) > local[i].BuildDate().Unix())) ||
(alpm.VerCmp(local[i].Version(), qtemp[x].Version) < 0) {
if local[i].ShouldIgnore() {
fmt.Print(yellowFg("Warning: "))
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", local[i].Name(), local[i].Version(), qtemp[x].Version)
} else {
packageC <- upgrade{qtemp[x].Name, "aur", local[i].Version(), qtemp[x].Version}
}
}
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(yellowFg("Warning: "))
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", pkg.Name(), left, right)
} else {
missing++
packageC <- upgrade{aurPkg.Name, "aur", pkg.Version(), aurPkg.Version}
}
}
done <- true
}(remote[j:i], remoteNames[j:i])
}
done <- true
}(remote, remoteNames, dt)
if routineDone == routines {
err = nil
return
}
for {
@ -305,31 +289,33 @@ func removeIntListFromList(src, target []int) []int {
}
// upgradePkgs handles updating the cache and installing updates.
func upgradePkgs(flags []string) error {
aurUp, repoUp, err := upList()
if err != nil {
return err
} else if len(aurUp)+len(repoUp) == 0 {
fmt.Println("\nThere is nothing to do")
return err
}
func upgradePkgs(dt *depTree) (stringSet, stringSet, error) {
var repoNums []int
var aurNums []int
repoNames := make(stringSet)
aurNames := make(stringSet)
aurUp, repoUp, err := upList(dt)
if err != nil {
return repoNames, aurNames, err
} else if len(aurUp)+len(repoUp) == 0 {
return repoNames, aurNames, err
}
sort.Sort(repoUp)
fmt.Println(boldBlueFg("::"), len(aurUp)+len(repoUp), boldWhiteFg("Packages to upgrade."))
repoUp.Print(len(aurUp) + 1)
aurUp.Print(1)
if !config.NoConfirm {
fmt.Println(greenFg("Enter packages you don't want to upgrade."))
fmt.Print("Numbers: ")
fmt.Println(boldGreenFg(arrow) + greenFg(" Packages to not upgrade (eg: 1 2 3, 1-3 or ^4)"))
fmt.Print(boldGreenFg(arrow + " "))
reader := bufio.NewReader(os.Stdin)
numberBuf, overflow, err := reader.ReadLine()
if err != nil || overflow {
fmt.Println(err)
return err
return repoNames, aurNames, err
}
result := strings.Fields(string(numberBuf))
@ -383,13 +369,6 @@ func upgradePkgs(flags []string) error {
repoNums = removeIntListFromList(excludeRepo, repoNums)
}
arguments := cmdArgs.copy()
arguments.delArg("u", "sysupgrade")
arguments.delArg("y", "refresh")
var repoNames []string
var aurNames []string
if len(repoUp) != 0 {
repoloop:
for i, k := range repoUp {
@ -398,7 +377,7 @@ func upgradePkgs(flags []string) error {
continue repoloop
}
}
repoNames = append(repoNames, k.Name)
repoNames.set(k.Name)
}
}
@ -410,12 +389,9 @@ func upgradePkgs(flags []string) error {
continue aurloop
}
}
aurNames = append(aurNames, k.Name)
aurNames.set(k.Name)
}
}
arguments.addTarget(repoNames...)
arguments.addTarget(aurNames...)
err = install(arguments)
return err
return repoNames, aurNames, err
}