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) { func handleGetpkgbuild() (err error) {
for pkg := range cmdArgs.targets { err = getPkgbuilds(cmdArgs.formatTargets())
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)
}
}
return return
} }
@ -497,10 +488,10 @@ func handleSync() (err error) {
err = syncSearch(targets) err = syncSearch(targets)
} else if cmdArgs.existsArg("c", "clean") { } else if cmdArgs.existsArg("c", "clean") {
err = passToPacman(cmdArgs) err = passToPacman(cmdArgs)
} else if cmdArgs.existsArg("u", "sysupgrade") {
err = upgradePkgs(make([]string, 0))
} else if cmdArgs.existsArg("i", "info") { } else if cmdArgs.existsArg("i", "info") {
err = syncInfo(targets) err = syncInfo(targets)
} else if cmdArgs.existsArg("u", "sysupgrade") {
err = install(cmdArgs)
} else if len(cmdArgs.targets) > 0 { } else if len(cmdArgs.targets) > 0 {
err = install(cmdArgs) err = install(cmdArgs)
} }
@ -602,9 +593,8 @@ func numberMenu(pkgS []string, flags []string) (err error) {
aurQ.printSearch(numpq + 1) aurQ.printSearch(numpq + 1)
} }
fmt.Println(greenFg("Type the numbers or ranges (e.g. 1-10) you want to install. " + fmt.Println(boldGreenFg(arrow) + boldGreenFg(" Packages to not upgrade (eg: 1 2 3, 1-3 or ^4)"))
"Separate each one of them with a space.")) fmt.Print(boldGreenFg(arrow + " "))
fmt.Print("Numbers: ")
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
numberBuf, overflow, err := reader.ReadLine() numberBuf, overflow, err := reader.ReadLine()
if err != nil || overflow { if err != nil || overflow {

View File

@ -1,14 +1,13 @@
package main package main
import ( import (
"strings"
alpm "github.com/jguer/go-alpm" alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur" rpc "github.com/mikkeloscar/aur"
"strings"
) )
type depTree struct { type depTree struct {
ToProcess []string ToProcess stringSet
Repo map[string]*alpm.Package Repo map[string]*alpm.Package
Aur map[string]*rpc.Pkg Aur map[string]*rpc.Pkg
Missing stringSet Missing stringSet
@ -23,7 +22,7 @@ type depCatagories struct {
func makeDepTree() *depTree { func makeDepTree() *depTree {
dt := depTree{ dt := depTree{
make([]string, 0), make(stringSet),
make(map[string]*alpm.Package), make(map[string]*alpm.Package),
make(map[string]*rpc.Pkg), make(map[string]*rpc.Pkg),
make(stringSet), 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) { 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 { for _, _dep := range deps {
dep := getNameFromDep(_dep) dep := getNameFromDep(_dep)
@ -188,12 +187,10 @@ func getDepTree(pkgs []string) (*depTree, error) {
continue 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 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) { func depTreeRecursive(dt *depTree, localDb *alpm.Db, syncDb alpm.DbList, isMake bool) (err error) {
nextProcess := make([]string, 0) if len(dt.ToProcess) == 0 {
currentProcess := make([]string, 0, len(dt.ToProcess)) return
}
nextProcess := make(stringSet)
currentProcess := make(stringSet)
//strip version conditions //strip version conditions
for _, dep := range dt.ToProcess { for dep := range dt.ToProcess {
currentProcess = append(currentProcess, getNameFromDep(dep)) currentProcess.set(getNameFromDep(dep))
} }
//assume toprocess only contains aur stuff we have not seen //assume toprocess only contains aur stuff we have not seen
info, err := rpc.Info(currentProcess) info, err := aurInfo(currentProcess.toSlice())
if err != nil { if err != nil {
return 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 //loop through to process and check if we now have
//each packaged cached //each packaged cached
//if its not cached we assume its missing //if its not cached we assume its missing
for k, pkgName := range currentProcess { for pkgName := range currentProcess {
pkg, exists := dt.Aur[pkgName] pkg, exists := dt.Aur[pkgName]
//did not get it in the request //did not get it in the request
if !exists { if !exists {
dt.Missing.set(dt.ToProcess[k]) dt.Missing.set(pkgName)
continue continue
} }
//for reach dep and makedep //for each dep and makedep
for _, deps := range [2][]string{pkg.Depends, pkg.MakeDepends} { for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, versionedDep := range deps { for _, versionedDep := range deps {
dep := getNameFromDep(versionedDep) 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 //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"
"os/exec" "os/exec"
"strings" "strings"
rpc "github.com/mikkeloscar/aur"
) )
func downloadFile(path string, url string) (err error) { func downloadFile(path string, url string) (err error) {
@ -63,60 +61,71 @@ func downloadAndUnpack(url string, path string, trim bool) (err error) {
return return
} }
func getPkgbuild(pkg string) (err error) { func getPkgbuilds(pkgs []string) error {
//possibleAurs := make([]string, 0, 0)
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
return return err
} }
wd = wd + "/" wd = wd + "/"
err = getPkgbuildfromABS(pkg, wd) missing, err := getPkgbuildsfromABS(pkgs, wd)
if err == nil { if err != nil {
return return err
} }
err = getPkgbuildfromAUR(pkg, wd) err = getPkgbuildsfromAUR(missing, wd)
return return err
} }
// GetPkgbuild downloads pkgbuild from the ABS. // 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() dbList, err := alpmHandle.SyncDbs()
if err != nil { if err != nil {
return return
} }
for _, db := range dbList.Slice() { nextPkg:
pkg, err := db.PkgByName(pkgN) for _, pkgN := range pkgs {
if err == nil { for _, db := range dbList.Slice() {
var url string pkg, err := db.PkgByName(pkgN)
if db.Name() == "core" || db.Name() == "extra" { if err == nil {
url = "https://projects.archlinux.org/svntogit/packages.git/snapshot/packages/" + pkg.Base() + ".tar.gz" var url string
} else if db.Name() == "community" { if db.Name() == "core" || db.Name() == "extra" {
url = "https://projects.archlinux.org/svntogit/community.git/snapshot/community-packages/" + pkg.Base() + ".tar.gz" url = "https://projects.archlinux.org/svntogit/packages.git/snapshot/packages/" + pkg.Base() + ".tar.gz"
} else { } else if db.Name() == "community" {
return fmt.Errorf("Not in standard repositories") 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. // GetPkgbuild downloads pkgbuild from the AUR.
func getPkgbuildfromAUR(pkgN string, dir string) (err error) { func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) {
aq, err := rpc.Info([]string{pkgN}) aq, err := aurInfo(pkgs)
if err != nil { if err != nil {
return err return err
} }
if len(aq) == 0 { for _, pkg := range aq {
return fmt.Errorf("no results") 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 return
} }

View File

@ -5,8 +5,8 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"strings"
"strconv" "strconv"
"strings"
alpm "github.com/jguer/go-alpm" alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur" rpc "github.com/mikkeloscar/aur"
@ -15,87 +15,136 @@ import (
// Install handles package installs // Install handles package installs
func install(parser *arguments) error { func install(parser *arguments) error {
aurs, repos, missing, err := packageSlices(parser.targets.toSlice()) removeMake := false
srcinfos := make(map[string]*gopkg.PKGBUILD) aur, repo, err := packageSlices(parser.targets.toSlice())
if err != nil { if err != nil {
return err return err
} }
if len(missing) > 0 { srcinfos := make(map[string]*gopkg.PKGBUILD)
fmt.Println(missing) var dc *depCatagories
fmt.Println("Could not find all Targets")
//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 := parser.copy()
arguments.delArg("u", "sysupgrade") arguments.delArg("u", "sysupgrade")
arguments.delArg("y", "refresh") arguments.delArg("y", "refresh")
arguments.op = "S" arguments.op = "S"
arguments.targets = make(stringSet) arguments.targets = make(stringSet)
arguments.addTarget(repos...)
if len(repos) != 0 { if parser.existsArg("u", "sysupgrade") {
err := passToPacman(arguments) repoUp, aurUp, err := upgradePkgs(dt)
if err != nil { 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 { hasAur := len(dt.Aur) != 0
//todo mamakeke pretty dc, err = getDepCatagories(parser.formatTargets(), dt)
fmt.Println(greenFg(arrow), greenFg("Resolving Dependencies")) if err != nil {
return err
}
dt, err := getDepTree(aurs) for _, pkg := range dc.Repo {
if err != nil { arguments.addTarget(pkg.Name())
return err }
}
if len(dt.Missing) > 0 { for _, pkg := range repo {
fmt.Println(dt.Missing) arguments.addTarget(pkg)
return fmt.Errorf("Could not find all Deps") }
}
dc, err := getDepCatagories(aurs, dt) if len(dc.Aur) == 0 && len(arguments.targets) == 0 {
if err != nil { fmt.Println("There is nothing to do")
return err return nil
} }
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 hasAur {
printDepCatagories(dc) printDepCatagories(dc)
fmt.Println() 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) err = checkForConflicts(dc)
if err != nil { if err != nil {
return err return err
} }
} }
askCleanBuilds(dc.Aur, dc.Bases) if len(dc.MakeOnly) > 0 {
fmt.Println() if !continueTask("Remove make dependencies after install?", "yY") {
removeMake = true
if !continueTask("Proceed with install?", "nN") { }
return fmt.Errorf("Aborting due to user")
} }
// if !continueTask("Proceed with download?", "nN") { askCleanBuilds(dc.Aur, dc.Bases)
// return fmt.Errorf("Aborting due to user")
// } if !continueTask("Proceed with Download?", "nN") {
return fmt.Errorf("Aborting due to user")
}
err = dowloadPkgBuilds(dc.Aur, dc.Bases) err = dowloadPkgBuilds(dc.Aur, dc.Bases)
if err != nil { if err != nil {
@ -107,41 +156,35 @@ func install(parser *arguments) error {
return err return err
} }
if len(dc.Repo) > 0 { if !continueTask("Proceed with install?", "nN") {
arguments := parser.copy() return fmt.Errorf("Aborting due to user")
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())
}
oldConfirm := config.NoConfirm //conflicts have been checked so answer y for them
config.NoConfirm = true ask, _ := strconv.Atoi(cmdArgs.globals["ask"])
passToPacman(arguments) uask := alpm.Question(ask) | alpm.QuestionConflictPkg
config.NoConfirm = oldConfirm 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 { if err != nil {
return err return err
} }
}
if arguments.existsArg("gendb") { fmt.Println(boldGreenFg(arrow + " GenDB finished. No packages were installed"))
fmt.Println("GenDB finished. No packages were installed")
return nil return nil
} }
// if !continueTask("Proceed with install?", "nN") {
// return fmt.Errorf("Aborting due to user")
// }
err = downloadPkgBuildsSources(dc.Aur) err = downloadPkgBuildsSources(dc.Aur)
if err != nil { if err != nil {
return err return err
} }
err = parsesrcinfos(dc.Aur, srcinfos) err = parsesrcinfosGenerate(dc.Aur, srcinfos, dc.Bases)
if err != nil { if err != nil {
return err return err
} }
@ -152,7 +195,7 @@ func install(parser *arguments) error {
} }
if len(dc.MakeOnly) > 0 { if len(dc.MakeOnly) > 0 {
if continueTask("Remove make dependencies?", "yY") { if !removeMake {
return nil return nil
} }
@ -236,21 +279,13 @@ func checkForConflicts(dc *depCatagories) error {
fmt.Println( fmt.Println(
redFg("Package conflicts found:")) redFg("Package conflicts found:"))
for name, pkgs := range toRemove { for name, pkgs := range toRemove {
str := yellowFg("\t" + name) + " Replaces" str := "\tInstalling " + yellowFg(name) + " will remove"
for pkg := range pkgs { for pkg := range pkgs {
str += " " + yellowFg(pkg) str += " " + yellowFg(pkg)
} }
fmt.Println(str) 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 return nil
@ -279,10 +314,44 @@ func askEditPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error {
return nil return nil
} }
func parsesrcinfos(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) error { func updateVSCdb(pkgbuild *gopkg.PKGBUILD) {
for _, pkg := range pkgs { 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 + "/" 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 := exec.Command(config.MakepkgBin, "--printsrcinfo")
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
cmd.Dir = dir cmd.Dir = dir
@ -298,33 +367,18 @@ func parsesrcinfos(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) error {
} }
srcinfos[pkg.PackageBase] = pkgbuild srcinfos[pkg.PackageBase] = pkgbuild
updateVSCdb(pkgbuild)
for _, pkgsource := range pkgbuild.Source {
owner, repo := parseSource(pkgsource)
if owner != "" && repo != "" {
err = branchInfo(pkg.Name, owner, repo)
if err != nil {
return err
}
}
}
} }
return nil return nil
} }
func dowloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) (err error) { func dowloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) (err error) {
for _, pkg := range pkgs { for k, pkg := range pkgs {
//todo make pretty //todo make pretty
str := "Downloading: " + pkg.PackageBase + "-" + pkg.Version str := boldCyanFg("::") + boldFg(" Downloading (%d/%d): %s\n")
if len(bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name {
str += " (" fmt.Printf(str, k+1, len(pkgs), formatPkgbase(pkg, bases))
for _, split := range bases[pkg.PackageBase] {
str += split.Name + " "
}
str = str[:len(str)-1] + ")"
}
fmt.Println(str)
err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir, false) err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir, false)
if err != nil { if err != nil {
@ -340,7 +394,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg) (err error) {
dir := config.BuildDir + pkg.PackageBase + "/" dir := config.BuildDir + pkg.PackageBase + "/"
err = passToMakepkg(dir, "--nobuild", "--nocheck", "--noprepare", "--nodeps") err = passToMakepkg(dir, "--nobuild", "--nocheck", "--noprepare", "--nodeps")
if err != nil { 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:"), fmt.Println(boldRedFgBlackBg(arrow+" Warning:"),
blackBg(pkg.Name+"-"+pkg.Version+" Already made -- skipping build")) blackBg(pkg.Name+"-"+pkg.Version+" Already made -- skipping build"))
} else { } else {
err := passToMakepkg(dir, "-Cscf", "--noconfirm") err := passToMakepkg(dir, "-Ccf", "--noconfirm")
if err != nil { 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 // printDownloadsFromRepo prints repository packages to be downloaded
func printDepCatagories(dc *depCatagories) { func printDepCatagories(dc *depCatagories) {
repo := "" repo := ""
@ -201,6 +216,7 @@ func PrintInfo(a *rpc.Pkg) {
fmt.Println(boldWhiteFg("Licenses :"), strings.Join(a.License, " ")) fmt.Println(boldWhiteFg("Licenses :"), strings.Join(a.License, " "))
fmt.Println(boldWhiteFg("Depends On :"), strings.Join(a.Depends, " ")) fmt.Println(boldWhiteFg("Depends On :"), strings.Join(a.Depends, " "))
fmt.Println(boldWhiteFg("Make Deps :"), strings.Join(a.MakeDepends, " ")) 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("Optional Deps :"), strings.Join(a.OptDepends, " "))
fmt.Println(boldWhiteFg("Conflicts With :"), strings.Join(a.Conflicts, " ")) fmt.Println(boldWhiteFg("Conflicts With :"), strings.Join(a.Conflicts, " "))
fmt.Println(boldWhiteFg("Maintainer :"), a.Maintainer) fmt.Println(boldWhiteFg("Maintainer :"), a.Maintainer)
@ -256,53 +272,7 @@ func localStatistics() error {
biggestPackages() biggestPackages()
fmt.Println(boldCyanFg("===========================================")) fmt.Println(boldCyanFg("==========================================="))
var q aurQuery aurInfo(remoteNames)
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"))
}
return nil return nil
} }
@ -318,14 +288,18 @@ func printMissing(missing stringSet) {
//todo make it less hacky //todo make it less hacky
func printNumberOfUpdates() error { func printNumberOfUpdates() error {
//todo
old := os.Stdout // keep backup of the real stdout old := os.Stdout // keep backup of the real stdout
os.Stdout = nil 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 os.Stdout = old // restoring the real stdout
if err != nil { if err != nil {
return err return err
} }
fmt.Println(len(aurUp) + len(repoUp)) fmt.Println(len(aurUp) + len(repoUp))
return nil return nil
} }
@ -333,7 +307,10 @@ func printNumberOfUpdates() error {
func printUpdateList() error { func printUpdateList() error {
old := os.Stdout // keep backup of the real stdout old := os.Stdout // keep backup of the real stdout
os.Stdout = nil 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 os.Stdout = old // restoring the real stdout
if err != nil { if err != nil {
return err return err

144
query.go
View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
"sync"
alpm "github.com/jguer/go-alpm" alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur" 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. // SyncInfo serves as a pacman -Si for repo packages and AUR packages.
func syncInfo(pkgS []string) (err error) { func syncInfo(pkgS []string) (err error) {
aurS, repoS, missing, err := packageSlices(pkgS) var info []rpc.Pkg
aurS, repoS, err := packageSlices(pkgS)
if err != nil { if err != nil {
return return
} }
if len(aurS) != 0 {
info, err = aurInfo(aurS)
if err != nil {
fmt.Println(err)
}
}
//repo always goes first //repo always goes first
if len(repoS) != 0 { if len(repoS) != 0 {
arguments := cmdArgs.copy() arguments := cmdArgs.copy()
arguments.delTarget(aurS...) arguments.delTarget(aurS...)
arguments.delTarget(missing...)
err = passToPacman(arguments) err = passToPacman(arguments)
if err != nil { if err != nil {
@ -171,20 +179,11 @@ func syncInfo(pkgS []string) (err error) {
} }
if len(aurS) != 0 { if len(aurS) != 0 {
q, err := rpc.Info(aurS) for _, pkg := range info {
if err != nil { PrintInfo(&pkg)
fmt.Println(err)
}
for _, aurP := range q {
PrintInfo(&aurP)
} }
} }
//todo
//if len(missing) != 0 {
// printMissing(missing)
//}
return 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 // PackageSlices separates an input slice into aur and repo slices
func packageSlices(toCheck []string) (aur []string, repo []string, missing []string, err error) { func packageSlices(toCheck []string) (aur []string, repo []string, err error) {
possibleAur := make([]string, 0)
dbList, err := alpmHandle.SyncDbs() dbList, err := alpmHandle.SyncDbs()
if err != nil { if err != nil {
return return
@ -263,30 +261,10 @@ func packageSlices(toCheck []string) (aur []string, repo []string, missing []str
if found { if found {
repo = append(repo, pkg) repo = append(repo, pkg)
} else { } 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 return
} }
@ -380,3 +358,97 @@ big:
} }
return 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" "unicode"
alpm "github.com/jguer/go-alpm" alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
pkgb "github.com/mikkeloscar/gopkgbuild" pkgb "github.com/mikkeloscar/gopkgbuild"
) )
@ -57,12 +56,34 @@ func (u upSlice) Less(i, j int) bool {
return false 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. // Print prints the details of the packages to upgrade.
func (u upSlice) Print(start int) { func (u upSlice) Print(start int) {
for k, i := range u { for k, i := range u {
old, errOld := pkgb.NewCompleteVersion(i.LocalVersion) left, right := getVersionDiff(i.LocalVersion, i.RemoteVersion)
new, errNew := pkgb.NewCompleteVersion(i.RemoteVersion)
var left, right string
f := func(name string) (output string) { f := func(name string) (output string) {
if alpmConf.Options&alpm.ConfColor == 0 { 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(yellowFg(fmt.Sprintf("%2d ", len(u)+start-k-1)))
fmt.Print(f(i.Repository), "/", boldWhiteFg(i.Name)) 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) w := 70 - len(i.Repository) - len(i.Name) + len(left)
fmt.Printf(fmt.Sprintf("%%%ds", w), fmt.Printf(fmt.Sprintf("%%%ds", w),
fmt.Sprintf("%s -> %s\n", left, right)) 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. // 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() local, remote, _, remoteNames, err := filterPackages()
if err != nil { if err != nil {
return return
@ -123,7 +124,7 @@ func upList() (aurUp upSlice, repoUp upSlice, err error) {
fmt.Println(boldCyanFg("::"), boldFg("Searching AUR for updates...")) fmt.Println(boldCyanFg("::"), boldFg("Searching AUR for updates..."))
go func() { go func() {
aurUpList, err := upAUR(remote, remoteNames) aurUpList, err := upAUR(remote, remoteNames, dt)
errC <- err errC <- err
aurC <- aurUpList aurC <- aurUpList
}() }()
@ -168,7 +169,7 @@ func upDevel(remote []alpm.Package, packageC chan upgrade, done chan bool) {
fmt.Print(yellowFg("Warning: ")) fmt.Print(yellowFg("Warning: "))
fmt.Printf("%s ignoring package upgrade (%s => %s)\n", pkg.Name(), pkg.Version(), "git") fmt.Printf("%s ignoring package upgrade (%s => %s)\n", pkg.Name(), pkg.Version(), "git")
} else { } else {
packageC <- upgrade{e.Package, "devel", e.SHA[0:6], "git"} packageC <- upgrade{e.Package, "devel", pkg.Version(), "commit-" + e.SHA[0:6]}
} }
} else { } else {
removeVCSPackage([]string{e.Package}) 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. // upAUR gathers foreign packages and checks if they have new versions.
// Output: Upgrade type package list. // Output: Upgrade type package list.
func upAUR(remote []alpm.Package, remoteNames []string) (toUpgrade upSlice, err error) { func upAUR(remote []alpm.Package, remoteNames []string, dt *depTree) (toUpgrade upSlice, err error) {
var j int
var routines int var routines int
var routineDone 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...")) fmt.Println(boldCyanFg("::"), boldFg("Checking development packages..."))
} }
for i := len(remote); i != 0; i = j { routines++
//Split requests so AUR RPC doesn't get mad at us. go func(remote []alpm.Package, remoteNames []string, dt *depTree) {
j = i - config.RequestSplitN for _, pkg := range remote {
if j < 0 { aurPkg, ok := dt.Aur[pkg.Name()]
j = 0 if !ok {
} continue
routines++
go func(local []alpm.Package, remote []string) {
qtemp, err := rpc.Info(remote)
if err != nil {
fmt.Println(err)
done <- true
return
} }
// 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 { if (config.TimeUpdate && (int64(aurPkg.LastModified) > pkg.BuildDate().Unix())) ||
x = i - missing (alpm.VerCmp(pkg.Version(), aurPkg.Version) < 0) {
if x > max { if pkg.ShouldIgnore() {
break left, right := getVersionDiff(pkg.Version(), aurPkg.Version)
} else if qtemp[x].Name == local[i].Name() { fmt.Print(yellowFg("Warning: "))
if (config.TimeUpdate && (int64(qtemp[x].LastModified) > local[i].BuildDate().Unix())) || fmt.Printf("%s ignoring package upgrade (%s => %s)\n", pkg.Name(), left, right)
(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
} else { } 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 { for {
@ -305,31 +289,33 @@ func removeIntListFromList(src, target []int) []int {
} }
// upgradePkgs handles updating the cache and installing updates. // upgradePkgs handles updating the cache and installing updates.
func upgradePkgs(flags []string) error { func upgradePkgs(dt *depTree) (stringSet, stringSet, 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
}
var repoNums []int var repoNums []int
var aurNums []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) sort.Sort(repoUp)
fmt.Println(boldBlueFg("::"), len(aurUp)+len(repoUp), boldWhiteFg("Packages to upgrade.")) fmt.Println(boldBlueFg("::"), len(aurUp)+len(repoUp), boldWhiteFg("Packages to upgrade."))
repoUp.Print(len(aurUp) + 1) repoUp.Print(len(aurUp) + 1)
aurUp.Print(1) aurUp.Print(1)
if !config.NoConfirm { if !config.NoConfirm {
fmt.Println(greenFg("Enter packages you don't want to upgrade.")) fmt.Println(boldGreenFg(arrow) + greenFg(" Packages to not upgrade (eg: 1 2 3, 1-3 or ^4)"))
fmt.Print("Numbers: ") fmt.Print(boldGreenFg(arrow + " "))
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
numberBuf, overflow, err := reader.ReadLine() numberBuf, overflow, err := reader.ReadLine()
if err != nil || overflow { if err != nil || overflow {
fmt.Println(err) fmt.Println(err)
return err return repoNames, aurNames, err
} }
result := strings.Fields(string(numberBuf)) result := strings.Fields(string(numberBuf))
@ -383,13 +369,6 @@ func upgradePkgs(flags []string) error {
repoNums = removeIntListFromList(excludeRepo, repoNums) 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 { if len(repoUp) != 0 {
repoloop: repoloop:
for i, k := range repoUp { for i, k := range repoUp {
@ -398,7 +377,7 @@ func upgradePkgs(flags []string) error {
continue repoloop continue repoloop
} }
} }
repoNames = append(repoNames, k.Name) repoNames.set(k.Name)
} }
} }
@ -410,12 +389,9 @@ func upgradePkgs(flags []string) error {
continue aurloop continue aurloop
} }
} }
aurNames = append(aurNames, k.Name) aurNames.set(k.Name)
} }
} }
arguments.addTarget(repoNames...) return repoNames, aurNames, err
arguments.addTarget(aurNames...)
err = install(arguments)
return err
} }