From d319576303938ad09caea6bb800c53ca5bf13a0d Mon Sep 17 00:00:00 2001 From: Jguer Date: Fri, 27 Apr 2018 01:25:40 +0100 Subject: [PATCH 001/109] Use megacheck to lint project Signed-off-by: Jguer --- download.go | 6 +----- keys_test.go | 9 +++------ parser.go | 6 +++--- parser_test.go | 2 +- print.go | 4 ++++ query.go | 2 +- upgrade.go | 4 ++-- vcs.go | 4 ---- 8 files changed, 15 insertions(+), 22 deletions(-) diff --git a/download.go b/download.go index 79f8a30d..0a932108 100644 --- a/download.go +++ b/download.go @@ -21,11 +21,7 @@ func shouldUseGit(path string) bool { } _, err = os.Stat(filepath.Join(path, ".git")) - if os.IsNotExist(err) { - return false - } - - return true + return os.IsExist(err) } func downloadFile(path string, url string) (err error) { diff --git a/keys_test.go b/keys_test.go index f42941b3..ab8e0560 100644 --- a/keys_test.go +++ b/keys_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "context" "fmt" "io/ioutil" "net/http" @@ -36,10 +37,6 @@ func newPkg(basename string) *rpc.Pkg { return &rpc.Pkg{Name: basename, PackageBase: basename} } -func newSplitPkg(basename, name string) *rpc.Pkg { - return &rpc.Pkg{Name: name, PackageBase: basename} -} - func getPgpKey(key string) string { var buffer bytes.Buffer @@ -73,7 +70,7 @@ func TestImportKeys(t *testing.T) { config.GpgFlags = fmt.Sprintf("--homedir %s --keyserver 127.0.0.1", keyringDir) server := startPgpKeyServer() - defer server.Shutdown(nil) + defer server.Shutdown(context.TODO()) casetests := []struct { keys []string @@ -138,7 +135,7 @@ func TestCheckPgpKeys(t *testing.T) { config.GpgFlags = fmt.Sprintf("--homedir %s --keyserver 127.0.0.1", keyringDir) server := startPgpKeyServer() - defer server.Shutdown(nil) + defer server.Shutdown(context.TODO()) casetests := []struct { pkgs []*rpc.Pkg diff --git a/parser.go b/parser.go index 9957cb56..3d8199e4 100644 --- a/parser.go +++ b/parser.go @@ -220,7 +220,7 @@ func (parser *arguments) getArg(options ...string) (arg string, double bool, exi existCount := 0 for _, option := range options { - arg, exists = parser.options[option] + _, exists = parser.options[option] if exists { existCount++ @@ -619,8 +619,8 @@ func (parser *arguments) parseCommandLine() (err error) { //of course the implementation is up to the caller, this function mearley parses //the input and organizes it func parseNumberMenu(input string) (intRanges, intRanges, stringSet, stringSet) { - include := make(intRanges, 0, 0) - exclude := make(intRanges, 0, 0) + include := make(intRanges, 0) + exclude := make(intRanges, 0) otherInclude := make(stringSet) otherExclude := make(stringSet) diff --git a/parser_test.go b/parser_test.go index 47c05177..5aa57c67 100644 --- a/parser_test.go +++ b/parser_test.go @@ -19,7 +19,7 @@ func intRangesEqual(a, b intRanges) bool { r1 := a[n] r2 := b[n] - if r1.min != r1.min || r1.max != r2.max { + if r1.min != r2.min || r1.max != r2.max { return false } } diff --git a/print.go b/print.go index bb2873a8..293d1ef4 100644 --- a/print.go +++ b/print.go @@ -341,6 +341,10 @@ func printUpdateList(parser *arguments) error { old := os.Stdout // keep backup of the real stdout os.Stdout = nil _, _, localNames, remoteNames, err := filterPackages() + if err != nil { + return err + } + aurUp, repoUp, err := upList(warnings) os.Stdout = old // restoring the real stdout if err != nil { diff --git a/query.go b/query.go index 99dcfe20..3eb22f69 100644 --- a/query.go +++ b/query.go @@ -353,7 +353,7 @@ func hangingPackages(removeOptional bool) (hanging []string, err error) { iterateAgain := true processDependencies := func(pkg alpm.Package) error { - if state, _ := safePackages[pkg.Name()]; state == 0 || state == 2 { + if state := safePackages[pkg.Name()]; state == 0 || state == 2 { return nil } diff --git a/upgrade.go b/upgrade.go index f816d728..afa753e8 100644 --- a/upgrade.go +++ b/upgrade.go @@ -193,8 +193,8 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { } func upDevel(remote []alpm.Package) (toUpgrade upSlice, err error) { - toUpdate := make([]alpm.Package, 0, 0) - toRemove := make([]string, 0, 0) + toUpdate := make([]alpm.Package, 0) + toRemove := make([]string, 0) var mux1 sync.Mutex var mux2 sync.Mutex diff --git a/vcs.go b/vcs.go index 9b120b7d..5b219c3c 100644 --- a/vcs.go +++ b/vcs.go @@ -205,10 +205,6 @@ func (infos shaInfos) needsUpdate() bool { } } -func inStore(pkgName string) shaInfos { - return savedInfo[pkgName] -} - func saveVCSInfo() error { marshalledinfo, err := json.MarshalIndent(savedInfo, "", "\t") if err != nil || string(marshalledinfo) == "null" { From debe19278a589c7b785c993f0bcbd362a1a32105 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 27 Apr 2018 02:43:10 +0100 Subject: [PATCH 002/109] Fix warning by megacheck in parser --- parser.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 3d8199e4..4ce96228 100644 --- a/parser.go +++ b/parser.go @@ -220,9 +220,12 @@ func (parser *arguments) getArg(options ...string) (arg string, double bool, exi existCount := 0 for _, option := range options { - _, exists = parser.options[option] + var value string + + value, exists = parser.options[option] if exists { + arg = value existCount++ _, exists = parser.doubles[option] @@ -232,9 +235,10 @@ func (parser *arguments) getArg(options ...string) (arg string, double bool, exi } - arg, exists = parser.globals[option] + value, exists = parser.globals[option] if exists { + arg = value existCount++ _, exists = parser.doubles[option] From 58772c871b844b03382f22e72bbdb7ae8ffdf8c8 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 28 Apr 2018 11:53:10 +0100 Subject: [PATCH 003/109] Fixes #373 Signed-off-by: Jguer --- main.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/main.go b/main.go index d3604cf7..608a4c31 100644 --- a/main.go +++ b/main.go @@ -60,6 +60,14 @@ func initConfig() (err error) { err) defaultSettings(&config) } + if _, err = os.Stat(config.BuildDir); os.IsNotExist(err) { + err = os.MkdirAll(config.BuildDir, 0755) + if err != nil { + err = fmt.Errorf("Unable to create BuildDir directory:\n%s\n"+ + "The error was:\n%s", config.BuildDir, err) + return + } + } } } From ba4ef4f51ca78b9e180475de82121da0464e6b37 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 28 Apr 2018 12:12:41 +0100 Subject: [PATCH 004/109] Use more filepath.Join, standardize separators --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 608a4c31..8b05b961 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( func initPaths() { if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" { if info, err := os.Stat(configHome); err == nil && info.IsDir() { - configHome = configHome + "/yay" + configHome = filepath.Join(configHome, "yay") } else { configHome = filepath.Join(os.Getenv("HOME"), ".config/yay") } @@ -28,7 +28,7 @@ func initPaths() { cacheHome = filepath.Join(os.Getenv("HOME"), ".cache/yay") } } else { - cacheHome = filepath.Join(os.Getenv("HOME"), "/.cache/yay") + cacheHome = filepath.Join(os.Getenv("HOME"), ".cache/yay") } configFile = filepath.Join(configHome, configFileName) From 9b351b1779f60c269407609d070d220a5d0ccbb2 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 28 Apr 2018 14:44:23 +0100 Subject: [PATCH 005/109] Remove changelog from README. Update some pictures We use annotated tags and github releases already --- README.md | 199 ++---------------------------------------------------- 1 file changed, 6 insertions(+), 193 deletions(-) diff --git a/README.md b/README.md index e46e9089..becb5f18 100644 --- a/README.md +++ b/README.md @@ -41,197 +41,10 @@ Yay was created with a few objectives in mind and based on the design of [yaourt * `yay -Yc` cleans unneeded dependencies * `yay -G` downloads PKGBUILD from ABS or AUR * `yay -Y --gendb` generates development package DB used for devel updates. +* `yay -Syu --devel --timeupdate` Normal update but also check for development + package updates and uses PKGBUILD modification time and not version to + determine update - - - - -### Changelog - -#### v5.675 - -* Recursively remove dependencies when using yay -Yc -* Highlight diff between old and new versions better -* Fix regression where repo upgrades were marked as deps during sysupgrades -* Added `--editorflags` to add flags to editor execution - -#### v5.657 - -* By default running `yay` will trigger `yay -Syu` -* Updated Shell completions -* `-Ss` shows difference between installed and in-repo versions -* Allow sorting AUR results by fields other than votes - * votes|popularity|id|baseid|name|base|submitted|modified -* Added flags for automatic menu input - * --answerclean --answeredit --answerupgrade - * --noanswerclean --noansweredit --noanswerupgrade -* Fixed versioned dep checking -* Usual fixes to parsing, dependency sourcing and other PKGBUILD atrocities - -#### v5.608 - -* Updated Shell completions -* Added `-Qu` to extended pacman options -* Provides now supported in `-Si` -* Improved build method -* Improved conflict checking -* PKGBUILDs with unsupported arch can force build now -* PGP Key automatic importing -* GPG option passing -* `db/name` support re-added - -#### 4.505 - -* `yay` used to auto save permanent configuration options, now `--save` must be passed to save permanent configuration options -* Competions updated -* Number menu is now used to edit PKGBuilds and Clean Builds -* Devel updates of `-git` packages now uses `git ls-remote` which makes it compatible with other platforms besides github. -* Devel update checking is faster as well -* Updated man page - -#### 3.440 - -* Closed a lot of issues -* Updated bash and zsh completions -* New colour scheme -* Small parsing fixes -* Automatically delete package from transaction if $EDITOR exits with non-zero #140 -* Added check depends support - -#### 3.373 - -* Version bump to V3 to reflect all of the changes to syntax -* `yay -Pd` prints default config -* `yay -Pg` prints current config -* Fixes #174 -* Fixes #176 -* Fixes -G being unable to download split packages -* Fixes #171 -* Fixes -Si failing when given a non existing package on https://github.com/Jguer/yay/pull/155 -* Fixes other small bugs on 2.350 without adding new features - -#### 2.350 - -* Adds sudo loop (off by default, enable only by editing config file) #147 -* Adds replace package support #154 #134 -* Minor display improvements #150 for example -* Fixes GenDB -* Fixes Double options passing to pacman -* Noconfirm works more as expected -* Minor fixes and refactoring -* Yay filters out the repository name if it's included. -* Fixes #122 - -#### 2.298 - -* Adds #115 - -#### 2.296 - -* New argument parsing @Morganamilo (check manpage or --help for new - information) -* yay -Qstats changed to yay -Ps or yay -P --stats -* yay -Cd changed to yay -Yc or yay -Y --clean -* yay -Pu (--upgrades) prints update list -* yay -Pn (--numberupgrades) prints number of updates -* yay -G also possible through -Yg or -Y --getpkgbuild (yay -G will be - discontinued once it's possible to add options to the getpkgbuild operation) -* yay now counts from 1 instead of 0 @Morganamilo -* Support for ranges when selecting packages @samosaara -* Pacaur style ask all questions first and download first @Morganamilo -* Updated vendor dependencies (Fixes pacman.conf parsing errors and PKGBUILD - parsing errors) -* Updated completions - -#### 2.219 - -* Updated manpage -* Updated --help -* Fixed AUR update fails with large number of packages #59 -* Check if package is already in upgrade list and skip it. #60 -* Add -V and -h for flag parsing @AnthonyLam -* Prevent file corruption by truncating the files @maximbaz -* Print VCS error details @maximbaz -* Using '-' doesn't raise an error @PietroCarrara -* use Command.Dir in aur.PkgInstall; Fixes #32 #47 @afg984 -* Suffix YayConf.BuildDir with uid to avoid permission issues @afg984 (Not included in last changelog) - -#### 2.200 - -* Development github package support re-added - -#### 2.196 - -* XDG_CONFIG_HOME support -* XDG_CACHE_HOME support - -#### 2.165 - -* Upgrade list now allows skipping upgrade install - -#### 2.159 - -* Qstats now warns about packages not available in AUR - -#### 2.152 - -* Fetching backend changed to Mikkel Oscar's [Aur](https://github.com/mikkeloscar/aur) -* Added support for development packages from github. -* Pacman backend rewritten and simplified -* Added config framework. - -#### 1.115 - -* Added AUR completions (updates on first completion every 48h) - -#### 1.101 - -* Search speed and quality improved [#3](https://github.com/Jguer/yay/issues/3) - -#### 1.100 - -* Added manpage -* Improved search [#3](https://github.com/Jguer/yay/issues/3) -* Added -G to get pkgbuild from the AUR or ABS. [#6](https://github.com/Jguer/yay/issues/6) -* Fixed [#8](https://github.com/Jguer/yay/issues/8) -* Completed and decluttered zsh completions -* If `$EDITOR` or `$VISUAL` is not set yay will prompt you for an editor [#7](https://github.com/Jguer/yay/issues/7) - -#### 1.91 - -* `--downtop` has been replaced with `--bottomup` (as is logical) -* `yay -Ssq` and `yay -Sqs` now displays AUR packages with less information -* Repository search now uses the same criteria as pacman - -#### 1.85 - -* yay now does -Si for AUR packages -* Fixed package install bugs - -#### 1.83 - -* Added new dependency resolver for future features -* Sort package statistics - -#### 1.80 - -* yay now warns when installing orphan packages -* Added orphan status to number menu -* Qstats now checks if system has orphan packages installed - -#### 1.78 - -* Added foreign package statistics to Qstats -* Group installing is now possible -* Better handling of package dependency installing - -#### 1.76 - -* Fixed critical bug that prevented AUR dependencies from being installed. - -#### 1.70 - -* Stable for everyday use -* Bottom up package display -* Number menu like yaourt/apacman -* System package statistics + + + From 79bfa9fbc880f28818fe99967ffa2f2c53e5b93f Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 28 Apr 2018 17:35:05 +0100 Subject: [PATCH 006/109] Fix wrong license on badge Signed-off-by: Jguer --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index becb5f18..c4f5a4d7 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ Yet another Yogurt - An AUR Helper written in Go #### Packages -[![yay](https://img.shields.io/aur/version/yay.svg?label=yay)](https://aur.archlinux.org/packages/yay/) [![yay-bin](https://img.shields.io/aur/version/yay-bin.svg?label=yay-bin)](https://aur.archlinux.org/packages/yay-bin/) [![yay-git](https://img.shields.io/aur/version/yay-git.svg?label=yay-git)](https://aur.archlinux.org/packages/yay-git/) [![GitHub license](https://img.shields.io/badge/license-AGPL-blue.svg)](https://raw.githubusercontent.com/Jguer/yay/master/LICENSE) - +[![yay](https://img.shields.io/aur/version/yay.svg?label=yay)](https://aur.archlinux.org/packages/yay/) [![yay-bin](https://img.shields.io/aur/version/yay-bin.svg?label=yay-bin)](https://aur.archlinux.org/packages/yay-bin/) [![yay-git](https://img.shields.io/aur/version/yay-git.svg?label=yay-git)](https://aur.archlinux.org/packages/yay-git/) [![GitHub license](https://img.shields.io/github/license/jguer/yay.svg)](https://github.com/Jguer/yay/blob/master/LICENSE) There's a point in everyone's life when you feel the need to write an AUR helper because there are only about 20 of them. So say hi to 20+1. From dc10c4b6ddd311489bb3b5d18062293808acb13c Mon Sep 17 00:00:00 2001 From: J Guerreiro Date: Sat, 28 Apr 2018 17:35:53 +0100 Subject: [PATCH 007/109] Fix small indent issue --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4f5a4d7..51344d0f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Yet another Yogurt - An AUR Helper written in Go #### Packages -[![yay](https://img.shields.io/aur/version/yay.svg?label=yay)](https://aur.archlinux.org/packages/yay/) [![yay-bin](https://img.shields.io/aur/version/yay-bin.svg?label=yay-bin)](https://aur.archlinux.org/packages/yay-bin/) [![yay-git](https://img.shields.io/aur/version/yay-git.svg?label=yay-git)](https://aur.archlinux.org/packages/yay-git/) [![GitHub license](https://img.shields.io/github/license/jguer/yay.svg)](https://github.com/Jguer/yay/blob/master/LICENSE) +[![yay](https://img.shields.io/aur/version/yay.svg?label=yay)](https://aur.archlinux.org/packages/yay/) [![yay-bin](https://img.shields.io/aur/version/yay-bin.svg?label=yay-bin)](https://aur.archlinux.org/packages/yay-bin/) [![yay-git](https://img.shields.io/aur/version/yay-git.svg?label=yay-git)](https://aur.archlinux.org/packages/yay-git/) [![GitHub license](https://img.shields.io/github/license/jguer/yay.svg)](https://github.com/Jguer/yay/blob/master/LICENSE) There's a point in everyone's life when you feel the need to write an AUR helper because there are only about 20 of them. So say hi to 20+1. From ee75de013506c45ac51ab6b5e4c8a4d9ca327e39 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 3 May 2018 01:47:24 +0100 Subject: [PATCH 008/109] Add mised filepath.Join() calls --- download.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/download.go b/download.go index 0a932108..dbd44de6 100644 --- a/download.go +++ b/download.go @@ -96,7 +96,7 @@ func downloadAndUnpack(url string, path string, trim bool) (err error) { if trim { err = exec.Command("/bin/sh", "-c", config.TarBin+" --strip-components 2 --include='*/"+fileName[:len(fileName)-7]+"/trunk/' -xf "+tarLocation+" -C "+path).Run() - os.Rename(path+"trunk", path+fileName[:len(fileName)-7]) // kurwa + os.Rename(filepath.Join(path, "trunk"), filepath.Join(path,fileName[:len(fileName)-7])) } else { err = exec.Command(config.TarBin, "-xf", tarLocation, "-C", path).Run() } From e6dae0332923b6c07edad4a17f2037a2f810bc8b Mon Sep 17 00:00:00 2001 From: Simon Legner Date: Fri, 4 May 2018 12:36:14 +0200 Subject: [PATCH 009/109] Use ISO 8601 date format (yyyy-mm-dd) --- print.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print.go b/print.go index 293d1ef4..00ccd44f 100644 --- a/print.go +++ b/print.go @@ -398,10 +398,10 @@ outer: return nil } -// Formats a unix timestamp to yyyy/mm/dd +// Formats a unix timestamp to ISO 8601 date (yyyy-mm-dd) func formatTime(i int) string { t := time.Unix(int64(i), 0) - return fmt.Sprintf("%d/%02d/%02d", t.Year(), int(t.Month()), t.Day()) + return t.Format("2006-01-02") } const ( From 8dd08327b169cadfdbc6955a8bbd2d2d7819ec41 Mon Sep 17 00:00:00 2001 From: Jonas Thiem Date: Sun, 6 May 2018 02:26:03 +0200 Subject: [PATCH 010/109] Add --news to --print --- cmd.go | 2 ++ print.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/cmd.go b/cmd.go index a6957d2d..381573c5 100644 --- a/cmd.go +++ b/cmd.go @@ -318,6 +318,8 @@ func handlePrint() (err error) { err = printNumberOfUpdates() case cmdArgs.existsArg("u", "upgrades"): err = printUpdateList(cmdArgs) + case cmdArgs.existsArg("w", "news"): + err = printNewsFeed() case cmdArgs.existsArg("c", "complete"): switch { case cmdArgs.existsArg("f", "fish"): diff --git a/print.go b/print.go index 00ccd44f..1fe7ae41 100644 --- a/print.go +++ b/print.go @@ -1,7 +1,11 @@ package main import ( + "bytes" + "encoding/xml" "fmt" + "io/ioutil" + "net/http" "os" "strconv" "strings" @@ -398,6 +402,55 @@ outer: return nil } +type item struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + PubDate string `xml:"pubDate"` + Creator string `xml:"dc:creator"` +} + +type channel struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + Language string `xml:"language"` + Lastbuilddate string `xml:"lastbuilddate"` + Item []item `xml:"item"` +} + +type rss struct { + Channel channel `xml:"channel"` +} + +func printNewsFeed() error { + resp, err := http.Get("https://archlinux.org/feeds/news") + if err != nil { + return err + } + + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + rss := rss{} + + p := xml.NewDecoder(bytes.NewReader(body)) + + err = p.Decode(&rss) + if err != nil { + return err + } + + for _, item := range rss.Channel.Item { + fmt.Println(item.PubDate, item.Title) + } + + return nil +} + // Formats a unix timestamp to ISO 8601 date (yyyy-mm-dd) func formatTime(i int) string { t := time.Unix(int64(i), 0) From 976876961be6bdfc1fd291a01156ba088a1b1539 Mon Sep 17 00:00:00 2001 From: Jonas Thiem Date: Sun, 6 May 2018 03:31:09 +0200 Subject: [PATCH 011/109] Add completions for --news --- cmd.go | 1 + completions/bash | 4 ++-- completions/fish | 1 + completions/zsh | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd.go b/cmd.go index 381573c5..26865c05 100644 --- a/cmd.go +++ b/cmd.go @@ -91,6 +91,7 @@ Print specific options: -n --numberupgrades Print number of updates -s --stats Display system package statistics -u --upgrades Print update list + -w --news Print arch news Yay specific options: -c --clean Remove unneeded dependencies diff --git a/completions/bash b/completions/bash index cbc7c8cf..276389b7 100644 --- a/completions/bash +++ b/completions/bash @@ -65,8 +65,8 @@ _yay() { 'c g i l p s u w y') upgrade=('asdeps asexplicit force needed nodeps assume-installed print recursive' 'p') yays=('clean gendb' 'c') - print=('complete defaultconfig config numberupgrades stats upgrades' 'c d g n - s u') + print=('complete defaultconfig config numberupgrades stats upgrades news' 'c d g n + s u w') common=('arch cachedir color config confirm dbpath debug gpgdir help hookdir logfile noconfirm noprogressbar noscriptlet quiet save mflags buildir editor makepkg pacman tar git gpg gpgflags config requestsplitn sudoloop nosudoloop diff --git a/completions/fish b/completions/fish index 97e782ed..c61bc73c 100644 --- a/completions/fish +++ b/completions/fish @@ -108,6 +108,7 @@ complete -c $progname -n $print -s d -l defaultconfig -d 'Print current yay conf complete -c $progname -n $print -s n -l numberupgrades -d 'Print number of updates' -f complete -c $progname -n $print -s s -l stats -d 'Display system package statistics' -f complete -c $progname -n $print -s u -l upgrades -d 'Print update list' -f +complete -c $progname -n $print -s w -l news -d 'Print arch news' # Transaction options (sync, remove, upgrade) for condition in sync remove upgrade diff --git a/completions/zsh b/completions/zsh index b1c71db5..715adcd9 100644 --- a/completions/zsh +++ b/completions/zsh @@ -134,6 +134,7 @@ _pacman_opts_print_modifiers=( {-n,--numberupgrades}'[Print number of updates]' {-s,--stats}'[Display system package statistics]' {-u,--upgrades}'[Print update list]' + {-w,--news}'[Print arch news]' ) # options for passing to _arguments: options for --remove command _pacman_opts_remove=( From 2161dace3f21bb3c5bebc746ad76145dddc411b8 Mon Sep 17 00:00:00 2001 From: Jonas Thiem Date: Sun, 6 May 2018 04:06:58 +0200 Subject: [PATCH 012/109] Collapsing rss struct --- print.go | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/print.go b/print.go index 1fe7ae41..3f3c6cb0 100644 --- a/print.go +++ b/print.go @@ -402,25 +402,21 @@ outer: return nil } -type item struct { - Title string `xml:"title"` - Link string `xml:"link"` - Description string `xml:"description"` - PubDate string `xml:"pubDate"` - Creator string `xml:"dc:creator"` -} - -type channel struct { - Title string `xml:"title"` - Link string `xml:"link"` - Description string `xml:"description"` - Language string `xml:"language"` - Lastbuilddate string `xml:"lastbuilddate"` - Item []item `xml:"item"` -} - type rss struct { - Channel channel `xml:"channel"` + Channel struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + Language string `xml:"language"` + Lastbuilddate string `xml:"lastbuilddate"` + Item []struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + PubDate string `xml:"pubDate"` + Creator string `xml:"dc:creator"` + } `xml:"item"` + } `xml:"channel"` } func printNewsFeed() error { From 188df1ac93c467fcebb23fc169bbf03536b59e29 Mon Sep 17 00:00:00 2001 From: Jonas Thiem Date: Sun, 6 May 2018 04:25:23 +0200 Subject: [PATCH 013/109] Use formatTime for news --- print.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/print.go b/print.go index 3f3c6cb0..9b2c4cd9 100644 --- a/print.go +++ b/print.go @@ -433,15 +433,22 @@ func printNewsFeed() error { rss := rss{} - p := xml.NewDecoder(bytes.NewReader(body)) - - err = p.Decode(&rss) + d := xml.NewDecoder(bytes.NewReader(body)) + err = d.Decode(&rss) if err != nil { return err } for _, item := range rss.Channel.Item { - fmt.Println(item.PubDate, item.Title) + date, err := time.Parse(time.RFC1123Z, item.PubDate) + + if err != nil { + return err + } + + fd := formatTime(int(date.Unix())) + + fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) } return nil From 6af2b5c6e1433cab23f499ca91ce8a432c7ecc6d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 6 May 2018 22:04:04 +0100 Subject: [PATCH 014/109] Respect bottomup for -Pw This commit also refactors the news related sructs into their own types instead of being anonymous and moves the printing to its own .Print() function. --- print.go | 68 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/print.go b/print.go index 9b2c4cd9..8d7c2a09 100644 --- a/print.go +++ b/print.go @@ -402,21 +402,39 @@ outer: return nil } +type Item struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + PubDate string `xml:"pubDate"` + Creator string `xml:"dc:creator"` +} + +func (item Item) Print() error { + date, err := time.Parse(time.RFC1123Z, item.PubDate) + + if err != nil { + return err + } + + fd := formatTime(int(date.Unix())) + + fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) + + return nil +} + +type Channel struct { + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + Language string `xml:"language"` + Lastbuilddate string `xml:"lastbuilddate"` + Items []Item `xml:"item"` +} + type rss struct { - Channel struct { - Title string `xml:"title"` - Link string `xml:"link"` - Description string `xml:"description"` - Language string `xml:"language"` - Lastbuilddate string `xml:"lastbuilddate"` - Item []struct { - Title string `xml:"title"` - Link string `xml:"link"` - Description string `xml:"description"` - PubDate string `xml:"pubDate"` - Creator string `xml:"dc:creator"` - } `xml:"item"` - } `xml:"channel"` + Channel Channel `xml:"channel"` } func printNewsFeed() error { @@ -439,16 +457,20 @@ func printNewsFeed() error { return err } - for _, item := range rss.Channel.Item { - date, err := time.Parse(time.RFC1123Z, item.PubDate) - - if err != nil { - return err + if config.SortMode == BottomUp { + for i := len(rss.Channel.Items) - 1; i >= 0; i-- { + err := rss.Channel.Items[i].Print() + if err != nil { + return err + } + } + } else { + for i := 0; i < len(rss.Channel.Items); i++ { + err := rss.Channel.Items[i].Print() + if err != nil { + return err + } } - - fd := formatTime(int(date.Unix())) - - fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) } return nil From a10241f7ab5f0671da176179029aa18f9ee45e13 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 7 May 2018 01:25:47 +0100 Subject: [PATCH 015/109] Print descriptions of news Print the full descriptions of each news item. The description is formatted as html, basic parsing is done to display it properly. -q/--quiet can be used to diplay title only. --- parser.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ print.go | 8 ++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/parser.go b/parser.go index 4ce96228..67c2f05e 100644 --- a/parser.go +++ b/parser.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "io" "os" @@ -8,6 +9,15 @@ import ( "strings" ) +var htmlEscapeSequences = map[string]rune{ + "quot": '"', + "apos": '\'', + "amp": '&', + "lt": '<', + "gt": '>', + "nbsp": '\u008a', +} + // A basic set implementation for strings. // This is used a lot so it deserves its own type. // Other types of sets are used throughout the code but do not have @@ -673,3 +683,89 @@ func parseNumberMenu(input string) (intRanges, intRanges, stringSet, stringSet) return include, exclude, otherInclude, otherExclude } + +func unescapeHtmlChar(str string) rune { + var first string + var rest string + for i := range str { + first = str[0:i] + rest = str[i:] + } + + if first == "#" { + num, err := strconv.Atoi(rest) + if err != nil { + return '?' + } + + return rune(num) + } + + char, ok := htmlEscapeSequences[str] + if !ok { + return '?' + } + + return char +} + +// Crude html parsing, good enough for the arch news +// This is only displayed in the terminal so there should be no security +// concerns +func parseNews(str string) string { + var buffer bytes.Buffer + var tagBuffer bytes.Buffer + var escapeBuffer bytes.Buffer + inTag := false + inEscape := false + + for _, char := range str { + if inTag { + if char == '>' { + inTag = false + switch tagBuffer.String() { + case "code": + buffer.WriteString(cyanCode) + case "/code": + buffer.WriteString(resetCode) + case "/p": + buffer.WriteRune('\n') + } + + continue + } + + tagBuffer.WriteRune(char) + continue + } + + if inEscape { + if char == ';' { + inEscape = false + char := unescapeHtmlChar(escapeBuffer.String()) + buffer.WriteRune(char) + continue + } + + escapeBuffer.WriteRune(char) + continue + } + + if char == '<' { + inTag = true + tagBuffer.Reset() + continue + } + + if char == '&' { + inEscape = true + escapeBuffer.Reset() + continue + } + + buffer.WriteRune(char) + } + + buffer.WriteString(resetCode) + return buffer.String() +} diff --git a/print.go b/print.go index 8d7c2a09..8996e6d5 100644 --- a/print.go +++ b/print.go @@ -419,7 +419,13 @@ func (item Item) Print() error { fd := formatTime(int(date.Unix())) - fmt.Println(magenta(fd), strings.TrimSpace(item.Title)) + fmt.Println(bold(magenta(fd)), bold(strings.TrimSpace(item.Title))) + //fmt.Println(strings.TrimSpace(item.Link)) + + if !cmdArgs.existsArg("q", "quiet") { + desc := strings.TrimSpace(parseNews(item.Description)) + fmt.Println(desc) + } return nil } From 21b7899083fe6342cba7649ef8decc490bd2ba61 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 7 May 2018 06:26:29 +0100 Subject: [PATCH 016/109] Use built in html escaping --- parser.go | 41 +++++------------------------------------ 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/parser.go b/parser.go index 67c2f05e..826bd075 100644 --- a/parser.go +++ b/parser.go @@ -7,17 +7,9 @@ import ( "os" "strconv" "strings" + "html" ) -var htmlEscapeSequences = map[string]rune{ - "quot": '"', - "apos": '\'', - "amp": '&', - "lt": '<', - "gt": '>', - "nbsp": '\u008a', -} - // A basic set implementation for strings. // This is used a lot so it deserves its own type. // Other types of sets are used throughout the code but do not have @@ -684,31 +676,6 @@ func parseNumberMenu(input string) (intRanges, intRanges, stringSet, stringSet) return include, exclude, otherInclude, otherExclude } -func unescapeHtmlChar(str string) rune { - var first string - var rest string - for i := range str { - first = str[0:i] - rest = str[i:] - } - - if first == "#" { - num, err := strconv.Atoi(rest) - if err != nil { - return '?' - } - - return rune(num) - } - - char, ok := htmlEscapeSequences[str] - if !ok { - return '?' - } - - return char -} - // Crude html parsing, good enough for the arch news // This is only displayed in the terminal so there should be no security // concerns @@ -742,8 +709,9 @@ func parseNews(str string) string { if inEscape { if char == ';' { inEscape = false - char := unescapeHtmlChar(escapeBuffer.String()) - buffer.WriteRune(char) + escapeBuffer.WriteRune(char) + s := html.UnescapeString(escapeBuffer.String()) + buffer.WriteString(s) continue } @@ -760,6 +728,7 @@ func parseNews(str string) string { if char == '&' { inEscape = true escapeBuffer.Reset() + escapeBuffer.WriteRune(char) continue } From 58283a9799b4b50c4d93cc159739bc24bcfe9ca6 Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Wed, 2 May 2018 18:46:21 +0300 Subject: [PATCH 017/109] Make upgrade output as table --- print.go | 29 ++++++++++++++++++++++------- upgrade.go | 9 +++++---- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/print.go b/print.go index 293d1ef4..e9ca5b11 100644 --- a/print.go +++ b/print.go @@ -153,18 +153,33 @@ func formatPkgbase(pkg *rpc.Pkg, bases map[string][]*rpc.Pkg) string { return str } +func (u upgrade) StylizedNameWithRepository() string { + return bold(colourHash(u.Repository)) + "/" + bold(u.Name) +} + // Print prints the details of the packages to upgrade. -func (u upSlice) Print(start int) { +func (u upSlice) Print() { + longestName, longestVersion := 0, 0 + for _, pack := range u { + packNameLen := len(pack.StylizedNameWithRepository()) + version, _ := getVersionDiff(pack.LocalVersion, pack.RemoteVersion) + packVersionLen := len(version) + longestName = max(packNameLen, longestName) + longestVersion = max(packVersionLen, longestVersion) + } + + namePadding := fmt.Sprintf("%%-%ds ", longestName) + versionPadding := fmt.Sprintf("%%-%ds", longestVersion) + numberPadding := fmt.Sprintf("%%%dd ", len(fmt.Sprintf("%v", len(u)))) + for k, i := range u { left, right := getVersionDiff(i.LocalVersion, i.RemoteVersion) - fmt.Print(magenta(fmt.Sprintf("%3d ", len(u)+start-k-1))) - fmt.Print(bold(colourHash(i.Repository)), "/", bold(i.Name)) + fmt.Print(magenta(fmt.Sprintf(numberPadding, len(u)-k))) - w := 70 - len(i.Repository) - len(i.Name) - padding := fmt.Sprintf("%%%ds", w) - fmt.Printf(padding, left) - fmt.Printf(" -> %s\n", right) + fmt.Printf(namePadding, i.StylizedNameWithRepository()) + + fmt.Printf("%s -> %s\n", fmt.Sprintf(versionPadding, left), right) } } diff --git a/upgrade.go b/upgrade.go index afa753e8..ec78dce8 100644 --- a/upgrade.go +++ b/upgrade.go @@ -305,15 +305,16 @@ func upgradePkgs(aurUp, repoUp upSlice) (stringSet, stringSet, error) { ignore := make(stringSet) aurNames := make(stringSet) - if len(aurUp)+len(repoUp) == 0 { + allUpLen := len(repoUp) + len(aurUp) + if allUpLen == 0 { return ignore, aurNames, nil } sort.Sort(repoUp) sort.Sort(aurUp) - fmt.Printf("%s"+bold(" %d ")+"%s\n", bold(cyan("::")), len(aurUp)+len(repoUp), bold("Packages to upgrade.")) - repoUp.Print(len(aurUp) + 1) - aurUp.Print(1) + allUp := append(repoUp, aurUp...) + fmt.Printf("%s"+bold(" %d ")+"%s\n", bold(cyan("::")), allUpLen, bold("Packages to upgrade.")) + allUp.Print() fmt.Println(bold(green(arrow + " Packages to not upgrade: (eg: 1 2 3, 1-3, ^4 or repo name)"))) fmt.Print(bold(green(arrow + " "))) From c29a80d7f776dbb52bfd3f9081c8da3d94770204 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 7 May 2018 23:28:22 +0100 Subject: [PATCH 018/109] Fix -Sc sometimes cleaning split packages If a split package was installed and there was no package that matched the name of the package base Yay would remove it even though there could be other packages installed under that base but with a different name. Now only clean a package if there are no installed packages under the packagebase. --- clean.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clean.go b/clean.go index a9ecf9c7..a2722c34 100644 --- a/clean.go +++ b/clean.go @@ -138,7 +138,7 @@ func cleanAUR(keepInstalled, keepCurrent, removeAll bool) error { } for _, pkg := range remotePackages { - installedBases.set(pkg.Name()) + installedBases.set(pkg.Base()) } for _, file := range files { From ef7e8acb13ce5dffef8641fc69c95e9b1ff0087e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 7 May 2018 23:01:39 +0100 Subject: [PATCH 019/109] Refactor complex map types into their own type map[string][]string -> mapStringSlice mao[string]stringSet -> mapStringSet --- conflicts.go | 36 ++++++++++++++++++------------------ dependencies.go | 12 ++++++------ query.go | 4 ++-- utils.go | 19 +++++++++++-------- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/conflicts.go b/conflicts.go index 759de489..d12057a8 100644 --- a/conflicts.go +++ b/conflicts.go @@ -11,7 +11,7 @@ import ( // Checks a single conflict against every other to be installed package's // name and its provides. -func checkInnerConflict(name string, conflict string, conflicts map[string]stringSet, dc *depCatagories) { +func checkInnerConflict(name string, conflict string, conflicts mapStringSet, dc *depCatagories) { deps, err := gopkg.ParseDeps([]string{conflict}) if err != nil { return @@ -28,7 +28,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin return } if dep.Name == pkg.Name && version.Satisfies(dep) { - addMapStringSet(conflicts, name, pkg.Name) + conflicts.Add(name, pkg.Name) continue } @@ -57,7 +57,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin } if version != nil && version.Satisfies(dep) { - addMapStringSet(conflicts, name, pkg.Name) + conflicts.Add(name, pkg.Name) break } @@ -75,7 +75,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin } if dep.Name == pkg.Name() && version.Satisfies(dep) { - addMapStringSet(conflicts, name, pkg.Name()) + conflicts.Add(name, pkg.Name()) continue } @@ -92,7 +92,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin } if provide.Mod == alpm.DepModAny { - addMapStringSet(conflicts, name, pkg.Name()) + conflicts.Add(name, pkg.Name()) return fmt.Errorf("") } @@ -102,7 +102,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin } if version.Satisfies(dep) { - addMapStringSet(conflicts, name, pkg.Name()) + conflicts.Add(name, pkg.Name()) return fmt.Errorf("") } @@ -113,8 +113,8 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin // Checks every to be installed package's conflicts against every other to be // installed package and its provides. -func checkForInnerConflicts(dc *depCatagories) map[string]stringSet { - conflicts := make(map[string]stringSet) +func checkForInnerConflicts(dc *depCatagories) mapStringSet { + conflicts := make(mapStringSet) for _, pkg := range dc.Aur { for _, cpkg := range pkg.Conflicts { @@ -134,7 +134,7 @@ func checkForInnerConflicts(dc *depCatagories) map[string]stringSet { // Checks a provide or packagename from a to be installed package // against every already installed package's conflicts -func checkReverseConflict(name string, provide string, conflicts map[string]stringSet) error { +func checkReverseConflict(name string, provide string, conflicts mapStringSet) error { var version *gopkg.CompleteVersion var err error @@ -176,7 +176,7 @@ func checkReverseConflict(name string, provide string, conflicts map[string]stri if version == nil || version.Satisfies(dep) { // Todo - addMapStringSet(conflicts, name, pkg.Name()+" ("+provide+")") + conflicts.Add(name, pkg.Name()+" ("+provide+")") return fmt.Errorf("") } @@ -191,7 +191,7 @@ func checkReverseConflict(name string, provide string, conflicts map[string]stri // Checks the conflict of a to be installed package against the package name and // provides of every installed package. -func checkConflict(name string, conflict string, conflicts map[string]stringSet) error { +func checkConflict(name string, conflict string, conflicts mapStringSet) error { localDb, err := alpmHandle.LocalDb() if err != nil { return err @@ -215,7 +215,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet) } if dep.Name == pkg.Name() && version.Satisfies(dep) { - addMapStringSet(conflicts, name, pkg.Name()) + conflicts.Add(name, pkg.Name()) return nil } @@ -232,7 +232,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet) } if provide.Mod == alpm.DepModAny { - addMapStringSet(conflicts, name, pkg.Name()+" ("+provide.Name+")") + conflicts.Add(name, pkg.Name()+" ("+provide.Name+")") return fmt.Errorf("") } @@ -242,7 +242,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet) } if version.Satisfies(dep) { - addMapStringSet(conflicts, name, pkg.Name()+" ("+provide.Name+")") + conflicts.Add(name, pkg.Name()+" ("+provide.Name+")") return fmt.Errorf("") } @@ -258,8 +258,8 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet) // Checks every to be installed package's conflicts against the names and // provides of every already installed package and checks every to be installed // package's name and provides against every already installed package. -func checkForConflicts(dc *depCatagories) (map[string]stringSet, error) { - conflicts := make(map[string]stringSet) +func checkForConflicts(dc *depCatagories) (mapStringSet, error) { + conflicts := make(mapStringSet) for _, pkg := range dc.Aur { for _, cpkg := range pkg.Conflicts { @@ -296,8 +296,8 @@ func checkForConflicts(dc *depCatagories) (map[string]stringSet, error) { // does some printing. func checkForAllConflicts(dc *depCatagories) error { var err error - var conflicts map[string]stringSet - var innerConflicts map[string]stringSet + var conflicts mapStringSet + var innerConflicts mapStringSet var wg sync.WaitGroup wg.Add(2) diff --git a/dependencies.go b/dependencies.go index 31bc0e07..666e6778 100644 --- a/dependencies.go +++ b/dependencies.go @@ -548,7 +548,7 @@ func depTreeRecursive(dt *depTree, localDb *alpm.Db, syncDb alpm.DbList, isMake } func checkVersions(dt *depTree) error { - has := make(map[string][]string) + has := make(mapStringSlice) allDeps := make([]*gopkg.Dependency, 0) localDb, err := alpmHandle.LocalDb() @@ -569,13 +569,13 @@ func checkVersions(dt *depTree) error { } } - addMapStringSlice(has, pkg.Name, pkg.Version) + has.Add(pkg.Name, pkg.Version) if !isDevelName(pkg.Name) { for _, name := range pkg.Provides { _name, _ver := splitNameFromDep(name) if _ver != "" { - addMapStringSlice(has, _name, _ver) + has.Add(_name, _ver) } else { delete(has, _name) } @@ -594,11 +594,11 @@ func checkVersions(dt *depTree) error { return nil }) - addMapStringSlice(has, pkg.Name(), pkg.Version()) + has.Add(pkg.Name(), pkg.Version()) pkg.Provides().ForEach(func(dep alpm.Depend) error { if dep.Mod != alpm.DepModAny { - addMapStringSlice(has, dep.Name, dep.Version) + has.Add(dep.Name, dep.Version) } else { delete(has, dep.Name) } @@ -611,7 +611,7 @@ func checkVersions(dt *depTree) error { localDb.PkgCache().ForEach(func(pkg alpm.Package) error { pkg.Provides().ForEach(func(dep alpm.Depend) error { if dep.Mod != alpm.DepModAny { - addMapStringSlice(has, dep.Name, dep.Version) + has.Add(dep.Name, dep.Version) } else { delete(has, dep.Name) } diff --git a/query.go b/query.go index 3eb22f69..8e4c0a45 100644 --- a/query.go +++ b/query.go @@ -332,7 +332,7 @@ func hangingPackages(removeOptional bool) (hanging []string, err error) { // State = 2 - Keep package and have iterated over dependencies safePackages := make(map[string]uint8) // provides stores a mapping from the provides name back to the original package name - provides := make(map[string]stringSet) + provides := make(mapStringSet) packages := localDb.PkgCache() // Mark explicit dependencies and enumerate the provides list @@ -344,7 +344,7 @@ func hangingPackages(removeOptional bool) (hanging []string, err error) { } pkg.Provides().ForEach(func(dep alpm.Depend) error { - addMapStringSet(provides, dep.Name, pkg.Name()) + provides.Add(dep.Name, pkg.Name()) return nil }) return nil diff --git a/utils.go b/utils.go index be9f0449..2439981f 100644 --- a/utils.go +++ b/utils.go @@ -7,6 +7,9 @@ import ( "unicode" ) +type mapStringSlice map[string][]string +type mapStringSet map[string]stringSet + type intRange struct { min int max int @@ -49,20 +52,20 @@ func max(a, b int) int { return a } -func addMapStringSet(h map[string]stringSet, n string, v string) { - _, ok := h[n] +func (mss mapStringSet) Add(n string, v string) { + _, ok := mss[n] if !ok { - h[n] = make(stringSet) + mss[n] = make(stringSet) } - h[n].set(v) + mss[n].set(v) } -func addMapStringSlice(h map[string][]string, n string, v string) { - _, ok := h[n] +func (mss mapStringSlice) Add(n string, v string) { + _, ok := mss[n] if !ok { - h[n] = make([]string, 0, 1) + mss[n] = make([]string, 0, 1) } - h[n] = append(h[n], v) + mss[n] = append(mss[n], v) } func completeFileName(dir, name string) (string, error) { From dc0765918edf578b8c6065201ab3da9bbd57de64 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 00:43:49 +0100 Subject: [PATCH 020/109] Implement c29a80 properly It seems the pkgbase is null for installed packages that are not part of a split package. It was priviously assumed that if a package was not part of a split package, pkgbase == pkgname would always be true. Instead try to use pkgbase and if it does not exist fall back to pkgname. --- clean.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clean.go b/clean.go index a2722c34..6443444e 100644 --- a/clean.go +++ b/clean.go @@ -138,7 +138,11 @@ func cleanAUR(keepInstalled, keepCurrent, removeAll bool) error { } for _, pkg := range remotePackages { - installedBases.set(pkg.Base()) + if pkg.Base() != "" { + installedBases.set(pkg.Base()) + } else { + installedBases.set(pkg.Name()) + } } for _, file := range files { From 38818757c8ebd2c309ec154cf766c5ebf121a495 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 10 May 2018 20:08:16 +0100 Subject: [PATCH 021/109] Lint --- download.go | 2 +- parser.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/download.go b/download.go index dbd44de6..53ed0991 100644 --- a/download.go +++ b/download.go @@ -96,7 +96,7 @@ func downloadAndUnpack(url string, path string, trim bool) (err error) { if trim { err = exec.Command("/bin/sh", "-c", config.TarBin+" --strip-components 2 --include='*/"+fileName[:len(fileName)-7]+"/trunk/' -xf "+tarLocation+" -C "+path).Run() - os.Rename(filepath.Join(path, "trunk"), filepath.Join(path,fileName[:len(fileName)-7])) + os.Rename(filepath.Join(path, "trunk"), filepath.Join(path, fileName[:len(fileName)-7])) } else { err = exec.Command(config.TarBin, "-xf", tarLocation, "-C", path).Run() } diff --git a/parser.go b/parser.go index 826bd075..01645317 100644 --- a/parser.go +++ b/parser.go @@ -3,11 +3,11 @@ package main import ( "bytes" "fmt" + "html" "io" "os" "strconv" "strings" - "html" ) // A basic set implementation for strings. From 5e712b221eee840646ad8cafe95d089862a5ca4f Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 10 May 2018 20:56:12 +0100 Subject: [PATCH 022/109] Add missing --ignorearch arg to makepkg call --- install.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/install.go b/install.go index 21cc90b6..2188afe2 100644 --- a/install.go +++ b/install.go @@ -596,8 +596,14 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, srcinfo := srcinfos[pkg.PackageBase] + args := []string{"--nobuild", "-fCc"} + + if incompatible.get(pkg.PackageBase) { + args = append(args, "--ignorearch") + } + //pkgver bump - err := passToMakepkg(dir, "--nobuild", "-fCc") + err := passToMakepkg(dir, args...) if err != nil { return fmt.Errorf("Error making: %s", pkg.Name) } From 4c2986a0369310ec0c91c0bdef1932ebe0db8f40 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 11 May 2018 03:59:41 +0100 Subject: [PATCH 023/109] Tweak readme, add install and contrib sections --- README.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 51344d0f..0c338745 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Yet another Yogurt - An AUR Helper written in Go There's a point in everyone's life when you feel the need to write an AUR helper because there are only about 20 of them. So say hi to 20+1. -Yay was created with a few objectives in mind and based on the design of [yaourt](https://github.com/archlinuxfr/yaourt) and [apacman](https://github.com/oshazard/apacman): +Yay was created with a few objectives in mind and based on the design of [yaourt](https://github.com/archlinuxfr/yaourt), [apacman](https://github.com/oshazard/apacman) and [pacaur](https://github.com/rmarquis/pacaur): * Have almost no dependencies. * Provide an interface for pacman. @@ -24,15 +24,73 @@ Yay was created with a few objectives in mind and based on the design of [yaourt * Search narrowing (`yay linux header` will first search linux and then narrow on header) * No sourcing of PKGBUILD is done * The binary has no dependencies that pacman doesn't already have. -* Sources build dependencies -* Removes make dependencies at the end of build process +* Advanced dependency solving +* Remove make dependencies at the end of the build process -#### Frequently Asked Questions +## Installation -* Yay does not display colored output. How do I fix it? +If you are migrating from another AUR helper you can simply install Yay from +the AUR like any other package. + +The initial installation of Yay can be done by cloning the PKGBUILD and +building with makepkg. +```sh +git clone https://aur.archlinux.org/yay.git +cd yay +makepkg -si +``` + +## Contributing + +Contributors are always welcome! + +If you plan to make any large changes or changes that may not be 100% agreed +on, we suggest opening an issue detailing your ideas first. + +Otherwise send us a pull request and we will be happy to review it. + +### Code Style + +All code should be formated through `go fmt`. This tool will automatically +format code for you. Although it is recommended you write code in this style +and just use this tool to catch mistakes. + +### Building + +Yay is easy to build with its only build dependency being `go` and the +assumption of `base-devel` being installed. + +Run `make` to build Yay. This will generate a binary called `yay` in the same +directory as the Makefile. + +Run `make test` to test Yay. This will check the code is formatted correctly, +run the code through `go vet` and run unit tests. + +Yay's Makefile automaticly sets the `GOPATH` to `$PWD/.go`. This makes it easy to +build using the dependencies in `vendor/`. Running manual go commands such as +`go build` will require that you to either set the `GOPATH` manually or `go get` +The dependencies into your own `GOPATH`. + +### Vendored Dependencies + +Yay depends on a couple of other projects. These are stored in `vendor/` and +are built into Yay at build time. They do not need to be installed seperatly. + +Currently yay Depends on: + +* https://github.com/Jguer/go-alpm +* https://github.com/mikkeloscar/gopkgbuild +* https://github.com/mikkeloscar/aur + + + + +## Frequently Asked Questions + +* Yay does not display colored output. How do I fix it? Make sure you have the `Color` option in your `/etc/pacman.conf` [#123](https://github.com/Jguer/yay/issues/123) -#### Example of Custom Operations +## Examples of Custom Operations * `yay ` presents package selection menu * `yay -Ps` prints system statistics @@ -44,6 +102,8 @@ Yay was created with a few objectives in mind and based on the design of [yaourt package updates and uses PKGBUILD modification time and not version to determine update +## Images + From 2bf310d37caff8dcd59f01225ef9781f2145258e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 12 May 2018 00:12:33 +0100 Subject: [PATCH 024/109] Fix --ignore flag while skipping updates If --ignore was specified on the command line and the user skips packages using the number menu, packages would not be properly skipped because they the manual --ignore would overide the --ignore from the menu. Now correctly combine both --ignore flags into a single combined flag when passing to pacman. --- install.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/install.go b/install.go index 2188afe2..657e04df 100644 --- a/install.go +++ b/install.go @@ -114,7 +114,13 @@ func install(parser *arguments) error { requestTargets = append(requestTargets, up) } - arguments.addParam("ignore", strings.Join(ignore.toSlice(), ",")) + value, _, exists := cmdArgs.getArg("ignore") + ignoreStr := strings.Join(ignore.toSlice(), ",") + if exists { + ignoreStr += "," + value + } + + arguments.options["ignore"] = ignoreStr fmt.Println() for pkg := range aurUp { From 1b6d80f1223bb2aeb073cb89658ee3e7808322fa Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 12 May 2018 00:24:47 +0100 Subject: [PATCH 025/109] Fix --ignore flag while skipping updates ammended Ammend to 58d53b1 Thought this was already included in the commit. --- install.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/install.go b/install.go index 657e04df..e5225059 100644 --- a/install.go +++ b/install.go @@ -115,12 +115,15 @@ func install(parser *arguments) error { } value, _, exists := cmdArgs.getArg("ignore") - ignoreStr := strings.Join(ignore.toSlice(), ",") - if exists { - ignoreStr += "," + value + + if len(ignore) > 0 { + ignoreStr := strings.Join(ignore.toSlice(), ",") + if exists { + ignoreStr += "," + value + } + arguments.options["ignore"] = ignoreStr } - arguments.options["ignore"] = ignoreStr fmt.Println() for pkg := range aurUp { From 6c49436942cf05ecc6d14dd140f06305cf0491ce Mon Sep 17 00:00:00 2001 From: Gravemind Date: Sat, 12 May 2018 15:41:32 +0200 Subject: [PATCH 026/109] Fix typo --foreigne to --foreign --- print.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/print.go b/print.go index 27416f97..df65831a 100644 --- a/print.go +++ b/print.go @@ -372,7 +372,7 @@ func printUpdateList(parser *arguments) error { noTargets := len(parser.targets) == 0 - if !parser.existsArg("m", "foreigne") { + if !parser.existsArg("m", "foreign") { for _, pkg := range repoUp { if noTargets || parser.targets.get(pkg.Name) { fmt.Printf("%s %s -> %s\n", bold(pkg.Name), green(pkg.LocalVersion), green(pkg.RemoteVersion)) From c399996cabf1ff4679e167ae256372905499fa7e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 12 May 2018 17:16:48 +0100 Subject: [PATCH 027/109] Fix typos --- README.md | 6 +++--- clean.go | 2 +- conflicts.go | 2 +- dependencies.go | 8 ++++---- main.go | 2 +- parser.go | 14 +++++++------- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0c338745..994608f7 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Otherwise send us a pull request and we will be happy to review it. ### Code Style -All code should be formated through `go fmt`. This tool will automatically +All code should be formatted through `go fmt`. This tool will automatically format code for you. Although it is recommended you write code in this style and just use this tool to catch mistakes. @@ -66,7 +66,7 @@ directory as the Makefile. Run `make test` to test Yay. This will check the code is formatted correctly, run the code through `go vet` and run unit tests. -Yay's Makefile automaticly sets the `GOPATH` to `$PWD/.go`. This makes it easy to +Yay's Makefile automatically sets the `GOPATH` to `$PWD/.go`. This makes it easy to build using the dependencies in `vendor/`. Running manual go commands such as `go build` will require that you to either set the `GOPATH` manually or `go get` The dependencies into your own `GOPATH`. @@ -74,7 +74,7 @@ The dependencies into your own `GOPATH`. ### Vendored Dependencies Yay depends on a couple of other projects. These are stored in `vendor/` and -are built into Yay at build time. They do not need to be installed seperatly. +are built into Yay at build time. They do not need to be installed separately. Currently yay Depends on: diff --git a/clean.go b/clean.go index 6443444e..d4bd4836 100644 --- a/clean.go +++ b/clean.go @@ -124,7 +124,7 @@ func cleanAUR(keepInstalled, keepCurrent, removeAll bool) error { // Most people probably don't use keep current and that is the only // case where this is needed. - // Querying the AUR is slow and needs internet so dont do it if we + // Querying the AUR is slow and needs internet so don't do it if we // don't need to. if keepCurrent { info, err := aurInfo(cachedPackages, &aurWarnings{}) diff --git a/conflicts.go b/conflicts.go index d12057a8..9f03b945 100644 --- a/conflicts.go +++ b/conflicts.go @@ -224,7 +224,7 @@ func checkConflict(name string, conflict string, conflicts mapStringSet) error { return nil } - // Provides arent version unless explicitly defined as + // Provides aren't version unless explicitly defined as // such. If a conflict is versioned but a provide is // not it can not conflict. if (dep.MaxVer != nil || dep.MinVer != nil) && provide.Mod == alpm.DepModAny { diff --git a/dependencies.go b/dependencies.go index 666e6778..0a47d53c 100644 --- a/dependencies.go +++ b/dependencies.go @@ -311,7 +311,7 @@ func depCatagoriesRecursive(_pkg *rpc.Pkg, dc *depCatagories, dt *depTree, isMak // // Here is a visual expample of the request system. // Remember only unsatisfied packages are requested, if a package is already -// installed we dont bother. +// installed we don't bother. // // a // / \ @@ -323,7 +323,7 @@ func depCatagoriesRecursive(_pkg *rpc.Pkg, dc *depCatagories, dt *depTree, isMak // We see a wants b and c so we send a request for b and c // We see d and e so we send a request for d and e // -// Thats 5 packages in 3 requests. The amount of requests needed should always be +// That's 5 packages in 3 requests. The amount of requests needed should always be // the same as the height of the tree. // The example does not really do this justice, In the real world where packages // have 10+ dependencies each this is a very nice optimization. @@ -366,8 +366,8 @@ func getDepTree(pkgs []string, warnings *aurWarnings) (*depTree, error) { continue } else { //would be better to check the groups from singleDb if - //the user specified a db but theres no easy way to do - //it without making alpm_lists so dont bother for now + //the user specified a db but there's no easy way to do + //it without making alpm_lists so don't bother for now //db/group is probably a rare use case _, err := syncDb.PkgCachebyGroup(name) diff --git a/main.go b/main.go index 8b05b961..02bb42e3 100644 --- a/main.go +++ b/main.go @@ -220,7 +220,7 @@ func main() { cleanup: //cleanup - //from here on out dont exit if an error occurs + //from here on out don't exit if an error occurs //if we fail to save the configuration //at least continue on and try clean up other parts diff --git a/parser.go b/parser.go index 01645317..7a6787a1 100644 --- a/parser.go +++ b/parser.go @@ -15,7 +15,7 @@ import ( // Other types of sets are used throughout the code but do not have // their own typedef. // String sets and sets should be used throughout the code when applicable, -// they are a lot more flexable than slices and provide easy lookup. +// they are a lot more flexible than slices and provide easy lookup. type stringSet map[string]struct{} func (set stringSet) set(v string) { @@ -303,15 +303,15 @@ func (parser *arguments) formatArgs() (args []string) { continue } - formatedOption := formatArg(option) - args = append(args, formatedOption) + formattedOption := formatArg(option) + args = append(args, formattedOption) if hasParam(option) { args = append(args, arg) } if parser.existsDouble(option) { - args = append(args, formatedOption) + args = append(args, formattedOption) } } @@ -320,15 +320,15 @@ func (parser *arguments) formatArgs() (args []string) { func (parser *arguments) formatGlobals() (args []string) { for option, arg := range parser.globals { - formatedOption := formatArg(option) - args = append(args, formatedOption) + formattedOption := formatArg(option) + args = append(args, formattedOption) if hasParam(option) { args = append(args, arg) } if parser.existsDouble(option) { - args = append(args, formatedOption) + args = append(args, formattedOption) } } From 4b73ba37f3cc3278d9117a1a1408c9ab3c5e5819 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 13 May 2018 18:56:09 +0100 Subject: [PATCH 028/109] Updated vendor dependencies --- Gopkg.lock | 2 +- vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 158a2189..c1ea255d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -17,7 +17,7 @@ branch = "master" name = "github.com/mikkeloscar/gopkgbuild" packages = ["."] - revision = "32274fc52aa8f5eb28711da734179e9aea27b31f" + revision = "763d921490d8f4b23b1141c89ce8f9678ac025a7" [solve-meta] analyzer-name = "dep" diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go b/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go index f1f02b12..ac267f7f 100644 --- a/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go +++ b/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go @@ -616,7 +616,7 @@ func isLowerAlpha(c rune) bool { // check if c is a valid pkgname char func isValidPkgnameChar(c rune) bool { - return isLowerAlpha(c) || isDigit(c) || c == '@' || c == '.' || c == '_' || c == '+' || c == '-' + return isAlphaNumeric(c) || c == '@' || c == '.' || c == '_' || c == '+' || c == '-' } // check if c is a valid pkgver char From d1602083f223a8ff1b891335f297a77fad621470 Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Tue, 8 May 2018 09:51:49 +0300 Subject: [PATCH 029/109] Print warnings about newer local packages then remote versions Inspired by [`pakku`](https://github.com/kitsunyan/pakku) --- upgrade.go | 53 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/upgrade.go b/upgrade.go index ec78dce8..75b3e311 100644 --- a/upgrade.go +++ b/upgrade.go @@ -138,6 +138,8 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { var aurErr error var develErr error + pkgdata := make(map[string]*rpc.Pkg) + fmt.Println(bold(cyan("::") + bold(" Searching databases for updates..."))) wg.Add(1) go func() { @@ -148,7 +150,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { fmt.Println(bold(cyan("::") + bold(" Searching AUR for updates..."))) wg.Add(1) go func() { - aurUp, aurErr = upAUR(remote, remoteNames, warnings) + aurUp, aurErr = upAUR(remote, remoteNames, pkgdata, warnings) wg.Done() }() @@ -163,6 +165,8 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { wg.Wait() + printLocalNewerThanAUR(remote, pkgdata) + errs := make([]string, 0) for _, e := range []error{repoErr, aurErr, develErr} { if e != nil { @@ -228,9 +232,7 @@ func upDevel(remote []alpm.Package) (toUpgrade upSlice, err error) { for _, pkg := range toUpdate { if pkg.ShouldIgnore() { - left, right := getVersionDiff(pkg.Version(), "latest-commit") - fmt.Print(yellow(bold(smallArrow))) - fmt.Printf(" Ignoring package upgrade %s (%s => %s)\n", cyan(pkg.Name()), left, right) + printIgnoringPackage(pkg, "latest-commit") } else { toUpgrade = append(toUpgrade, upgrade{pkg.Name(), "devel", pkg.Version(), "latest-commit"}) } @@ -242,14 +244,16 @@ func upDevel(remote []alpm.Package) (toUpgrade upSlice, err error) { // upAUR gathers foreign packages and checks if they have new versions. // Output: Upgrade type package list. -func upAUR(remote []alpm.Package, remoteNames []string, warnings *aurWarnings) (upSlice, error) { +func upAUR( + remote []alpm.Package, remoteNames []string, + pkgdata map[string]*rpc.Pkg, warnings *aurWarnings) (upSlice, error) { + toUpgrade := make(upSlice, 0) _pkgdata, err := aurInfo(remoteNames, warnings) if err != nil { return nil, err } - pkgdata := make(map[string]*rpc.Pkg) for _, pkg := range _pkgdata { pkgdata[pkg.Name] = pkg } @@ -263,9 +267,7 @@ func upAUR(remote []alpm.Package, remoteNames []string, warnings *aurWarnings) ( 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(yellow(bold(smallArrow))) - fmt.Printf(" Ignoring package upgrade: %s (%s => %s)\n", cyan(pkg.Name()), left, right) + printIgnoringPackage(pkg, aurPkg.Version) } else { toUpgrade = append(toUpgrade, upgrade{aurPkg.Name, "aur", pkg.Version(), aurPkg.Version}) } @@ -275,6 +277,35 @@ func upAUR(remote []alpm.Package, remoteNames []string, warnings *aurWarnings) ( return toUpgrade, nil } +func printIgnoringPackage(pkg alpm.Package, newPkgVersion string) { + left, right := getVersionDiff(pkg.Version(), newPkgVersion) + + fmt.Println( + yellow(bold(smallArrow)) + fmt.Sprintf( + " Ignoring package upgrade: %s (%s -> %s)", + cyan(pkg.Name()), left, right)) +} + +func printLocalNewerThanAUR( + remote []alpm.Package, pkgdata map[string]*rpc.Pkg) { + for _, pkg := range remote { + aurPkg, ok := pkgdata[pkg.Name()] + if !ok { + continue + } + + left, right := getVersionDiff(pkg.Version(), aurPkg.Version) + + if !isDevelName(pkg.Name()) && + alpm.VerCmp(pkg.Version(), aurPkg.Version) > 0 { + fmt.Println( + yellow(bold(smallArrow)) + fmt.Sprintf( + " Local package is newer than AUR: %s (%s -> %s)", + cyan(pkg.Name()), left, right)) + } + } +} + // upRepo gathers local packages and checks if they have new versions. // Output: Upgrade type package list. func upRepo(local []alpm.Package) (upSlice, error) { @@ -289,9 +320,7 @@ func upRepo(local []alpm.Package) (upSlice, error) { newPkg := pkg.NewVersion(dbList) if newPkg != nil { if pkg.ShouldIgnore() { - left, right := getVersionDiff(pkg.Version(), newPkg.Version()) - fmt.Print(yellow(bold(smallArrow))) - fmt.Printf(" Ignoring package upgrade: %s (%s => %s)\n", cyan(pkg.Name()), left, right) + printIgnoringPackage(pkg, newPkg.Version()) } else { slice = append(slice, upgrade{pkg.Name(), newPkg.DB().Name(), pkg.Version(), newPkg.Version()}) } From d15f899809557122f81d30fdcb47fcf97c5d560a Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 14 May 2018 18:33:48 +0100 Subject: [PATCH 030/109] Fixes #417 Signed-off-by: Jguer --- download.go | 54 ++++++++++++++++++++++++++++++----------------------- install.go | 2 +- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/download.go b/download.go index 53ed0991..aace4b8b 100644 --- a/download.go +++ b/download.go @@ -7,7 +7,6 @@ import ( "os" "os/exec" "path/filepath" - "strings" ) // Decide what download method to use: @@ -76,14 +75,13 @@ func gitDownload(url string, path string, name string) error { } // DownloadAndUnpack downloads url tgz and extracts to path. -func downloadAndUnpack(url string, path string, trim bool) (err error) { +func downloadAndUnpack(url string, path string) (err error) { err = os.MkdirAll(path, 0755) if err != nil { return } - tokens := strings.Split(url, "/") - fileName := tokens[len(tokens)-1] + fileName := filepath.Base(url) tarLocation := filepath.Join(path, fileName) defer os.Remove(tarLocation) @@ -93,13 +91,7 @@ func downloadAndUnpack(url string, path string, trim bool) (err error) { return } - if trim { - err = exec.Command("/bin/sh", "-c", - config.TarBin+" --strip-components 2 --include='*/"+fileName[:len(fileName)-7]+"/trunk/' -xf "+tarLocation+" -C "+path).Run() - os.Rename(filepath.Join(path, "trunk"), filepath.Join(path, fileName[:len(fileName)-7])) - } else { - err = exec.Command(config.TarBin, "-xf", tarLocation, "-C", path).Run() - } + err = exec.Command(config.TarBin, "-xf", tarLocation, "-C", path).Run() if err != nil { return } @@ -141,21 +133,33 @@ nextPkg: name = pkg.Name() } - if db.Name() == "core" || db.Name() == "extra" { - url = "https://projects.archlinux.org/svntogit/packages.git/snapshot/packages/" + name + ".tar.gz" - } else if db.Name() == "community" || db.Name() == "multilib" { - url = "https://projects.archlinux.org/svntogit/community.git/snapshot/community-packages/" + name + ".tar.gz" - } else { - fmt.Println(pkgN + " not in standard repositories") + if _, err := os.Stat(filepath.Join(path, name)); err == nil { + fmt.Println(bold(red(arrow)), bold(cyan(name)), "directory already exists") continue nextPkg } - errD := downloadAndUnpack(url, path, true) - if errD != nil { - fmt.Println(bold(red(arrow))+" "+bold(cyan(pkg.Name())), bold(red(errD.Error()))) + switch db.Name() { + case "core", "extra": + url = "https://git.archlinux.org/svntogit/packages.git/snapshot/packages/" + name + ".tar.gz" + case "community", "multilib": + url = "https://git.archlinux.org/svntogit/community.git/snapshot/packages/" + name + ".tar.gz" + default: + fmt.Println(name + " not in standard repositories") + continue nextPkg + } + + errD := downloadAndUnpack(url, cacheHome) + if errD != nil { + fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name())), bold(red(errD.Error()))) + } + + errD = exec.Command("mv", filepath.Join(cacheHome, "packages", name, "trunk"), filepath.Join(path, name)).Run() + if errD != nil { + fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name())), bold(red(errD.Error()))) + } else { + fmt.Println(bold(yellow(arrow)), "Downloaded", cyan(pkg.Name()), "from ABS") } - fmt.Println(bold(yellow(arrow)), "Downloaded", cyan(pkg.Name()), "from ABS") continue nextPkg } } @@ -163,6 +167,10 @@ nextPkg: missing = append(missing, pkgN) } + if _, err := os.Stat(filepath.Join(cacheHome, "packages")); err == nil { + os.RemoveAll(filepath.Join(cacheHome, "packages")) + } + return } @@ -178,13 +186,13 @@ func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) { if shouldUseGit(filepath.Join(dir, pkg.PackageBase)) { err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", dir, pkg.PackageBase) } else { - err = downloadAndUnpack(baseURL+aq[0].URLPath, dir, false) + err = downloadAndUnpack(baseURL+aq[0].URLPath, dir) } if err != nil { fmt.Println(err) } else { - fmt.Println(bold(green(arrow)), bold(green("Downloaded")), bold(magenta(pkg.Name)), bold(green("from AUR"))) + fmt.Println(bold(yellow(arrow)), "Downloaded", cyan(pkg.PackageBase), "from AUR") } } diff --git a/install.go b/install.go index e5225059..3a5a9ca5 100644 --- a/install.go +++ b/install.go @@ -565,7 +565,7 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) } else { - err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir, false) + err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) } if err != nil { return err From 3dc5238bd25498d43b437c6d104a786fcbadf994 Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 14 May 2018 22:22:47 +0100 Subject: [PATCH 031/109] Implement new gopkgbuild Newer method Signed-off-by: Jguer --- Gopkg.lock | 4 +-- install.go | 7 ++--- .../mikkeloscar/gopkgbuild/pkgbuild.go | 2 +- .../mikkeloscar/gopkgbuild/version.go | 27 +++++-------------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 158a2189..5d78eeac 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,7 +5,7 @@ branch = "master" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "11d6aadda57c8fb4f93969333cb990677d28d4f9" + revision = "6150b61c07385c54c6dd8087b9be05cf8b064424" [[projects]] branch = "master" @@ -17,7 +17,7 @@ branch = "master" name = "github.com/mikkeloscar/gopkgbuild" packages = ["."] - revision = "32274fc52aa8f5eb28711da734179e9aea27b31f" + revision = "7b0e7c63b22efc73e1c10e6f3117fdc03cd21816" [solve-meta] analyzer-name = "dep" diff --git a/install.go b/install.go index e5225059..3806aada 100644 --- a/install.go +++ b/install.go @@ -546,9 +546,10 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r pkgbuild, err := gopkg.ParseSRCINFO(dir) if err == nil { - version, err := gopkg.NewCompleteVersion(pkg.Version) - if err == nil { - if !version.Newer(pkgbuild.Version()) { + versionRPC, errR := gopkg.NewCompleteVersion(pkg.Version) + versionPKG, errP := gopkg.NewCompleteVersion(pkgbuild.Version()) + if errP == nil && errR == nil { + if !versionRPC.Newer(versionPKG) { str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) continue diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go b/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go index f1f02b12..ac267f7f 100644 --- a/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go +++ b/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go @@ -616,7 +616,7 @@ func isLowerAlpha(c rune) bool { // check if c is a valid pkgname char func isValidPkgnameChar(c rune) bool { - return isLowerAlpha(c) || isDigit(c) || c == '@' || c == '.' || c == '_' || c == '+' || c == '-' + return isAlphaNumeric(c) || c == '@' || c == '.' || c == '_' || c == '+' || c == '-' } // check if c is a valid pkgver char diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/version.go b/vendor/github.com/mikkeloscar/gopkgbuild/version.go index cae63a87..1695377d 100644 --- a/vendor/github.com/mikkeloscar/gopkgbuild/version.go +++ b/vendor/github.com/mikkeloscar/gopkgbuild/version.go @@ -74,33 +74,18 @@ func NewCompleteVersion(s string) (*CompleteVersion, error) { return nil, fmt.Errorf("invalid version format: %s", s) } -// Older returns true if a is older than the argument version string -func (a *CompleteVersion) Older(v string) bool { - b, err := NewCompleteVersion(v) - if err != nil { - return false - } - +// Older returns true if a is older than the argument version +func (a *CompleteVersion) Older(b *CompleteVersion) bool { return a.cmp(b) == -1 } -// Newer returns true if a is newer than the argument version string -func (a *CompleteVersion) Newer(v string) bool { - b, err := NewCompleteVersion(v) - if err != nil { - return false - } - +// Newer returns true if a is newer than the argument version +func (a *CompleteVersion) Newer(b *CompleteVersion) bool { return a.cmp(b) == 1 } -// Equal returns true if a is equal to the argument version string -func (a *CompleteVersion) Equal(v string) bool { - b, err := NewCompleteVersion(v) - if err != nil { - return false - } - +// Equal returns true if a is equal to the argument version +func (a *CompleteVersion) Equal(b *CompleteVersion) bool { return a.cmp(b) == 0 } From 9f071a8e9bfbfd32c35e92d00e5b9ce9ad04ef10 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 16 May 2018 16:59:46 +0100 Subject: [PATCH 032/109] Only show new news when calling -Pw New news is defined as news that is newer than the install date of the newest package on the users system. All news can be shown using -Pww --- print.go | 31 ++++++++++++++++++------------- query.go | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/print.go b/print.go index df65831a..405b3754 100644 --- a/print.go +++ b/print.go @@ -425,15 +425,21 @@ type Item struct { Creator string `xml:"dc:creator"` } -func (item Item) Print() error { +func (item Item) Print(installTime time.Time) { + var fd string date, err := time.Parse(time.RFC1123Z, item.PubDate) if err != nil { - return err + fmt.Println(err) + } else { + fd = formatTime(int(date.Unix())) + if _, double, _ := cmdArgs.getArg("news", "w"); !double && !installTime.IsZero() { + if installTime.After(date) { + return + } + } } - fd := formatTime(int(date.Unix())) - fmt.Println(bold(magenta(fd)), bold(strings.TrimSpace(item.Title))) //fmt.Println(strings.TrimSpace(item.Link)) @@ -442,7 +448,7 @@ func (item Item) Print() error { fmt.Println(desc) } - return nil + return } type Channel struct { @@ -478,19 +484,18 @@ func printNewsFeed() error { return err } + installTime, err := lastInstallTime() + if err != nil { + return err + } + if config.SortMode == BottomUp { for i := len(rss.Channel.Items) - 1; i >= 0; i-- { - err := rss.Channel.Items[i].Print() - if err != nil { - return err - } + rss.Channel.Items[i].Print(installTime) } } else { for i := 0; i < len(rss.Channel.Items); i++ { - err := rss.Channel.Items[i].Print() - if err != nil { - return err - } + rss.Channel.Items[i].Print(installTime) } } diff --git a/query.go b/query.go index 8e4c0a45..94ec1994 100644 --- a/query.go +++ b/query.go @@ -5,6 +5,7 @@ import ( "sort" "strings" "sync" + "time" alpm "github.com/jguer/go-alpm" rpc "github.com/mikkeloscar/aur" @@ -407,6 +408,26 @@ func hangingPackages(removeOptional bool) (hanging []string, err error) { return } +func lastInstallTime() (time.Time, error) { + var time time.Time + + localDb, err := alpmHandle.LocalDb() + if err != nil { + return time, err + } + + localDb.PkgCache().ForEach(func(pkg alpm.Package) error { + thisTime := pkg.InstallDate() + if thisTime.After(time) { + time = thisTime + } + + return nil + }) + + return time, nil +} + // Statistics returns statistics about packages installed in system func statistics() (info struct { Totaln int From d6ab6ed9ac12ce5370bae5d02d285cce81dbe463 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 17 May 2018 20:09:43 +0100 Subject: [PATCH 033/109] Use native build date when printing news Use the build date of the newest native package instead of the install date of any package. --- print.go | 12 ++++++------ query.go | 12 +++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/print.go b/print.go index 405b3754..a74e3d64 100644 --- a/print.go +++ b/print.go @@ -425,7 +425,7 @@ type Item struct { Creator string `xml:"dc:creator"` } -func (item Item) Print(installTime time.Time) { +func (item Item) Print(buildTime time.Time) { var fd string date, err := time.Parse(time.RFC1123Z, item.PubDate) @@ -433,8 +433,8 @@ func (item Item) Print(installTime time.Time) { fmt.Println(err) } else { fd = formatTime(int(date.Unix())) - if _, double, _ := cmdArgs.getArg("news", "w"); !double && !installTime.IsZero() { - if installTime.After(date) { + if _, double, _ := cmdArgs.getArg("news", "w"); !double && !buildTime.IsZero() { + if buildTime.After(date) { return } } @@ -484,18 +484,18 @@ func printNewsFeed() error { return err } - installTime, err := lastInstallTime() + buildTime, err := lastBuildTime() if err != nil { return err } if config.SortMode == BottomUp { for i := len(rss.Channel.Items) - 1; i >= 0; i-- { - rss.Channel.Items[i].Print(installTime) + rss.Channel.Items[i].Print(buildTime) } } else { for i := 0; i < len(rss.Channel.Items); i++ { - rss.Channel.Items[i].Print(installTime) + rss.Channel.Items[i].Print(buildTime) } } diff --git a/query.go b/query.go index 94ec1994..d244acd9 100644 --- a/query.go +++ b/query.go @@ -408,22 +408,20 @@ func hangingPackages(removeOptional bool) (hanging []string, err error) { return } -func lastInstallTime() (time.Time, error) { +func lastBuildTime() (time.Time, error) { var time time.Time - localDb, err := alpmHandle.LocalDb() + pkgs, _, _, _, err := filterPackages() if err != nil { return time, err } - localDb.PkgCache().ForEach(func(pkg alpm.Package) error { - thisTime := pkg.InstallDate() + for _, pkg := range pkgs { + thisTime := pkg.BuildDate() if thisTime.After(time) { time = thisTime } - - return nil - }) + } return time, nil } From 84810a61af7db4d08a42169b27d28994068f4daa Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 17 May 2018 19:47:12 +0100 Subject: [PATCH 034/109] Document news --- doc/yay.8 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/yay.8 b/doc/yay.8 index da608bb0..74bc218c 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -119,6 +119,19 @@ be displayed\&. .RS 4 Print Names of packages that need to be updated\&. Note this does not perform a database refresh\&. Run \fByay -Sy\fR Before this for an up to date result\&. +.RE +.PP +\fB\-w --news\fR +.RS 4 +Print new news from the Archlinux homepage\&. News is considered new if it is +newer than the build date of all native packages\&. Pass this twice to show all +avaliable news\&. +.RE +.PP +\fB\-q --quiet\fR +.RS 4 +Only show titles when printing news\&. +.RE .PP .SH "PERMANENT CONFIGURATION SETTINGS" .PP From 6b7ee97479d86208c726d4fd478c2d08c9d90a3d Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 20 May 2018 15:28:43 +0100 Subject: [PATCH 035/109] add quiet to print options. fish complete --- completions/fish | 1 + 1 file changed, 1 insertion(+) diff --git a/completions/fish b/completions/fish index c61bc73c..f1446adf 100644 --- a/completions/fish +++ b/completions/fish @@ -109,6 +109,7 @@ complete -c $progname -n $print -s n -l numberupgrades -d 'Print number of updat complete -c $progname -n $print -s s -l stats -d 'Display system package statistics' -f complete -c $progname -n $print -s u -l upgrades -d 'Print update list' -f complete -c $progname -n $print -s w -l news -d 'Print arch news' +complete -c $progname -n $print -s q -l quiet -d 'Do not print news description' # Transaction options (sync, remove, upgrade) for condition in sync remove upgrade From 3f15788c6a03bdba170b1bd30f5a3a1b39c0db11 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 20 May 2018 16:17:05 +0100 Subject: [PATCH 036/109] Unexport functions and structures --- dependencies.go | 2 +- print.go | 20 +++++++++----------- query.go | 2 +- upgrade.go | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/dependencies.go b/dependencies.go index 0a47d53c..b795673b 100644 --- a/dependencies.go +++ b/dependencies.go @@ -397,7 +397,7 @@ func getDepTree(pkgs []string, warnings *aurWarnings) (*depTree, error) { err = checkVersions(dt) } - dt.Warnings.Print() + dt.Warnings.print() return dt, err } diff --git a/print.go b/print.go index a74e3d64..11ff9f32 100644 --- a/print.go +++ b/print.go @@ -17,7 +17,7 @@ import ( const arrow = "==>" const smallArrow = " ->" -func (warnings *aurWarnings) Print() { +func (warnings *aurWarnings) print() { if len(warnings.Missing) > 0 { fmt.Print(bold(yellow(smallArrow)) + " Missing AUR Packages:") for _, name := range warnings.Missing { @@ -162,7 +162,7 @@ func (u upgrade) StylizedNameWithRepository() string { } // Print prints the details of the packages to upgrade. -func (u upSlice) Print() { +func (u upSlice) print() { longestName, longestVersion := 0, 0 for _, pack := range u { packNameLen := len(pack.StylizedNameWithRepository()) @@ -417,7 +417,7 @@ outer: return nil } -type Item struct { +type item struct { Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"` @@ -425,7 +425,7 @@ type Item struct { Creator string `xml:"dc:creator"` } -func (item Item) Print(buildTime time.Time) { +func (item item) print(buildTime time.Time) { var fd string date, err := time.Parse(time.RFC1123Z, item.PubDate) @@ -447,21 +447,19 @@ func (item Item) Print(buildTime time.Time) { desc := strings.TrimSpace(parseNews(item.Description)) fmt.Println(desc) } - - return } -type Channel struct { +type channel struct { Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"` Language string `xml:"language"` Lastbuilddate string `xml:"lastbuilddate"` - Items []Item `xml:"item"` + Items []item `xml:"item"` } type rss struct { - Channel Channel `xml:"channel"` + Channel channel `xml:"channel"` } func printNewsFeed() error { @@ -491,11 +489,11 @@ func printNewsFeed() error { if config.SortMode == BottomUp { for i := len(rss.Channel.Items) - 1; i >= 0; i-- { - rss.Channel.Items[i].Print(buildTime) + rss.Channel.Items[i].print(buildTime) } } else { for i := 0; i < len(rss.Channel.Items); i++ { - rss.Channel.Items[i].Print(buildTime) + rss.Channel.Items[i].print(buildTime) } } diff --git a/query.go b/query.go index d244acd9..c5b7323b 100644 --- a/query.go +++ b/query.go @@ -535,7 +535,7 @@ func aurInfoPrint(names []string) ([]*rpc.Pkg, error) { return info, err } - warnings.Print() + warnings.print() return info, nil } diff --git a/upgrade.go b/upgrade.go index 75b3e311..3099e455 100644 --- a/upgrade.go +++ b/upgrade.go @@ -343,7 +343,7 @@ func upgradePkgs(aurUp, repoUp upSlice) (stringSet, stringSet, error) { sort.Sort(aurUp) allUp := append(repoUp, aurUp...) fmt.Printf("%s"+bold(" %d ")+"%s\n", bold(cyan("::")), allUpLen, bold("Packages to upgrade.")) - allUp.Print() + allUp.print() fmt.Println(bold(green(arrow + " Packages to not upgrade: (eg: 1 2 3, 1-3, ^4 or repo name)"))) fmt.Print(bold(green(arrow + " "))) From 70e5f43171eac9f2fb4c9568eeff8099f7f918fc Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 28 May 2018 13:31:33 +0100 Subject: [PATCH 037/109] Quick fix to yay -G error code #430 Signed-off-by: Jguer --- download.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/download.go b/download.go index aace4b8b..b90f3c6a 100644 --- a/download.go +++ b/download.go @@ -181,6 +181,10 @@ func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) { return err } + if (len(aq) != len(pkgs)) { + return fmt.Errorf("Could not find all required packages"); + } + for _, pkg := range aq { var err error if shouldUseGit(filepath.Join(dir, pkg.PackageBase)) { From 6d70716ba216db804cde7ba68c65d238bfb03b70 Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 28 May 2018 13:43:02 +0100 Subject: [PATCH 038/109] Quick fix to yay -Si error code #430. Will return all possible values and then error Signed-off-by: Jguer --- query.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/query.go b/query.go index c5b7323b..04ff8386 100644 --- a/query.go +++ b/query.go @@ -214,12 +214,16 @@ func syncInfo(pkgS []string) (err error) { } } - if len(aurS) != 0 { + if len(info) != 0 { for _, pkg := range info { PrintInfo(pkg) } } + if len(aurS) != len(info) { + return fmt.Errorf("Could not find all required packages") + } + return } From 2b5c725a0cf0fb97c93fb92bac533879d3a3fd7d Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 28 May 2018 13:45:11 +0100 Subject: [PATCH 039/109] Fixes #430. Don't abort -G just error to signal not all was good Signed-off-by: Jguer --- download.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/download.go b/download.go index b90f3c6a..7359aed9 100644 --- a/download.go +++ b/download.go @@ -181,10 +181,6 @@ func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) { return err } - if (len(aq) != len(pkgs)) { - return fmt.Errorf("Could not find all required packages"); - } - for _, pkg := range aq { var err error if shouldUseGit(filepath.Join(dir, pkg.PackageBase)) { @@ -200,5 +196,9 @@ func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) { } } + if len(aq) != len(pkgs) { + return fmt.Errorf("Could not find all required packages") + } + return } From cd4f74a04d3d9fb586ce82e552ee7767cd646734 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 29 May 2018 00:05:37 +0100 Subject: [PATCH 040/109] 5.1 vendor update Signed-off-by: Jguer --- Gopkg.lock | 4 ++-- vendor/github.com/jguer/go-alpm/conf.go | 10 +++------- vendor/github.com/jguer/go-alpm/db.go | 2 +- vendor/github.com/jguer/go-alpm/enums.go | 4 ++-- vendor/github.com/jguer/go-alpm/handle.go | 6 +++--- vendor/github.com/jguer/go-alpm/package.go | 10 ++++------ 6 files changed, 15 insertions(+), 21 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index bf537b1a..ebb57c37 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,7 +5,7 @@ branch = "master" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "6150b61c07385c54c6dd8087b9be05cf8b064424" + revision = "ad1a7ae8a5232dbbe48dc3f75a42e6812f2dce11" [[projects]] branch = "master" @@ -18,7 +18,7 @@ name = "github.com/mikkeloscar/gopkgbuild" packages = ["."] revision = "7b0e7c63b22efc73e1c10e6f3117fdc03cd21816" - + [solve-meta] analyzer-name = "dep" analyzer-version = 1 diff --git a/vendor/github.com/jguer/go-alpm/conf.go b/vendor/github.com/jguer/go-alpm/conf.go index f449d8e2..a9922565 100644 --- a/vendor/github.com/jguer/go-alpm/conf.go +++ b/vendor/github.com/jguer/go-alpm/conf.go @@ -114,18 +114,14 @@ func (rdr *confReader) ParseLine() (tok iniToken, err error) { rdr.Lineno++ line = bytes.TrimSpace(line) - - comment := bytes.IndexByte(line, '#') - if comment >= 0 { - line = line[:comment] - } - if len(line) == 0 { tok.Type = tokenComment return } - switch line[0] { + case '#': + tok.Type = tokenComment + return case '[': closing := bytes.IndexByte(line, ']') if closing < 0 { diff --git a/vendor/github.com/jguer/go-alpm/db.go b/vendor/github.com/jguer/go-alpm/db.go index 90d1698c..214984de 100644 --- a/vendor/github.com/jguer/go-alpm/db.go +++ b/vendor/github.com/jguer/go-alpm/db.go @@ -89,7 +89,7 @@ func (h Handle) RegisterSyncDb(dbname string, siglevel SigLevel) (*Db, error) { cName := C.CString(dbname) defer C.free(unsafe.Pointer(cName)) - db := C.alpm_register_syncdb(h.ptr, cName, C.alpm_siglevel_t(siglevel)) + db := C.alpm_register_syncdb(h.ptr, cName, C.int(siglevel)) if db == nil { return nil, h.LastError() } diff --git a/vendor/github.com/jguer/go-alpm/enums.go b/vendor/github.com/jguer/go-alpm/enums.go index 2b1bdd3a..ba228089 100644 --- a/vendor/github.com/jguer/go-alpm/enums.go +++ b/vendor/github.com/jguer/go-alpm/enums.go @@ -62,7 +62,7 @@ func (mod DepMod) String() string { } // Signature checking level. -type SigLevel uint +type SigLevel int const ( SigPackage SigLevel = 1 << iota @@ -79,7 +79,7 @@ const ( const SigUseDefault SigLevel = 1 << 31 // Signature status -type SigStatus uint +type SigStatus int const ( SigStatusValid SigStatus = iota diff --git a/vendor/github.com/jguer/go-alpm/handle.go b/vendor/github.com/jguer/go-alpm/handle.go index cdf4a432..d2c8ee82 100644 --- a/vendor/github.com/jguer/go-alpm/handle.go +++ b/vendor/github.com/jguer/go-alpm/handle.go @@ -534,7 +534,7 @@ func (h Handle) GetDefaultSigLevel() (SigLevel, error) { } func (h Handle) SetDefaultSigLevel(siglevel SigLevel) error { - ok := C.alpm_option_set_default_siglevel(h.ptr, C.alpm_siglevel_t(siglevel)) + ok := C.alpm_option_set_default_siglevel(h.ptr, C.int(siglevel)) if ok < 0 { return h.LastError() @@ -552,7 +552,7 @@ func (h Handle) GetLocalFileSigLevel() (SigLevel, error) { } func (h Handle) SetLocalFileSigLevel(siglevel SigLevel) error { - ok := C.alpm_option_set_local_file_siglevel(h.ptr, C.alpm_siglevel_t(siglevel)) + ok := C.alpm_option_set_local_file_siglevel(h.ptr, C.int(siglevel)) if ok < 0 { return h.LastError() @@ -570,7 +570,7 @@ func (h Handle) GetRemoteFileSigLevel() (SigLevel, error) { } func (h Handle) SetRemoteFileSigLevel(siglevel SigLevel) error { - ok := C.alpm_option_set_remote_file_siglevel(h.ptr, C.alpm_siglevel_t(siglevel)) + ok := C.alpm_option_set_remote_file_siglevel(h.ptr, C.int(siglevel)) if ok < 0 { return h.LastError() diff --git a/vendor/github.com/jguer/go-alpm/package.go b/vendor/github.com/jguer/go-alpm/package.go index ef589dd0..8873eb5b 100644 --- a/vendor/github.com/jguer/go-alpm/package.go +++ b/vendor/github.com/jguer/go-alpm/package.go @@ -159,18 +159,16 @@ func (pkg Package) OptionalDepends() DependList { } // Depends returns the package's check dependency list. -//Exists in futre alpm -/*func (pkg Package) CheckDepends() DependList { +func (pkg Package) CheckDepends() DependList { ptr := unsafe.Pointer(C.alpm_pkg_get_checkdepends(pkg.pmpkg)) return DependList{(*list)(ptr)} -}*/ +} // Depends returns the package's make dependency list. -//Exists in futre alpm -/*func (pkg Package) MakeDepends() DependList { +func (pkg Package) MakeDepends() DependList { ptr := unsafe.Pointer(C.alpm_pkg_get_makedepends(pkg.pmpkg)) return DependList{(*list)(ptr)} -}*/ +} // Description returns the package's description. func (pkg Package) Description() string { From cc2322f492688f7afcaf42ec1f66aa092dd25c34 Mon Sep 17 00:00:00 2001 From: J Guerreiro Date: Tue, 29 May 2018 00:40:53 +0100 Subject: [PATCH 041/109] Update README.md to include temporary notice of manual intervention --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 994608f7..28e6b90a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ Yet another Yogurt - An AUR Helper written in Go +`yay: error while loading shared libraries: libalpm.so.10: cannot open shared object file: No such file or directory` +Pacman 5.1 migration explained [here](https://github.com/Jguer/yay/releases/tag/v6.784) + #### Packages [![yay](https://img.shields.io/aur/version/yay.svg?label=yay)](https://aur.archlinux.org/packages/yay/) [![yay-bin](https://img.shields.io/aur/version/yay-bin.svg?label=yay-bin)](https://aur.archlinux.org/packages/yay-bin/) [![yay-git](https://img.shields.io/aur/version/yay-git.svg?label=yay-git)](https://aur.archlinux.org/packages/yay-git/) [![GitHub license](https://img.shields.io/github/license/jguer/yay.svg)](https://github.com/Jguer/yay/blob/master/LICENSE) From d442af9dccc964f6f6b74d5f1dca9cf8a4ea1923 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 29 May 2018 11:36:45 +0100 Subject: [PATCH 042/109] Fix #435. Update vendor to include SIGLEVEL overflow fix --- Gopkg.lock | 2 +- vendor/github.com/jguer/go-alpm/enums.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index ebb57c37..2e4449b9 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,7 +5,7 @@ branch = "master" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "ad1a7ae8a5232dbbe48dc3f75a42e6812f2dce11" + revision = "525cfc02951f197145144587c42d51baac160eb7" [[projects]] branch = "master" diff --git a/vendor/github.com/jguer/go-alpm/enums.go b/vendor/github.com/jguer/go-alpm/enums.go index ba228089..3c692bc1 100644 --- a/vendor/github.com/jguer/go-alpm/enums.go +++ b/vendor/github.com/jguer/go-alpm/enums.go @@ -76,7 +76,7 @@ const ( SigDatabaseMarginalOk SigDatabaseUnknownOk ) -const SigUseDefault SigLevel = 1 << 31 +const SigUseDefault SigLevel = 1 << 30 // Signature status type SigStatus int From b2d3eb5c4924230ddb4f1dcf3a891cd610320463 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 05:06:25 +0100 Subject: [PATCH 043/109] Add new dependency code to replace the old code This is a rewrite of the dependency system, It aims to be cleaner written, with a better idea of what is needed from the start, meaning less new code being hacked on for things that were not thought about. This version also aims to use as many small functions as possible, for cleaner code and better testing. Added dep.go: general dependency functions Added depPool.go: Replacement of depTree, dependencies were never ordered so a tree did not really make sense. Instead the term pool makes more sense. Added depOrder.go: Replacement of depCatagories, This simply orders the dependencies, dependencies are still catagorized as repo and AUR but I believe this to be a better name Added depCheck.go: Replaces conflicts.go and also contains the missing dependency code This version is mostly the same as the old version with a few improvments: Missing packages will print the full dependency tree Versioned dependency checking errors should be fixed Make depends should be calculated properly Experimental AUR provide searcher This code has been added along side the old code for testing and is not currently used by the install process. Once the install process is moved to use this code, the old code will be removed. --- dep.go | 104 ++++++++++++ depCheck.go | 264 +++++++++++++++++++++++++++++ depOrder.go | 138 +++++++++++++++ depPool.go | 477 ++++++++++++++++++++++++++++++++++++++++++++++++++++ parser.go | 10 ++ print.go | 59 +++++++ utils.go | 22 +++ 7 files changed, 1074 insertions(+) create mode 100644 dep.go create mode 100644 depCheck.go create mode 100644 depOrder.go create mode 100644 depPool.go diff --git a/dep.go b/dep.go new file mode 100644 index 00000000..2958ef71 --- /dev/null +++ b/dep.go @@ -0,0 +1,104 @@ +package main + +import ( + "fmt" + "strings" + + alpm "github.com/jguer/go-alpm" + rpc "github.com/mikkeloscar/aur" +) + +func splitDep(dep string) (string, string, string) { + mod := "" + + split := strings.FieldsFunc(dep, func(c rune) bool { + match := c == '>' || c == '<' || c == '=' + + if match { + mod += string(c) + } + + return match + }) + + 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 *alpm.Package) bool { + if pkgSatisfies(pkg.Name(), pkg.Version(), dep) { + return true + } + + if pkg.Provides().ForEach(func(provide alpm.Depend) error { + if provideSatisfies(provide.String(), dep) { + return fmt.Errorf("") + } + + return nil + }) != nil { + return true + } + + return false +} diff --git a/depCheck.go b/depCheck.go new file mode 100644 index 00000000..de6a4635 --- /dev/null +++ b/depCheck.go @@ -0,0 +1,264 @@ +package main + +import ( + "fmt" + "strings" + "sync" + + alpm "github.com/jguer/go-alpm" + // gopkg "github.com/mikkeloscar/gopkgbuild" +) + +func (dp *depPool) checkInnerConflict(name string, conflict string, conflicts mapStringSet) { + for _, pkg := range dp.Aur { + if pkg.Name == name { + continue + } + + if satisfiesAur(conflict, pkg) { + conflicts.Add(name, pkg.Name) + } + } + + for _, pkg := range dp.Repo { + if pkg.Name() == name { + continue + } + + if satisfiesRepo(conflict, pkg) { + conflicts.Add(name, pkg.Name()) + } + } +} + +func (dp *depPool) checkForwardConflict(name string, conflict string, conflicts mapStringSet) { + dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error { + if pkg.Name() == name { + return nil + } + + if satisfiesRepo(conflict, &pkg) { + n := pkg.Name() + if n != conflict { + n += " (" + conflict + ")" + } + conflicts.Add(name, n) + } + + return nil + }) +} + +func (dp *depPool) checkReverseConflict(name string, conflict string, conflicts mapStringSet) { + for _, pkg := range dp.Aur { + if pkg.Name == name { + continue + } + + if satisfiesAur(conflict, pkg) { + if name != conflict { + name += " (" + conflict + ")" + } + + conflicts.Add(pkg.Name, name) + } + } + + for _, pkg := range dp.Repo { + if pkg.Name() == name { + continue + } + + if satisfiesRepo(conflict, pkg) { + if name != conflict { + name += " (" + conflict + ")" + } + + conflicts.Add(pkg.Name(), name) + } + } +} + +func (dp *depPool) checkInnerConflicts(conflicts mapStringSet) { + for _, pkg := range dp.Aur { + for _, conflict := range pkg.Conflicts { + dp.checkInnerConflict(pkg.Name, conflict, conflicts) + } + } + + for _, pkg := range dp.Repo { + pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { + dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts) + return nil + }) + } +} + +func (dp *depPool) checkForwardConflicts(conflicts mapStringSet) { + for _, pkg := range dp.Aur { + for _, conflict := range pkg.Conflicts { + dp.checkForwardConflict(pkg.Name, conflict, conflicts) + } + } + + for _, pkg := range dp.Repo { + pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { + dp.checkForwardConflict(pkg.Name(), conflict.String(), conflicts) + return nil + }) + } +} + +func (dp *depPool) checkReverseConflicts(conflicts mapStringSet) { + dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error { + pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { + dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts) + return nil + }) + + return nil + }) +} + +func (dp *depPool) CheckConflicts() error { + var wg sync.WaitGroup + innerConflicts := make(mapStringSet) + conflicts := make(mapStringSet) + wg.Add(2) + + fmt.Println(bold(cyan("::") + bold(" Checking for conflicts..."))) + go func() { + dp.checkForwardConflicts(conflicts) + dp.checkReverseConflicts(conflicts) + wg.Done() + }() + + fmt.Println(bold(cyan("::") + bold(" Checking for inner conflicts..."))) + go func() { + dp.checkInnerConflicts(innerConflicts) + wg.Done() + }() + + wg.Wait() + + if len(innerConflicts) != 0 { + fmt.Println() + fmt.Println(bold(red(arrow)), bold("Inner conflicts found:")) + + for name, pkgs := range innerConflicts { + str := red(bold(smallArrow)) + " " + name + ":" + for pkg := range pkgs { + str += " " + cyan(pkg) + "," + } + str = strings.TrimSuffix(str, ",") + + fmt.Println(str) + } + + return fmt.Errorf("Unresolvable package conflicts, aborting") + } + + if len(conflicts) != 0 { + fmt.Println() + fmt.Println(bold(red(arrow)), bold("Package conflicts found:")) + for name, pkgs := range conflicts { + str := red(bold(smallArrow)) + " Installing " + cyan(name) + " will remove:" + for pkg := range pkgs { + str += " " + cyan(pkg) + "," + } + str = strings.TrimSuffix(str, ",") + + fmt.Println(str) + } + + fmt.Println() + } + + return nil +} + +type missing struct { + Good stringSet + Missing map[string][][]string +} + +func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { + if _, err := dp.LocalDb.PkgCache().FindSatisfier(dep); err == nil { + missing.Good.set(dep) + return + } + + if missing.Good.get(dep) { + return + } + + if trees, ok := missing.Missing[dep]; ok { + for _, tree := range trees { + if stringSliceEqual(tree, stack) { + return + } + } + missing.Missing[dep] = append(missing.Missing[dep], stack) + return + } + + aurPkg := dp.findSatisfierAur(dep) + if aurPkg != nil { + missing.Good.set(dep) + for _, deps := range [3][]string{aurPkg.Depends, aurPkg.MakeDepends, aurPkg.CheckDepends} { + for _, aurDep := range deps { + dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing) + } + } + + return + } + + repoPkg := dp.findSatisfierRepo(dep) + if repoPkg != nil { + missing.Good.set(dep) + repoPkg.Depends().ForEach(func(repoDep alpm.Depend) error { + dp._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing) + return nil + }) + + return + } + + missing.Missing[dep] = [][]string{stack} +} + +func (dp *depPool) CheckMissing() error { + missing := &missing{ + make(stringSet), + make(map[string][][]string), + } + + for _, target := range dp.Targets { + dp._checkMissing(target.DepString(), make([]string, 0), missing) + } + + if len(missing.Missing) == 0 { + return nil + } + + fmt.Println(bold(red(arrow+" Error: ")) + "Could not find all required packages:") + for dep, trees := range missing.Missing { + for _, tree := range trees { + + fmt.Print(" "+cyan(dep), " (Tree: ") + + if len(tree) == 0 { + fmt.Print(cyan("Target ")) + } else { + for _, pkg := range tree { + fmt.Print(cyan(pkg), " -> ") + } + } + + fmt.Println(")") + } + } + + return fmt.Errorf("") +} diff --git a/depOrder.go b/depOrder.go new file mode 100644 index 00000000..acb00ad6 --- /dev/null +++ b/depOrder.go @@ -0,0 +1,138 @@ +package main + +import ( + // "fmt" + "strconv" + // "strings" + // "sync" + + alpm "github.com/jguer/go-alpm" + rpc "github.com/mikkeloscar/aur" + //gopkg "github.com/mikkeloscar/gopkgbuild" +) + +type depOrder struct { + Aur []*rpc.Pkg + Repo []*alpm.Package + Missing []string + Runtime stringSet +} + +func (do *depOrder) String() string { + str := "" + str += "\n" + red("Repo") + " (" + strconv.Itoa(len(do.Repo)) + ") :" + for _, pkg := range do.Repo { + if do.Runtime.get(pkg.Name()) { + str += " " + pkg.Name() + } + } + + str += "\n" + red("Aur") + " (" + strconv.Itoa(len(do.Aur)) + ") :" + for _, pkg := range do.Aur { + if do.Runtime.get(pkg.Name) { + str += " " + pkg.Name + } + + } + + str += "\n" + red("Repo Make") + " (" + strconv.Itoa(len(do.Repo)) + ") :" + for _, pkg := range do.Repo { + if !do.Runtime.get(pkg.Name()) { + str += " " + pkg.Name() + } + } + + str += "\n" + red("Aur Make") + " (" + strconv.Itoa(len(do.Aur)) + ") :" + for _, pkg := range do.Aur { + if !do.Runtime.get(pkg.Name) { + str += " " + pkg.Name + } + + } + + return str +} + +func makeDepOrder() *depOrder { + return &depOrder{ + make([]*rpc.Pkg, 0), + make([]*alpm.Package, 0), + make([]string, 0), + make(stringSet), + } +} + +func getDepOrder(dp *depPool) *depOrder { + do := makeDepOrder() + + for _, target := range dp.Targets { + dep := target.DepString() + aurPkg := dp.findSatisfierAur(dep) + if aurPkg != nil { + do.orderPkgAur(aurPkg, dp, true) + } + + repoPkg := dp.findSatisfierRepo(dep) + if repoPkg != nil { + do.orderPkgRepo(repoPkg, dp, true) + } + } + + return do +} + +func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { + if runtime { + do.Runtime.set(pkg.Name) + } + do.Aur = append(do.Aur, pkg) + delete(dp.Aur, pkg.Name) + + for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { + for _, dep := range deps { + aurPkg := dp.findSatisfierAur(dep) + if aurPkg != nil { + do.orderPkgAur(aurPkg, dp, runtime) + } + + repoPkg := dp.findSatisfierRepo(dep) + if repoPkg != nil { + do.orderPkgRepo(repoPkg, dp, runtime) + } + + runtime = false + } + } +} + +func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { + if runtime { + do.Runtime.set(pkg.Name()) + } + do.Repo = append(do.Repo, pkg) + delete(dp.Repo, pkg.Name()) + + pkg.Depends().ForEach(func(dep alpm.Depend) (err error) { + repoPkg := dp.findSatisfierRepo(dep.String()) + if repoPkg != nil { + do.orderPkgRepo(repoPkg, dp, runtime) + } + + return nil + }) +} + +func (do *depOrder) getMakeOnlyRepo() stringSet { + makeOnly := make(stringSet) + + for _, pkg := range do.Repo { + if !do.Runtime.get(pkg.Name()) { + makeOnly.set(pkg.Name()) + } + } + + return makeOnly +} + +func (do *depOrder) checkMissing() { +} diff --git a/depPool.go b/depPool.go new file mode 100644 index 00000000..db6442f7 --- /dev/null +++ b/depPool.go @@ -0,0 +1,477 @@ +package main + +import ( + "fmt" + "strconv" + "strings" + "sync" + + alpm "github.com/jguer/go-alpm" + rpc "github.com/mikkeloscar/aur" + //gopkg "github.com/mikkeloscar/gopkgbuild" +) + +const PROVIDES = false + +type target struct { + Db string + Name string + Mod string + Version string +} + +func toTarget(pkg string) target { + db, dep := splitDbFromName(pkg) + name, mod, version := splitDep(dep) + + return target{ + db, + name, + mod, + version, + } +} + +func (t target) DepString() string { + return t.Name + t.Mod + t.Version +} + +func (t target) String() string { + if t.Db != "" { + return t.Db + "/" + t.DepString() + } + + return t.DepString() +} + +type depPool struct { + Targets []target + Repo map[string]*alpm.Package + Aur map[string]*rpc.Pkg + AurCache map[string]*rpc.Pkg + Groups []string + LocalDb *alpm.Db + SyncDb alpm.DbList + Warnings *aurWarnings +} + +func makeDepPool() (*depPool, error) { + localDb, err := alpmHandle.LocalDb() + if err != nil { + return nil, err + } + syncDb, err := alpmHandle.SyncDbs() + if err != nil { + return nil, err + } + + dp := &depPool{ + make([]target, 0), + make(map[string]*alpm.Package), + make(map[string]*rpc.Pkg), + make(map[string]*rpc.Pkg), + make([]string, 0), + localDb, + syncDb, + &aurWarnings{}, + } + + return dp, nil +} + +func (dp *depPool) String() string { + str := "" + str += "\n" + red("Targets") + " (" + strconv.Itoa(len(dp.Targets)) + ") :" + for _, pkg := range dp.Targets { + str += " " + pkg.String() + } + + str += "\n" + red("Repo") + " (" + strconv.Itoa(len(dp.Repo)) + ") :" + for pkg := range dp.Repo { + str += " " + pkg + } + + str += "\n" + red("Aur") + " (" + strconv.Itoa(len(dp.Aur)) + ") :" + for pkg := range dp.Aur { + str += " " + pkg + } + + str += "\n" + red("Aur Cache") + " (" + strconv.Itoa(len(dp.AurCache)) + ") :" + for pkg := range dp.AurCache { + str += " " + pkg + } + + str += "\n" + red("Groups") + " (" + strconv.Itoa(len(dp.Groups)) + ") :" + for _, pkg := range dp.Groups { + str += " " + pkg + } + + return str +} + +// Includes db/ prefixes and group installs +func (dp *depPool) ResolveTargets(pkgs []string) error { + for _, pkg := range pkgs { + target := toTarget(pkg) + dp.Targets = append(dp.Targets, target) + } + + // RPC requests are slow + // Combine as many AUR package requests as possible into a single RPC + // call + aurTargets := make(stringSet) + var err error + //repo := make([]*alpm.Package, 0) + + for _, target := range dp.Targets { + + // skip targets already satisfied + // even if the user enters db/pkg and aur/pkg the latter will + // still get skiped even if it's from a different database to + // the one specified + // this is how pacman behaves + if dp.hasSatisfier(target.DepString()) { + fmt.Println("Skipping target", target) + continue + } + + var foundPkg *alpm.Package + var singleDb *alpm.Db + + // aur/ prefix means we only check the aur + if target.Db == "aur" { + aurTargets.set(target.DepString()) + continue + } + + // if theres a different priefix only look in that repo + if target.Db != "" { + singleDb, err = alpmHandle.SyncDbByName(target.Db) + if err != nil { + return err + } + foundPkg, err = singleDb.PkgCache().FindSatisfier(target.DepString()) + //otherwise find it in any repo + } else { + foundPkg, err = dp.SyncDb.FindSatisfier(target.DepString()) + } + + if err == nil { + dp.ResolveRepoDependency(foundPkg) + continue + } else { + //check for groups + //currently we dont resolve the packages in a group + //only check if the group exists + //would be better to check the groups from singleDb if + //the user specified a db but theres no easy way to do + //it without making alpm_lists so dont bother for now + //db/group is probably a rare use case + _, err := dp.SyncDb.PkgCachebyGroup(target.Name) + + if err == nil { + dp.Groups = append(dp.Groups, target.String()) + continue + } + } + + //if there was no db prefix check the aur + if target.Db == "" { + aurTargets.set(target.DepString()) + } + } + + if len(aurTargets) > 0 { + err = dp.resolveAURPackages(aurTargets) + } + + return nil +} + +// Pseudo provides finder. +// Try to find provides by performing a search of the package name +// This effectively performs -Ss on each package +// then runs -Si on each result to cache the information. +// +// For example if you were to -S yay then yay -Ss would give: +// yay-git yay-bin yay realyog pacui pacui-git ruby-yard +// These packages will all be added to the cache incase they are needed later +// Ofcouse only the first three packages provide yay, the rest are just false +// positives. +// +// This method increases dependency resolve time +func (dp *depPool) findProvides(pkgs stringSet) error { + var mux sync.Mutex + var wg sync.WaitGroup + + doSearch := func(pkg string) { + defer wg.Done() + var err error + var results []rpc.Pkg + + // Hack for a bigger search result, if the user wants + // java-envronment we can search for just java instead and get + // more hits. + words := strings.Split(pkg, "-") + + for i := range words { + results, err = rpc.SearchByNameDesc(strings.Join(words[:i+1], "-")) + if err == nil { + break + } + } + + if err != nil { + return + } + + for _, result := range results { + mux.Lock() + if _, ok := dp.AurCache[result.Name]; !ok { + pkgs.set(result.Name) + } + mux.Unlock() + } + } + + for pkg := range pkgs { + wg.Add(1) + go doSearch(pkg) + } + + wg.Wait() + + return nil +} + +func (dp *depPool) cacheAURPackages(_pkgs stringSet) error { + pkgs := _pkgs.copy() + query := make([]string, 0) + + for pkg := range pkgs { + if _, ok := dp.AurCache[pkg]; ok { + pkgs.remove(pkg) + } + } + + if len(pkgs) == 0 { + return nil + } + + //TODO: config option, maybe --deepsearh but aurman uses that flag for + //something else already which might be confusing + //maybe --provides + if PROVIDES { + err := dp.findProvides(pkgs) + if err != nil { + return err + } + } + + for pkg := range pkgs { + if _, ok := dp.AurCache[pkg]; !ok { + name, _, _ := splitDep(pkg) + query = append(query, name) + } + } + + info, err := aurInfo(query, dp.Warnings) + if err != nil { + return err + } + + for _, pkg := range info { + // Dump everything in cache just in case we need it later + dp.AurCache[pkg.Name] = pkg + } + + return nil +} + +func (dp *depPool) resolveAURPackages(pkgs stringSet) error { + newPackages := make(stringSet) + newAURPackages := make(stringSet) + + err := dp.cacheAURPackages(pkgs) + if err != nil { + return err + } + + if len(pkgs) == 0 { + return nil + } + + for name := range pkgs { + _, ok := dp.Aur[name] + if ok { + continue + } + + pkg := dp.findSatisfierAurCache(name) + if pkg == nil { + continue + } + + dp.Aur[pkg.Name] = pkg + + for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { + for _, dep := range deps { + newPackages.set(dep) + } + } + } + + for dep := range newPackages { + if dp.hasSatisfier(dep) { + continue + } + + //has satisfier installed: skip + _, isInstalled := dp.LocalDb.PkgCache().FindSatisfier(dep) + if isInstalled == nil { + continue + } + + //has satisfier in repo: fetch it + repoPkg, inRepos := dp.SyncDb.FindSatisfier(dep) + if inRepos == nil { + dp.ResolveRepoDependency(repoPkg) + continue + } + + //assume it's in the aur + //ditch the versioning because the RPC cant handle it + newAURPackages.set(dep) + + } + + err = dp.resolveAURPackages(newAURPackages) + + return err +} + +func (dp *depPool) ResolveRepoDependency(pkg *alpm.Package) { + dp.Repo[pkg.Name()] = pkg + + pkg.Depends().ForEach(func(dep alpm.Depend) (err error) { + //have satisfier in dep tree: skip + if dp.hasSatisfier(dep.String()) { + return + } + + //has satisfier installed: skip + _, isInstalled := dp.LocalDb.PkgCache().FindSatisfier(dep.String()) + if isInstalled == nil { + return + } + + //has satisfier in repo: fetch it + repoPkg, inRepos := dp.SyncDb.FindSatisfier(dep.String()) + if inRepos != nil { + return + } + + dp.ResolveRepoDependency(repoPkg) + + return nil + }) + +} + +func (dp *depPool) queryAUR(pkgs []string) error { + _, err := aurInfo(pkgs, dp.Warnings) + if err != nil { + return err + } + + return nil +} + +func getDepPool(pkgs []string) (*depPool, error) { + dp, err := makeDepPool() + if err != nil { + return nil, err + } + + err = dp.ResolveTargets(pkgs) + + return dp, err +} + +func (dp *depPool) findSatisfierAur(dep string) *rpc.Pkg { + for _, pkg := range dp.Aur { + if satisfiesAur(dep, pkg) { + return pkg + } + } + + return nil +} + +// This is mostly used to promote packages from the cache +// to the Install list +// Provide a pacman style provider menu if theres more than one candidate +// TODO: maybe intermix repo providers in the menu +func (dp *depPool) findSatisfierAurCache(dep string) *rpc.Pkg { + //try to match providers + providers := make([]*rpc.Pkg, 0) + for _, pkg := range dp.AurCache { + if pkgSatisfies(pkg.Name, pkg.Version, dep) { + return pkg + } + } + + for _, pkg := range dp.AurCache { + for _, provide := range pkg.Provides { + if provideSatisfies(provide, dep) { + providers = append(providers, pkg) + } + } + } + + if len(providers) == 1 { + return providers[0] + } + + if len(providers) > 1 { + return providerMenu(dep, providers) + } + + return nil +} + +func (dp *depPool) findSatisfierRepo(dep string) *alpm.Package { + for _, pkg := range dp.Repo { + if satisfiesRepo(dep, pkg) { + return pkg + } + } + + return nil +} + +func (dp *depPool) hasSatisfier(dep string) bool { + return dp.findSatisfierRepo(dep) != nil || dp.findSatisfierAur(dep) != nil +} + +func (dp *depPool) hasPackage(name string) bool { + for _, pkg := range dp.Repo { + if pkg.Name() == name { + return true + } + } + + for _, pkg := range dp.Aur { + if pkg.Name == name { + return true + } + } + + for _, pkg := range dp.Groups { + if pkg == name { + return true + } + } + + return false +} diff --git a/parser.go b/parser.go index 7a6787a1..c384a79d 100644 --- a/parser.go +++ b/parser.go @@ -41,6 +41,16 @@ func (set stringSet) toSlice() []string { return slice } +func (set stringSet) copy() stringSet { + newSet := make(stringSet) + + for str := range set { + newSet.set(str) + } + + return newSet +} + func sliceToStringSet(in []string) stringSet { set := make(stringSet) diff --git a/print.go b/print.go index 11ff9f32..5b7dd546 100644 --- a/print.go +++ b/print.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "bytes" "encoding/xml" "fmt" @@ -566,3 +567,61 @@ func colourHash(name string) (output string) { } return fmt.Sprintf("\x1b[%dm%s\x1b[0m", hash%6+31, name) } + +func providerMenu(dep string, providers []*rpc.Pkg) *rpc.Pkg { + size := len(providers) + + fmt.Print(bold(cyan(":: "))) + str := bold(fmt.Sprintf(bold("There are %d providers available for %s:"), size, dep)) + + size = 1 + str += bold(cyan("\n:: ")) + bold("Repository AUR\n ") + + for _, pkg := range providers { + str += fmt.Sprintf("%d) %s ", size, pkg.Name) + size++ + } + + fmt.Println(str) + + for { + fmt.Print("\nEnter a number (default=1): ") + + if config.NoConfirm { + fmt.Println() + break + } + + reader := bufio.NewReader(os.Stdin) + numberBuf, overflow, err := reader.ReadLine() + + if err != nil { + fmt.Println(err) + break + } + + if overflow { + fmt.Println("Input too long") + continue + } + + if string(numberBuf) == "" { + return providers[0] + } + + num, err := strconv.Atoi(string(numberBuf)) + if err != nil { + fmt.Printf("%s invalid number: %s\n", red("error:"), string(numberBuf)) + continue + } + + if num < 1 || num > size { + fmt.Printf("%s invalid value: %d is not between %d and %d\n", red("error:"), num, 1, size) + continue + } + + return providers[num-1] + } + + return nil +} diff --git a/utils.go b/utils.go index 2439981f..260b2769 100644 --- a/utils.go +++ b/utils.go @@ -112,3 +112,25 @@ func lessRunes(iRunes, jRunes []rune) bool { return len(iRunes) < len(jRunes) } + +func stringSliceEqual(a, b []string) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + if len(a) != len(b) { + return false + } + + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + + return true +} From b585cec123527052f7be768426db4e7066579cba Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 05:23:00 +0100 Subject: [PATCH 044/109] Add Basses to depOrder This should act exaclty like depCatagories.Basses --- depOrder.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/depOrder.go b/depOrder.go index acb00ad6..0ce10a31 100644 --- a/depOrder.go +++ b/depOrder.go @@ -14,8 +14,8 @@ import ( type depOrder struct { Aur []*rpc.Pkg Repo []*alpm.Package - Missing []string Runtime stringSet + Bases map[string][]*rpc.Pkg } func (do *depOrder) String() string { @@ -57,8 +57,8 @@ func makeDepOrder() *depOrder { return &depOrder{ make([]*rpc.Pkg, 0), make([]*alpm.Package, 0), - make([]string, 0), make(stringSet), + make(map[string][]*rpc.Pkg, 0), } } @@ -78,6 +78,8 @@ func getDepOrder(dp *depPool) *depOrder { } } + do.getBases() + return do } @@ -122,17 +124,12 @@ func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { }) } -func (do *depOrder) getMakeOnlyRepo() stringSet { - makeOnly := make(stringSet) - - for _, pkg := range do.Repo { - if !do.Runtime.get(pkg.Name()) { - makeOnly.set(pkg.Name()) +func (do *depOrder) getBases() { + for _, pkg := range do.Aur { + if _, ok := do.Bases[pkg.PackageBase]; !ok { + do.Bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) } + + do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg) } - - return makeOnly -} - -func (do *depOrder) checkMissing() { } From 2e7a022b7c92917cdb87dee484bca272a5a3be9f Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 05:41:04 +0100 Subject: [PATCH 045/109] Use new dependency code in install() The old depTree and depCatagories has been changed to depPool and depOrder in the install function. --- depOrder.go | 18 +++++++++++++ install.go | 73 +++++++++++++++++++++++------------------------------ print.go | 36 +++++++++++++------------- 3 files changed, 67 insertions(+), 60 deletions(-) diff --git a/depOrder.go b/depOrder.go index 0ce10a31..0a91756f 100644 --- a/depOrder.go +++ b/depOrder.go @@ -133,3 +133,21 @@ func (do *depOrder) getBases() { do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg) } } + +func (do *depOrder) HasMake() bool { + return len(do.Runtime) != len(do.Aur)+len(do.Repo) +} + +func (do *depOrder) getMake() []string { + makeOnly := make([]string, 0, len(do.Aur)+len(do.Repo)-len(do.Runtime)) + + for _, pkg := range do.Aur { + makeOnly = append(makeOnly, pkg.Name) + } + + for _, pkg := range do.Repo { + makeOnly = append(makeOnly, pkg.Name()) + } + + return makeOnly +} diff --git a/install.go b/install.go index af09391f..bd7381f9 100644 --- a/install.go +++ b/install.go @@ -18,7 +18,7 @@ func install(parser *arguments) error { requestTargets := parser.targets.toSlice() var err error var incompatible stringSet - var dc *depCatagories + var do *depOrder var toClean []*rpc.Pkg var toEdit []*rpc.Pkg @@ -61,7 +61,17 @@ func install(parser *arguments) error { //if len(aurTargets) > 0 || parser.existsArg("u", "sysupgrade") && len(remoteNames) > 0 { // fmt.Println(bold(cyan("::") + " Querying AUR...")) //} - dt, err := getDepTree(requestTargets, warnings) + dp, err := getDepPool(cmdArgs.targets.toSlice()) + if err != nil { + return err + } + + err = dp.CheckMissing() + if err != nil { + return err + } + + err = dp.CheckConflicts() if err != nil { return err } @@ -79,16 +89,6 @@ func install(parser *arguments) error { requestTargets[i] = name } - if len(dt.Missing) > 0 { - str := bold(red(arrow+" Error: ")) + "Could not find all required packages:" - - for name := range dt.Missing { - str += "\n " + name - } - - return fmt.Errorf("%s", str) - } - //create the arguments to pass for the repo install arguments := parser.copy() arguments.delArg("y", "refresh") @@ -131,61 +131,50 @@ func install(parser *arguments) error { } } - hasAur := false - for pkg := range parser.targets { - _, ok := dt.Aur[pkg] - if ok { - hasAur = true - } - } + hasAur := len(dp.Aur) > 0 if hasAur && 0 == os.Geteuid() { return fmt.Errorf(bold(red(arrow)) + " Refusing to install AUR Packages as root, Aborting.") } - dc, err = getDepCatagories(requestTargets, dt) + do = getDepOrder(dp) if err != nil { return err } - for _, pkg := range dc.Repo { + for _, pkg := range do.Repo { arguments.addTarget(pkg.DB().Name() + "/" + pkg.Name()) } - for pkg := range dt.Groups { + for _, pkg := range dp.Groups { arguments.addTarget(pkg) } - if len(dc.Aur) == 0 && len(arguments.targets) == 0 && !parser.existsArg("u", "sysupgrade") { + if len(do.Aur) == 0 && len(arguments.targets) == 0 && !parser.existsArg("u", "sysupgrade") { fmt.Println("There is nothing to do") return nil } if hasAur { - hasAur = len(dc.Aur) != 0 + hasAur = len(do.Aur) != 0 - err = checkForAllConflicts(dc) - if err != nil { - return err - } - - printDepCatagories(dc) + do.Print() fmt.Println() - if len(dc.MakeOnly) > 0 { + if do.HasMake() { if !continueTask("Remove make dependencies after install?", "yY") { removeMake = true } } - toClean, toEdit, err = cleanEditNumberMenu(dc.Aur, dc.Bases, remoteNamesCache) + toClean, toEdit, err = cleanEditNumberMenu(do.Aur, do.Bases, remoteNamesCache) if err != nil { return err } cleanBuilds(toClean) - err = downloadPkgBuilds(dc.Aur, parser.targets, dc.Bases) + err = downloadPkgBuilds(do.Aur, parser.targets, do.Bases) if err != nil { return err } @@ -205,17 +194,17 @@ func install(parser *arguments) error { } //initial srcinfo parse before pkgver() bump - err = parseSRCINFOFiles(dc.Aur, srcinfosStale, dc.Bases) + err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) if err != nil { return err } - incompatible, err = getIncompatible(dc.Aur, srcinfosStale, dc.Bases) + incompatible, err = getIncompatible(do.Aur, srcinfosStale, do.Bases) if err != nil { return err } - err = checkPgpKeys(dc.Aur, dc.Bases, srcinfosStale) + err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) if err != nil { return err } @@ -230,7 +219,7 @@ func install(parser *arguments) error { depArguments := makeArguments() depArguments.addArg("D", "asdeps") - for _, pkg := range dc.Repo { + for _, pkg := range do.Repo { if !parser.targets.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) { depArguments.addTarget(pkg.Name()) } @@ -250,17 +239,17 @@ func install(parser *arguments) error { uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg cmdArgs.globals["ask"] = fmt.Sprint(uask) - err = downloadPkgBuildsSources(dc.Aur, dc.Bases, incompatible) + err = downloadPkgBuildsSources(do.Aur, do.Bases, incompatible) if err != nil { return err } - err = buildInstallPkgBuilds(dc.Aur, srcinfosStale, parser.targets, parser, dc.Bases, incompatible) + err = buildInstallPkgBuilds(do.Aur, srcinfosStale, parser.targets, parser, do.Bases, incompatible) if err != nil { return err } - if len(dc.MakeOnly) > 0 { + if do.HasMake() { if !removeMake { return nil } @@ -268,7 +257,7 @@ func install(parser *arguments) error { removeArguments := makeArguments() removeArguments.addArg("R", "u") - for pkg := range dc.MakeOnly { + for _, pkg := range do.getMake() { removeArguments.addTarget(pkg) } @@ -283,7 +272,7 @@ func install(parser *arguments) error { } if config.CleanAfter { - clean(dc.Aur) + clean(do.Aur) } return nil diff --git a/print.go b/print.go index 5b7dd546..19a20db1 100644 --- a/print.go +++ b/print.go @@ -189,7 +189,7 @@ func (u upSlice) print() { } // printDownloadsFromRepo prints repository packages to be downloaded -func printDepCatagories(dc *depCatagories) { +func (do *depOrder) Print() { repo := "" repoMake := "" aur := "" @@ -200,47 +200,47 @@ func printDepCatagories(dc *depCatagories) { aurLen := 0 aurMakeLen := 0 - for _, pkg := range dc.Repo { - if dc.MakeOnly.get(pkg.Name()) { - repoMake += " " + pkg.Name() + "-" + pkg.Version() - repoMakeLen++ - } else { + for _, pkg := range do.Repo { + if do.Runtime.get(pkg.Name()) { repo += " " + pkg.Name() + "-" + pkg.Version() repoLen++ + } else { + repoMake += " " + pkg.Name() + "-" + pkg.Version() + repoMakeLen++ } } - for _, pkg := range dc.Aur { + for _, pkg := range do.Aur { pkgStr := " " + pkg.PackageBase + "-" + pkg.Version pkgStrMake := pkgStr push := false pushMake := false - if len(dc.Bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name { + if len(do.Bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name { pkgStr += " (" pkgStrMake += " (" - for _, split := range dc.Bases[pkg.PackageBase] { - if dc.MakeOnly.get(split.Name) { - pkgStrMake += split.Name + " " - aurMakeLen++ - pushMake = true - } else { + for _, split := range do.Bases[pkg.PackageBase] { + if do.Runtime.get(split.Name) { pkgStr += split.Name + " " aurLen++ push = true + } else { + pkgStrMake += split.Name + " " + aurMakeLen++ + pushMake = true } } pkgStr = pkgStr[:len(pkgStr)-1] + ")" pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")" - } else if dc.MakeOnly.get(pkg.Name) { - aurMakeLen++ - pushMake = true - } else { + } else if do.Runtime.get(pkg.Name) { aurLen++ push = true + } else { + aurMakeLen++ + pushMake = true } if push { From c019a2cc0240220c28927f0608334b51b2de4cd0 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 05:50:52 +0100 Subject: [PATCH 046/109] Remove old dependency code --- conflicts.go | 354 -------------------------- dep.go | 25 ++ dependencies.go | 650 ------------------------------------------------ 3 files changed, 25 insertions(+), 1004 deletions(-) delete mode 100644 conflicts.go delete mode 100644 dependencies.go diff --git a/conflicts.go b/conflicts.go deleted file mode 100644 index 9f03b945..00000000 --- a/conflicts.go +++ /dev/null @@ -1,354 +0,0 @@ -package main - -import ( - "fmt" - "strings" - "sync" - - alpm "github.com/jguer/go-alpm" - gopkg "github.com/mikkeloscar/gopkgbuild" -) - -// Checks a single conflict against every other to be installed package's -// name and its provides. -func checkInnerConflict(name string, conflict string, conflicts mapStringSet, dc *depCatagories) { - deps, err := gopkg.ParseDeps([]string{conflict}) - if err != nil { - return - } - dep := deps[0] - - for _, pkg := range dc.Aur { - if name == pkg.Name { - continue - } - - version, err := gopkg.NewCompleteVersion(pkg.Version) - if err != nil { - return - } - if dep.Name == pkg.Name && version.Satisfies(dep) { - conflicts.Add(name, pkg.Name) - continue - } - - for _, provide := range pkg.Provides { - // Provides are not versioned unless explicitly defined as - // such. If a conflict is versioned but a provide is - // not it can not conflict. - if (dep.MaxVer != nil || dep.MinVer != nil) && !strings.ContainsAny(provide, "><=") { - continue - } - - var version *gopkg.CompleteVersion - var err error - - pname, pversion := splitNameFromDep(provide) - - if dep.Name != pname { - continue - } - - if pversion != "" { - version, err = gopkg.NewCompleteVersion(provide) - if err != nil { - return - } - } - - if version != nil && version.Satisfies(dep) { - conflicts.Add(name, pkg.Name) - break - } - - } - } - - for _, pkg := range dc.Repo { - if name == pkg.Name() { - continue - } - - version, err := gopkg.NewCompleteVersion(pkg.Version()) - if err != nil { - return - } - - if dep.Name == pkg.Name() && version.Satisfies(dep) { - conflicts.Add(name, pkg.Name()) - continue - } - - pkg.Provides().ForEach(func(provide alpm.Depend) error { - // Provides are not versioned unless explicitly defined as - // such. If a conflict is versioned but a provide is - // not it can not conflict. - if (dep.MaxVer != nil || dep.MinVer != nil) && provide.Mod == alpm.DepModAny { - return nil - } - - if dep.Name != pkg.Name() { - return nil - } - - if provide.Mod == alpm.DepModAny { - conflicts.Add(name, pkg.Name()) - return fmt.Errorf("") - } - - version, err := gopkg.NewCompleteVersion(provide.Version) - if err != nil { - return nil - } - - if version.Satisfies(dep) { - conflicts.Add(name, pkg.Name()) - return fmt.Errorf("") - } - - return nil - }) - } -} - -// Checks every to be installed package's conflicts against every other to be -// installed package and its provides. -func checkForInnerConflicts(dc *depCatagories) mapStringSet { - conflicts := make(mapStringSet) - - for _, pkg := range dc.Aur { - for _, cpkg := range pkg.Conflicts { - checkInnerConflict(pkg.Name, cpkg, conflicts, dc) - } - } - - for _, pkg := range dc.Repo { - pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { - checkInnerConflict(pkg.Name(), conflict.String(), conflicts, dc) - return nil - }) - } - - return conflicts -} - -// Checks a provide or packagename from a to be installed package -// against every already installed package's conflicts -func checkReverseConflict(name string, provide string, conflicts mapStringSet) error { - var version *gopkg.CompleteVersion - var err error - - localDb, err := alpmHandle.LocalDb() - if err != nil { - return err - } - - pname, pversion := splitNameFromDep(provide) - if pversion != "" { - version, err = gopkg.NewCompleteVersion(pversion) - if err != nil { - return nil - } - } - - localDb.PkgCache().ForEach(func(pkg alpm.Package) error { - if name == pkg.Name() { - return nil - } - - pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { - deps, err := gopkg.ParseDeps([]string{conflict.String()}) - if err != nil { - return nil - } - - dep := deps[0] - // Provides are not versioned unless explicitly defined as - // such. If a conflict is versioned but a provide is - // not it can not conflict. - if (dep.MaxVer != nil || dep.MinVer != nil) && version == nil { - return nil - } - - if dep.Name != pname { - return nil - } - - if version == nil || version.Satisfies(dep) { - // Todo - conflicts.Add(name, pkg.Name()+" ("+provide+")") - return fmt.Errorf("") - } - - return nil - }) - - return nil - }) - - return nil -} - -// Checks the conflict of a to be installed package against the package name and -// provides of every installed package. -func checkConflict(name string, conflict string, conflicts mapStringSet) error { - localDb, err := alpmHandle.LocalDb() - if err != nil { - return err - } - - deps, err := gopkg.ParseDeps([]string{conflict}) - if err != nil { - return nil - } - - dep := deps[0] - - localDb.PkgCache().ForEach(func(pkg alpm.Package) error { - if name == pkg.Name() { - return nil - } - - version, err := gopkg.NewCompleteVersion(pkg.Version()) - if err != nil { - return nil - } - - if dep.Name == pkg.Name() && version.Satisfies(dep) { - conflicts.Add(name, pkg.Name()) - return nil - } - - pkg.Provides().ForEach(func(provide alpm.Depend) error { - if dep.Name != provide.Name { - return nil - } - - // Provides aren't version unless explicitly defined as - // such. If a conflict is versioned but a provide is - // not it can not conflict. - if (dep.MaxVer != nil || dep.MinVer != nil) && provide.Mod == alpm.DepModAny { - return nil - } - - if provide.Mod == alpm.DepModAny { - conflicts.Add(name, pkg.Name()+" ("+provide.Name+")") - return fmt.Errorf("") - } - - version, err := gopkg.NewCompleteVersion(provide.Version) - if err != nil { - return nil - } - - if version.Satisfies(dep) { - conflicts.Add(name, pkg.Name()+" ("+provide.Name+")") - return fmt.Errorf("") - } - - return nil - }) - - return nil - }) - - return nil -} - -// Checks every to be installed package's conflicts against the names and -// provides of every already installed package and checks every to be installed -// package's name and provides against every already installed package. -func checkForConflicts(dc *depCatagories) (mapStringSet, error) { - conflicts := make(mapStringSet) - - for _, pkg := range dc.Aur { - for _, cpkg := range pkg.Conflicts { - checkConflict(pkg.Name, cpkg, conflicts) - } - } - - for _, pkg := range dc.Repo { - pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { - checkConflict(pkg.Name(), conflict.String(), conflicts) - return nil - }) - } - - for _, pkg := range dc.Aur { - checkReverseConflict(pkg.Name, pkg.Name, conflicts) - for _, ppkg := range pkg.Provides { - checkReverseConflict(pkg.Name, ppkg, conflicts) - } - } - - for _, pkg := range dc.Repo { - checkReverseConflict(pkg.Name(), pkg.Name(), conflicts) - pkg.Provides().ForEach(func(provide alpm.Depend) error { - checkReverseConflict(pkg.Name(), provide.String(), conflicts) - return nil - }) - } - - return conflicts, nil -} - -// Combiles checkForConflicts() and checkForInnerConflicts() in parallel and -// does some printing. -func checkForAllConflicts(dc *depCatagories) error { - var err error - var conflicts mapStringSet - var innerConflicts mapStringSet - var wg sync.WaitGroup - wg.Add(2) - - fmt.Println(bold(cyan("::") + bold(" Checking for conflicts..."))) - go func() { - conflicts, err = checkForConflicts(dc) - wg.Done() - }() - - fmt.Println(bold(cyan("::") + bold(" Checking for inner conflicts..."))) - go func() { - innerConflicts = checkForInnerConflicts(dc) - wg.Done() - }() - - wg.Wait() - - if err != nil { - return err - } - - if len(innerConflicts) != 0 { - fmt.Println() - fmt.Println(bold(red(arrow)), bold("Inner conflicts found:")) - - for name, pkgs := range innerConflicts { - str := red(bold(smallArrow)) + " " + name + ":" - for pkg := range pkgs { - str += " " + cyan(pkg) - } - - fmt.Println(str) - } - - return fmt.Errorf("Unresolvable package conflicts, aborting") - } - - if len(conflicts) != 0 { - fmt.Println() - fmt.Println(bold(red(arrow)), bold("Package conflicts found:")) - for name, pkgs := range conflicts { - str := red(bold(smallArrow)) + " Installing " + cyan(name) + " will remove:" - for pkg := range pkgs { - str += " " + cyan(pkg) - } - - fmt.Println(str) - } - - fmt.Println() - } - - return nil -} diff --git a/dep.go b/dep.go index 2958ef71..e604c3f1 100644 --- a/dep.go +++ b/dep.go @@ -102,3 +102,28 @@ func satisfiesRepo(dep string, pkg *alpm.Package) bool { return false } + +//split apart db/package to db and package +func splitDbFromName(pkg string) (string, string) { + split := strings.SplitN(pkg, "/", 2) + + if len(split) == 2 { + return split[0], split[1] + } + return "", split[0] +} + +func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { + bases := make(map[string][]*rpc.Pkg) + + for _, pkg := range pkgs { + _, ok := bases[pkg.PackageBase] + if !ok { + bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) + } + bases[pkg.PackageBase] = append(bases[pkg.PackageBase], pkg) + } + + return bases +} + diff --git a/dependencies.go b/dependencies.go deleted file mode 100644 index b795673b..00000000 --- a/dependencies.go +++ /dev/null @@ -1,650 +0,0 @@ -package main - -import ( - "fmt" - "strings" - - alpm "github.com/jguer/go-alpm" - rpc "github.com/mikkeloscar/aur" - gopkg "github.com/mikkeloscar/gopkgbuild" -) - -type depTree struct { - ToProcess stringSet - Repo map[string]*alpm.Package - Aur map[string]*rpc.Pkg - Missing stringSet - Groups stringSet - Provides map[string]string - Warnings *aurWarnings -} - -type depCatagories struct { - Repo []*alpm.Package - Aur []*rpc.Pkg - MakeOnly stringSet - Bases map[string][]*rpc.Pkg -} - -func makeDepTree() *depTree { - dt := depTree{ - make(stringSet), - make(map[string]*alpm.Package), - make(map[string]*rpc.Pkg), - make(stringSet), - make(stringSet), - make(map[string]string), - &aurWarnings{}, - } - - return &dt -} - -func makeDependCatagories() *depCatagories { - dc := depCatagories{ - make([]*alpm.Package, 0), - make([]*rpc.Pkg, 0), - make(stringSet), - make(map[string][]*rpc.Pkg), - } - - return &dc -} - -// Cut the version requirement from a dependency leaving just the name. -func splitNameFromDep(dep string) (string, string) { - split := strings.FieldsFunc(dep, func(c rune) bool { - return c == '>' || c == '<' || c == '=' - }) - - if len(split) == 1 { - return split[0], "" - } - - return split[0], split[1] -} - -//split apart db/package to db and package -func splitDbFromName(pkg string) (string, string) { - split := strings.SplitN(pkg, "/", 2) - - if len(split) == 2 { - return split[0], split[1] - } - return "", split[0] -} - -func isDevelName(name string) bool { - for _, suffix := range []string{"git", "svn", "hg", "bzr", "nightly"} { - if strings.HasSuffix(name, suffix) { - return true - } - } - - return strings.Contains(name, "-always-") -} - -func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { - bases := make(map[string][]*rpc.Pkg) - -nextpkg: - for _, pkg := range pkgs { - for _, base := range bases[pkg.PackageBase] { - if base == pkg { - continue nextpkg - } - } - - _, ok := bases[pkg.PackageBase] - if !ok { - bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) - } - bases[pkg.PackageBase] = append(bases[pkg.PackageBase], pkg) - } - - return bases -} - -func aurFindProvider(name string, dt *depTree) (string, *rpc.Pkg) { - dep, _ := splitNameFromDep(name) - aurpkg, exists := dt.Aur[dep] - - if exists { - return dep, aurpkg - } - - dep, exists = dt.Provides[dep] - if exists { - aurpkg, exists = dt.Aur[dep] - if exists { - return dep, aurpkg - } - } - - return "", nil - -} - -func repoFindProvider(name string, dt *depTree) (string, *alpm.Package) { - dep, _ := splitNameFromDep(name) - alpmpkg, exists := dt.Repo[dep] - - if exists { - return dep, alpmpkg - } - - dep, exists = dt.Provides[dep] - if exists { - alpmpkg, exists = dt.Repo[dep] - if exists { - return dep, alpmpkg - } - } - - return "", nil - -} - -// Step two of dependency resolving. We already have all the information on the -// packages we need, now it's just about ordering them correctly. -// pkgs is a list of targets, the packages we want to install. Dependencies are -// not included. -// For each package we want we iterate down the tree until we hit the bottom. -// This is done recursively for each branch. -// The start of the tree is defined as the package we want. -// When we hit the bottom of the branch we know thats the first package -// we need to install so we add it to the start of the to install -// list (dc.Aur and dc.Repo). -// We work our way up until there is another branch to go down and do it all -// again. -// -// Here is a visual example: -// -// a -// / \ -// b c -// / \ -// d e -// -// We see a and it needs b and c -// We see b and it needs d and e -// We see d - it needs nothing so we add d to our list and move up -// We see e - it needs nothing so we add e to our list and move up -// We see c - it needs nothing so we add c to our list and move up -// -// The final install order would come out as debca -// -// There is a little more to this, handling provides, multiple packages wanting the -// same dependencies, etc. This is just the basic premise. -func getDepCatagories(pkgs []string, dt *depTree) (*depCatagories, error) { - dc := makeDependCatagories() - seen := make(stringSet) - - dc.Bases = getBases(dt.Aur) - - for _, pkg := range pkgs { - dep, alpmpkg := repoFindProvider(pkg, dt) - if alpmpkg != nil { - repoDepCatagoriesRecursive(alpmpkg, dc, dt, false) - dc.Repo = append(dc.Repo, alpmpkg) - delete(dt.Repo, dep) - } - - dep, aurpkg := aurFindProvider(pkg, dt) - if aurpkg != nil { - depCatagoriesRecursive(aurpkg, dc, dt, false, seen) - if !seen.get(aurpkg.PackageBase) { - dc.Aur = append(dc.Aur, aurpkg) - seen.set(aurpkg.PackageBase) - } - - delete(dt.Aur, dep) - } - } - - for _, base := range dc.Bases { - for _, pkg := range base { - for _, dep := range pkg.Depends { - dc.MakeOnly.remove(dep) - } - } - } - - for _, pkg := range dc.Repo { - pkg.Depends().ForEach(func(_dep alpm.Depend) error { - dep := _dep.Name - dc.MakeOnly.remove(dep) - - return nil - }) - } - - for _, pkg := range pkgs { - dc.MakeOnly.remove(pkg) - } - - dupes := make(map[*alpm.Package]struct{}) - filteredRepo := make([]*alpm.Package, 0) - - for _, pkg := range dc.Repo { - _, ok := dupes[pkg] - if ok { - continue - } - dupes[pkg] = struct{}{} - filteredRepo = append(filteredRepo, pkg) - } - - dc.Repo = filteredRepo - - return dc, nil -} - -func repoDepCatagoriesRecursive(pkg *alpm.Package, dc *depCatagories, dt *depTree, isMake bool) { - pkg.Depends().ForEach(func(_dep alpm.Depend) error { - dep, alpmpkg := repoFindProvider(_dep.Name, dt) - if alpmpkg != nil { - delete(dt.Repo, dep) - repoDepCatagoriesRecursive(alpmpkg, dc, dt, isMake) - - if isMake { - dc.MakeOnly.set(alpmpkg.Name()) - } - - dc.Repo = append(dc.Repo, alpmpkg) - } - - return nil - }) -} - -func depCatagoriesRecursive(_pkg *rpc.Pkg, dc *depCatagories, dt *depTree, isMake bool, seen stringSet) { - for _, pkg := range dc.Bases[_pkg.PackageBase] { - for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { - for _, pkg := range deps { - dep, aurpkg := aurFindProvider(pkg, dt) - if aurpkg != nil { - delete(dt.Aur, dep) - depCatagoriesRecursive(aurpkg, dc, dt, isMake, seen) - - if !seen.get(aurpkg.PackageBase) { - dc.Aur = append(dc.Aur, aurpkg) - seen.set(aurpkg.PackageBase) - } - - if isMake { - dc.MakeOnly.set(aurpkg.Name) - } - } - - dep, alpmpkg := repoFindProvider(pkg, dt) - if alpmpkg != nil { - delete(dt.Repo, dep) - repoDepCatagoriesRecursive(alpmpkg, dc, dt, isMake) - - if isMake { - dc.MakeOnly.set(alpmpkg.Name()) - } - - dc.Repo = append(dc.Repo, alpmpkg) - } - - } - isMake = true - } - } -} - -// This is step one for dependency resolving. pkgs is a slice of the packages you -// want to resolve the dependencies for. They can be a mix of aur and repo -// dependencies. All unmet dependencies will be resolved. -// -// For Aur dependencies depends, makedepends and checkdepends are resolved but -// for repo packages only depends are resolved as they are prebuilt. -// The return will be split into three categories: Repo, Aur and Missing. -// The return is in no way ordered. This step is is just aimed at gathering the -// packages we need. -// -// This has been designed to make the least amount of rpc requests as possible. -// Web requests are probably going to be the bottleneck here so minimizing them -// provides a nice speed boost. -// -// Here is a visual expample of the request system. -// Remember only unsatisfied packages are requested, if a package is already -// installed we don't bother. -// -// a -// / \ -// b c -// / \ -// d e -// -// We see a so we send a request for a -// We see a wants b and c so we send a request for b and c -// We see d and e so we send a request for d and e -// -// That's 5 packages in 3 requests. The amount of requests needed should always be -// the same as the height of the tree. -// The example does not really do this justice, In the real world where packages -// have 10+ dependencies each this is a very nice optimization. -func getDepTree(pkgs []string, warnings *aurWarnings) (*depTree, error) { - dt := makeDepTree() - dt.Warnings = warnings - - localDb, err := alpmHandle.LocalDb() - if err != nil { - return dt, err - } - syncDb, err := alpmHandle.SyncDbs() - if err != nil { - return dt, err - } - - for _, pkg := range pkgs { - db, name := splitDbFromName(pkg) - var foundPkg *alpm.Package - var singleDb *alpm.Db - - if db == "aur" { - dt.ToProcess.set(name) - continue - } - - // Check the repos for a matching dep - if db != "" { - singleDb, err = alpmHandle.SyncDbByName(db) - if err != nil { - return dt, err - } - foundPkg, err = singleDb.PkgCache().FindSatisfier(name) - } else { - foundPkg, err = syncDb.FindSatisfier(name) - } - - if err == nil { - repoTreeRecursive(foundPkg, dt, localDb, syncDb) - continue - } else { - //would be better to check the groups from singleDb if - //the user specified a db but there's no easy way to do - //it without making alpm_lists so don't bother for now - //db/group is probably a rare use case - _, err := syncDb.PkgCachebyGroup(name) - - if err == nil { - dt.Groups.set(pkg) - continue - } - } - - if db == "" { - dt.ToProcess.set(name) - } else { - dt.Missing.set(pkg) - } - } - - if len(dt.ToProcess) > 0 { - fmt.Println(bold(cyan("::") + bold(" Querying AUR..."))) - } - - err = depTreeRecursive(dt, localDb, syncDb, false) - if err != nil { - return dt, err - } - - if !cmdArgs.existsArg("d", "nodeps") { - err = checkVersions(dt) - } - - dt.Warnings.print() - - return dt, err -} - -// Takes a repo package, -// gives all of the non installed deps, -// repeats 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 - } - - _, exists = dt.Provides[pkg.Name()] - if exists { - return - } - - dt.Repo[pkg.Name()] = pkg - (*pkg).Provides().ForEach(func(dep alpm.Depend) (err error) { - dt.Provides[dep.Name] = pkg.Name() - 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) { - if len(dt.ToProcess) == 0 { - return - } - - nextProcess := make(stringSet) - currentProcess := make(stringSet) - // Strip version conditions - for _dep := range dt.ToProcess { - dep, _ := splitNameFromDep(_dep) - currentProcess.set(dep) - } - - // Assume toprocess only contains aur stuff we have not seen - info, err := aurInfo(currentProcess.toSlice(), dt.Warnings) - - if err != nil { - return - } - - // Cache the results - for _, pkg := range info { - dt.Aur[pkg.Name] = pkg - - for _, provide := range pkg.Provides { - name, _ := splitNameFromDep(provide) - dt.Provides[name] = pkg.Name - } - } - - // Loop through to process and check if we now have - // each packaged cached. - // If not cached, we assume it is missing. - for pkgName := range currentProcess { - pkg, exists := dt.Aur[pkgName] - - // Did not get it in the request. - if !exists { - dt.Missing.set(pkgName) - continue - } - - // for each dep and makedep - for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { - for _, versionedDep := range deps { - dep, _ := splitNameFromDep(versionedDep) - - _, exists = dt.Aur[dep] - // We have it cached so skip. - if exists { - continue - } - - _, exists = dt.Provides[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 && config.ReBuild != "tree" { - continue - } - - // Check the repos for a matching dep. - repoPkg, inRepos := syncDb.FindSatisfier(versionedDep) - if inRepos == nil { - if isInstalled == nil && config.ReBuild == "tree" { - continue - } - - repoTreeRecursive(repoPkg, dt, localDb, syncDb) - continue - } - - // If all else fails add it to next search. - nextProcess.set(versionedDep) - } - } - } - - dt.ToProcess = nextProcess - depTreeRecursive(dt, localDb, syncDb, true) - - return -} - -func checkVersions(dt *depTree) error { - has := make(mapStringSlice) - allDeps := make([]*gopkg.Dependency, 0) - - localDb, err := alpmHandle.LocalDb() - if err != nil { - return err - } - - for _, pkg := range dt.Aur { - for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { - for _, dep := range deps { - _, _dep := splitNameFromDep(dep) - if _dep != "" { - deps, _ := gopkg.ParseDeps([]string{dep}) - if deps[0] != nil { - allDeps = append(allDeps, deps[0]) - } - } - } - } - - has.Add(pkg.Name, pkg.Version) - - if !isDevelName(pkg.Name) { - for _, name := range pkg.Provides { - _name, _ver := splitNameFromDep(name) - if _ver != "" { - has.Add(_name, _ver) - } else { - delete(has, _name) - } - } - } - } - - for _, pkg := range dt.Repo { - pkg.Depends().ForEach(func(dep alpm.Depend) error { - if dep.Mod != alpm.DepModAny { - deps, _ := gopkg.ParseDeps([]string{dep.String()}) - if deps[0] != nil { - allDeps = append(allDeps, deps[0]) - } - } - return nil - }) - - has.Add(pkg.Name(), pkg.Version()) - - pkg.Provides().ForEach(func(dep alpm.Depend) error { - if dep.Mod != alpm.DepModAny { - has.Add(dep.Name, dep.Version) - } else { - delete(has, dep.Name) - } - - return nil - }) - - } - - localDb.PkgCache().ForEach(func(pkg alpm.Package) error { - pkg.Provides().ForEach(func(dep alpm.Depend) error { - if dep.Mod != alpm.DepModAny { - has.Add(dep.Name, dep.Version) - } else { - delete(has, dep.Name) - } - - return nil - }) - - return nil - }) - - for _, dep := range allDeps { - satisfied := false - verStrs, ok := has[dep.Name] - if !ok { - continue - } - - for _, verStr := range verStrs { - version, err := gopkg.NewCompleteVersion(verStr) - if err != nil { - return err - } - - if version.Satisfies(dep) { - satisfied = true - break - } - } - - if !satisfied { - dt.Missing.set(dep.String()) - } - } - - return nil -} From 671f836ec5aecc454aa11b5fac5591d2ceb8ca25 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 19:42:19 +0100 Subject: [PATCH 047/109] Calculate makeDeps properly MakeOnly would be set to true when moving from normal deps to make deps But would incorrectly stay set to true when moving to the deps of the following packages. depOrder.Aur now only holds one package from each base like depCatagories does. --- dep.go | 1 - depOrder.go | 36 +++++++++++++++++++++++++----------- install.go | 6 +----- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/dep.go b/dep.go index e604c3f1..c921c0da 100644 --- a/dep.go +++ b/dep.go @@ -126,4 +126,3 @@ func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { return bases } - diff --git a/depOrder.go b/depOrder.go index 0a91756f..8c0cffda 100644 --- a/depOrder.go +++ b/depOrder.go @@ -78,7 +78,7 @@ func getDepOrder(dp *depPool) *depOrder { } } - do.getBases() + //do.getBases() return do } @@ -87,22 +87,25 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { if runtime { do.Runtime.set(pkg.Name) } - do.Aur = append(do.Aur, pkg) + if _, ok := do.Bases[pkg.PackageBase]; !ok { + do.Aur = append(do.Aur, pkg) + do.Bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) + } + do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg) + delete(dp.Aur, pkg.Name) - for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { + for i, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { for _, dep := range deps { aurPkg := dp.findSatisfierAur(dep) if aurPkg != nil { - do.orderPkgAur(aurPkg, dp, runtime) + do.orderPkgAur(aurPkg, dp, runtime && i == 0) } repoPkg := dp.findSatisfierRepo(dep) if repoPkg != nil { - do.orderPkgRepo(repoPkg, dp, runtime) + do.orderPkgRepo(repoPkg, dp, runtime && i == 0) } - - runtime = false } } } @@ -135,18 +138,29 @@ func (do *depOrder) getBases() { } func (do *depOrder) HasMake() bool { - return len(do.Runtime) != len(do.Aur)+len(do.Repo) + lenAur := 0 + for _, base := range do.Bases { + lenAur += len(base) + } + + return len(do.Runtime) != lenAur+len(do.Repo) } func (do *depOrder) getMake() []string { makeOnly := make([]string, 0, len(do.Aur)+len(do.Repo)-len(do.Runtime)) - for _, pkg := range do.Aur { - makeOnly = append(makeOnly, pkg.Name) + for _, base := range do.Bases { + for _, pkg := range base { + if !do.Runtime.get(pkg.Name) { + makeOnly = append(makeOnly, pkg.Name) + } + } } for _, pkg := range do.Repo { - makeOnly = append(makeOnly, pkg.Name()) + if !do.Runtime.get(pkg.Name()) { + makeOnly = append(makeOnly, pkg.Name()) + } } return makeOnly diff --git a/install.go b/install.go index bd7381f9..6ada45af 100644 --- a/install.go +++ b/install.go @@ -249,11 +249,7 @@ func install(parser *arguments) error { return err } - if do.HasMake() { - if !removeMake { - return nil - } - + if removeMake { removeArguments := makeArguments() removeArguments.addArg("R", "u") From 8c77ad061e65cae1a8ef36b62e95922fc770657c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 19:53:03 +0100 Subject: [PATCH 048/109] Clean up unused code --- depOrder.go | 55 +---------------------------------------------------- depPool.go | 45 ++----------------------------------------- utils.go | 9 --------- 3 files changed, 3 insertions(+), 106 deletions(-) diff --git a/depOrder.go b/depOrder.go index 8c0cffda..6fccbafd 100644 --- a/depOrder.go +++ b/depOrder.go @@ -1,14 +1,8 @@ package main import ( - // "fmt" - "strconv" - // "strings" - // "sync" - alpm "github.com/jguer/go-alpm" rpc "github.com/mikkeloscar/aur" - //gopkg "github.com/mikkeloscar/gopkgbuild" ) type depOrder struct { @@ -18,47 +12,12 @@ type depOrder struct { Bases map[string][]*rpc.Pkg } -func (do *depOrder) String() string { - str := "" - str += "\n" + red("Repo") + " (" + strconv.Itoa(len(do.Repo)) + ") :" - for _, pkg := range do.Repo { - if do.Runtime.get(pkg.Name()) { - str += " " + pkg.Name() - } - } - - str += "\n" + red("Aur") + " (" + strconv.Itoa(len(do.Aur)) + ") :" - for _, pkg := range do.Aur { - if do.Runtime.get(pkg.Name) { - str += " " + pkg.Name - } - - } - - str += "\n" + red("Repo Make") + " (" + strconv.Itoa(len(do.Repo)) + ") :" - for _, pkg := range do.Repo { - if !do.Runtime.get(pkg.Name()) { - str += " " + pkg.Name() - } - } - - str += "\n" + red("Aur Make") + " (" + strconv.Itoa(len(do.Aur)) + ") :" - for _, pkg := range do.Aur { - if !do.Runtime.get(pkg.Name) { - str += " " + pkg.Name - } - - } - - return str -} - func makeDepOrder() *depOrder { return &depOrder{ make([]*rpc.Pkg, 0), make([]*alpm.Package, 0), make(stringSet), - make(map[string][]*rpc.Pkg, 0), + make(map[string][]*rpc.Pkg), } } @@ -78,8 +37,6 @@ func getDepOrder(dp *depPool) *depOrder { } } - //do.getBases() - return do } @@ -127,16 +84,6 @@ func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { }) } -func (do *depOrder) getBases() { - for _, pkg := range do.Aur { - if _, ok := do.Bases[pkg.PackageBase]; !ok { - do.Bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) - } - - do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg) - } -} - func (do *depOrder) HasMake() bool { lenAur := 0 for _, base := range do.Bases { diff --git a/depPool.go b/depPool.go index db6442f7..b520b05c 100644 --- a/depPool.go +++ b/depPool.go @@ -2,13 +2,11 @@ package main import ( "fmt" - "strconv" "strings" "sync" alpm "github.com/jguer/go-alpm" rpc "github.com/mikkeloscar/aur" - //gopkg "github.com/mikkeloscar/gopkgbuild" ) const PROVIDES = false @@ -79,36 +77,6 @@ func makeDepPool() (*depPool, error) { return dp, nil } -func (dp *depPool) String() string { - str := "" - str += "\n" + red("Targets") + " (" + strconv.Itoa(len(dp.Targets)) + ") :" - for _, pkg := range dp.Targets { - str += " " + pkg.String() - } - - str += "\n" + red("Repo") + " (" + strconv.Itoa(len(dp.Repo)) + ") :" - for pkg := range dp.Repo { - str += " " + pkg - } - - str += "\n" + red("Aur") + " (" + strconv.Itoa(len(dp.Aur)) + ") :" - for pkg := range dp.Aur { - str += " " + pkg - } - - str += "\n" + red("Aur Cache") + " (" + strconv.Itoa(len(dp.AurCache)) + ") :" - for pkg := range dp.AurCache { - str += " " + pkg - } - - str += "\n" + red("Groups") + " (" + strconv.Itoa(len(dp.Groups)) + ") :" - for _, pkg := range dp.Groups { - str += " " + pkg - } - - return str -} - // Includes db/ prefixes and group installs func (dp *depPool) ResolveTargets(pkgs []string) error { for _, pkg := range pkgs { @@ -185,7 +153,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { err = dp.resolveAURPackages(aurTargets) } - return nil + return err } // Pseudo provides finder. @@ -375,16 +343,6 @@ func (dp *depPool) ResolveRepoDependency(pkg *alpm.Package) { return nil }) - -} - -func (dp *depPool) queryAUR(pkgs []string) error { - _, err := aurInfo(pkgs, dp.Warnings) - if err != nil { - return err - } - - return nil } func getDepPool(pkgs []string) (*depPool, error) { @@ -475,3 +433,4 @@ func (dp *depPool) hasPackage(name string) bool { return false } + diff --git a/utils.go b/utils.go index 260b2769..f1760677 100644 --- a/utils.go +++ b/utils.go @@ -7,7 +7,6 @@ import ( "unicode" ) -type mapStringSlice map[string][]string type mapStringSet map[string]stringSet type intRange struct { @@ -60,14 +59,6 @@ func (mss mapStringSet) Add(n string, v string) { mss[n].set(v) } -func (mss mapStringSlice) Add(n string, v string) { - _, ok := mss[n] - if !ok { - mss[n] = make([]string, 0, 1) - } - mss[n] = append(mss[n], v) -} - func completeFileName(dir, name string) (string, error) { files, err := ioutil.ReadDir(dir) if err != nil { From 7b558ba47ca5cfec42934bf5ca9ae232431d885e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 8 May 2018 22:54:28 +0100 Subject: [PATCH 049/109] Fix check for missing dependencies We dont check the dependencies of things already installed becuase, well, they're already installed. But we should check the dependencies of targets even if they are installed because they get reinstalled. --- depCheck.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/depCheck.go b/depCheck.go index de6a4635..47e762ff 100644 --- a/depCheck.go +++ b/depCheck.go @@ -183,11 +183,6 @@ type missing struct { } func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { - if _, err := dp.LocalDb.PkgCache().FindSatisfier(dep); err == nil { - missing.Good.set(dep) - return - } - if missing.Good.get(dep) { return } @@ -207,6 +202,11 @@ func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { missing.Good.set(dep) for _, deps := range [3][]string{aurPkg.Depends, aurPkg.MakeDepends, aurPkg.CheckDepends} { for _, aurDep := range deps { + if _, err := dp.LocalDb.PkgCache().FindSatisfier(aurDep); err == nil { + missing.Good.set(aurDep) + continue + } + dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing) } } @@ -218,6 +218,11 @@ func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) { if repoPkg != nil { missing.Good.set(dep) repoPkg.Depends().ForEach(func(repoDep alpm.Depend) error { + if _, err := dp.LocalDb.PkgCache().FindSatisfier(repoDep.String()); err == nil { + missing.Good.set(repoDep.String()) + return nil + } + dp._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing) return nil }) From 6423fb55b55b27dbb090e22f46621cc88effdf36 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 10 May 2018 01:50:19 +0100 Subject: [PATCH 050/109] Fix build order being reversed --- depOrder.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/depOrder.go b/depOrder.go index 6fccbafd..bb3a5273 100644 --- a/depOrder.go +++ b/depOrder.go @@ -26,7 +26,12 @@ func getDepOrder(dp *depPool) *depOrder { for _, target := range dp.Targets { dep := target.DepString() - aurPkg := dp.findSatisfierAur(dep) + aurPkg := dp.Aur[dep] + if aurPkg != nil && pkgSatisfies(aurPkg.Name, aurPkg.Version, dep) { + do.orderPkgAur(aurPkg, dp, true) + } + + aurPkg = dp.findSatisfierAur(dep) if aurPkg != nil { do.orderPkgAur(aurPkg, dp, true) } @@ -44,12 +49,6 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { if runtime { do.Runtime.set(pkg.Name) } - if _, ok := do.Bases[pkg.PackageBase]; !ok { - do.Aur = append(do.Aur, pkg) - do.Bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) - } - do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg) - delete(dp.Aur, pkg.Name) for i, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { @@ -65,13 +64,18 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { } } } + + if _, ok := do.Bases[pkg.PackageBase]; !ok { + do.Aur = append(do.Aur, pkg) + do.Bases[pkg.PackageBase] = make([]*rpc.Pkg, 0) + } + do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg) } func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { if runtime { do.Runtime.set(pkg.Name()) } - do.Repo = append(do.Repo, pkg) delete(dp.Repo, pkg.Name()) pkg.Depends().ForEach(func(dep alpm.Depend) (err error) { @@ -82,6 +86,8 @@ func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { return nil }) + + do.Repo = append(do.Repo, pkg) } func (do *depOrder) HasMake() bool { From b76d0854187b99f1d0e1140adabdf5657017dcfd Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 10 May 2018 02:22:21 +0100 Subject: [PATCH 051/109] Improve provider menu Sort the provider menu alphabetically. Always ensure direct matches show up first. This ensures hitting enter for the default value will always be the same package that the user/dependency requested if an exact match exists. If a package is already installed pick that instead of providing a menu. Ensure duplicates do not show up in the menu. --- dep.go | 32 +++++++++++++++++++++++++++ depPool.go | 63 ++++++++++++++++++++++++++++++++++++++++++++---------- install.go | 2 +- print.go | 10 ++++----- 4 files changed, 90 insertions(+), 17 deletions(-) diff --git a/dep.go b/dep.go index c921c0da..72795247 100644 --- a/dep.go +++ b/dep.go @@ -8,6 +8,38 @@ import ( rpc "github.com/mikkeloscar/aur" ) +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 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) (string, string, string) { mod := "" diff --git a/depPool.go b/depPool.go index b520b05c..2c19fdc9 100644 --- a/depPool.go +++ b/depPool.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "sort" "strings" "sync" @@ -9,7 +10,7 @@ import ( rpc "github.com/mikkeloscar/aur" ) -const PROVIDES = false +const PROVIDES = true type target struct { Db string @@ -98,7 +99,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { // still get skiped even if it's from a different database to // the one specified // this is how pacman behaves - if dp.hasSatisfier(target.DepString()) { + if dp.hasPackage(target.DepString()) { fmt.Println("Skipping target", target) continue } @@ -371,27 +372,68 @@ func (dp *depPool) findSatisfierAur(dep string) *rpc.Pkg { // Provide a pacman style provider menu if theres more than one candidate // TODO: maybe intermix repo providers in the menu func (dp *depPool) findSatisfierAurCache(dep string) *rpc.Pkg { - //try to match providers - providers := make([]*rpc.Pkg, 0) - for _, pkg := range dp.AurCache { - if pkgSatisfies(pkg.Name, pkg.Version, dep) { + depName, _, _ := splitDep(dep) + seen := make(stringSet) + providers := makeProviders(depName) + + if _, err := dp.LocalDb.PkgByName(depName); err == nil { + if pkg, ok := dp.AurCache[dep]; ok && pkgSatisfies(pkg.Name, pkg.Version, dep) { return pkg } } + //this version prioratizes name over provides + //if theres a direct match for a package return + //that instead of using the menu + // + //providers := make(rpcPkgs, 0) + //for _, pkg := range dp.AurCache { + // if pkgSatisfies(pkg.Name, pkg.Version, dep) { + // return pkg + // } + //} + + //for _, pkg := range dp.AurCache { + // for _, provide := range pkg.Provides { + // if provideSatisfies(provide, dep) { + // providers = append(providers, pkg) + // } + // } + //} + + // This version acts slightly differenly from Pacman, It will give + // a menu even if a package with a matching name exists. I believe this + // method is better because most of the time you are choosing between + // foo and foo-git. + // Using Pacman's ways trying to install foo would never give you + // a menu. + for _, pkg := range dp.AurCache { + if seen.get(pkg.Name) { + continue + } + + if pkgSatisfies(pkg.Name, pkg.Version, dep){ + providers.Pkgs = append(providers.Pkgs, pkg) + seen.set(pkg.Name) + continue + } + for _, provide := range pkg.Provides { if provideSatisfies(provide, dep) { - providers = append(providers, pkg) + providers.Pkgs = append(providers.Pkgs, pkg) + seen.set(pkg.Name) + continue } } } - if len(providers) == 1 { - return providers[0] + if providers.Len() == 1 { + return providers.Pkgs[0] } - if len(providers) > 1 { + if providers.Len() > 1 { + sort.Sort(providers) return providerMenu(dep, providers) } @@ -433,4 +475,3 @@ func (dp *depPool) hasPackage(name string) bool { return false } - diff --git a/install.go b/install.go index 6ada45af..f527aa53 100644 --- a/install.go +++ b/install.go @@ -61,7 +61,7 @@ func install(parser *arguments) error { //if len(aurTargets) > 0 || parser.existsArg("u", "sysupgrade") && len(remoteNames) > 0 { // fmt.Println(bold(cyan("::") + " Querying AUR...")) //} - dp, err := getDepPool(cmdArgs.targets.toSlice()) + dp, err := getDepPool(requestTargets) if err != nil { return err } diff --git a/print.go b/print.go index 19a20db1..87676091 100644 --- a/print.go +++ b/print.go @@ -568,8 +568,8 @@ func colourHash(name string) (output string) { return fmt.Sprintf("\x1b[%dm%s\x1b[0m", hash%6+31, name) } -func providerMenu(dep string, providers []*rpc.Pkg) *rpc.Pkg { - size := len(providers) +func providerMenu(dep string, providers providers) *rpc.Pkg { + size := providers.Len() fmt.Print(bold(cyan(":: "))) str := bold(fmt.Sprintf(bold("There are %d providers available for %s:"), size, dep)) @@ -577,7 +577,7 @@ func providerMenu(dep string, providers []*rpc.Pkg) *rpc.Pkg { size = 1 str += bold(cyan("\n:: ")) + bold("Repository AUR\n ") - for _, pkg := range providers { + for _, pkg := range providers.Pkgs { str += fmt.Sprintf("%d) %s ", size, pkg.Name) size++ } @@ -606,7 +606,7 @@ func providerMenu(dep string, providers []*rpc.Pkg) *rpc.Pkg { } if string(numberBuf) == "" { - return providers[0] + return providers.Pkgs[0] } num, err := strconv.Atoi(string(numberBuf)) @@ -620,7 +620,7 @@ func providerMenu(dep string, providers []*rpc.Pkg) *rpc.Pkg { continue } - return providers[num-1] + return providers.Pkgs[num-1] } return nil From d51205194ee3f8a74e3f209616aa0bd3fa1fb45f Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 10 May 2018 14:36:38 +0100 Subject: [PATCH 052/109] Support skiping updates and showing warnings The warnings were moved down to after the upgrade menu, mainly because it is a lot easier to do this way, it may get moved back if it can be done in a non hacky way, --- depPool.go | 9 ++++----- install.go | 48 +++++++++++++++++------------------------------- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/depPool.go b/depPool.go index 2c19fdc9..64bf815a 100644 --- a/depPool.go +++ b/depPool.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "sort" "strings" "sync" @@ -72,7 +71,7 @@ func makeDepPool() (*depPool, error) { make([]string, 0), localDb, syncDb, - &aurWarnings{}, + nil, } return dp, nil @@ -100,7 +99,6 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { // the one specified // this is how pacman behaves if dp.hasPackage(target.DepString()) { - fmt.Println("Skipping target", target) continue } @@ -346,12 +344,13 @@ func (dp *depPool) ResolveRepoDependency(pkg *alpm.Package) { }) } -func getDepPool(pkgs []string) (*depPool, error) { +func getDepPool(pkgs []string, warnings *aurWarnings) (*depPool, error) { dp, err := makeDepPool() if err != nil { return nil, err } + dp.Warnings = warnings err = dp.ResolveTargets(pkgs) return dp, err @@ -413,7 +412,7 @@ func (dp *depPool) findSatisfierAurCache(dep string) *rpc.Pkg { continue } - if pkgSatisfies(pkg.Name, pkg.Version, dep){ + if pkgSatisfies(pkg.Name, pkg.Version, dep) { providers.Pkgs = append(providers.Pkgs, pkg) seen.set(pkg.Name) continue diff --git a/install.go b/install.go index f527aa53..9fd505e4 100644 --- a/install.go +++ b/install.go @@ -58,37 +58,6 @@ func install(parser *arguments) error { } - //if len(aurTargets) > 0 || parser.existsArg("u", "sysupgrade") && len(remoteNames) > 0 { - // fmt.Println(bold(cyan("::") + " Querying AUR...")) - //} - dp, err := getDepPool(requestTargets) - if err != nil { - return err - } - - err = dp.CheckMissing() - if err != nil { - return err - } - - err = dp.CheckConflicts() - if err != nil { - return err - } - - // Deptree will handle db/pkg prefixes. Now they can be striped from the - // targets. - for pkg := range parser.targets { - _, name := splitDbFromName(pkg) - parser.targets.remove(pkg) - parser.targets.set(name) - } - - for i, pkg := range requestTargets { - _, name := splitDbFromName(pkg) - requestTargets[i] = name - } - //create the arguments to pass for the repo install arguments := parser.copy() arguments.delArg("y", "refresh") @@ -131,6 +100,23 @@ func install(parser *arguments) error { } } + dp, err := getDepPool(requestTargets, warnings) + if err != nil { + return err + } + + warnings.print() + + err = dp.CheckMissing() + if err != nil { + return err + } + + err = dp.CheckConflicts() + if err != nil { + return err + } + hasAur := len(dp.Aur) > 0 if hasAur && 0 == os.Geteuid() { From 6e990e4dc505c8fa9683d31dd98d6f325de45a48 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 19 May 2018 05:30:21 +0100 Subject: [PATCH 053/109] Don't conflict with pkgs that are in the depPool When upgrading multiple packages that are already installed we should not conflict with already installed packages that are in the depPool. This is because the version in the depTree is going to replace the currently installed version of the package and may have different conflicts. If there is a conflict between stuff in the depPool these should be handled by the innerConflicts check anyway. --- depCheck.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/depCheck.go b/depCheck.go index 47e762ff..9c14ed17 100644 --- a/depCheck.go +++ b/depCheck.go @@ -33,7 +33,7 @@ func (dp *depPool) checkInnerConflict(name string, conflict string, conflicts ma func (dp *depPool) checkForwardConflict(name string, conflict string, conflicts mapStringSet) { dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error { - if pkg.Name() == name { + if pkg.Name() == name || dp.hasPackage(pkg.Name()) { return nil } @@ -111,6 +111,10 @@ func (dp *depPool) checkForwardConflicts(conflicts mapStringSet) { func (dp *depPool) checkReverseConflicts(conflicts mapStringSet) { dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error { + if dp.hasPackage(pkg.Name()) { + return nil + } + pkg.Conflicts().ForEach(func(conflict alpm.Depend) error { dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts) return nil From 6df8c58e00a0969961e271beb216a50c5b9f2b7c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 19 May 2018 06:07:58 +0100 Subject: [PATCH 054/109] Re add isDevelName() --- dep.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dep.go b/dep.go index 72795247..3af9cb59 100644 --- a/dep.go +++ b/dep.go @@ -158,3 +158,13 @@ func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { return bases } + +func isDevelName(name string) bool { + for _, suffix := range []string{"git", "svn", "hg", "bzr", "nightly"} { + if strings.HasSuffix(name, "-" + suffix) { + return true + } + } + + return strings.Contains(name, "-always-") +} From 33d056e9ac32c6aada49c6ea63408efb908df775 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 29 May 2018 16:47:43 +0100 Subject: [PATCH 055/109] Split Targets to Targets and Explicit Targets are used for tracking wether a package should be marked as explicitly installed or as a dependency. This is not ideal because you can have a target such as java-environment that resolves to a different package. Therefore Targets are now used only for the initial dependency resolving and checking for missing dependencies. The Explicit set is now used to mark what packages are explicit, seperate from the targets. --- depPool.go | 12 +++++++++--- install.go | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/depPool.go b/depPool.go index 64bf815a..ad899ee2 100644 --- a/depPool.go +++ b/depPool.go @@ -44,6 +44,7 @@ func (t target) String() string { type depPool struct { Targets []target + Explicit stringSet Repo map[string]*alpm.Package Aur map[string]*rpc.Pkg AurCache map[string]*rpc.Pkg @@ -65,6 +66,7 @@ func makeDepPool() (*depPool, error) { dp := &depPool{ make([]target, 0), + make(stringSet), make(map[string]*alpm.Package), make(map[string]*rpc.Pkg), make(map[string]*rpc.Pkg), @@ -124,6 +126,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { } if err == nil { + dp.Explicit.set(foundPkg.Name()) dp.ResolveRepoDependency(foundPkg) continue } else { @@ -149,7 +152,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { } if len(aurTargets) > 0 { - err = dp.resolveAURPackages(aurTargets) + err = dp.resolveAURPackages(aurTargets, true) } return err @@ -255,7 +258,7 @@ func (dp *depPool) cacheAURPackages(_pkgs stringSet) error { return nil } -func (dp *depPool) resolveAURPackages(pkgs stringSet) error { +func (dp *depPool) resolveAURPackages(pkgs stringSet, explicit bool) error { newPackages := make(stringSet) newAURPackages := make(stringSet) @@ -279,6 +282,9 @@ func (dp *depPool) resolveAURPackages(pkgs stringSet) error { continue } + if explicit { + dp.Explicit.set(pkg.Name) + } dp.Aur[pkg.Name] = pkg for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} { @@ -312,7 +318,7 @@ func (dp *depPool) resolveAURPackages(pkgs stringSet) error { } - err = dp.resolveAURPackages(newAURPackages) + err = dp.resolveAURPackages(newAURPackages, false) return err } diff --git a/install.go b/install.go index 9fd505e4..810dc601 100644 --- a/install.go +++ b/install.go @@ -206,7 +206,7 @@ func install(parser *arguments) error { depArguments.addArg("D", "asdeps") for _, pkg := range do.Repo { - if !parser.targets.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) { + if !dp.Explicit.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) { depArguments.addTarget(pkg.Name()) } } @@ -230,7 +230,7 @@ func install(parser *arguments) error { return err } - err = buildInstallPkgBuilds(do.Aur, srcinfosStale, parser.targets, parser, do.Bases, incompatible) + err = buildInstallPkgBuilds(do.Aur, srcinfosStale, dp.Explicit, parser, do.Bases, incompatible) if err != nil { return err } From c464af6b9bee6f62e7f3d69614957690cbc11cee Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 29 May 2018 17:39:38 +0100 Subject: [PATCH 056/109] Implement config option for provider searching --- cmd.go | 4 ++++ config.go | 2 ++ depPool.go | 7 +------ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmd.go b/cmd.go index 26865c05..1441f3b5 100644 --- a/cmd.go +++ b/cmd.go @@ -296,6 +296,10 @@ func handleConfig(option, value string) bool { config.SudoLoop = true case "nosudoloop": config.SudoLoop = false + case "provides": + config.Provides = true + case "noprovides": + config.Provides = false default: return false } diff --git a/config.go b/config.go index 00a9c8f4..105b397a 100644 --- a/config.go +++ b/config.go @@ -54,6 +54,7 @@ type Configuration struct { Devel bool `json:"devel"` CleanAfter bool `json:"cleanAfter"` GitClone bool `json:"gitclone"` + Provides bool `json:"provides"` } var version = "5.688" @@ -152,6 +153,7 @@ func defaultSettings(config *Configuration) { config.AnswerEdit = "" config.AnswerUpgrade = "" config.GitClone = true + config.Provides = true } // Editor returns the preferred system editor. diff --git a/depPool.go b/depPool.go index ad899ee2..0e082e6b 100644 --- a/depPool.go +++ b/depPool.go @@ -9,8 +9,6 @@ import ( rpc "github.com/mikkeloscar/aur" ) -const PROVIDES = true - type target struct { Db string Name string @@ -228,10 +226,7 @@ func (dp *depPool) cacheAURPackages(_pkgs stringSet) error { return nil } - //TODO: config option, maybe --deepsearh but aurman uses that flag for - //something else already which might be confusing - //maybe --provides - if PROVIDES { + if config.Provides { err := dp.findProvides(pkgs) if err != nil { return err From b140e66f6ad7f981b6c592ccd87c03bbe3d8dfc3 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 29 May 2018 22:35:58 +0100 Subject: [PATCH 057/109] Improve --asdeps and --asexplicit handling Correctly handle --asdeps and --asexplicit for both repo packages and aur packages. --- dep.go | 2 +- install.go | 54 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/dep.go b/dep.go index 3af9cb59..3328331f 100644 --- a/dep.go +++ b/dep.go @@ -161,7 +161,7 @@ func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { func isDevelName(name string) bool { for _, suffix := range []string{"git", "svn", "hg", "bzr", "nightly"} { - if strings.HasSuffix(name, "-" + suffix) { + if strings.HasSuffix(name, "-"+suffix) { return true } } diff --git a/install.go b/install.go index 810dc601..43aa2dcf 100644 --- a/install.go +++ b/install.go @@ -47,20 +47,13 @@ func install(parser *arguments) error { if err != nil { return err } - - for _, up := range aurUp { - requestTargets = append(requestTargets, "aur/"+up.Name) - } - - for _, up := range repoUp { - requestTargets = append(requestTargets, up.Name) - } - } //create the arguments to pass for the repo install arguments := parser.copy() arguments.delArg("y", "refresh") + arguments.delArg("asdeps", "asdep") + arguments.delArg("asexplicit", "asexp") arguments.op = "S" arguments.targets = make(stringSet) @@ -204,10 +197,19 @@ func install(parser *arguments) error { depArguments := makeArguments() depArguments.addArg("D", "asdeps") + expArguments := makeArguments() + expArguments.addArg("D", "asexplicit") for _, pkg := range do.Repo { if !dp.Explicit.get(pkg.Name()) && !localNamesCache.get(pkg.Name()) && !remoteNamesCache.get(pkg.Name()) { depArguments.addTarget(pkg.Name()) + continue + } + + if parser.existsArg("asdeps", "asdep") && dp.Explicit.get(pkg.Name()) { + depArguments.addTarget(pkg.Name()) + } else if parser.existsArg("asexp", "asexplicit") && dp.Explicit.get(pkg.Name()) { + expArguments.addTarget(pkg.Name()) } } @@ -217,6 +219,13 @@ func install(parser *arguments) error { return fmt.Errorf("%s%s", stderr, err) } } + + if len(expArguments.targets) > 0 { + _, stderr, err := passToPacmanCapture(expArguments) + if err != nil { + return fmt.Errorf("%s%s", stderr, err) + } + } } if hasAur { @@ -230,7 +239,7 @@ func install(parser *arguments) error { return err } - err = buildInstallPkgBuilds(do.Aur, srcinfosStale, dp.Explicit, parser, do.Bases, incompatible) + err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible) if err != nil { return err } @@ -565,13 +574,13 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco return } -func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, targets stringSet, parser *arguments, bases map[string][]*rpc.Pkg, incompatible stringSet) error { +func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg.PKGBUILD, parser *arguments, incompatible stringSet) error { arch, err := alpmHandle.Arch() if err != nil { return err } - for _, pkg := range pkgs { + for _, pkg := range do.Aur { dir := filepath.Join(config.BuildDir, pkg.PackageBase) built := true @@ -594,8 +603,8 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, return err } - if config.ReBuild == "no" || (config.ReBuild == "yes" && !targets.get(pkg.Name)) { - for _, split := range bases[pkg.PackageBase] { + if config.ReBuild == "no" || (config.ReBuild == "yes" && !dp.Explicit.get(pkg.Name)) { + for _, split := range do.Bases[pkg.PackageBase] { file, err := completeFileName(dir, split.Name+"-"+version+"-"+arch+".pkg") if err != nil { return err @@ -645,6 +654,8 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, depArguments := makeArguments() depArguments.addArg("D", "asdeps") + expArguments := makeArguments() + expArguments.addArg("D", "asexplicit") //remotenames: names of all non repo packages on the system _, _, localNames, remoteNames, err := filterPackages() @@ -657,7 +668,7 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, remoteNamesCache := sliceToStringSet(remoteNames) localNamesCache := sliceToStringSet(localNames) - for _, split := range bases[pkg.PackageBase] { + for _, split := range do.Bases[pkg.PackageBase] { file, err := completeFileName(dir, split.Name+"-"+version+"-"+arch+".pkg") if err != nil { return err @@ -675,10 +686,17 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, } arguments.addTarget(file) - //if !targets.get(split.Name) { - if !targets.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) { + if !dp.Explicit.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) { depArguments.addTarget(split.Name) } + + if dp.Explicit.get(split.Name) { + if parser.existsArg("asdeps", "asdep") { + depArguments.addTarget(split.Name) + } else if parser.existsArg("asexplicit", "asexp") { + expArguments.addTarget(split.Name) + } + } } oldConfirm := config.NoConfirm @@ -688,7 +706,7 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, return err } - for _, pkg := range bases[pkg.PackageBase] { + for _, pkg := range do.Bases[pkg.PackageBase] { updateVCSData(pkg.Name, srcinfo.Source) } From e76f978d635262583a220351aea4bb24867459bc Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 29 May 2018 23:39:02 +0100 Subject: [PATCH 058/109] Only show warnings for pkgs that are being updated The previous warning system would show warnings recursivley for all packages being resolved. While I like this, other have complained at it being overly verbose. Either way the main purpose of this is to allow warnings to be printed before the upgrade menu shows. This is mostly just to get a usable warning system. This may change if a better solution is found. --- install.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.go b/install.go index 43aa2dcf..5886a54a 100644 --- a/install.go +++ b/install.go @@ -47,6 +47,8 @@ func install(parser *arguments) error { if err != nil { return err } + + warnings.print() } //create the arguments to pass for the repo install @@ -98,8 +100,6 @@ func install(parser *arguments) error { return err } - warnings.print() - err = dp.CheckMissing() if err != nil { return err From 7a1e2de6cd96b172095ccc3a6a59e8dee2c1fb44 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 30 May 2018 03:21:17 +0100 Subject: [PATCH 059/109] Simplfy upgrade skipping --- install.go | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/install.go b/install.go index 5886a54a..ccd64143 100644 --- a/install.go +++ b/install.go @@ -41,16 +41,6 @@ func install(parser *arguments) error { remoteNamesCache := sliceToStringSet(remoteNames) localNamesCache := sliceToStringSet(localNames) - //if we are doing -u also request all packages needing update - if parser.existsArg("u", "sysupgrade") { - aurUp, repoUp, err = upList(warnings) - if err != nil { - return err - } - - warnings.print() - } - //create the arguments to pass for the repo install arguments := parser.copy() arguments.delArg("y", "refresh") @@ -59,13 +49,19 @@ func install(parser *arguments) error { arguments.op = "S" arguments.targets = make(stringSet) + //if we are doing -u also request all packages needing update if parser.existsArg("u", "sysupgrade") { - ignore, aurUp, err := upgradePkgs(aurUp, repoUp) + aurUp, repoUp, err = upList(warnings) if err != nil { return err } - requestTargets = parser.targets.toSlice() + warnings.print() + + ignore, aurUp, err := upgradePkgs(aurUp, repoUp) + if err != nil { + return err + } for _, up := range repoUp { if !ignore.get(up.Name) { From 53227082a5df236a500efa6b143004e58218302d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 30 May 2018 03:31:21 +0100 Subject: [PATCH 060/109] Skip provider searching for already installed pkgs We do not offer a provider menu for already installed packages. For example if you already have yay installed then yay -S yay will just reinstall yay. No prompt will be given for yay-git or yay-bin. Therefore it makes sense to disable provider searching for these packages. Expecially because it is the slowest part of dependency resolving and many already installed packages are going to be resolved when using -u. --- depPool.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/depPool.go b/depPool.go index 0e082e6b..aede9404 100644 --- a/depPool.go +++ b/depPool.go @@ -203,6 +203,9 @@ func (dp *depPool) findProvides(pkgs stringSet) error { } for pkg := range pkgs { + if _, err := dp.LocalDb.PkgByName(pkg); err == nil { + continue + } wg.Add(1) go doSearch(pkg) } From 943b2f931a15d1dbb8cdeb79e1bb435343b325f1 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 30 May 2018 04:06:29 +0100 Subject: [PATCH 061/109] Tweak missing packages text --- depCheck.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/depCheck.go b/depCheck.go index 9c14ed17..08e9a632 100644 --- a/depCheck.go +++ b/depCheck.go @@ -255,14 +255,16 @@ func (dp *depPool) CheckMissing() error { for dep, trees := range missing.Missing { for _, tree := range trees { - fmt.Print(" "+cyan(dep), " (Tree: ") + fmt.Print(" ", cyan(dep)) if len(tree) == 0 { - fmt.Print(cyan("Target ")) + fmt.Print(" (Target") } else { - for _, pkg := range tree { - fmt.Print(cyan(pkg), " -> ") + fmt.Print(" (Wanted by: ") + for n := 0; n < len(tree)-1; n++ { + fmt.Print(cyan(tree[n]), " -> ") } + fmt.Print(cyan(tree[len(tree)-1])) } fmt.Println(")") From 13754722fd92b82909a64c6ec0c2b7e155fe57ab Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 30 May 2018 04:41:59 +0100 Subject: [PATCH 062/109] Fix group install Using --asdeps with a group install does not work, this seems like a rare use case so ignoring for now. --- depPool.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/depPool.go b/depPool.go index aede9404..0ccc27de 100644 --- a/depPool.go +++ b/depPool.go @@ -79,19 +79,14 @@ func makeDepPool() (*depPool, error) { // Includes db/ prefixes and group installs func (dp *depPool) ResolveTargets(pkgs []string) error { - for _, pkg := range pkgs { - target := toTarget(pkg) - dp.Targets = append(dp.Targets, target) - } - // RPC requests are slow // Combine as many AUR package requests as possible into a single RPC // call aurTargets := make(stringSet) - var err error - //repo := make([]*alpm.Package, 0) - for _, target := range dp.Targets { + for _, pkg := range pkgs { + var err error + target := toTarget(pkg) // skip targets already satisfied // even if the user enters db/pkg and aur/pkg the latter will @@ -107,6 +102,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { // aur/ prefix means we only check the aur if target.Db == "aur" { + dp.Targets = append(dp.Targets, target) aurTargets.set(target.DepString()) continue } @@ -124,6 +120,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { } if err == nil { + dp.Targets = append(dp.Targets, target) dp.Explicit.set(foundPkg.Name()) dp.ResolveRepoDependency(foundPkg) continue @@ -135,10 +132,13 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { //the user specified a db but theres no easy way to do //it without making alpm_lists so dont bother for now //db/group is probably a rare use case - _, err := dp.SyncDb.PkgCachebyGroup(target.Name) - + group, err := dp.SyncDb.PkgCachebyGroup(target.Name) if err == nil { dp.Groups = append(dp.Groups, target.String()) + group.ForEach(func(pkg alpm.Package) error { + dp.Explicit.set(pkg.Name()) + return nil + }) continue } } @@ -147,13 +147,15 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { if target.Db == "" { aurTargets.set(target.DepString()) } + + dp.Targets = append(dp.Targets, target) } if len(aurTargets) > 0 { - err = dp.resolveAURPackages(aurTargets, true) + return dp.resolveAURPackages(aurTargets, true) } - return err + return nil } // Pseudo provides finder. From 7ba552e91fb67557f5247c6b8490e184ba9e0f9b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 30 May 2018 16:00:40 +0100 Subject: [PATCH 063/109] Tweak -Si output Always show popularity as a decimal Always show out of date value --- print.go | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/print.go b/print.go index 11ff9f32..8bbd1037 100644 --- a/print.go +++ b/print.go @@ -266,25 +266,31 @@ func printDownloads(repoName string, length int, packages string) { fmt.Println(repoInfo + cyan(packages)) } +func printInfoValue(str, value string) { + fmt.Printf(bold("%-16s%s")+" %s\n", str, ":", value) +} + // PrintInfo prints package info like pacman -Si. func PrintInfo(a *rpc.Pkg) { - fmt.Println(bold("Repository :"), "aur") - fmt.Println(bold("Name :"), a.Name) - fmt.Println(bold("Version :"), a.Version) - fmt.Println(bold("Description :"), a.Description) - fmt.Println(bold("URL :"), a.URL) - fmt.Println(bold("Licenses :"), strings.Join(a.License, " ")) - fmt.Println(bold("Provides :"), strings.Join(a.Provides, " ")) - fmt.Println(bold("Depends On :"), strings.Join(a.Depends, " ")) - fmt.Println(bold("Make Deps :"), strings.Join(a.MakeDepends, " ")) - fmt.Println(bold("Check Deps :"), strings.Join(a.CheckDepends, " ")) - fmt.Println(bold("Optional Deps :"), strings.Join(a.OptDepends, " ")) - fmt.Println(bold("Conflicts With :"), strings.Join(a.Conflicts, " ")) - fmt.Println(bold("Maintainer :"), a.Maintainer) - fmt.Println(bold("Votes :"), a.NumVotes) - fmt.Println(bold("Popularity :"), a.Popularity) + printInfoValue("Repository", "aur") + printInfoValue("Name", a.Name) + printInfoValue("Version", a.Version) + printInfoValue("Description", a.Description) + printInfoValue("URL", a.URL) + printInfoValue("Licenses", strings.Join(a.License, " ")) + printInfoValue("Provides", strings.Join(a.Provides, " ")) + printInfoValue("Depends On", strings.Join(a.Depends, " ")) + printInfoValue("Make Deps", strings.Join(a.MakeDepends, " ")) + printInfoValue("Check Deps", strings.Join(a.CheckDepends, " ")) + printInfoValue("Optional Deps", strings.Join(a.OptDepends, " ")) + printInfoValue("Conflicts With", strings.Join(a.Conflicts, " ")) + printInfoValue("Maintainer", a.Maintainer) + printInfoValue("Votes", fmt.Sprintf("%d", a.NumVotes)) + printInfoValue("Popularity", fmt.Sprintf("%f", a.Popularity)) if a.OutOfDate != 0 { - fmt.Println(bold("Out-of-date :"), "Yes", "["+formatTime(a.OutOfDate)+"]") + printInfoValue("Out-of-date", "Yes ["+formatTime(a.OutOfDate)+"]") + } else { + printInfoValue("Out-of-date", "No") } fmt.Println() From 9afd67190508491ce5fb563e5e3371ef2a2c6866 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 31 May 2018 04:37:08 +0100 Subject: [PATCH 064/109] Support any PKGDEST and PKGEXT Pacman 5.1 removes the symlink to the current directory for built packages. This causes Yay to break for people who have set an external PKGDEST. Pacman 5.1 also brings an improved --packagelist option. This makes it much simpler to find where packages will be placed. Hence this fix also simplifies the code. Yay has an -Sc option to clear it's cache. If using an external PKGDEST this is now mostly useful for clearing out old pkgbuilds and sources. paccache should be used for cleaning build packages. --- install.go | 76 +++++++++++++++++++++++++----------------------------- utils.go | 22 ---------------- 2 files changed, 35 insertions(+), 63 deletions(-) diff --git a/install.go b/install.go index ccd64143..ba597b2c 100644 --- a/install.go +++ b/install.go @@ -303,22 +303,36 @@ nextpkg: return incompatible, nil } -func getVersionFromPkgbuild(dir string) (string, error) { +func parsePackageList(dir string) (map[string]string, error) { stdout, stderr, err := passToMakepkgCapture(dir, "--packagelist") if err != nil { - return "", fmt.Errorf("%s%s", stderr, err) + return nil, fmt.Errorf("%s%s", stderr, err) } - line := strings.Split(stdout, "\n")[0] - split := strings.Split(line, "-") + lines := strings.Split(stdout, "\n") + pkgdests := make(map[string]string) - if len(split) < 4 { - return "", fmt.Errorf("Can not parse version from: %s", split) + for _, line := range lines { + if line == "" { + continue + } + + fileName := filepath.Base(line) + split := strings.Split(fileName, "-") + + if len(split) < 4 { + return nil, fmt.Errorf("Can not find package name : %s", split) + } + + // pkgname-pkgver-pkgrel-arch.pkgext + // This assumes 3 dashes after the pkgname, Will cause an error + // if the PKGEXT contains a dash. Please no one do that. + pkgname := strings.Join(split[:len(split)-3], "-") + pkgdests[pkgname] = line } - //pkg-name-pkgver-pkgrel-arch: extract pkgver-pkgrel - ver := split[len(split)-3] + "-" + split[len(split)-2] - return ver, nil + + return pkgdests, nil } func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, []*rpc.Pkg, error) { @@ -571,11 +585,6 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco } func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg.PKGBUILD, parser *arguments, incompatible stringSet) error { - arch, err := alpmHandle.Arch() - if err != nil { - return err - } - for _, pkg := range do.Aur { dir := filepath.Join(config.BuildDir, pkg.PackageBase) built := true @@ -594,27 +603,23 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg return fmt.Errorf("Error making: %s", pkg.Name) } - version, err := getVersionFromPkgbuild(dir) + pkgdests, err := parsePackageList(dir) if err != nil { return err } if config.ReBuild == "no" || (config.ReBuild == "yes" && !dp.Explicit.get(pkg.Name)) { for _, split := range do.Bases[pkg.PackageBase] { - file, err := completeFileName(dir, split.Name+"-"+version+"-"+arch+".pkg") - if err != nil { - return err + pkgdest, ok := pkgdests[split.Name] + if !ok { + return fmt.Errorf("Could not find PKGDEST for: %s", split.Name) } - if file == "" { - file, err = completeFileName(dir, split.Name+"-"+version+"-"+"any"+".pkg") - if err != nil { - return err - } - } - - if file == "" { + _, err := os.Stat(pkgdest) + if os.IsNotExist(err) { built = false + } else if err != nil { + return err } } } else { @@ -665,23 +670,12 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg localNamesCache := sliceToStringSet(localNames) for _, split := range do.Bases[pkg.PackageBase] { - file, err := completeFileName(dir, split.Name+"-"+version+"-"+arch+".pkg") - if err != nil { - return err + pkgdest, ok := pkgdests[split.Name] + if !ok { + return fmt.Errorf("Could not find PKGDEST for: %s", split.Name) } - if file == "" { - file, err = completeFileName(dir, split.Name+"-"+version+"-"+"any"+".pkg") - if err != nil { - return err - } - } - - if file == "" { - return fmt.Errorf("Could not find built package " + split.Name + "-" + version + "-" + arch + ".pkg") - } - - arguments.addTarget(file) + arguments.addTarget(pkgdest) if !dp.Explicit.get(split.Name) && !localNamesCache.get(split.Name) && !remoteNamesCache.get(split.Name) { depArguments.addTarget(split.Name) } diff --git a/utils.go b/utils.go index f1760677..71d0dd21 100644 --- a/utils.go +++ b/utils.go @@ -1,9 +1,6 @@ package main import ( - "io/ioutil" - "path/filepath" - "strings" "unicode" ) @@ -59,25 +56,6 @@ func (mss mapStringSet) Add(n string, v string) { mss[n].set(v) } -func completeFileName(dir, name string) (string, error) { - files, err := ioutil.ReadDir(dir) - if err != nil { - return "", err - } - - for _, file := range files { - if file.IsDir() { - continue - } - - if strings.HasPrefix(file.Name(), name) { - return filepath.Join(dir, file.Name()), nil - } - } - - return "", nil -} - func lessRunes(iRunes, jRunes []rune) bool { max := len(iRunes) if max > len(jRunes) { From b5715de4fd3588b435101d7a6ada240fbb83ea7b Mon Sep 17 00:00:00 2001 From: Jguer Date: Thu, 31 May 2018 09:23:20 +0100 Subject: [PATCH 065/109] Update vendored aur --- Gopkg.lock | 4 ++-- vendor/github.com/mikkeloscar/aur/aur.go | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 2e4449b9..72030adc 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,13 +5,13 @@ branch = "master" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "525cfc02951f197145144587c42d51baac160eb7" + revision = "f09b14fad0ccb0df7e5b699da8bcf3b45db4d0ab" [[projects]] branch = "master" name = "github.com/mikkeloscar/aur" packages = ["."] - revision = "9050804dc7d471393053322aaaa40428fbd32de3" + revision = "837b260b8e90895c45737e2e72313fe5bce6f2c4" [[projects]] branch = "master" diff --git a/vendor/github.com/mikkeloscar/aur/aur.go b/vendor/github.com/mikkeloscar/aur/aur.go index 8ae7cc3b..6e0a804a 100644 --- a/vendor/github.com/mikkeloscar/aur/aur.go +++ b/vendor/github.com/mikkeloscar/aur/aur.go @@ -7,7 +7,8 @@ import ( "net/url" ) -const aurURL = "https://aur.archlinux.org/rpc.php?" +//AURURL is the base string from which the query is built +var AURURL = "https://aur.archlinux.org/rpc.php?" type response struct { Error string `json:"error"` @@ -46,7 +47,7 @@ type Pkg struct { func get(values url.Values) ([]Pkg, error) { values.Set("v", "5") - resp, err := http.Get(aurURL + values.Encode()) + resp, err := http.Get(AURURL + values.Encode()) if err != nil { return nil, err } From 0ae8fc2a06ca4ea698434d414b95a0f570e574a7 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 31 May 2018 16:23:15 +0100 Subject: [PATCH 066/109] Support --aur and --repo flags These flags limit operations to only check the repos or only check the AUR. These flags apply to -S, -Si and -Su. -a may also be used as a short option for --aur. --repo has no short option as -r is taken. --- cmd.go | 4 ++++ config.go | 11 +++++++++++ depPool.go | 9 +++++++-- install.go | 6 +++++- query.go | 12 ++++++++---- upgrade.go | 38 +++++++++++++++++++++----------------- 6 files changed, 56 insertions(+), 24 deletions(-) diff --git a/cmd.go b/cmd.go index 1441f3b5..aee37e8c 100644 --- a/cmd.go +++ b/cmd.go @@ -300,6 +300,10 @@ func handleConfig(option, value string) bool { config.Provides = true case "noprovides": config.Provides = false + case "a", "aur": + mode = ModeAUR + case "repo": + mode = ModeRepo default: return false } diff --git a/config.go b/config.go index 105b397a..2ba18df1 100644 --- a/config.go +++ b/config.go @@ -25,6 +25,14 @@ const ( TopDown ) +type targetMode int + +const ( + ModeAUR targetMode = iota + ModeRepo + ModeAny +) + // Configuration stores yay's config. type Configuration struct { BuildDir string `json:"buildDir"` @@ -98,6 +106,9 @@ var alpmConf alpm.PacmanConfig // AlpmHandle is the alpm handle used by yay. var alpmHandle *alpm.Handle +// Mode is used to restrict yay to AUR or repo only modes +var mode targetMode = ModeAny + func readAlpmConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { file, err := os.Open(pacmanconf) if err != nil { diff --git a/depPool.go b/depPool.go index 0ccc27de..945984bc 100644 --- a/depPool.go +++ b/depPool.go @@ -101,12 +101,17 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { var singleDb *alpm.Db // aur/ prefix means we only check the aur - if target.Db == "aur" { + if target.Db == "aur" || (target.Db == "" && mode == ModeAUR) { dp.Targets = append(dp.Targets, target) aurTargets.set(target.DepString()) continue } + if mode == ModeAUR { + dp.Targets = append(dp.Targets, target) + continue + } + // if theres a different priefix only look in that repo if target.Db != "" { singleDb, err = alpmHandle.SyncDbByName(target.Db) @@ -151,7 +156,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { dp.Targets = append(dp.Targets, target) } - if len(aurTargets) > 0 { + if len(aurTargets) > 0 && (mode == ModeAny || mode == ModeAUR) { return dp.resolveAURPackages(aurTargets, true) } diff --git a/install.go b/install.go index ba597b2c..c34091b1 100644 --- a/install.go +++ b/install.go @@ -49,6 +49,10 @@ func install(parser *arguments) error { arguments.op = "S" arguments.targets = make(stringSet) + if mode == ModeAUR { + arguments.delArg("u", "sysupgrade") + } + //if we are doing -u also request all packages needing update if parser.existsArg("u", "sysupgrade") { aurUp, repoUp, err = upList(warnings) @@ -125,7 +129,7 @@ func install(parser *arguments) error { arguments.addTarget(pkg) } - if len(do.Aur) == 0 && len(arguments.targets) == 0 && !parser.existsArg("u", "sysupgrade") { + if len(do.Aur) == 0 && len(arguments.targets) == 0 && (!parser.existsArg("u", "sysupgrade") || mode == ModeAUR) { fmt.Println("There is nothing to do") return nil } diff --git a/query.go b/query.go index 04ff8386..150b6a47 100644 --- a/query.go +++ b/query.go @@ -220,8 +220,8 @@ func syncInfo(pkgS []string) (err error) { } } - if len(aurS) != len(info) { - return fmt.Errorf("Could not find all required packages") + if len(repoS)+len(aurS) != len(pkgS) { + return fmt.Errorf("Could not find all packages") } return @@ -288,10 +288,14 @@ func packageSlices(toCheck []string) (aur []string, repo []string, err error) { db, name := splitDbFromName(_pkg) found := false - if db == "aur" { + if db == "aur" || (mode == ModeAUR && db != "") { + continue + } + + if db == "aur" || (mode == ModeAUR && db == "") { aur = append(aur, _pkg) continue - } else if db != "" { + } else if db != "" || mode == ModeRepo { repo = append(repo, _pkg) continue } diff --git a/upgrade.go b/upgrade.go index 3099e455..2ffb3333 100644 --- a/upgrade.go +++ b/upgrade.go @@ -140,29 +140,33 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { pkgdata := make(map[string]*rpc.Pkg) - fmt.Println(bold(cyan("::") + bold(" Searching databases for updates..."))) - wg.Add(1) - go func() { - repoUp, repoErr = upRepo(local) - wg.Done() - }() - - fmt.Println(bold(cyan("::") + bold(" Searching AUR for updates..."))) - wg.Add(1) - go func() { - aurUp, aurErr = upAUR(remote, remoteNames, pkgdata, warnings) - wg.Done() - }() - - if config.Devel { - fmt.Println(bold(cyan("::") + bold(" Checking development packages..."))) + if mode == ModeAny || mode == ModeRepo { + fmt.Println(bold(cyan("::") + bold(" Searching databases for updates..."))) wg.Add(1) go func() { - develUp, develErr = upDevel(remote) + repoUp, repoErr = upRepo(local) wg.Done() }() } + if mode == ModeAny || mode == ModeAUR { + fmt.Println(bold(cyan("::") + bold(" Searching AUR for updates..."))) + wg.Add(1) + go func() { + aurUp, aurErr = upAUR(remote, remoteNames, pkgdata, warnings) + wg.Done() + }() + + if config.Devel { + fmt.Println(bold(cyan("::") + bold(" Checking development packages..."))) + wg.Add(1) + go func() { + develUp, develErr = upDevel(remote) + wg.Done() + }() + } + } + wg.Wait() printLocalNewerThanAUR(remote, pkgdata) From 682040319e5acfced10b7a8f82079db001f6ed14 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 31 May 2018 16:36:36 +0100 Subject: [PATCH 067/109] Add config option for pgp key fetching --- cmd.go | 4 ++++ config.go | 2 ++ install.go | 8 +++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cmd.go b/cmd.go index aee37e8c..d5706489 100644 --- a/cmd.go +++ b/cmd.go @@ -300,6 +300,10 @@ func handleConfig(option, value string) bool { config.Provides = true case "noprovides": config.Provides = false + case "pgpfetch": + config.PGPFetch = true + case "nopgpfetch": + config.PGPFetch = false case "a", "aur": mode = ModeAUR case "repo": diff --git a/config.go b/config.go index 2ba18df1..cf85b017 100644 --- a/config.go +++ b/config.go @@ -63,6 +63,7 @@ type Configuration struct { CleanAfter bool `json:"cleanAfter"` GitClone bool `json:"gitclone"` Provides bool `json:"provides"` + PGPFetch bool `json:"pgpfetch"` } var version = "5.688" @@ -146,6 +147,7 @@ func defaultSettings(config *Configuration) { config.MakepkgBin = "makepkg" config.NoConfirm = false config.PacmanBin = "pacman" + config.PGPFetch = true config.PacmanConf = "/etc/pacman.conf" config.GpgFlags = "" config.MFlags = "" diff --git a/install.go b/install.go index c34091b1..c4a5829f 100644 --- a/install.go +++ b/install.go @@ -183,9 +183,11 @@ func install(parser *arguments) error { return err } - err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) - if err != nil { - return err + if config.PGPFetch { + err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) + if err != nil { + return err + } } } From 477d3b937e09e8824e3c37b4b33e9b556de859d4 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 1 Jun 2018 03:26:22 +0100 Subject: [PATCH 068/109] Fix mixing of db prefix with --repo/--aur flags --- query.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/query.go b/query.go index 150b6a47..d3a4fd44 100644 --- a/query.go +++ b/query.go @@ -288,11 +288,15 @@ func packageSlices(toCheck []string) (aur []string, repo []string, err error) { db, name := splitDbFromName(_pkg) found := false - if db == "aur" || (mode == ModeAUR && db != "") { + if db == "aur" && mode == ModeRepo { continue } - if db == "aur" || (mode == ModeAUR && db == "") { + if db != "aur" && db != "" && mode == ModeAUR { + continue + } + + if db == "aur" || mode == ModeAUR { aur = append(aur, _pkg) continue } else if db != "" || mode == ModeRepo { From 444ccce92531b46e8d887617c11b37064f9a74f9 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 1 Jun 2018 04:20:49 +0100 Subject: [PATCH 069/109] Filter out invalid tatgets instead of ignoring them Invalid targets that occur when combining aur/foo with --repo or db/foo with --aur. Instead of ignoring them, filter them out and give a warning as it happens. --- depPool.go | 9 +++------ query.go | 19 +++++++++---------- utils.go | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/depPool.go b/depPool.go index 945984bc..7f1dd386 100644 --- a/depPool.go +++ b/depPool.go @@ -84,6 +84,8 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { // call aurTargets := make(stringSet) + pkgs = removeInvalidTargets(pkgs) + for _, pkg := range pkgs { var err error target := toTarget(pkg) @@ -101,17 +103,12 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { var singleDb *alpm.Db // aur/ prefix means we only check the aur - if target.Db == "aur" || (target.Db == "" && mode == ModeAUR) { + if target.Db == "aur" || mode == ModeAUR { dp.Targets = append(dp.Targets, target) aurTargets.set(target.DepString()) continue } - if mode == ModeAUR { - dp.Targets = append(dp.Targets, target) - continue - } - // if theres a different priefix only look in that repo if target.Db != "" { singleDb, err = alpmHandle.SyncDbByName(target.Db) diff --git a/query.go b/query.go index d3a4fd44..f0897c98 100644 --- a/query.go +++ b/query.go @@ -184,6 +184,8 @@ func syncSearch(pkgS []string) (err error) { // SyncInfo serves as a pacman -Si for repo packages and AUR packages. func syncInfo(pkgS []string) (err error) { var info []*rpc.Pkg + missing := false + pkgS = removeInvalidTargets(pkgS) aurS, repoS, err := packageSlices(pkgS) if err != nil { return @@ -199,6 +201,7 @@ func syncInfo(pkgS []string) (err error) { info, err = aurInfoPrint(noDb) if err != nil { + missing = true fmt.Println(err) } } @@ -214,14 +217,18 @@ func syncInfo(pkgS []string) (err error) { } } + if len(aurS) != len(info) { + missing = true + } + if len(info) != 0 { for _, pkg := range info { PrintInfo(pkg) } } - if len(repoS)+len(aurS) != len(pkgS) { - return fmt.Errorf("Could not find all packages") + if missing { + err = fmt.Errorf("") } return @@ -288,14 +295,6 @@ func packageSlices(toCheck []string) (aur []string, repo []string, err error) { db, name := splitDbFromName(_pkg) found := false - if db == "aur" && mode == ModeRepo { - continue - } - - if db != "aur" && db != "" && mode == ModeAUR { - continue - } - if db == "aur" || mode == ModeAUR { aur = append(aur, _pkg) continue diff --git a/utils.go b/utils.go index 71d0dd21..1e926717 100644 --- a/utils.go +++ b/utils.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "unicode" ) @@ -103,3 +104,25 @@ func stringSliceEqual(a, b []string) bool { return true } + +func removeInvalidTargets(targets []string) []string { + filteredTargets := make([]string, 0) + + for _, target := range targets { + db, _ := splitDbFromName(target) + + if db == "aur" && mode == ModeRepo { + fmt.Printf("%s %s %s\n", bold(yellow(arrow)), cyan(target), bold("Can't use target with option --repo -- skipping")) + continue + } + + if db != "aur" && db != "" && mode == ModeAUR { + fmt.Printf("%s %s %s\n", bold(yellow(arrow)), cyan(target), bold("Can't use target with option --aur -- skipping")) + continue + } + + filteredTargets = append(filteredTargets, target) + } + + return filteredTargets +} From 14b66043a22c0bd19d271b8b006e8f5a1faf3a9b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 1 Jun 2018 05:04:15 +0100 Subject: [PATCH 070/109] Support db prefix and --repo/--aur on -G --- download.go | 65 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/download.go b/download.go index 7359aed9..c00a6b96 100644 --- a/download.go +++ b/download.go @@ -100,23 +100,40 @@ func downloadAndUnpack(url string, path string) (err error) { } func getPkgbuilds(pkgs []string) error { - //possibleAurs := make([]string, 0, 0) + missing := false wd, err := os.Getwd() if err != nil { return err } - missing, err := getPkgbuildsfromABS(pkgs, wd) - if err != nil { - return err + pkgs = removeInvalidTargets(pkgs) + + aur, repo, err := packageSlices(pkgs) + + if len(repo) > 0 { + missing, err = getPkgbuildsfromABS(repo, wd) + if err != nil { + return err + } + } + + if len(aur) > 0 { + _missing, err := getPkgbuildsfromAUR(aur, wd) + if err != nil { + return err + } + missing = missing || _missing + } + + if missing { + err = fmt.Errorf("") } - err = getPkgbuildsfromAUR(missing, wd) return err } // GetPkgbuild downloads pkgbuild from the ABS. -func getPkgbuildsfromABS(pkgs []string, path string) (missing []string, err error) { +func getPkgbuildsfromABS(pkgs []string, path string) (missing bool,err error) { dbList, err := alpmHandle.SyncDbs() if err != nil { return @@ -124,8 +141,14 @@ func getPkgbuildsfromABS(pkgs []string, path string) (missing []string, err erro nextPkg: for _, pkgN := range pkgs { + pkgDb, name := splitDbFromName(pkgN) + for _, db := range dbList.Slice() { - pkg, err := db.PkgByName(pkgN) + if pkgDb != "" && db.Name() != pkgDb { + continue + } + + pkg, err := db.PkgByName(name) if err == nil { var url string name := pkg.Base() @@ -144,7 +167,7 @@ nextPkg: case "community", "multilib": url = "https://git.archlinux.org/svntogit/community.git/snapshot/packages/" + name + ".tar.gz" default: - fmt.Println(name + " not in standard repositories") + fmt.Println(pkgN, "not in standard repositories") continue nextPkg } @@ -164,7 +187,8 @@ nextPkg: } } - missing = append(missing, pkgN) + fmt.Println(pkgN, "could not find package in database") + missing = true } if _, err := os.Stat(filepath.Join(cacheHome, "packages")); err == nil { @@ -175,14 +199,25 @@ nextPkg: } // GetPkgbuild downloads pkgbuild from the AUR. -func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) { - aq, err := aurInfoPrint(pkgs) +func getPkgbuildsfromAUR(pkgs []string, dir string) (bool, error) { + missing := false + strippedPkgs := make([]string, 0) + for _, pkg := range pkgs { + _, name := splitDbFromName(pkg) + strippedPkgs = append(strippedPkgs, name) + } + + aq, err := aurInfoPrint(strippedPkgs) if err != nil { - return err + return missing, err } for _, pkg := range aq { - var err error + if _, err := os.Stat(filepath.Join(dir, pkg.PackageBase)); err == nil { + fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name)), "directory already exists") + continue + } + if shouldUseGit(filepath.Join(dir, pkg.PackageBase)) { err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", dir, pkg.PackageBase) } else { @@ -197,8 +232,8 @@ func getPkgbuildsfromAUR(pkgs []string, dir string) (err error) { } if len(aq) != len(pkgs) { - return fmt.Errorf("Could not find all required packages") + missing = true } - return + return missing, err } From f20fbd25c11f5a7298830d9bc6faf79e6fefd3e2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 31 May 2018 20:31:45 +0100 Subject: [PATCH 071/109] Implement diffs for pkgbuild viewing. diff viewing can be toggled via --[no]showdiffs. When enabled diffs will be shown for packages between the current HEAD and upstream's HEAD. Packages downloaded via tarballs will be shown in full using the editor git diff is used to show diffs. Therefore the pager for diffs can be set via the PAGER and GIT_PAGER enviroment variables. --- cmd.go | 24 +++++++++++- config.go | 2 + download.go | 18 ++++++++- install.go | 111 +++++++++++++++++++++++++++++++++++++++++++--------- utils.go | 2 + 5 files changed, 137 insertions(+), 20 deletions(-) diff --git a/cmd.go b/cmd.go index d5706489..1b421267 100644 --- a/cmd.go +++ b/cmd.go @@ -304,6 +304,10 @@ func handleConfig(option, value string) bool { config.PGPFetch = true case "nopgpfetch": config.PGPFetch = false + case "showdiffs": + config.ShowDiffs = true + case "noshowdiffs": + config.ShowDiffs = false case "a", "aur": mode = ModeAUR case "repo": @@ -603,7 +607,6 @@ func passToMakepkgCapture(dir string, args ...string) (string, string, error) { args = append(args, mflags...) cmd := exec.Command(config.MakepkgBin, args...) - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr cmd.Dir = dir cmd.Stdout = &outbuf cmd.Stderr = &errbuf @@ -630,3 +633,22 @@ func passToGit(dir string, _args ...string) (err error) { err = cmd.Run() return } + +func passToGitCapture(dir string, _args ...string) (string, string, error) { + var outbuf, errbuf bytes.Buffer + gitflags := strings.Fields(config.GitFlags) + args := []string{"-C", dir} + args = append(args, gitflags...) + args = append(args, _args...) + + cmd := exec.Command(config.GitBin, args...) + cmd.Dir = dir + cmd.Stdout = &outbuf + cmd.Stderr = &errbuf + + err := cmd.Run() + stdout := outbuf.String() + stderr := errbuf.String() + + return stdout, stderr, err +} diff --git a/config.go b/config.go index cf85b017..9eaa02e4 100644 --- a/config.go +++ b/config.go @@ -64,6 +64,7 @@ type Configuration struct { GitClone bool `json:"gitclone"` Provides bool `json:"provides"` PGPFetch bool `json:"pgpfetch"` + ShowDiffs bool `json:"showdifs"` } var version = "5.688" @@ -167,6 +168,7 @@ func defaultSettings(config *Configuration) { config.AnswerUpgrade = "" config.GitClone = true config.Provides = true + config.ShowDiffs = true } // Editor returns the preferred system editor. diff --git a/download.go b/download.go index 7359aed9..7aad2d7e 100644 --- a/download.go +++ b/download.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" ) // Decide what download method to use: @@ -20,7 +21,7 @@ func shouldUseGit(path string) bool { } _, err = os.Stat(filepath.Join(path, ".git")) - return os.IsExist(err) + return err == nil || os.IsExist(err) } func downloadFile(path string, url string) (err error) { @@ -43,6 +44,15 @@ func downloadFile(path string, url string) (err error) { return err } +func gitGetHash(path string, name string) (string, error) { + stdout, stderr, err := passToGitCapture(filepath.Join(path, name), "rev-parse", "HEAD") + if err != nil { + return "", fmt.Errorf("%s%s", stderr, err) + } + + return strings.TrimSpace(stdout), nil +} + func gitDownload(url string, path string, name string) error { _, err := os.Stat(filepath.Join(path, name, ".git")) if os.IsNotExist(err) { @@ -74,6 +84,12 @@ func gitDownload(url string, path string, name string) error { return nil } +func gitDiff(path string, name string) error { + err := passToGit(filepath.Join(path, name), "diff", "HEAD..HEAD@{upstream}") + + return err +} + // DownloadAndUnpack downloads url tgz and extracts to path. func downloadAndUnpack(url string, path string) (err error) { err = os.MkdirAll(path, 0755) diff --git a/install.go b/install.go index c4a5829f..8cdf223e 100644 --- a/install.go +++ b/install.go @@ -153,13 +153,17 @@ func install(parser *arguments) error { cleanBuilds(toClean) - err = downloadPkgBuilds(do.Aur, parser.targets, do.Bases) + oldHashes, err := downloadPkgBuilds(do.Aur, parser.targets, do.Bases) if err != nil { return err } if len(toEdit) > 0 { - err = editPkgBuilds(toEdit) + if config.ShowDiffs { + err = showPkgBuildDiffs(toEdit, do.Bases, oldHashes) + } else { + err = editPkgBuilds(toEdit, do.Bases, oldHashes) + } if err != nil { return err } @@ -422,7 +426,11 @@ func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed } } - fmt.Println(bold(green(arrow + " PKGBUILDs to edit?"))) + if config.ShowDiffs { + fmt.Println(bold(green(arrow + " Diffs to show?"))) + } else { + fmt.Println(bold(green(arrow + " PKGBUILDs to edit?"))) + } fmt.Println(bold(green(arrow) + cyan(" [N]one ") + "[A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)")) fmt.Print(bold(green(arrow + " "))) @@ -481,20 +489,66 @@ func cleanBuilds(pkgs []*rpc.Pkg) { } } -func editPkgBuilds(pkgs []*rpc.Pkg) error { +func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[string]string) error { + for _, pkg := range pkgs { + dir := filepath.Join(config.BuildDir, pkg.PackageBase) + if shouldUseGit(dir) { + hash, _ := hashes[pkg.PackageBase] + if hash == "" { + hash = gitEmptyTree + } + + head, err := gitGetHash(config.BuildDir, pkg.PackageBase) + if err != nil { + return err + } + + if head == hash { + fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(pkg, bases)), bold("No changes -- skipping")) + continue + } + + args := []string{"diff", hash + "..HEAD", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"} + if useColor { + args = append(args, "--color=always") + } else { + args = append(args, "--color=never") + } + err = passToGit(dir, args...) + if err != nil { + return err + } + } else { + editor, editorArgs := editor() + editorArgs = append(editorArgs, filepath.Join(dir, "PKGBUILD")) + editcmd := exec.Command(editor, editorArgs...) + editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr + err := editcmd.Run() + if err != nil { + return fmt.Errorf("Editor did not exit successfully, Aborting: %s", err) + } + } + } + + return nil +} + +func editPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[string]string) error { pkgbuilds := make([]string, 0, len(pkgs)) for _, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD")) } - editor, editorArgs := editor() - editorArgs = append(editorArgs, pkgbuilds...) - editcmd := exec.Command(editor, editorArgs...) - editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr - err := editcmd.Run() - if err != nil { - return fmt.Errorf("Editor did not exit successfully, Aborting: %s", err) + if len(pkgbuilds) > 0 { + editor, editorArgs := editor() + editorArgs = append(editorArgs, pkgbuilds...) + editcmd := exec.Command(editor, editorArgs...) + editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr + err := editcmd.Run() + if err != nil { + return fmt.Errorf("Editor did not exit successfully, Aborting: %s", err) + } } return nil @@ -535,8 +589,11 @@ func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, } } -func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*rpc.Pkg) error { - for k, pkg := range pkgs { +func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*rpc.Pkg) (map[string]string, error) { + toSkip := make(stringSet) + hashes := make(map[string]string) + + for _, pkg := range pkgs { if config.ReDownload == "no" || (config.ReDownload == "yes" && !targets.get(pkg.Name)) { dir := filepath.Join(config.BuildDir, pkg.PackageBase, ".SRCINFO") pkgbuild, err := gopkg.ParseSRCINFO(dir) @@ -546,13 +603,28 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r versionPKG, errP := gopkg.NewCompleteVersion(pkgbuild.Version()) if errP == nil && errR == nil { if !versionRPC.Newer(versionPKG) { - str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) - continue + toSkip.set(pkg.PackageBase) } } } } + } + + for k, pkg := range pkgs { + if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { + hash, err := gitGetHash(config.BuildDir, pkg.PackageBase) + if err == nil { + hashes[pkg.PackageBase] = hash + } else { + hashes[pkg.PackageBase] = "" + } + } + + if toSkip.get(pkg.PackageBase) { + str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") + fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) + continue + } str := bold(cyan("::") + " Downloading PKGBUILD (%d/%d): %s\n") @@ -561,15 +633,18 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r var err error if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) + if err != nil { + return hashes, err + } } else { err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) } if err != nil { - return err + return hashes, err } } - return nil + return hashes, nil } func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) { diff --git a/utils.go b/utils.go index 71d0dd21..522bebd3 100644 --- a/utils.go +++ b/utils.go @@ -4,6 +4,8 @@ import ( "unicode" ) +const gitEmptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" + type mapStringSet map[string]stringSet type intRange struct { From c4d319268c69f91b80e2d19db648e477086dcd69 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 2 Jun 2018 13:52:18 +0100 Subject: [PATCH 072/109] Disable git terminal prompt This allows requests that want authentication to fail instantly and silently. Rather than delying the program and printing to the terminal. --- download.go | 2 +- vcs.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/download.go b/download.go index d2e86177..6bba35b9 100644 --- a/download.go +++ b/download.go @@ -149,7 +149,7 @@ func getPkgbuilds(pkgs []string) error { } // GetPkgbuild downloads pkgbuild from the ABS. -func getPkgbuildsfromABS(pkgs []string, path string) (missing bool,err error) { +func getPkgbuildsfromABS(pkgs []string, path string) (missing bool, err error) { dbList, err := alpmHandle.SyncDbs() if err != nil { return diff --git a/vcs.go b/vcs.go index 5b219c3c..e64b32cf 100644 --- a/vcs.go +++ b/vcs.go @@ -136,6 +136,7 @@ func getCommit(url string, branch string, protocols []string) string { cmd := exec.Command(config.GitBin, "ls-remote", protocol+"://"+url, branch) cmd.Stdout = &outbuf + cmd.Env = append(cmd.Env, "GIT_TERMINAL_PROMPT=0") err := cmd.Start() if err != nil { From 942e389d85cebaf765df323a84d86072edcf7fb1 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 2 Jun 2018 14:16:00 +0100 Subject: [PATCH 073/109] Stop prepare running twice Prepare ends up getting ran twice every time we install a package, theres not problems with doing so apart from a little inefficiency. Previously the install flow would be like this: downlod sources + verify prepare + pkgver bump full build (prepare included) Now on the last point pass no extract to use the srcdir from the previous command and pass noprepare and holdver because we allready did these steps previously. --- install.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.go b/install.go index c4a5829f..dbb5c118 100644 --- a/install.go +++ b/install.go @@ -597,7 +597,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg srcinfo := srcinfos[pkg.PackageBase] - args := []string{"--nobuild", "-fCc"} + args := []string{"--nobuild", "-fC"} if incompatible.get(pkg.PackageBase) { args = append(args, "--ignorearch") @@ -636,7 +636,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg fmt.Println(bold(yellow(arrow)), cyan(pkg.Name+"-"+pkg.Version)+bold(" Already made -- skipping build")) } else { - args := []string{"-Ccf", "--noconfirm"} + args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} if incompatible.get(pkg.PackageBase) { args = append(args, "--ignorearch") From 5f2933271ab1d82c5edf2e794b21db8052e6cd31 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 2 Jun 2018 15:01:39 +0100 Subject: [PATCH 074/109] Use slices for targets instead of stringsets The order of targets does somewhat matter. For example doing something like 'pacman -S db1/foo db2/foo' should cause the second package to be skipped. The order of targets also effects in which order they are resolved. This should make errors more reproducable if any ever occur. --- cmd.go | 15 +++++++-------- install.go | 10 ++++++---- parser.go | 27 +++++++-------------------- print.go | 13 +++++++------ query.go | 3 ++- 5 files changed, 29 insertions(+), 39 deletions(-) diff --git a/cmd.go b/cmd.go index 1b421267..ad6dd4da 100644 --- a/cmd.go +++ b/cmd.go @@ -369,22 +369,21 @@ func handleYay() (err error) { } func handleGetpkgbuild() (err error) { - err = getPkgbuilds(cmdArgs.formatTargets()) + err = getPkgbuilds(cmdArgs.targets) return } func handleYogurt() (err error) { options := cmdArgs.formatArgs() - targets := cmdArgs.formatTargets() config.SearchMode = NumberMenu - err = numberMenu(targets, options) + err = numberMenu(cmdArgs.targets, options) return } func handleSync() (err error) { - targets := cmdArgs.formatTargets() + targets := cmdArgs.targets if cmdArgs.existsArg("y", "refresh") { arguments := cmdArgs.copy() @@ -393,7 +392,7 @@ func handleSync() (err error) { arguments.delArg("s", "search") arguments.delArg("i", "info") arguments.delArg("l", "list") - arguments.targets = make(stringSet) + arguments.clearTargets() err = passToPacman(arguments) if err != nil { return @@ -426,7 +425,7 @@ func handleSync() (err error) { } func handleRemove() (err error) { - removeVCSPackage(cmdArgs.formatTargets()) + removeVCSPackage(cmdArgs.targets) err = passToPacman(cmdArgs) return } @@ -531,7 +530,7 @@ func passToPacman(args *arguments) error { argArr = append(argArr, "--") - argArr = append(argArr, args.formatTargets()...) + argArr = append(argArr, args.targets...) cmd = exec.Command(argArr[0], argArr[1:]...) @@ -563,7 +562,7 @@ func passToPacmanCapture(args *arguments) (string, string, error) { argArr = append(argArr, "--") - argArr = append(argArr, args.formatTargets()...) + argArr = append(argArr, args.targets...) cmd = exec.Command(argArr[0], argArr[1:]...) cmd.Stdout = &outbuf diff --git a/install.go b/install.go index 62db8686..6fd256ff 100644 --- a/install.go +++ b/install.go @@ -15,7 +15,6 @@ import ( // Install handles package installs func install(parser *arguments) error { - requestTargets := parser.targets.toSlice() var err error var incompatible stringSet var do *depOrder @@ -25,6 +24,7 @@ func install(parser *arguments) error { var aurUp upSlice var repoUp upSlice + requestTargets := parser.copy().targets warnings := &aurWarnings{} removeMake := false @@ -47,7 +47,7 @@ func install(parser *arguments) error { arguments.delArg("asdeps", "asdep") arguments.delArg("asexplicit", "asexp") arguments.op = "S" - arguments.targets = make(stringSet) + arguments.clearTargets() if mode == ModeAUR { arguments.delArg("u", "sysupgrade") @@ -95,6 +95,8 @@ func install(parser *arguments) error { } } + targets := sliceToStringSet(parser.targets) + dp, err := getDepPool(requestTargets, warnings) if err != nil { return err @@ -153,7 +155,7 @@ func install(parser *arguments) error { cleanBuilds(toClean) - oldHashes, err := downloadPkgBuilds(do.Aur, parser.targets, do.Bases) + oldHashes, err := downloadPkgBuilds(do.Aur, targets, do.Bases) if err != nil { return err } @@ -724,7 +726,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg } arguments := parser.copy() - arguments.targets = make(stringSet) + arguments.clearTargets() arguments.op = "U" arguments.delArg("confirm") arguments.delArg("c", "clean") diff --git a/parser.go b/parser.go index c384a79d..f2a64d80 100644 --- a/parser.go +++ b/parser.go @@ -72,7 +72,7 @@ type arguments struct { options map[string]string globals map[string]string doubles stringSet // Tracks args passed twice such as -yy and -dd - targets stringSet + targets []string } func makeArguments() *arguments { @@ -81,7 +81,7 @@ func makeArguments() *arguments { make(map[string]string), make(map[string]string), make(stringSet), - make(stringSet), + make([]string, 0), } } @@ -98,9 +98,8 @@ func (parser *arguments) copy() (cp *arguments) { cp.globals[k] = v } - for k, v := range parser.targets { - cp.targets[k] = v - } + cp.targets = make([]string, len(parser.targets)) + copy(cp.targets, parser.targets) for k, v := range parser.doubles { cp.doubles[k] = v @@ -268,15 +267,11 @@ func (parser *arguments) getArg(options ...string) (arg string, double bool, exi } func (parser *arguments) addTarget(targets ...string) { - for _, target := range targets { - parser.targets[target] = struct{}{} - } + parser.targets = append(parser.targets, targets...) } -func (parser *arguments) delTarget(targets ...string) { - for _, target := range targets { - delete(parser.targets, target) - } +func (parser *arguments) clearTargets() { + parser.targets = make([]string, 0) } // Multiple args acts as an OR operator @@ -291,14 +286,6 @@ func (parser *arguments) existsDouble(options ...string) bool { return false } -func (parser *arguments) formatTargets() (args []string) { - for target := range parser.targets { - args = append(args, target) - } - - return -} - func (parser *arguments) formatArgs() (args []string) { var op string diff --git a/print.go b/print.go index 06fa18a6..f71fc5a7 100644 --- a/print.go +++ b/print.go @@ -363,6 +363,7 @@ func printNumberOfUpdates() error { //TODO: Make it less hacky func printUpdateList(parser *arguments) error { + targets := sliceToStringSet(parser.targets) warnings := &aurWarnings{} old := os.Stdout // keep backup of the real stdout os.Stdout = nil @@ -377,22 +378,22 @@ func printUpdateList(parser *arguments) error { return err } - noTargets := len(parser.targets) == 0 + noTargets := len(targets) == 0 if !parser.existsArg("m", "foreign") { for _, pkg := range repoUp { - if noTargets || parser.targets.get(pkg.Name) { + if noTargets || targets.get(pkg.Name) { fmt.Printf("%s %s -> %s\n", bold(pkg.Name), green(pkg.LocalVersion), green(pkg.RemoteVersion)) - delete(parser.targets, pkg.Name) + delete(targets, pkg.Name) } } } if !parser.existsArg("n", "native") { for _, pkg := range aurUp { - if noTargets || parser.targets.get(pkg.Name) { + if noTargets || targets.get(pkg.Name) { fmt.Printf("%s %s -> %s\n", bold(pkg.Name), green(pkg.LocalVersion), green(pkg.RemoteVersion)) - delete(parser.targets, pkg.Name) + delete(targets, pkg.Name) } } } @@ -400,7 +401,7 @@ func printUpdateList(parser *arguments) error { missing := false outer: - for pkg := range parser.targets { + for pkg := range targets { for _, name := range localNames { if name == pkg { continue outer diff --git a/query.go b/query.go index f0897c98..10e4dfd3 100644 --- a/query.go +++ b/query.go @@ -209,7 +209,8 @@ func syncInfo(pkgS []string) (err error) { // Repo always goes first if len(repoS) != 0 { arguments := cmdArgs.copy() - arguments.delTarget(aurS...) + arguments.clearTargets() + arguments.addTarget(repoS...) err = passToPacman(arguments) if err != nil { From bf562ee9a721e8779dc052396fb742e11d2de820 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 2 Jun 2018 18:27:26 +0100 Subject: [PATCH 075/109] Don't show provider menu for targets during -Y Doing `yay -S yay` I expect the provider menu to show, giving me the choice between yay, yay-bin and yay-git If I do `yay yay` I will then get a menu of all matching packages. upon entering 2 for the package yay I would not expect a provider menu. I have already choosen an exact package. This commit disables the provider menu during yogurt mode. Only for targets, the dependencies can still open provider menus. --- depPool.go | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/depPool.go b/depPool.go index 7f1dd386..2b87ca64 100644 --- a/depPool.go +++ b/depPool.go @@ -377,6 +377,12 @@ func (dp *depPool) findSatisfierAur(dep string) *rpc.Pkg { // This is mostly used to promote packages from the cache // to the Install list // Provide a pacman style provider menu if theres more than one candidate +// This acts slightly differenly from Pacman, It will give +// a menu even if a package with a matching name exists. I believe this +// method is better because most of the time you are choosing between +// foo and foo-git. +// Using Pacman's ways trying to install foo would never give you +// a menu. // TODO: maybe intermix repo providers in the menu func (dp *depPool) findSatisfierAurCache(dep string) *rpc.Pkg { depName, _, _ := splitDep(dep) @@ -387,33 +393,20 @@ func (dp *depPool) findSatisfierAurCache(dep string) *rpc.Pkg { if pkg, ok := dp.AurCache[dep]; ok && pkgSatisfies(pkg.Name, pkg.Version, dep) { return pkg } + } - //this version prioratizes name over provides - //if theres a direct match for a package return - //that instead of using the menu - // - //providers := make(rpcPkgs, 0) - //for _, pkg := range dp.AurCache { - // if pkgSatisfies(pkg.Name, pkg.Version, dep) { - // return pkg - // } - //} - - //for _, pkg := range dp.AurCache { - // for _, provide := range pkg.Provides { - // if provideSatisfies(provide, dep) { - // providers = append(providers, pkg) - // } - // } - //} - - // This version acts slightly differenly from Pacman, It will give - // a menu even if a package with a matching name exists. I believe this - // method is better because most of the time you are choosing between - // foo and foo-git. - // Using Pacman's ways trying to install foo would never give you - // a menu. + if cmdArgs.op == "Y" || cmdArgs.op == "yay" { + for _, pkg := range dp.AurCache { + if pkgSatisfies(pkg.Name, pkg.Version, dep) { + for _, target := range dp.Targets { + if target.Name == pkg.Name { + return pkg + } + } + } + } + } for _, pkg := range dp.AurCache { if seen.get(pkg.Name) { From a71784684c4ab974d470211414f36476e551f421 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 4 Jun 2018 19:16:43 +0100 Subject: [PATCH 076/109] Add new options to usage --- cmd.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index ad6dd4da..1fe1cdcf 100644 --- a/cmd.go +++ b/cmd.go @@ -35,6 +35,9 @@ New operations: yay {-P --print} [options] yay {-G --getpkgbuild} [package(s)] +New options: + --repo Assume targets are from the repositories + -a --aur Assume targets are from the AUR Permanent configuration options: --save Causes the following options to be saved back to the config file when used @@ -53,7 +56,7 @@ Permanent configuration options: --config pacman.conf file to use --requestsplitn Max amount of packages to query per AUR request - --sortby Sort AUR results by a specific field during search + --sortby Sort AUR results by a specific field during search --answerclean Set a predetermined answer for the clean build menu --answeredit Set a predetermined answer for the edit pkgbuild menu --answerupgrade Set a predetermined answer for the upgrade menu @@ -70,6 +73,8 @@ Permanent configuration options: --nodevel Do not check development packages --gitclone Use git clone for PKGBUILD retrieval --nogitclone Never use git clone for PKGBUILD retrieval + --showdiffs Show diffs for build files + --noshowdiffs Always show the entire PKGBUILD --rebuild Always build target packages --rebuildall Always build all AUR packages --norebuild Skip package build if in cache and up to date @@ -77,6 +82,10 @@ Permanent configuration options: --redownload Always download pkgbuilds of targets --noredownload Skip pkgbuild download if in cache and up to date --redownloadall Always download pkgbuilds of all AUR packages + --provides Look for matching provders when searching for packages + --noprovides Just look for packages by pkgname + --pgpfetch Prompt to import PGP keys from PKGBUILDs + --nopgpfetch Don't prompt to import PGP keys --sudoloop Loop sudo calls in the background to avoid timeout --nosudoloop Do not loop sudo calls in the background From 63509365c1c061e2fd3fe7b429cc27922d0b048c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 4 Jun 2018 19:22:16 +0100 Subject: [PATCH 077/109] Add less not always paging to the faq --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 28e6b90a..85a46d13 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,12 @@ Currently yay Depends on: * Yay does not display colored output. How do I fix it? Make sure you have the `Color` option in your `/etc/pacman.conf` [#123](https://github.com/Jguer/yay/issues/123) +* Sometimes diffs are printed to the terminal and other times they are pages + via less. How do I fix this? + Yay uses `git diff` to display diffs, by default git tells less to not page + if the output can fit one terminal length. This can be overridden by + exporting your own flags `export LESS=SRX`. + ## Examples of Custom Operations * `yay ` presents package selection menu From 6c22d5987cef7711f47eda1f191fcbd1c083b590 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 4 Jun 2018 20:00:01 +0100 Subject: [PATCH 078/109] Update man page --- doc/yay.8 | 104 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 26 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index 74bc218c..9b65a740 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -1,5 +1,5 @@ '\" t -.TH "YAY" "8" "2018-02-29" "Yay v3\&.460+" "Yay Manual" +.TH "YAY" "8" "2018\-06\-04" "Yay v6\&.784+" "Yay Manual" .nh .ad l .SH "NAME" @@ -20,29 +20,29 @@ This manpage only covers options unique to Yay\&. For other options see \fBpacman(8)\fR\&. .SH "YAY OPERATIONS" .PP -\fB\-Y, --yay\fR +\fB\-Y, \-\-yay\fR .RS 4 Perform yay specific operations\&. This is the default if no other operation is selected\&. .RE .PP -\fB\-P, --print\fR +\fB\-P, \-\-print\fR .RS 4 Perform yay specific print operations\&. .RE .PP -\fB\-G, --getpkgbuild\fR +\fB\-G, \-\-getpkgbuild\fR .RS 4 Downloads PKGBUILD from ABS or AUR\&. .RE .PP -If no arguments are provided 'yay -Syu' will be performed\&. +If no arguments are provided 'yay \-Syu' will be performed\&. .RE .PP -If no operation is selected -Y will be assumed\&. +If no operation is selected \-Y will be assumed\&. .SH "EXTENDED PACMAN OPERATIONS" .PP -\fB\-S, -Si, -Ss, -Su, -Sc, -Qu\fR +\fB\-S, \-Si, \-Ss, \-Su, \-Sc, \-Qu\fR .RS 4 These operations are extended to support both AUR and repo packages\&. .RE @@ -58,9 +58,23 @@ sources or built packages but will keep already downloaded vcs sources\&. \fB\-R\fR .RS 4 Yay will also remove cached data about devel packages\&. - .RE -.SH "YAY OPTIONS (APPLY TO -Y AND --YAY)" +.SH "NEW OPTIONS" +.PP +\fB \-\-repo\fR +.RS 4 +Assume all targets are from the repositories\&. Aditionally Actions such as +sysupgrade will only act on repository packages\&. +.RE +\fB\-a \-\-aur\fR +.RS 4 +Assume all targets are from the AUR\&. Aditionally Actions such as +sysupgrade will only act on AUR packages\&. + +Note that dependency resolving will still act as normal and include repository +packages\&. +.RE +.SH "YAY OPTIONS (APPLY TO \-Y AND \-\-YAY)" .PP \fB\fR .RS 4 @@ -80,7 +94,7 @@ used when migrating to Yay from another AUR helper. .RS 4 Remove unneeded dependencies\&. .RE -.SH "PRINT OPTIONS (APPLY TO -P AND --PRINT)" +.SH "PRINT OPTIONS (APPLY TO \-P AND \-\-PRINT)" \fB\-c \-\-complete\fR .RS 4 Print a list of all AUR and repo packages\&. This is to allow shell completion @@ -105,30 +119,30 @@ Print current yay configuration\&. \fB\-n \-\-numberupgrades\fR .RS 4 Print number of packages that need to be updated\&. Note this does not perform -a database refresh\&. Run \fByay -Sy\fR Before this for an up to date result\&. +a database refresh\&. Run \fByay \-Sy\fR Before this for an up to date result\&. .RE .PP \fB\-s \-\-stats\fR .RS 4 Displays information about installed packages and system health\&. If there are -orphaned, out-of-date or packages that no longer exist on the AUR warnings will +orphaned, out\-of\-date or packages that no longer exist on the AUR warnings will be displayed\&. .RE .PP \fB\-u \-\-upgrades\fR .RS 4 Print Names of packages that need to be updated\&. Note this does not perform -a database refresh\&. Run \fByay -Sy\fR Before this for an up to date result\&. +a database refresh\&. Run \fByay \-Sy\fR Before this for an up to date result\&. .RE .PP -\fB\-w --news\fR +\fB\-w \-\-news\fR .RS 4 Print new news from the Archlinux homepage\&. News is considered new if it is newer than the build date of all native packages\&. Pass this twice to show all avaliable news\&. .RE .PP -\fB\-q --quiet\fR +\fB\-q \-\-quiet\fR .RS 4 Only show titles when printing news\&. .RE @@ -271,9 +285,9 @@ Do not check for development packages updates during sysupgrade\&. \fB\-\-gitclone\fR .RS 4 Use git to download and update PKGBUILDs\&. PKGBUILDs previously downloaded -using tarball will continue to use tarballs until the package is clean built\&. -Similarly, PKGBUILDs managed with git will continue to use git until the package -is clean built.\&. +using tarball will continue to use tarballs until the package is clean +built\&. Similarly, PKGBUILDs managed with git will continue to use git until +the package is clean built.\&. .RE .PP \fB\-\-nogitclone\fR @@ -282,6 +296,18 @@ Download and update PKGBUILDs using tarballs\&. The above conditions about previously installed packages still apply\&. .RE .PP +\fB\-\-showdiffs\fR +.RS 4 +Show diffs for build files\&. Diffs are shown via \fBgit diff\fR which uses +less by default\&. This behaviour can be changed via git's config, the +\fB$GIT_PAGER\fR or \fB$PAGER\fR environment variables\&. +.RE +.PP +\fB\-\-noshowdiffs\fR +.RS 4 +Show diffs for build files\&. Files will be opened by the editor\%. +.RE +.PP \fB\-\-afterclean\fR .RS 4 Remove package sources after successful Install\&. @@ -320,6 +346,32 @@ When downloading pkgbuilds if the pkgbuild is found in cache and is equal or newer than the AUR's version use that instead of downloading a new one\&. .RE .PP +\fB\-\-provides\fR +.RS 4 +Look for matching providers when searching for AUR packages\&. When multiple +providers are found a menu will appear prompting you to pick one\&. This +increases dependency resolve time although this should not be noticable\&. +.RE +.PP +\fB\-\-noprovides\fR +.RS 4 +Do not look for matching providers when searching for AUR packages\&. If +multiple providers happen to be found the menu will still apear\&. +.RE +.PP +\fB\-\-pgpfetch\fR +.RS 4 +Prompt to import unknown PGP keys from the \fBvalidpgpkeys\fR field of each +PKGBUILD. +.RE +.PP +\fB\-\-pgpfetch\fR +.RS 4 +Do not prompt to import unknown PGP keys\&. This is likley to cause a build +failiure unless using options such as \fB\-\-skippgpcheck\fR or a customized +gpg config\%. +.RE +.PP \fB\-\-rebuild\fR .RS 4 Always build target packages even when a copy is available in cache\&. @@ -378,37 +430,37 @@ yay \fIfoo\fR Search and install from the repos and the \fBAUR\fR\ using yogurt mode\&. .RE .PP -yay -Syu +yay \-Syu .RS 4 Update package list and upgrade all currently installed repo and \fBAUR\fR\&. .RE .PP -yay -S \fIfoo\fR +yay \-S \fIfoo\fR .RS 4 Installs package \fIfoo\fR from the repos or the \fBAUR\fR\&. .RE .PP -yay -Ss \fIfoo\fR +yay \-Ss \fIfoo\fR .RS 4 Searches for package \fIfoo\fR on the repos or the \fBAUR\fR\&. .RE .PP -yay -Si \fIfoo\fR +yay \-Si \fIfoo\fR .RS 4 Gets information about package \fIfoo\fR from the repos or the \fBAUR\fR\&. .RE .PP -yay -S \fIfoo\fR --mflags "--skipchecksums --skippgpcheck" +yay \-S \fIfoo\fR \-\-mflags "\-\-skipchecksums \-\-skippgpcheck" .RS 4 Installs \fIfoo\fR while skipping checksums and pgp checks\&. .RE .PP -yay --devel --save +yay \-\-devel \-\-save .RS 4 Sets devel to true in the config\&. .RE .PP -yay -P --stats +yay \-P \-\-stats .RS 4 Shows statistics for installed packages and system health\&. .RE @@ -448,7 +500,7 @@ and built packages from those packages\&. \fBPACMAN.CONF\fR .RS 4 Yay uses Pacman's config file to set certain pacman options either through -go-alpm or Yay itself. Options inherited include most libalpm options and +go\-alpm or Yay itself. Options inherited include most libalpm options and pacman options\&. .PP Notably \fBDatabases\fR, \fBColor\fR and \fB*Path/*Dir\fR options are used\&. From bad0af1a8a0c713fb920e3df07cf7b5167ab73ef Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 4 Jun 2018 20:12:26 +0100 Subject: [PATCH 079/109] Fix typos --- depPool.go | 18 +++++++++--------- doc/yay.8 | 10 +++++----- vcs.go | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/depPool.go b/depPool.go index 2b87ca64..ef6ee0a1 100644 --- a/depPool.go +++ b/depPool.go @@ -92,7 +92,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { // skip targets already satisfied // even if the user enters db/pkg and aur/pkg the latter will - // still get skiped even if it's from a different database to + // still get skipped even if it's from a different database to // the one specified // this is how pacman behaves if dp.hasPackage(target.DepString()) { @@ -109,7 +109,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { continue } - // if theres a different priefix only look in that repo + // If there'ss a different priefix only look in that repo if target.Db != "" { singleDb, err = alpmHandle.SyncDbByName(target.Db) if err != nil { @@ -128,11 +128,11 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { continue } else { //check for groups - //currently we dont resolve the packages in a group + //currently we don't resolve the packages in a group //only check if the group exists //would be better to check the groups from singleDb if - //the user specified a db but theres no easy way to do - //it without making alpm_lists so dont bother for now + //the user specified a db but there's no easy way to do + //it without making alpm_lists so don't bother for now //db/group is probably a rare use case group, err := dp.SyncDb.PkgCachebyGroup(target.Name) if err == nil { @@ -167,7 +167,7 @@ func (dp *depPool) ResolveTargets(pkgs []string) error { // // For example if you were to -S yay then yay -Ss would give: // yay-git yay-bin yay realyog pacui pacui-git ruby-yard -// These packages will all be added to the cache incase they are needed later +// These packages will all be added to the cache in case they are needed later // Ofcouse only the first three packages provide yay, the rest are just false // positives. // @@ -315,7 +315,7 @@ func (dp *depPool) resolveAURPackages(pkgs stringSet, explicit bool) error { } //assume it's in the aur - //ditch the versioning because the RPC cant handle it + //ditch the versioning because the RPC can't handle it newAURPackages.set(dep) } @@ -376,8 +376,8 @@ func (dp *depPool) findSatisfierAur(dep string) *rpc.Pkg { // This is mostly used to promote packages from the cache // to the Install list -// Provide a pacman style provider menu if theres more than one candidate -// This acts slightly differenly from Pacman, It will give +// Provide a pacman style provider menu if there's more than one candidate +// This acts slightly differently from Pacman, It will give // a menu even if a package with a matching name exists. I believe this // method is better because most of the time you are choosing between // foo and foo-git. diff --git a/doc/yay.8 b/doc/yay.8 index 9b65a740..642fae28 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -63,12 +63,12 @@ Yay will also remove cached data about devel packages\&. .PP \fB \-\-repo\fR .RS 4 -Assume all targets are from the repositories\&. Aditionally Actions such as +Assume all targets are from the repositories\&. Additionally Actions such as sysupgrade will only act on repository packages\&. .RE \fB\-a \-\-aur\fR .RS 4 -Assume all targets are from the AUR\&. Aditionally Actions such as +Assume all targets are from the AUR\&. Additionally Actions such as sysupgrade will only act on AUR packages\&. Note that dependency resolving will still act as normal and include repository @@ -139,7 +139,7 @@ a database refresh\&. Run \fByay \-Sy\fR Before this for an up to date result\&. .RS 4 Print new news from the Archlinux homepage\&. News is considered new if it is newer than the build date of all native packages\&. Pass this twice to show all -avaliable news\&. +available news\&. .RE .PP \fB\-q \-\-quiet\fR @@ -350,13 +350,13 @@ newer than the AUR's version use that instead of downloading a new one\&. .RS 4 Look for matching providers when searching for AUR packages\&. When multiple providers are found a menu will appear prompting you to pick one\&. This -increases dependency resolve time although this should not be noticable\&. +increases dependency resolve time although this should not be noticeable\&. .RE .PP \fB\-\-noprovides\fR .RS 4 Do not look for matching providers when searching for AUR packages\&. If -multiple providers happen to be found the menu will still apear\&. +multiple providers happen to be found the menu will still appear\&. .RE .PP \fB\-\-pgpfetch\fR diff --git a/vcs.go b/vcs.go index e64b32cf..e9b695b7 100644 --- a/vcs.go +++ b/vcs.go @@ -18,7 +18,7 @@ type vcsInfo map[string]shaInfos type shaInfos map[string]shaInfo type shaInfo struct { Protocols []string `json:"protocols"` - Brach string `json:"branch"` + Branch string `json:"branch"` SHA string `json:"sha"` } @@ -180,7 +180,7 @@ func (infos shaInfos) needsUpdate() bool { hasUpdate := make(chan struct{}) checkHash := func(url string, info shaInfo) { - hash := getCommit(url, info.Brach, info.Protocols) + hash := getCommit(url, info.Branch, info.Protocols) if hash != "" && hash != info.SHA { hasUpdate <- struct{}{} } else { From ced35af5154cbeaa67e32d4c14da9913e8f33189 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 4 Jun 2018 20:36:10 +0100 Subject: [PATCH 080/109] Support --aur/--repo for -Ss and -Y --- cmd.go | 52 ++++++++++++++++++++++++++++++++++++---------------- query.go | 34 ++++++++++++++++++++++++++-------- vcs.go | 2 +- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/cmd.go b/cmd.go index 1fe1cdcf..621c71f4 100644 --- a/cmd.go +++ b/cmd.go @@ -441,23 +441,43 @@ func handleRemove() (err error) { // NumberMenu presents a CLI for selecting packages to install. func numberMenu(pkgS []string, flags []string) (err error) { - aurQ, aurErr := narrowSearch(pkgS, true) - numaq := len(aurQ) - repoQ, numpq, err := queryRepo(pkgS) - if err != nil { - return + pkgS = removeInvalidTargets(pkgS) + var aurErr error + var repoErr error + var aq aurQuery + var pq repoQuery + var lenaq int + var lenpq int + + if mode == ModeAUR || mode == ModeAny { + aq, aurErr = narrowSearch(pkgS, true) + lenaq = len(aq) + } + if mode == ModeRepo || mode == ModeAny { + pq, lenpq, repoErr = queryRepo(pkgS) + if repoErr != nil { + return err + } } - if numpq == 0 && numaq == 0 { - return fmt.Errorf("no packages match search") + if lenpq == 0 && lenaq == 0 { + return fmt.Errorf("No packages match search") } if config.SortMode == BottomUp { - aurQ.printSearch(numpq + 1) - repoQ.printSearch() + if mode == ModeAUR || mode == ModeAny { + aq.printSearch(lenpq + 1) + } + if mode == ModeRepo || mode == ModeAny { + pq.printSearch() + } } else { - repoQ.printSearch() - aurQ.printSearch(numpq + 1) + if mode == ModeRepo || mode == ModeAny { + pq.printSearch() + } + if mode == ModeAUR || mode == ModeAny { + aq.printSearch(lenpq + 1) + } } if aurErr != nil { @@ -484,8 +504,8 @@ func numberMenu(pkgS []string, flags []string) (err error) { isInclude := len(exclude) == 0 && len(otherExclude) == 0 - for i, pkg := range repoQ { - target := len(repoQ) - i + for i, pkg := range pq { + target := len(pq) - i if config.SortMode == TopDown { target = i + 1 } @@ -498,10 +518,10 @@ func numberMenu(pkgS []string, flags []string) (err error) { } } - for i, pkg := range aurQ { - target := len(aurQ) - i + len(repoQ) + for i, pkg := range aq { + target := len(aq) - i + len(pq) if config.SortMode == TopDown { - target = i + 1 + len(repoQ) + target = i + 1 + len(pq) } if isInclude && include.get(target) { diff --git a/query.go b/query.go index 10e4dfd3..4a2993d6 100644 --- a/query.go +++ b/query.go @@ -159,18 +159,36 @@ func narrowSearch(pkgS []string, sortS bool) (aurQuery, error) { // SyncSearch presents a query to the local repos and to the AUR. func syncSearch(pkgS []string) (err error) { - aq, aurErr := narrowSearch(pkgS, true) - pq, _, err := queryRepo(pkgS) - if err != nil { - return err + pkgS = removeInvalidTargets(pkgS) + var aurErr error + var repoErr error + var aq aurQuery + var pq repoQuery + + if mode == ModeAUR || mode == ModeAny { + aq, aurErr = narrowSearch(pkgS, true) + } + if mode == ModeRepo || mode == ModeAny { + pq, _, repoErr = queryRepo(pkgS) + if repoErr != nil { + return err + } } if config.SortMode == BottomUp { - aq.printSearch(1) - pq.printSearch() + if mode == ModeAUR || mode == ModeAny { + aq.printSearch(1) + } + if mode == ModeRepo || mode == ModeAny { + pq.printSearch() + } } else { - pq.printSearch() - aq.printSearch(1) + if mode == ModeRepo || mode == ModeAny { + pq.printSearch() + } + if mode == ModeAUR || mode == ModeAny { + aq.printSearch(1) + } } if aurErr != nil { diff --git a/vcs.go b/vcs.go index e9b695b7..b6554a05 100644 --- a/vcs.go +++ b/vcs.go @@ -18,7 +18,7 @@ type vcsInfo map[string]shaInfos type shaInfos map[string]shaInfo type shaInfo struct { Protocols []string `json:"protocols"` - Branch string `json:"branch"` + Branch string `json:"branch"` SHA string `json:"sha"` } From 3aea877ab92ea6b17b3d282155c1e12aa6378fed Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 4 Jun 2018 23:31:50 +0100 Subject: [PATCH 081/109] Tweek config and cache dir initialization Check if enviroment variables are set instead if they are empty strings. Don't care if the dir exists just take the path at face value. Error if $HOME and the respective $XDG.. variables are not set. --- main.go | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index 02bb42e3..dc946c7b 100644 --- a/main.go +++ b/main.go @@ -10,29 +10,27 @@ import ( alpm "github.com/jguer/go-alpm" ) -func initPaths() { - if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" { - if info, err := os.Stat(configHome); err == nil && info.IsDir() { - configHome = filepath.Join(configHome, "yay") - } else { - configHome = filepath.Join(os.Getenv("HOME"), ".config/yay") - } +func setPaths() error { + if _configHome, set := os.LookupEnv("XDG_CONFIG_HOME"); set { + cacheHome = filepath.Join(_configHome, "yay") + } else if _configHome, set := os.LookupEnv("HOME"); set { + cacheHome = filepath.Join(_configHome, ".config/yay") } else { - configHome = filepath.Join(os.Getenv("HOME"), ".config/yay") + fmt.Errorf("XDG_CONFIG_HOME and HOME unset") } - if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" { - if info, err := os.Stat(cacheHome); err == nil && info.IsDir() { - cacheHome = filepath.Join(cacheHome, "yay") - } else { - cacheHome = filepath.Join(os.Getenv("HOME"), ".cache/yay") - } + if _cacheHome, set := os.LookupEnv("XDG_CACHE_HOME"); set { + cacheHome = filepath.Join(_cacheHome, "yay") + } else if _cacheHome, set := os.LookupEnv("HOME"); set { + cacheHome = filepath.Join(_cacheHome, ".cache/yay") } else { - cacheHome = filepath.Join(os.Getenv("HOME"), ".cache/yay") + fmt.Errorf("XDG_CACHE_HOME and HOME unset") } configFile = filepath.Join(configHome, configFileName) vcsFile = filepath.Join(cacheHome, vcsFileName) + + return nil } func initConfig() (err error) { @@ -184,7 +182,12 @@ func main() { goto cleanup } - initPaths() + err = setPaths() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + } err = initConfig() if err != nil { From e5d7cce49c2d7f6155fc1d5b2ea01fe8de8a2c49 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 5 Jun 2018 14:14:49 +0100 Subject: [PATCH 082/109] Fix file paths --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index dc946c7b..c34d95d5 100644 --- a/main.go +++ b/main.go @@ -12,9 +12,9 @@ import ( func setPaths() error { if _configHome, set := os.LookupEnv("XDG_CONFIG_HOME"); set { - cacheHome = filepath.Join(_configHome, "yay") + configHome = filepath.Join(_configHome, "yay") } else if _configHome, set := os.LookupEnv("HOME"); set { - cacheHome = filepath.Join(_configHome, ".config/yay") + configHome = filepath.Join(_configHome, ".config/yay") } else { fmt.Errorf("XDG_CONFIG_HOME and HOME unset") } From 7fdb5c2007fcaac22ad02fedbad39ec5448f436a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 5 Jun 2018 14:17:07 +0100 Subject: [PATCH 083/109] Make sure enviroment paths are not empty --- main.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/main.go b/main.go index c34d95d5..2880396c 100644 --- a/main.go +++ b/main.go @@ -12,16 +12,28 @@ import ( func setPaths() error { if _configHome, set := os.LookupEnv("XDG_CONFIG_HOME"); set { + if _configHome == "" { + fmt.Errorf("XDG_CONFIG_HOME set but empty") + } configHome = filepath.Join(_configHome, "yay") } else if _configHome, set := os.LookupEnv("HOME"); set { + if _configHome == "" { + fmt.Errorf("HOME set but empty") + } configHome = filepath.Join(_configHome, ".config/yay") } else { fmt.Errorf("XDG_CONFIG_HOME and HOME unset") } if _cacheHome, set := os.LookupEnv("XDG_CACHE_HOME"); set { + if _cacheHome == "" { + fmt.Errorf("XDG_CACHE_HOME set but empty") + } cacheHome = filepath.Join(_cacheHome, "yay") } else if _cacheHome, set := os.LookupEnv("HOME"); set { + if _cacheHome == "" { + fmt.Errorf("XDG_CACHE_HOME set but empty") + } cacheHome = filepath.Join(_cacheHome, ".cache/yay") } else { fmt.Errorf("XDG_CACHE_HOME and HOME unset") From 64ab60f4b4d3b252474f3b1f8ec9b53ff80d123d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 5 Jun 2018 14:47:55 +0100 Subject: [PATCH 084/109] Print true pkgver when skipping build --- install.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/install.go b/install.go index 6fd256ff..4ab48e31 100644 --- a/install.go +++ b/install.go @@ -315,13 +315,14 @@ nextpkg: return incompatible, nil } -func parsePackageList(dir string) (map[string]string, error) { +func parsePackageList(dir string) (map[string]string, string, error) { stdout, stderr, err := passToMakepkgCapture(dir, "--packagelist") if err != nil { - return nil, fmt.Errorf("%s%s", stderr, err) + return nil, "", fmt.Errorf("%s%s", stderr, err) } + var version string lines := strings.Split(stdout, "\n") pkgdests := make(map[string]string) @@ -334,17 +335,18 @@ func parsePackageList(dir string) (map[string]string, error) { split := strings.Split(fileName, "-") if len(split) < 4 { - return nil, fmt.Errorf("Can not find package name : %s", split) + return nil, "", fmt.Errorf("Can not find package name : %s", split) } // pkgname-pkgver-pkgrel-arch.pkgext // This assumes 3 dashes after the pkgname, Will cause an error // if the PKGEXT contains a dash. Please no one do that. pkgname := strings.Join(split[:len(split)-3], "-") + version = strings.Join(split[len(split)-3:len(split)-2], "-") pkgdests[pkgname] = line } - return pkgdests, nil + return pkgdests, version, nil } func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, []*rpc.Pkg, error) { @@ -686,7 +688,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg return fmt.Errorf("Error making: %s", pkg.Name) } - pkgdests, err := parsePackageList(dir) + pkgdests, version, err := parsePackageList(dir) if err != nil { return err } @@ -711,7 +713,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg if built { fmt.Println(bold(yellow(arrow)), - cyan(pkg.Name+"-"+pkg.Version)+bold(" Already made -- skipping build")) + cyan(pkg.Name+"-"+version)+bold(" Already made -- skipping build")) } else { args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} From c3a94edd20b4c82a04414c3050b0cac81c07e6b3 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Sat, 9 Jun 2018 14:33:28 +0100 Subject: [PATCH 085/109] Fix failing tests There were several calls to fmt.Errorf in setPaths where the returned error was not being used. This was indicated by ```make test``` as shown here: ``` make test gofmt -l *.go go vet ./main.go:16: result of fmt.Errorf call not used ./main.go:21: result of fmt.Errorf call not used ./main.go:25: result of fmt.Errorf call not used ./main.go:30: result of fmt.Errorf call not used ./main.go:35: result of fmt.Errorf call not used ./main.go:39: result of fmt.Errorf call not used make: *** [Makefile:43: test] Error 2 ``` With these changes the tests now all pass with no errors. --- main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index 2880396c..17d6f819 100644 --- a/main.go +++ b/main.go @@ -13,30 +13,30 @@ import ( func setPaths() error { if _configHome, set := os.LookupEnv("XDG_CONFIG_HOME"); set { if _configHome == "" { - fmt.Errorf("XDG_CONFIG_HOME set but empty") + return fmt.Errorf("XDG_CONFIG_HOME set but empty") } configHome = filepath.Join(_configHome, "yay") } else if _configHome, set := os.LookupEnv("HOME"); set { if _configHome == "" { - fmt.Errorf("HOME set but empty") + return fmt.Errorf("HOME set but empty") } configHome = filepath.Join(_configHome, ".config/yay") } else { - fmt.Errorf("XDG_CONFIG_HOME and HOME unset") + return fmt.Errorf("XDG_CONFIG_HOME and HOME unset") } if _cacheHome, set := os.LookupEnv("XDG_CACHE_HOME"); set { if _cacheHome == "" { - fmt.Errorf("XDG_CACHE_HOME set but empty") + return fmt.Errorf("XDG_CACHE_HOME set but empty") } cacheHome = filepath.Join(_cacheHome, "yay") } else if _cacheHome, set := os.LookupEnv("HOME"); set { if _cacheHome == "" { - fmt.Errorf("XDG_CACHE_HOME set but empty") + return fmt.Errorf("XDG_CACHE_HOME set but empty") } cacheHome = filepath.Join(_cacheHome, ".cache/yay") } else { - fmt.Errorf("XDG_CACHE_HOME and HOME unset") + return fmt.Errorf("XDG_CACHE_HOME and HOME unset") } configFile = filepath.Join(configHome, configFileName) From 5775e3c0b79b5598fd4016ca6ba6afd3cf4a24cc Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 00:42:58 +0100 Subject: [PATCH 086/109] Split git clone/pull and merge function --- download.go | 6 +++++- install.go | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/download.go b/download.go index 6bba35b9..7d761cf9 100644 --- a/download.go +++ b/download.go @@ -71,7 +71,11 @@ func gitDownload(url string, path string, name string) error { return fmt.Errorf("error fetching %s", name) } - err = passToGit(filepath.Join(path, name), "reset", "--hard", "HEAD") + return nil +} + +func gitMerge(url string, path string, name string) error { + err := passToGit(filepath.Join(path, name), "reset", "--hard", "HEAD") if err != nil { return fmt.Errorf("error resetting %s", name) } diff --git a/install.go b/install.go index 4ab48e31..8b45885d 100644 --- a/install.go +++ b/install.go @@ -636,10 +636,16 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r var err error if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) + err = gitDownload(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) if err != nil { return hashes, err } + + err = gitMerge(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) + if err != nil { + return hashes, err + } + } else { err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) } From 1b8d9317e4aa6b69efcb3cc76c5a11ef1f55aa92 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 01:04:04 +0100 Subject: [PATCH 087/109] Split pkgbuild downloading and up to date checks --- install.go | 12 +++++++++--- vcs.go | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/install.go b/install.go index 8b45885d..5d7e371e 100644 --- a/install.go +++ b/install.go @@ -155,7 +155,8 @@ func install(parser *arguments) error { cleanBuilds(toClean) - oldHashes, err := downloadPkgBuilds(do.Aur, targets, do.Bases) + toSkip := pkgBuildsToSkip(do.Aur, targets) + oldHashes, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) if err != nil { return err } @@ -593,9 +594,8 @@ func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, } } -func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*rpc.Pkg) (map[string]string, error) { +func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { toSkip := make(stringSet) - hashes := make(map[string]string) for _, pkg := range pkgs { if config.ReDownload == "no" || (config.ReDownload == "yes" && !targets.get(pkg.Name)) { @@ -614,6 +614,12 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r } } + return toSkip +} + +func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) (map[string]string, error) { + hashes := make(map[string]string) + for k, pkg := range pkgs { if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { hash, err := gitGetHash(config.BuildDir, pkg.PackageBase) diff --git a/vcs.go b/vcs.go index b6554a05..857185d3 100644 --- a/vcs.go +++ b/vcs.go @@ -43,7 +43,8 @@ func createDevelDB() error { bases := getBases(infoMap) - downloadPkgBuilds(info, sliceToStringSet(remoteNames), bases) + toSkip := pkgBuildsToSkip(info, sliceToStringSet(remoteNames)) + downloadPkgBuilds(info, bases, toSkip) tryParsesrcinfosFile(info, srcinfosStale, bases) for _, pkg := range info { From 73bd713217b253b94646c429b003ad51ec3b1692 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 01:21:20 +0100 Subject: [PATCH 088/109] Split hash fetching and pkgbuild downloading --- install.go | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/install.go b/install.go index 5d7e371e..94df54e7 100644 --- a/install.go +++ b/install.go @@ -155,8 +155,13 @@ func install(parser *arguments) error { cleanBuilds(toClean) + oldHashes, err := getHashes(do.Aur) + if err != nil { + return err + } + toSkip := pkgBuildsToSkip(do.Aur, targets) - oldHashes, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) + err = downloadPkgBuilds(do.Aur, do.Bases, toSkip) if err != nil { return err } @@ -617,19 +622,25 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { return toSkip } -func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) (map[string]string, error) { +func getHashes(pkgs []*rpc.Pkg) (map[string]string, error) { hashes := make(map[string]string) - for k, pkg := range pkgs { + for _, pkg := range pkgs { if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { hash, err := gitGetHash(config.BuildDir, pkg.PackageBase) - if err == nil { - hashes[pkg.PackageBase] = hash - } else { - hashes[pkg.PackageBase] = "" + if err != nil { + return hashes, err } - } + hashes[pkg.PackageBase] = hash + } + } + + return hashes, nil +} + +func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) error { + for k, pkg := range pkgs { if toSkip.get(pkg.PackageBase) { str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) @@ -640,27 +651,26 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) - var err error if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - err = gitDownload(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) + err := gitDownload(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) if err != nil { - return hashes, err + return err } err = gitMerge(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) if err != nil { - return hashes, err + return err } } else { - err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) - } - if err != nil { - return hashes, err + err := downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) + if err != nil { + return err + } } } - return hashes, nil + return nil } func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) { From 43d2a6601ab7d710ca11fce04e936c5f17a28530 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 01:29:54 +0100 Subject: [PATCH 089/109] Split pkgbuild downloading and merging --- install.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/install.go b/install.go index 94df54e7..af9a525c 100644 --- a/install.go +++ b/install.go @@ -166,6 +166,11 @@ func install(parser *arguments) error { return err } + err = mergePkgBuilds(do.Aur) + if err != nil { + return err + } + if len(toEdit) > 0 { if config.ShowDiffs { err = showPkgBuildDiffs(toEdit, do.Bases, oldHashes) @@ -639,6 +644,20 @@ func getHashes(pkgs []*rpc.Pkg) (map[string]string, error) { return hashes, nil } +func mergePkgBuilds(pkgs []*rpc.Pkg) error { + for _, pkg := range pkgs { + if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { + err := gitMerge(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) + if err != nil { + return err + } + } + } + + return nil +} + + func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) error { for k, pkg := range pkgs { if toSkip.get(pkg.PackageBase) { @@ -656,12 +675,6 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri if err != nil { return err } - - err = gitMerge(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) - if err != nil { - return err - } - } else { err := downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) if err != nil { From 4f8b43cd604c63bbadbe199913802eae31c1971e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 01:57:17 +0100 Subject: [PATCH 090/109] Show diffs before merging This is what 5775e3..43d2a6 has been leading up to. Git fetch will be called on all pkgbuilds, then the user is offered a chance to view the diffs. If they choose to continue, merging happens. This allows users to abort the install after viewing diffs and still be able to see thoes diffs again if they try to install later on. This also makes the git stuff a little more modular which should help in organzing diff showing + pkgbuild editing. --- download.go | 15 ++++++++++++--- install.go | 54 ++++++++++++++--------------------------------------- 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/download.go b/download.go index 7d761cf9..831c3832 100644 --- a/download.go +++ b/download.go @@ -44,13 +44,22 @@ func downloadFile(path string, url string) (err error) { return err } -func gitGetHash(path string, name string) (string, error) { +func gitHasDiff(path string, name string) (bool, error) { stdout, stderr, err := passToGitCapture(filepath.Join(path, name), "rev-parse", "HEAD") if err != nil { - return "", fmt.Errorf("%s%s", stderr, err) + return false, fmt.Errorf("%s%s", stderr, err) } - return strings.TrimSpace(stdout), nil + head := strings.TrimSpace(stdout) + + stdout, stderr, err = passToGitCapture(filepath.Join(path, name), "rev-parse", "HEAD@{upstream}") + if err != nil { + return false, fmt.Errorf("%s%s", stderr, err) + } + + upstream := strings.TrimSpace(stdout) + + return head != upstream, nil } func gitDownload(url string, path string, name string) error { diff --git a/install.go b/install.go index af9a525c..7f1ed71b 100644 --- a/install.go +++ b/install.go @@ -155,27 +155,17 @@ func install(parser *arguments) error { cleanBuilds(toClean) - oldHashes, err := getHashes(do.Aur) - if err != nil { - return err - } - toSkip := pkgBuildsToSkip(do.Aur, targets) err = downloadPkgBuilds(do.Aur, do.Bases, toSkip) if err != nil { return err } - - err = mergePkgBuilds(do.Aur) - if err != nil { - return err - } - + if len(toEdit) > 0 { if config.ShowDiffs { - err = showPkgBuildDiffs(toEdit, do.Bases, oldHashes) + err = showPkgBuildDiffs(toEdit, do.Bases) } else { - err = editPkgBuilds(toEdit, do.Bases, oldHashes) + err = editPkgBuilds(toEdit, do.Bases) } if err != nil { return err @@ -189,6 +179,12 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } + err = mergePkgBuilds(do.Aur) + if err != nil { + return err + } + + //initial srcinfo parse before pkgver() bump err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) if err != nil { @@ -504,26 +500,21 @@ func cleanBuilds(pkgs []*rpc.Pkg) { } } -func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[string]string) error { +func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { for _, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) if shouldUseGit(dir) { - hash, _ := hashes[pkg.PackageBase] - if hash == "" { - hash = gitEmptyTree - } - - head, err := gitGetHash(config.BuildDir, pkg.PackageBase) + hasDiff, err := gitHasDiff(config.BuildDir, pkg.PackageBase) if err != nil { return err } - if head == hash { + if !hasDiff { fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(pkg, bases)), bold("No changes -- skipping")) continue } - args := []string{"diff", hash + "..HEAD", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"} + args := []string{"diff", "HEAD..HEAD@{upstream}", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"} if useColor { args = append(args, "--color=always") } else { @@ -548,7 +539,7 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[ return nil } -func editPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, hashes map[string]string) error { +func editPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { pkgbuilds := make([]string, 0, len(pkgs)) for _, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) @@ -627,23 +618,6 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { return toSkip } -func getHashes(pkgs []*rpc.Pkg) (map[string]string, error) { - hashes := make(map[string]string) - - for _, pkg := range pkgs { - if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - hash, err := gitGetHash(config.BuildDir, pkg.PackageBase) - if err != nil { - return hashes, err - } - - hashes[pkg.PackageBase] = hash - } - } - - return hashes, nil -} - func mergePkgBuilds(pkgs []*rpc.Pkg) error { for _, pkg := range pkgs { if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { From 2b925aefa3abcd058cf587ff61248514fbf8908d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 02:02:24 +0100 Subject: [PATCH 091/109] Lint --- install.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/install.go b/install.go index 7f1ed71b..47b20d06 100644 --- a/install.go +++ b/install.go @@ -160,7 +160,7 @@ func install(parser *arguments) error { if err != nil { return err } - + if len(toEdit) > 0 { if config.ShowDiffs { err = showPkgBuildDiffs(toEdit, do.Bases) @@ -184,7 +184,6 @@ func install(parser *arguments) error { return err } - //initial srcinfo parse before pkgver() bump err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) if err != nil { @@ -621,7 +620,7 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { func mergePkgBuilds(pkgs []*rpc.Pkg) error { for _, pkg := range pkgs { if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - err := gitMerge(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) + err := gitMerge(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) if err != nil { return err } @@ -631,7 +630,6 @@ func mergePkgBuilds(pkgs []*rpc.Pkg) error { return nil } - func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) error { for k, pkg := range pkgs { if toSkip.get(pkg.PackageBase) { @@ -645,7 +643,7 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - err := gitDownload(baseURL + "/" + pkg.PackageBase + ".git", config.BuildDir, pkg.PackageBase) + err := gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) if err != nil { return err } From 00da26a3ce1d60627df7d0f8fd4e0df85ba0c73e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 03:41:25 +0100 Subject: [PATCH 092/109] Always show diffs for newly cloned packages Newly cloned packages already start out at origin/master, so there is no diff to show. Track if we cloned a package and if so make sure to show the full diff --- download.go | 14 +++++++------- install.go | 47 +++++++++++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/download.go b/download.go index 831c3832..4b25a02f 100644 --- a/download.go +++ b/download.go @@ -62,25 +62,25 @@ func gitHasDiff(path string, name string) (bool, error) { return head != upstream, nil } -func gitDownload(url string, path string, name string) error { +func gitDownload(url string, path string, name string) (bool, error) { _, err := os.Stat(filepath.Join(path, name, ".git")) if os.IsNotExist(err) { err = passToGit(path, "clone", url, name) if err != nil { - return fmt.Errorf("error cloning %s", name) + return false, fmt.Errorf("error cloning %s", name) } - return nil + return true, nil } else if err != nil { - return fmt.Errorf("error reading %s", filepath.Join(path, name, ".git")) + return false, fmt.Errorf("error reading %s", filepath.Join(path, name, ".git")) } err = passToGit(filepath.Join(path, name), "fetch") if err != nil { - return fmt.Errorf("error fetching %s", name) + return false, fmt.Errorf("error fetching %s", name) } - return nil + return false, nil } func gitMerge(url string, path string, name string) error { @@ -248,7 +248,7 @@ func getPkgbuildsfromAUR(pkgs []string, dir string) (bool, error) { } if shouldUseGit(filepath.Join(dir, pkg.PackageBase)) { - err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", dir, pkg.PackageBase) + _, err = gitDownload(baseURL+"/"+pkg.PackageBase+".git", dir, pkg.PackageBase) } else { err = downloadAndUnpack(baseURL+aq[0].URLPath, dir) } diff --git a/install.go b/install.go index 47b20d06..4ea59039 100644 --- a/install.go +++ b/install.go @@ -156,14 +156,14 @@ func install(parser *arguments) error { cleanBuilds(toClean) toSkip := pkgBuildsToSkip(do.Aur, targets) - err = downloadPkgBuilds(do.Aur, do.Bases, toSkip) + cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) if err != nil { return err } if len(toEdit) > 0 { if config.ShowDiffs { - err = showPkgBuildDiffs(toEdit, do.Bases) + err = showPkgBuildDiffs(toEdit, do.Bases, cloned) } else { err = editPkgBuilds(toEdit, do.Bases) } @@ -499,27 +499,33 @@ func cleanBuilds(pkgs []*rpc.Pkg) { } } -func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { +func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stringSet) error { for _, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) if shouldUseGit(dir) { - hasDiff, err := gitHasDiff(config.BuildDir, pkg.PackageBase) - if err != nil { - return err + start := "HEAD" + + if cloned.get(pkg.PackageBase) { + start = gitEmptyTree + } else { + hasDiff, err := gitHasDiff(config.BuildDir, pkg.PackageBase) + if err != nil { + return err + } + + if !hasDiff { + fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(pkg, bases)), bold("No changes -- skipping")) + continue + } } - if !hasDiff { - fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(pkg, bases)), bold("No changes -- skipping")) - continue - } - - args := []string{"diff", "HEAD..HEAD@{upstream}", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"} + args := []string{"diff", start + "..HEAD@{upstream}", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"} if useColor { args = append(args, "--color=always") } else { args = append(args, "--color=never") } - err = passToGit(dir, args...) + err := passToGit(dir, args...) if err != nil { return err } @@ -630,7 +636,9 @@ func mergePkgBuilds(pkgs []*rpc.Pkg) error { return nil } -func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) error { +func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) (stringSet, error) { + cloned := make(stringSet) + for k, pkg := range pkgs { if toSkip.get(pkg.PackageBase) { str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") @@ -643,19 +651,22 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - err := gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) + clone, err := gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) if err != nil { - return err + return nil, err + } + if clone { + cloned.set(pkg.PackageBase) } } else { err := downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) if err != nil { - return err + return nil, err } } } - return nil + return cloned, nil } func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) { From 219e50e66820bac177b267d12ad46ac69a571ff2 Mon Sep 17 00:00:00 2001 From: Govind KP Date: Sun, 10 Jun 2018 13:58:21 +0530 Subject: [PATCH 093/109] Fixed trivial typo packags -> packages --- query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query.go b/query.go index 4a2993d6..8ead0b79 100644 --- a/query.go +++ b/query.go @@ -193,7 +193,7 @@ func syncSearch(pkgS []string) (err error) { if aurErr != nil { fmt.Printf("Error during AUR search: %s\n", aurErr) - fmt.Println("Showing Repo packags only") + fmt.Println("Showing Repo packages only") } return nil From 8430c41be99694ecaa11e54c31de06dc59b7f109 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 10 Jun 2018 15:56:57 +0100 Subject: [PATCH 094/109] Rework editing and diff showing Clean build needs to happen before downloading pkgbuilds so that they can be deletd before downloading. Editing and diff viewing needs to happen after downloading the pkgbuilds. Prevously we asked to clean and edit at the same time. Then clean, download pkgbuilds and open the editor. This poeses a problem for diff viewing and editing. It's likley that the user will see the diff and use that to decide if they want to edit the pkgbuild. Using the current method, the user will be asked to view diffs and edit before actually seeing any diffs. Instead split cleaning diff showing and editing to three seperate menus in the following order: show clean menu clean download pkgbuilds show diff menu show diffs show edit menu edit pkgbuilds Also each menu is seperatly enableable. By default only the diff menu is shows. If the user wishes to clean build, edit pkgbuilds or disable diffs then the user can use the --[no]{clean,diff,edit}menu flags. This replaces the --[no]showdiffs flags. --- cmd.go | 16 +++-- config.go | 7 ++- install.go | 171 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 126 insertions(+), 68 deletions(-) diff --git a/cmd.go b/cmd.go index 621c71f4..a9f75fe5 100644 --- a/cmd.go +++ b/cmd.go @@ -313,10 +313,18 @@ func handleConfig(option, value string) bool { config.PGPFetch = true case "nopgpfetch": config.PGPFetch = false - case "showdiffs": - config.ShowDiffs = true - case "noshowdiffs": - config.ShowDiffs = false + case "cleanmenu": + config.CleanMenu = true + case "nocleanmenu": + config.CleanMenu = false + case "diffmenu": + config.DiffMenu = true + case "nodiffmenu": + config.DiffMenu = false + case "editmenu": + config.EditMenu = true + case "noeditmenu": + config.EditMenu = false case "a", "aur": mode = ModeAUR case "repo": diff --git a/config.go b/config.go index 9eaa02e4..0e03126b 100644 --- a/config.go +++ b/config.go @@ -65,6 +65,9 @@ type Configuration struct { Provides bool `json:"provides"` PGPFetch bool `json:"pgpfetch"` ShowDiffs bool `json:"showdifs"` + CleanMenu bool `json:"cleanmenu"` + DiffMenu bool `json:"diffmenu"` + EditMenu bool `json:"editmenu"` } var version = "5.688" @@ -168,7 +171,9 @@ func defaultSettings(config *Configuration) { config.AnswerUpgrade = "" config.GitClone = true config.Provides = true - config.ShowDiffs = true + config.CleanMenu = false + config.DiffMenu = true + config.EditMenu = false } // Editor returns the preferred system editor. diff --git a/install.go b/install.go index 4ea59039..f52d3ad8 100644 --- a/install.go +++ b/install.go @@ -18,8 +18,6 @@ func install(parser *arguments) error { var err error var incompatible stringSet var do *depOrder - var toClean []*rpc.Pkg - var toEdit []*rpc.Pkg var aurUp upSlice var repoUp upSlice @@ -148,12 +146,15 @@ func install(parser *arguments) error { } } - toClean, toEdit, err = cleanEditNumberMenu(do.Aur, do.Bases, remoteNamesCache) - if err != nil { - return err - } + if config.CleanMenu { + askClean := pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toClean, err := cleanNumberMenu(do.Aur, do.Bases, remoteNamesCache, askClean) + if err != nil { + return err + } - cleanBuilds(toClean) + cleanBuilds(toClean) + } toSkip := pkgBuildsToSkip(do.Aur, targets) cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) @@ -161,18 +162,43 @@ func install(parser *arguments) error { return err } - if len(toEdit) > 0 { - if config.ShowDiffs { - err = showPkgBuildDiffs(toEdit, do.Bases, cloned) - } else { - err = editPkgBuilds(toEdit, do.Bases) - } + var toDiff []*rpc.Pkg + var toEdit []*rpc.Pkg + + if config.DiffMenu { + pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toDiff, err = diffNumberMenu(do.Aur, do.Bases, remoteNamesCache) if err != nil { return err } + if len(toDiff) > 0 { + err = showPkgBuildDiffs(toDiff, do.Bases, cloned) + if err != nil { + return err + } + } + } + + if config.EditMenu { + pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toEdit, err = editNumberMenu(do.Aur, do.Bases, remoteNamesCache) + if err != nil { + return err + } + + if len(toEdit) > 0 { + err = editPkgBuilds(toEdit, do.Bases) + if err != nil { + return err + } + } + } + + if len(toDiff) > 0 || len(toEdit) > 0 { oldValue := config.NoConfirm config.NoConfirm = false + fmt.Println() if !continueTask(bold(green("Proceed with install?")), "nN") { return fmt.Errorf("Aborting due to user") } @@ -355,13 +381,10 @@ func parsePackageList(dir string) (map[string]string, string, error) { return pkgdests, version, nil } -func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, []*rpc.Pkg, error) { +func pkgbuildNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) bool { toPrint := "" askClean := false - toClean := make([]*rpc.Pkg, 0) - toEdit := make([]*rpc.Pkg, 0) - for n, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) @@ -381,62 +404,84 @@ func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed fmt.Print(toPrint) - if askClean { - fmt.Println(bold(green(arrow + " Packages to cleanBuild?"))) - fmt.Println(bold(green(arrow) + cyan(" [N]one ") + "[A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)")) - fmt.Print(bold(green(arrow + " "))) - cleanInput, err := getInput(config.AnswerClean) - if err != nil { - return nil, nil, err - } + return askClean +} - cInclude, cExclude, cOtherInclude, cOtherExclude := parseNumberMenu(cleanInput) - cIsInclude := len(cExclude) == 0 && len(cOtherExclude) == 0 +func cleanNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet, hasClean bool) ([]*rpc.Pkg, error) { + toClean := make([]*rpc.Pkg, 0) - if cOtherInclude.get("abort") || cOtherInclude.get("ab") { - return nil, nil, fmt.Errorf("Aborting due to user") - } + if !hasClean { + return toClean, nil + } - if !cOtherInclude.get("n") && !cOtherInclude.get("none") { - for i, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) - if _, err := os.Stat(dir); os.IsNotExist(err) { - continue - } + fmt.Println(bold(green(arrow + " Packages to cleanBuild?"))) + fmt.Println(bold(green(arrow) + cyan(" [N]one ") + "[A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)")) + fmt.Print(bold(green(arrow + " "))) + cleanInput, err := getInput(config.AnswerClean) + if err != nil { + return nil, err + } - if !cIsInclude && cExclude.get(len(pkgs)-i) { - continue - } + cInclude, cExclude, cOtherInclude, cOtherExclude := parseNumberMenu(cleanInput) + cIsInclude := len(cExclude) == 0 && len(cOtherExclude) == 0 - if installed.get(pkg.Name) && (cOtherInclude.get("i") || cOtherInclude.get("installed")) { - toClean = append(toClean, pkg) - continue - } + if cOtherInclude.get("abort") || cOtherInclude.get("ab") { + return nil, fmt.Errorf("Aborting due to user") + } - if !installed.get(pkg.Name) && (cOtherInclude.get("no") || cOtherInclude.get("notinstalled")) { - toClean = append(toClean, pkg) - continue - } + if !cOtherInclude.get("n") && !cOtherInclude.get("none") { + for i, pkg := range pkgs { + dir := filepath.Join(config.BuildDir, pkg.PackageBase) + if _, err := os.Stat(dir); os.IsNotExist(err) { + continue + } - if cOtherInclude.get("a") || cOtherInclude.get("all") { - toClean = append(toClean, pkg) - continue - } + if !cIsInclude && cExclude.get(len(pkgs)-i) { + continue + } - if cIsInclude && (cInclude.get(len(pkgs)-i) || cOtherInclude.get(pkg.PackageBase)) { - toClean = append(toClean, pkg) - continue - } + if installed.get(pkg.Name) && (cOtherInclude.get("i") || cOtherInclude.get("installed")) { + toClean = append(toClean, pkg) + continue + } - if !cIsInclude && (!cExclude.get(len(pkgs)-i) && !cOtherExclude.get(pkg.PackageBase)) { - toClean = append(toClean, pkg) - continue - } + if !installed.get(pkg.Name) && (cOtherInclude.get("no") || cOtherInclude.get("notinstalled")) { + toClean = append(toClean, pkg) + continue + } + + if cOtherInclude.get("a") || cOtherInclude.get("all") { + toClean = append(toClean, pkg) + continue + } + + if cIsInclude && (cInclude.get(len(pkgs)-i) || cOtherInclude.get(pkg.PackageBase)) { + toClean = append(toClean, pkg) + continue + } + + if !cIsInclude && (!cExclude.get(len(pkgs)-i) && !cOtherExclude.get(pkg.PackageBase)) { + toClean = append(toClean, pkg) + continue } } } - if config.ShowDiffs { + return toClean, nil +} + +func editNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { + return editDiffNumberMenu(pkgs, bases, installed, false) +} + +func diffNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { + return editDiffNumberMenu(pkgs, bases, installed, true) +} + +func editDiffNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet, diff bool) ([]*rpc.Pkg, error) { + toEdit := make([]*rpc.Pkg, 0) + + if diff { fmt.Println(bold(green(arrow + " Diffs to show?"))) } else { fmt.Println(bold(green(arrow + " PKGBUILDs to edit?"))) @@ -447,14 +492,14 @@ func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed editInput, err := getInput(config.AnswerEdit) if err != nil { - return nil, nil, err + return nil, err } eInclude, eExclude, eOtherInclude, eOtherExclude := parseNumberMenu(editInput) eIsInclude := len(eExclude) == 0 && len(eOtherExclude) == 0 if eOtherInclude.get("abort") || eOtherInclude.get("ab") { - return nil, nil, fmt.Errorf("Aborting due to user") + return nil, fmt.Errorf("Aborting due to user") } if !eOtherInclude.get("n") && !eOtherInclude.get("none") { @@ -488,7 +533,7 @@ func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed } } - return toClean, toEdit, nil + return toEdit, nil } func cleanBuilds(pkgs []*rpc.Pkg) { From fcb8c350461b314f5e1959ea6c88a9aae7ddcab1 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 00:26:36 +0100 Subject: [PATCH 095/109] Pass to pacman when there's no AUR packages Instead of doing all the AUR stuff just pass to pacman and return. No need for any of Yay's stuff when there's no AUR involved. Of couse everything before that still happens. Upgrade menu ect. --- install.go | 243 ++++++++++++++++++++++++++--------------------------- 1 file changed, 119 insertions(+), 124 deletions(-) diff --git a/install.go b/install.go index f52d3ad8..e2cd0276 100644 --- a/install.go +++ b/install.go @@ -104,18 +104,21 @@ func install(parser *arguments) error { if err != nil { return err } + + if len(dp.Aur) == 0 { + parser.delArg("y", "refresh") + return passToPacman(parser) + } + + if len(dp.Aur) > 0 && 0 == os.Geteuid() { + return fmt.Errorf(bold(red(arrow)) + " Refusing to install AUR Packages as root, Aborting.") + } err = dp.CheckConflicts() if err != nil { return err } - hasAur := len(dp.Aur) > 0 - - if hasAur && 0 == os.Geteuid() { - return fmt.Errorf(bold(red(arrow)) + " Refusing to install AUR Packages as root, Aborting.") - } - do = getDepOrder(dp) if err != nil { return err @@ -134,99 +137,95 @@ func install(parser *arguments) error { return nil } - if hasAur { - hasAur = len(do.Aur) != 0 + do.Print() + fmt.Println() - do.Print() + if do.HasMake() { + if !continueTask("Remove make dependencies after install?", "yY") { + removeMake = true + } + } + + if config.CleanMenu { + askClean := pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toClean, err := cleanNumberMenu(do.Aur, do.Bases, remoteNamesCache, askClean) + if err != nil { + return err + } + + cleanBuilds(toClean) + } + + toSkip := pkgBuildsToSkip(do.Aur, targets) + cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) + if err != nil { + return err + } + + var toDiff []*rpc.Pkg + var toEdit []*rpc.Pkg + + if config.DiffMenu { + pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toDiff, err = diffNumberMenu(do.Aur, do.Bases, remoteNamesCache) + if err != nil { + return err + } + + if len(toDiff) > 0 { + err = showPkgBuildDiffs(toDiff, do.Bases, cloned) + if err != nil { + return err + } + } + } + + if config.EditMenu { + pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toEdit, err = editNumberMenu(do.Aur, do.Bases, remoteNamesCache) + if err != nil { + return err + } + + if len(toEdit) > 0 { + err = editPkgBuilds(toEdit, do.Bases) + if err != nil { + return err + } + } + } + + if len(toDiff) > 0 || len(toEdit) > 0 { + oldValue := config.NoConfirm + config.NoConfirm = false fmt.Println() - - if do.HasMake() { - if !continueTask("Remove make dependencies after install?", "yY") { - removeMake = true - } + if !continueTask(bold(green("Proceed with install?")), "nN") { + return fmt.Errorf("Aborting due to user") } + config.NoConfirm = oldValue + } - if config.CleanMenu { - askClean := pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) - toClean, err := cleanNumberMenu(do.Aur, do.Bases, remoteNamesCache, askClean) - if err != nil { - return err - } + err = mergePkgBuilds(do.Aur) + if err != nil { + return err + } - cleanBuilds(toClean) - } + //initial srcinfo parse before pkgver() bump + err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) + if err != nil { + return err + } - toSkip := pkgBuildsToSkip(do.Aur, targets) - cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) + incompatible, err = getIncompatible(do.Aur, srcinfosStale, do.Bases) + if err != nil { + return err + } + + if config.PGPFetch { + err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) if err != nil { return err } - - var toDiff []*rpc.Pkg - var toEdit []*rpc.Pkg - - if config.DiffMenu { - pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) - toDiff, err = diffNumberMenu(do.Aur, do.Bases, remoteNamesCache) - if err != nil { - return err - } - - if len(toDiff) > 0 { - err = showPkgBuildDiffs(toDiff, do.Bases, cloned) - if err != nil { - return err - } - } - } - - if config.EditMenu { - pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) - toEdit, err = editNumberMenu(do.Aur, do.Bases, remoteNamesCache) - if err != nil { - return err - } - - if len(toEdit) > 0 { - err = editPkgBuilds(toEdit, do.Bases) - if err != nil { - return err - } - } - } - - if len(toDiff) > 0 || len(toEdit) > 0 { - oldValue := config.NoConfirm - config.NoConfirm = false - fmt.Println() - if !continueTask(bold(green("Proceed with install?")), "nN") { - return fmt.Errorf("Aborting due to user") - } - config.NoConfirm = oldValue - } - - err = mergePkgBuilds(do.Aur) - if err != nil { - return err - } - - //initial srcinfo parse before pkgver() bump - err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) - if err != nil { - return err - } - - incompatible, err = getIncompatible(do.Aur, srcinfosStale, do.Bases) - if err != nil { - return err - } - - if config.PGPFetch { - err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) - if err != nil { - return err - } - } } if len(arguments.targets) > 0 || arguments.existsArg("u") { @@ -268,45 +267,41 @@ func install(parser *arguments) error { } } - if hasAur { - //conflicts have been checked so answer y for them - ask, _ := strconv.Atoi(cmdArgs.globals["ask"]) - uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg - cmdArgs.globals["ask"] = fmt.Sprint(uask) + //conflicts have been checked so answer y for them + ask, _ := strconv.Atoi(cmdArgs.globals["ask"]) + uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg + cmdArgs.globals["ask"] = fmt.Sprint(uask) + + err = downloadPkgBuildsSources(do.Aur, do.Bases, incompatible) + if err != nil { + return err + } + + err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible) + if err != nil { + return err + } + + if removeMake { + removeArguments := makeArguments() + removeArguments.addArg("R", "u") + + for _, pkg := range do.getMake() { + removeArguments.addTarget(pkg) + } + + oldValue := config.NoConfirm + config.NoConfirm = true + err = passToPacman(removeArguments) + config.NoConfirm = oldValue - err = downloadPkgBuildsSources(do.Aur, do.Bases, incompatible) if err != nil { return err } + } - err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible) - if err != nil { - return err - } - - if removeMake { - removeArguments := makeArguments() - removeArguments.addArg("R", "u") - - for _, pkg := range do.getMake() { - removeArguments.addTarget(pkg) - } - - oldValue := config.NoConfirm - config.NoConfirm = true - err = passToPacman(removeArguments) - config.NoConfirm = oldValue - - if err != nil { - return err - } - } - - if config.CleanAfter { - clean(do.Aur) - } - - return nil + if config.CleanAfter { + clean(do.Aur) } return nil From ab38507beacdfe33b541df8a18bbd656d4dd06d2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 18:49:35 +0100 Subject: [PATCH 096/109] Correctly set op and ignore for repo only installs --- install.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/install.go b/install.go index e2cd0276..99e3868a 100644 --- a/install.go +++ b/install.go @@ -106,7 +106,9 @@ func install(parser *arguments) error { } if len(dp.Aur) == 0 { + parser.op = "S" parser.delArg("y", "refresh") + parser.options["ignore"] = arguments.options["ignore"] return passToPacman(parser) } From 065efdbcc06713930197bf7e6cce3a1b95b1e34d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 19:50:03 +0100 Subject: [PATCH 097/109] Enable clean menu by default I swear set this to true before merging 8430c41 but apparently I didnt. --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 0e03126b..bb66d6ea 100644 --- a/config.go +++ b/config.go @@ -171,7 +171,7 @@ func defaultSettings(config *Configuration) { config.AnswerUpgrade = "" config.GitClone = true config.Provides = true - config.CleanMenu = false + config.CleanMenu = true config.DiffMenu = true config.EditMenu = false } From 01fa34093f18c1f0d3b8c6a3178264428a9baa0c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 19:13:40 +0100 Subject: [PATCH 098/109] Support answerdiff to match answer{clean,edit} --- cmd.go | 4 ++++ config.go | 2 ++ install.go | 22 ++++++++++++++-------- parser.go | 2 ++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/cmd.go b/cmd.go index a9f75fe5..083a6654 100644 --- a/cmd.go +++ b/cmd.go @@ -262,6 +262,10 @@ func handleConfig(option, value string) bool { config.AnswerClean = value case "noanswerclean": config.AnswerClean = "" + case "answerdiff": + config.AnswerDiff = value + case "noanswerdiff": + config.AnswerDiff = "" case "answeredit": config.AnswerEdit = value case "noansweredit": diff --git a/config.go b/config.go index bb66d6ea..4e50f32d 100644 --- a/config.go +++ b/config.go @@ -45,6 +45,7 @@ type Configuration struct { ReDownload string `json:"redownload"` ReBuild string `json:"rebuild"` AnswerClean string `json:"answerclean"` + AnswerDiff string `json:"answerdiff"` AnswerEdit string `json:"answeredit"` AnswerUpgrade string `json:"answerupgrade"` GitBin string `json:"gitbin"` @@ -167,6 +168,7 @@ func defaultSettings(config *Configuration) { config.ReDownload = "no" config.ReBuild = "no" config.AnswerClean = "" + config.AnswerDiff = "" config.AnswerEdit = "" config.AnswerUpgrade = "" config.GitClone = true diff --git a/install.go b/install.go index 99e3868a..cb8b0d42 100644 --- a/install.go +++ b/install.go @@ -477,19 +477,25 @@ func diffNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stri func editDiffNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet, diff bool) ([]*rpc.Pkg, error) { toEdit := make([]*rpc.Pkg, 0) + var editInput string + var err error + + fmt.Println(bold(green(arrow) + cyan(" [N]one ") + "[A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)")) if diff { fmt.Println(bold(green(arrow + " Diffs to show?"))) + fmt.Print(bold(green(arrow + " "))) + editInput, err = getInput(config.AnswerDiff) + if err != nil { + return nil, err + } } else { fmt.Println(bold(green(arrow + " PKGBUILDs to edit?"))) - } - fmt.Println(bold(green(arrow) + cyan(" [N]one ") + "[A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)")) - - fmt.Print(bold(green(arrow + " "))) - - editInput, err := getInput(config.AnswerEdit) - if err != nil { - return nil, err + fmt.Print(bold(green(arrow + " "))) + editInput, err = getInput(config.AnswerEdit) + if err != nil { + return nil, err + } } eInclude, eExclude, eOtherInclude, eOtherExclude := parseNumberMenu(editInput) diff --git a/parser.go b/parser.go index f2a64d80..8a2ce936 100644 --- a/parser.go +++ b/parser.go @@ -469,6 +469,8 @@ func hasParam(arg string) bool { return true case "answerclean": return true + case "answerdiff": + return true case "answeredit": return true case "answerupgrade": From d0bc1d70d9947f68add6ddfaa53a318a2ca11b9a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 19:38:53 +0100 Subject: [PATCH 099/109] Document new flags --- cmd.go | 10 ++++++++-- doc/yay.8 | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/cmd.go b/cmd.go index 083a6654..b147064a 100644 --- a/cmd.go +++ b/cmd.go @@ -58,11 +58,19 @@ Permanent configuration options: --requestsplitn Max amount of packages to query per AUR request --sortby Sort AUR results by a specific field during search --answerclean Set a predetermined answer for the clean build menu + --answerdiff Set a predetermined answer for the diff menu --answeredit Set a predetermined answer for the edit pkgbuild menu --answerupgrade Set a predetermined answer for the upgrade menu --noanswerclean Unset the answer for the clean build menu + --noanswerdiff Unset the answer for the edit diff menu --noansweredit Unset the answer for the edit pkgbuild menu --noanswerupgrade Unset the answer for the upgrade menu + --cleanmenu Give the option to clean build PKGBUILDS + --diffmenu Give the option to show diffs for build files + --editmenu Give the option to edit/view PKGBUILDS + --nocleanmenu Don't clean build PKGBUILDS + --nodiffmenu Don't show diffs for build files + --noeditmenu Don't edit/view PKGBUILDS --afterclean Remove package sources after successful install --noafterclean Do not remove package sources after successful build @@ -73,8 +81,6 @@ Permanent configuration options: --nodevel Do not check development packages --gitclone Use git clone for PKGBUILD retrieval --nogitclone Never use git clone for PKGBUILD retrieval - --showdiffs Show diffs for build files - --noshowdiffs Always show the entire PKGBUILD --rebuild Always build target packages --rebuildall Always build all AUR packages --norebuild Skip package build if in cache and up to date diff --git a/doc/yay.8 b/doc/yay.8 index 642fae28..3a87b9bc 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -232,6 +232,13 @@ will be used instead of reading from standard input but will be treated exactly the same when parsed\&. .RE .PP +\fB\-\-answerdiff \fR +.RS 4 +Set a predetermined answer for the edit diff menu question\&. This answer +will be used instead of reading from standard input but will be treated exactly +the same when parsed\&. +.RE +.PP \fB\-\-answeredit \fR .RS 4 Set a predetermined answer for the edit pkgbuild menu question\&. This answer @@ -251,6 +258,11 @@ reading from standard input but will be treated exactly the same\&. Unset the answer for the clean build menu\&. .RE .PP +\fB\-\-noanswerdiff\fR +.RS 4 +Unset the answer for the diff menu\&. +.RE +.PP \fB\-\-noansweredit\fR .RS 4 Unset the answer for the edit pkgbuild menu\&. @@ -261,6 +273,42 @@ Unset the answer for the edit pkgbuild menu\&. Unset the answer for the upgrade menu\&. .RE .PP +\fB\-\-cleanmenu\fR +.RS 4 +Show the clean menu\&. This menu gives you the chance to fully delete the +downloaded build files from Yay's cache before redownloing a fresh copy\&. +.RE +.PP +\fB\-\-diffmenu\fR +.RS 4 +Show the diff menu\&. This menu gives you the option to view diffs from +build files before building\&. +.RE +.PP +\fB\-\-editmenu\fR +.RS 4 +Show the edit menu\&. This menu gives you the option to edit or view PKGBUILDs +before building\&. + +\fBWarning\fR: Yay resolves dependencies ahead of time via the RPC\&. It is not +recommended to edit pkgbuild variables unless you know what you are doing\&. +.RE +.PP +\fB\-\-nocleanmenu\fR +.RS 4 +Do not show the clean menu\&. +.RE +.PP +\fB\-\-nodiffmenu\fR +.RS 4 +Do not show the diff menu\&. +.RE +.PP +\fB\-\-noeditmenu\fR +.RS 4 +Do not show the edit menu\&. +.RE +.PP \fB\-\-topdown\fR .RS 4 Display repository packages first and then AUR packages\&. From 42f05086250d7cde147a85b05a24b3a3d765211e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 19:48:20 +0100 Subject: [PATCH 100/109] Add upgrademenu to match {clean,diff,edit}menu --- cmd.go | 4 ++++ config.go | 2 ++ install.go | 2 +- upgrade.go | 8 ++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index b147064a..d07efa86 100644 --- a/cmd.go +++ b/cmd.go @@ -323,6 +323,10 @@ func handleConfig(option, value string) bool { config.PGPFetch = true case "nopgpfetch": config.PGPFetch = false + case "upgrademenu": + config.UpgradeMenu = true + case "noupgrademenu": + config.UpgradeMenu = false case "cleanmenu": config.CleanMenu = true case "nocleanmenu": diff --git a/config.go b/config.go index 4e50f32d..bd8efcf2 100644 --- a/config.go +++ b/config.go @@ -66,6 +66,7 @@ type Configuration struct { Provides bool `json:"provides"` PGPFetch bool `json:"pgpfetch"` ShowDiffs bool `json:"showdifs"` + UpgradeMenu bool `json:"upgrademenu"` CleanMenu bool `json:"cleanmenu"` DiffMenu bool `json:"diffmenu"` EditMenu bool `json:"editmenu"` @@ -173,6 +174,7 @@ func defaultSettings(config *Configuration) { config.AnswerUpgrade = "" config.GitClone = true config.Provides = true + config.UpgradeMenu = true config.CleanMenu = true config.DiffMenu = true config.EditMenu = false diff --git a/install.go b/install.go index cb8b0d42..b07677db 100644 --- a/install.go +++ b/install.go @@ -104,7 +104,7 @@ func install(parser *arguments) error { if err != nil { return err } - + if len(dp.Aur) == 0 { parser.op = "S" parser.delArg("y", "refresh") diff --git a/upgrade.go b/upgrade.go index 2ffb3333..4daac107 100644 --- a/upgrade.go +++ b/upgrade.go @@ -343,6 +343,14 @@ func upgradePkgs(aurUp, repoUp upSlice) (stringSet, stringSet, error) { return ignore, aurNames, nil } + if !config.UpgradeMenu { + for _, pkg := range aurUp { + aurNames.set(pkg.Name) + } + + return ignore, aurNames, nil + } + sort.Sort(repoUp) sort.Sort(aurUp) allUp := append(repoUp, aurUp...) From 4bfa5f6128d8d5c027855b665791a994f0e1d053 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 11 Jun 2018 20:09:29 +0100 Subject: [PATCH 101/109] Document --[no]upgrademenu --- cmd.go | 2 ++ doc/yay.8 | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/cmd.go b/cmd.go index d07efa86..bea4a537 100644 --- a/cmd.go +++ b/cmd.go @@ -68,9 +68,11 @@ Permanent configuration options: --cleanmenu Give the option to clean build PKGBUILDS --diffmenu Give the option to show diffs for build files --editmenu Give the option to edit/view PKGBUILDS + --upgrademenu Show a detailed list of updates with the option to skip any --nocleanmenu Don't clean build PKGBUILDS --nodiffmenu Don't show diffs for build files --noeditmenu Don't edit/view PKGBUILDS + --noupgrademenu Don't show the upgrade menu --afterclean Remove package sources after successful install --noafterclean Do not remove package sources after successful build diff --git a/doc/yay.8 b/doc/yay.8 index 3a87b9bc..dfd26df9 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -294,6 +294,18 @@ before building\&. recommended to edit pkgbuild variables unless you know what you are doing\&. .RE .PP +\fB\-\-upgrademenu\fR +.RS 4 +Show a detailed list of updates in a similar format to VerbosePkgLists\&. +Upgrades can also be skipped using numbers, number ranges or repo names\&. +Adidionally ^ can be used to invert the selection\&. + +\fBWarning\fR: It is not recommended to skip updates from the repositores as +this can lead to partial upgrades\&. This feature is intended to easily skip AUR +updates on the fly that may be broken or have a long compile time\&. Ultimately +it is up to the user what upgrades they skip\&. +.RE +.PP \fB\-\-nocleanmenu\fR .RS 4 Do not show the clean menu\&. @@ -309,6 +321,11 @@ Do not show the diff menu\&. Do not show the edit menu\&. .RE .PP +\fB\-\-noupgrademenu\fR +.RS 4 +Do not show the upgrade menu\&. +.RE +.PP \fB\-\-topdown\fR .RS 4 Display repository packages first and then AUR packages\&. From b76fbc8694396d04e48500d5514c376e6254e4b0 Mon Sep 17 00:00:00 2001 From: Stephen Brown II Date: Mon, 11 Jun 2018 15:11:16 -0500 Subject: [PATCH 102/109] Remove ShowDiffs from config struct Following the improvements in #480, #485, #486, a tiny bit of cleanup for a lone, forgotten line. Plus the typo had been bugging me since I first saw it. --- config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config.go b/config.go index bd8efcf2..60d34c5d 100644 --- a/config.go +++ b/config.go @@ -65,7 +65,6 @@ type Configuration struct { GitClone bool `json:"gitclone"` Provides bool `json:"provides"` PGPFetch bool `json:"pgpfetch"` - ShowDiffs bool `json:"showdifs"` UpgradeMenu bool `json:"upgrademenu"` CleanMenu bool `json:"cleanmenu"` DiffMenu bool `json:"diffmenu"` From 9ecc60455854d2862b4546dc18a982a02693a7bc Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 12 Jun 2018 21:06:21 +0100 Subject: [PATCH 103/109] Reset before editing Edits where reset via git before building packages. This allows edits to actually effect the build package. --- install.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/install.go b/install.go index b07677db..b890bf6a 100644 --- a/install.go +++ b/install.go @@ -182,6 +182,21 @@ func install(parser *arguments) error { } } + if len(toDiff) > 0 { + oldValue := config.NoConfirm + config.NoConfirm = false + fmt.Println() + if !continueTask(bold(green("Proceed with install?")), "nN") { + return fmt.Errorf("Aborting due to user") + } + config.NoConfirm = oldValue + } + + err = mergePkgBuilds(do.Aur) + if err != nil { + return err + } + if config.EditMenu { pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) toEdit, err = editNumberMenu(do.Aur, do.Bases, remoteNamesCache) @@ -197,7 +212,7 @@ func install(parser *arguments) error { } } - if len(toDiff) > 0 || len(toEdit) > 0 { + if len(toEdit) > 0 { oldValue := config.NoConfirm config.NoConfirm = false fmt.Println() @@ -207,11 +222,6 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - err = mergePkgBuilds(do.Aur) - if err != nil { - return err - } - //initial srcinfo parse before pkgver() bump err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) if err != nil { From 1952f88c34cf8991496aef2eea581fff5d055b2c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 12 Jun 2018 19:27:19 +0100 Subject: [PATCH 104/109] Remove a space --- cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index bea4a537..67607085 100644 --- a/cmd.go +++ b/cmd.go @@ -58,7 +58,7 @@ Permanent configuration options: --requestsplitn Max amount of packages to query per AUR request --sortby Sort AUR results by a specific field during search --answerclean Set a predetermined answer for the clean build menu - --answerdiff Set a predetermined answer for the diff menu + --answerdiff Set a predetermined answer for the diff menu --answeredit Set a predetermined answer for the edit pkgbuild menu --answerupgrade Set a predetermined answer for the upgrade menu --noanswerclean Unset the answer for the clean build menu From 07b3d76a66e6d098a2b1e12a3ebd643b13a6eaff Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 12 Jun 2018 19:43:04 +0100 Subject: [PATCH 105/109] Update bash and zsh completion --- completions/bash | 9 +++++++-- completions/zsh | 18 ++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/completions/bash b/completions/bash index 276389b7..64fd5558 100644 --- a/completions/bash +++ b/completions/bash @@ -51,6 +51,9 @@ _pacman_pkg() { )" } + + + _yay() { local common core cur database prev query remove sync upgrade yays print o COMPREPLY=() @@ -71,8 +74,10 @@ _yay() { noconfirm noprogressbar noscriptlet quiet save mflags buildir editor makepkg pacman tar git gpg gpgflags config requestsplitn sudoloop nosudoloop redownload noredownload redownloadall rebuild rebuildall rebuildtree norebuild - sortby answerclean answeredit answerupgrade noanswerclean noansweredit - noanswerupgrade root verbose' 'b d h q r v') + sortby answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff + noansweredit noanswerupgrade cleanmenu diffmenu editmenu upgrademenu + nocleanmenu nodiffmenu noupgrademenu provides noprovides pgpfetch nopgpfetch + root verbose aur repo' 'a b d h q r v') core=('database files help query remove sync upgrade version' 'D F Q R S U V h') for o in 'D database' 'F files' 'Q query' 'R remove' 'S sync' 'U upgrade' 'Y yays' 'P print'; do diff --git a/completions/zsh b/completions/zsh index 715adcd9..2ee389e1 100644 --- a/completions/zsh +++ b/completions/zsh @@ -22,6 +22,9 @@ _pacman_opts_commands=( # options for passing to _arguments: options common to all commands _pacman_opts_common=( + '--repo[Assume targets are from the repositories]' + {-a,--aur}'[Assume targets are from the AUR]' + '--arch[Set an alternate architecture]' {-b,--dbpath}'[Alternate database location]:database_location:_files -/' '--color[colorize the output]:color options:(always never auto)' @@ -52,11 +55,18 @@ _pacman_opts_common=( '--sortby[Sort AUR results by a specific field during search]:sortby options:(votes popularity id baseid name base submitted modified)' '--answerclean[Set a predetermined answer for the clean build menu]:answer' '--answeredit[Set a predetermined answer for the edit pkgbuild menu]:answer' - '--answerupgrade[Set a predetermined answer for the upgrade menu]:answe' + '--answerupgrade[Set a predetermined answer for the upgrade menu]:answer' '--noanswerclean[Unset the answer for the clean build menu]' '--noansweredit[Unset the answer for the edit pkgbuild menu]' '--noanswerupgrade[Unset the answer for the upgrade menu]' - + '--cleanmenu[Give the option to clean build PKGBUILDS]' + '--diffmenu[Give the option to show diffs for build files]' + '--editmenu[Give the option to edit/view PKGBUILDS]' + '--upgrademenu[Show a detailed list of updates with the option to skip any]' + "--nocleanmenu[Don't clean build PKGBUILDS]" + "--nodiffmenu[Don't show diffs for build files]" + "--noeditmenu[Don't edit/view PKGBUILDS]" + "--noupgrademenu[Don't show the upgrade menu]" '--bottomup[Show AUR packages first]' '--topdown[Show repository packages first]' @@ -71,6 +81,10 @@ _pacman_opts_common=( '--noredownload[Skip pkgbuild download if in cache and up to date]' '--rebuild[Always build target packages]' '--rebuildall[Always build all AUR packages]' + '--provides[Look for matching provders when searching for packages]' + '--noprovides[Just look for packages by pkgname]' + '--pgpfetch[Prompt to import PGP keys from PKGBUILDs]' + "--nopgpfetch[Don't prompt to import PGP keys]" '--rebuildtree[Always build all AUR packages even if installed]' '--norebuild[Skip package build if in cache and up to date]' '--mflags[Pass arguments to makepkg]:mflags' From 87daef421eda9bffc6bfb9905a6a3f7bf380e6fd Mon Sep 17 00:00:00 2001 From: J Guerreiro Date: Tue, 19 Jun 2018 10:13:56 +0100 Subject: [PATCH 106/109] Update for yay release Prepare README for predicted issues so when they do appear users can be shamed for not reading `READMEs` --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 85a46d13..52131ae7 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,6 @@ Yet another Yogurt - An AUR Helper written in Go -`yay: error while loading shared libraries: libalpm.so.10: cannot open shared object file: No such file or directory` -Pacman 5.1 migration explained [here](https://github.com/Jguer/yay/releases/tag/v6.784) - #### Packages [![yay](https://img.shields.io/aur/version/yay.svg?label=yay)](https://aur.archlinux.org/packages/yay/) [![yay-bin](https://img.shields.io/aur/version/yay-bin.svg?label=yay-bin)](https://aur.archlinux.org/packages/yay-bin/) [![yay-git](https://img.shields.io/aur/version/yay-git.svg?label=yay-git)](https://aur.archlinux.org/packages/yay-git/) [![GitHub license](https://img.shields.io/github/license/jguer/yay.svg)](https://github.com/Jguer/yay/blob/master/LICENSE) @@ -85,9 +82,6 @@ Currently yay Depends on: * https://github.com/mikkeloscar/gopkgbuild * https://github.com/mikkeloscar/aur - - - ## Frequently Asked Questions * Yay does not display colored output. How do I fix it? @@ -99,6 +93,13 @@ Currently yay Depends on: if the output can fit one terminal length. This can be overridden by exporting your own flags `export LESS=SRX`. +* Yay is not asking me to edit PKGBUILDS and I don't like diff menu! What do? + `yay --editmenu --nodiffmenu --save` + +* Only act on AUR packages or only on repo packages? + `yay -{OPERATION} --aur` + `yay -{OPERATION} --repo` + ## Examples of Custom Operations * `yay ` presents package selection menu From a8d91661134fc0e4d363127f87b579bf4e088124 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 19 Jun 2018 10:51:10 +0100 Subject: [PATCH 107/109] Fix some fish completions. Fixes #498. Add missing flags --- completions/fish | 51 +++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/completions/fish b/completions/fish index f1446adf..3049384c 100644 --- a/completions/fish +++ b/completions/fish @@ -3,6 +3,8 @@ # Updated for yay by jguer set -l progname yay +complete -e -c $progname +complete -c $progname -f set -l listinstalled "(pacman -Q | string replace ' ' \t)" # This might be an issue if another package manager is also installed (e.g. for containers) @@ -10,7 +12,7 @@ set -l listall "(yay -Pcf)" set -l listrepos "(__fish_print_pacman_repos)" set -l listgroups "(pacman -Sg)\t'Package Group'" set -l listpacman "(__fish_print_packages)" -set -l noopt 'not __fish_contains_opt -s S -s D -s Q -s R -s U -s T -s F database query sync remove upgrade deptest files' +set -l noopt 'not __fish_contains_opt -s Y -s G -s V -s S -s D -s Q -s R -s U -s T -s F database query sync remove upgrade deptest files' set -l database '__fish_contains_opt -s D database' set -l getpkgbuild '__fish_contains_opt -s G getpkgbuild' set -l print '__fish_contains_opt -s P print' @@ -21,30 +23,29 @@ set -l upgrade '__fish_contains_opt -s U upgrade' set -l files '__fish_contains_opt -s F files' set -l yayspecific '__fish_contains_opt -s Y yay' -complete -c pacman -e -complete -c pacman -f - # HACK: We only need these two to coerce fish to stop file completion and complete options -complete -c $progname -n $noopt -a "-D" -d "Modify the package database" -complete -c $progname -n $noopt -a "-Q" -d "Query the package database" +# complete -c $progname -n $noopt -a "-D" -d "Modify the package database" +# complete -c $progname -n $noopt -a "-Q" -d "Query the package database" + # Primary operations complete -c $progname -s D -f -l database -n $noopt -d 'Modify the package database' -complete -c $progname -s Q -f -l query -n $noopt -d 'Query the package database' +complete -c $progname -s F -f -l files -n $noopt -d 'Query the files database' complete -c $progname -s G -f -l getpkgbuild -n $noopt -d 'Get PKGBUILD from ABS or AUR' +complete -c $progname -s P -f -l print -n $noopt -d 'Print information' +complete -c $progname -s Q -f -l query -n $noopt -d 'Query the package database' complete -c $progname -s R -f -l remove -n $noopt -d 'Remove packages from the system' complete -c $progname -s S -f -l sync -n $noopt -d 'Synchronize packages' complete -c $progname -s T -f -l deptest -n $noopt -d 'Check if dependencies are installed' complete -c $progname -s U -f -l upgrade -n $noopt -d 'Upgrade or add a local package' -complete -c $progname -s F -f -l files -n $noopt -d 'Query the files database' -complete -c $progname -s G -f -l getpkgbuild -n $noopt -d 'Get PKGBUILD from ABS or AUR' -complete -c $progname -s P -f -l print -n $noopt -d 'Print information' complete -c $progname -s Y -f -l yay -n $noopt -d 'Yay specific operations' - -complete -c $progname -s V -f -l version -d 'Display version and exit' -complete -c $progname -s h -f -l help -d 'Display help' +complete -c $progname -s V -f -l version -n $noopt -d 'Display version and exit' +complete -c $progname -s h -f -l help -n $noopt -d 'Display help' # General options # Only offer these once a command has been given so they get prominent display +complete -c $progname -n "not $noopt" -s a -l aur -d 'Assume targets are from the repositories' +complete -c $progname -n "not $noopt" -l repo -d 'Assume targets are from the AUR' + complete -c $progname -n "not $noopt" -s b -l dbpath -d 'Alternative database location' -xa '(__fish_complete_directories)' complete -c $progname -n "not $noopt" -s r -l root -d 'Alternative installation root' complete -c $progname -n "not $noopt" -s v -l verbose -d 'Output more status messages' @@ -73,6 +74,7 @@ complete -c $progname -n "not $noopt" -l mflags -d 'Pass the following options t complete -c $progname -n "not $noopt" -l gpgflags -d 'Pass the following options to gpg' -f complete -c $progname -n "not $noopt" -l buildir -d 'Specify the build directory' -f complete -c $progname -n "not $noopt" -l editor -d 'Editor to use' -f +complete -c $progname -n "not $noopt" -l editorflags -d 'Editor flags to use' -f complete -c $progname -n "not $noopt" -l makepkg -d 'Makepkg command to use' -f complete -c $progname -n "not $noopt" -l pacman -d 'Pacman command to use' -f complete -c $progname -n "not $noopt" -l tar -d 'Tar command to use' -f @@ -98,10 +100,24 @@ complete -c $progname -n "not $noopt" -l noanswerclean -d 'Unset the answer for complete -c $progname -n "not $noopt" -l noansweredit -d 'Unset the answer for the edit pkgbuild menu' -f complete -c $progname -n "not $noopt" -l noanswerupgrade -d 'Unset the answer for the upgrade menu' -f +complete -c $progname -n "not $noopt" -l cleanmenu -d 'Give the option to clean build PKGBUILDS' -f +complete -c $progname -n "not $noopt" -l diffmenu -d 'Give the option to show diffs for build files' -f +complete -c $progname -n "not $noopt" -l editmenu -d 'Give the option to edit/view PKGBUILDS' -f +complete -c $progname -n "not $noopt" -l upgrademenu -d 'Show a detailed list of updates with the option to skip any' -f +complete -c $progname -n "not $noopt" -l nocleanmenu -d 'Do not clean build PKGBUILDS' -f +complete -c $progname -n "not $noopt" -l nodiffmenu -d 'Do not show diffs for build files' -f +complete -c $progname -n "not $noopt" -l noeditmenu -d 'Do not edit/view PKGBUILDS' -f +complete -c $progname -n "not $noopt" -l noupgrademenu -d 'Do not show the upgrade menu' -f + + +complete -c $progname -n "not $noopt" -l provides -d 'Look for matching provders when searching for packages' +complete -c $progname -n "not $noopt" -l noprovides -d 'Just look for packages by pkgname' +complete -c $progname -n "not $noopt" -l pgpfetch -d 'Prompt to import PGP keys from PKGBUILDs' +complete -c $progname -n "not $noopt" -l nopgpfetch -d 'Do not prompt to import PGP keys' + # Yay options complete -c $progname -n $yayspecific -s c -l clean -d 'Remove unneeded dependencies' -f -complete -c $progname -n $yayspecific -s g -l getpkgbuild -d 'Download PKGBUILD from ABS or AUR' -xa "$listall" -f -complete -c $progname -n $yayspecific -l gendb -d 'Display system package statistics' -f +complete -c $progname -n $yayspecific -l gendb -d 'Generate development package DB' -f # Print options complete -c $progname -n $print -s d -l defaultconfig -d 'Print current yay configuration' -f @@ -197,8 +213,7 @@ complete -c $progname -n "$files" -s q -l quiet -d 'Show less information' -f complete -c $progname -n "$files" -l machinereadable -d 'Show in machine readable format: repo\0pkgname\0pkgver\0path\n' -f # Upgrade options -# Theoretically, pacman reads packages in all formats that libarchive supports -# In practice, it's going to be tar.xz or tar.gz -# Using "pkg.tar.*" here would change __fish_complete_suffix's descriptions to "unknown" complete -c $progname -n "$upgrade" -xa '(__fish_complete_suffix pkg.tar.xz)' -d 'Package file' complete -c $progname -n "$upgrade" -xa '(__fish_complete_suffix pkg.tar.gz)' -d 'Package file' +complete -c $progname -n "$upgrade" -xa '(__fish_complete_suffix pkg.tar.lzo)' -d 'Package file' +complete -c $progname -n "$upgrade" -xa '(__fish_complete_suffix pkg.tar)' -d 'Package file' From 21a8569fb04e5b7bd05a39253217b510b179d815 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 19 Jun 2018 10:54:27 +0100 Subject: [PATCH 108/109] Add missing editorflags --- completions/zsh | 1 + 1 file changed, 1 insertion(+) diff --git a/completions/zsh b/completions/zsh index 2ee389e1..d1df34a1 100644 --- a/completions/zsh +++ b/completions/zsh @@ -46,6 +46,7 @@ _pacman_opts_common=( '--builddir[Directory to use for building AUR Packages]:build dir:_files -/' '--editor[Editor to use when editing PKGBUILDs]:editor:_files' + '--editorflags[Flags to pass to editor]' '--makepkg[makepkg command to use]:makepkg:_files' '--pacman[pacman command to use]:pacman:_files' '--tar[bsdtar command to use]:tar:_files' From 6d04c2ebce40848abdbc2a777bfa27f95cda247a Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 19 Jun 2018 11:00:47 +0100 Subject: [PATCH 109/109] Update vendored dependencies --- Gopkg.lock | 4 ++-- vendor/github.com/jguer/go-alpm/conf.go | 1 + vendor/github.com/mikkeloscar/gopkgbuild/lex.go | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 72030adc..1f3275b6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,7 +5,7 @@ branch = "master" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "f09b14fad0ccb0df7e5b699da8bcf3b45db4d0ab" + revision = "1114f773cdfb05f577438f7a0538eccabc9cf012" [[projects]] branch = "master" @@ -17,7 +17,7 @@ branch = "master" name = "github.com/mikkeloscar/gopkgbuild" packages = ["."] - revision = "7b0e7c63b22efc73e1c10e6f3117fdc03cd21816" + revision = "2bb4f1f1db67f81fe50f9c1c4ad9db4f20fd6b22" [solve-meta] analyzer-name = "dep" diff --git a/vendor/github.com/jguer/go-alpm/conf.go b/vendor/github.com/jguer/go-alpm/conf.go index a9922565..18033239 100644 --- a/vendor/github.com/jguer/go-alpm/conf.go +++ b/vendor/github.com/jguer/go-alpm/conf.go @@ -201,6 +201,7 @@ lineloop: curRepo.Servers = append(curRepo.Servers, line.Values...) continue lineloop case "Include": + conf.Include = append(conf.Include, line.Values[0]) f, err := os.Open(line.Values[0]) if err != nil { err = fmt.Errorf("error while processing Include directive at line %d: %s", diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/lex.go b/vendor/github.com/mikkeloscar/gopkgbuild/lex.go index 12518bcb..dd2d429f 100644 --- a/vendor/github.com/mikkeloscar/gopkgbuild/lex.go +++ b/vendor/github.com/mikkeloscar/gopkgbuild/lex.go @@ -211,6 +211,8 @@ func lexEnv(l *lexer) stateFn { } case r == '\t': l.ignore() + case r == ' ': + l.ignore() case r == '#': return lexComment default: