From 2e8d2b4d2caabc5afdde870245330077ac39b1b7 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 19 Jun 2018 11:31:39 +0100 Subject: [PATCH 001/155] Bump MAJOR_VERSION --- Makefile | 2 +- config.go | 2 +- doc/yay.8 | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 912aec57..d2fd34fa 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ PREFIX := /usr DESTDIR := ifndef VERSION -MAJORVERSION := 6 +MAJORVERSION := 7 MINORVERSION ?= $(shell git rev-list --count master) endif VERSION := ${MAJORVERSION}.${MINORVERSION} diff --git a/config.go b/config.go index 60d34c5d..2afca209 100644 --- a/config.go +++ b/config.go @@ -71,7 +71,7 @@ type Configuration struct { EditMenu bool `json:"editmenu"` } -var version = "5.688" +var version = "7.885" // configFileName holds the name of the config file. const configFileName string = "config.json" diff --git a/doc/yay.8 b/doc/yay.8 index dfd26df9..4a359041 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -1,5 +1,5 @@ '\" t -.TH "YAY" "8" "2018\-06\-04" "Yay v6\&.784+" "Yay Manual" +.TH "YAY" "8" "2018\-06\-04" "Yay v7\&.885+" "Yay Manual" .nh .ad l .SH "NAME" @@ -365,7 +365,7 @@ previously installed packages still apply\&. .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\&. +\fB$GIT_PAGER\fR or \fB$PAGER\fR environment variables\&. .RE .PP \fB\-\-noshowdiffs\fR From f5a35d4d1d6e6c70b29f70efc715628e9608177c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 19 Jun 2018 22:20:24 +0100 Subject: [PATCH 002/155] Correctly handle AUR providers during noconfirm --- print.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print.go b/print.go index f71fc5a7..3f571a27 100644 --- a/print.go +++ b/print.go @@ -595,8 +595,8 @@ func providerMenu(dep string, providers providers) *rpc.Pkg { fmt.Print("\nEnter a number (default=1): ") if config.NoConfirm { - fmt.Println() - break + fmt.Println("1") + return providers.Pkgs[0] } reader := bufio.NewReader(os.Stdin) From ea5a94e0f8bb5f76879099e6d319c0c0102231c2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 22 Jun 2018 15:17:34 +0100 Subject: [PATCH 003/155] Remove default usage of --ask --ask is no longer used when installing AUR packages, instead pass no confirm when we know there are no conflicts and wait for manual confirmation when there are. This means that when there are no conflicts there should be no change in behaviour and the user will not need to intervene at all. The old behaviour can still be used with --useask. --- cmd.go | 4 ++++ config.go | 2 ++ depCheck.go | 11 ++++++++--- install.go | 34 ++++++++++++++++++++++++---------- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/cmd.go b/cmd.go index 67607085..aaf99f74 100644 --- a/cmd.go +++ b/cmd.go @@ -341,6 +341,10 @@ func handleConfig(option, value string) bool { config.EditMenu = true case "noeditmenu": config.EditMenu = false + case "useask": + config.UseAsk = true + case "nouseask": + config.UseAsk = false case "a", "aur": mode = ModeAUR case "repo": diff --git a/config.go b/config.go index 2afca209..18f47161 100644 --- a/config.go +++ b/config.go @@ -69,6 +69,7 @@ type Configuration struct { CleanMenu bool `json:"cleanmenu"` DiffMenu bool `json:"diffmenu"` EditMenu bool `json:"editmenu"` + UseAsk bool `json:"useask"` } var version = "7.885" @@ -177,6 +178,7 @@ func defaultSettings(config *Configuration) { config.CleanMenu = true config.DiffMenu = true config.EditMenu = false + config.UseAsk = false } // Editor returns the preferred system editor. diff --git a/depCheck.go b/depCheck.go index 08e9a632..3ed42150 100644 --- a/depCheck.go +++ b/depCheck.go @@ -124,7 +124,7 @@ func (dp *depPool) checkReverseConflicts(conflicts mapStringSet) { }) } -func (dp *depPool) CheckConflicts() error { +func (dp *depPool) CheckConflicts() (mapStringSet, error) { var wg sync.WaitGroup innerConflicts := make(mapStringSet) conflicts := make(mapStringSet) @@ -159,12 +159,17 @@ func (dp *depPool) CheckConflicts() error { fmt.Println(str) } - return fmt.Errorf("Unresolvable package conflicts, aborting") + return nil, fmt.Errorf("Unresolvable package conflicts, aborting") } if len(conflicts) != 0 { fmt.Println() fmt.Println(bold(red(arrow)), bold("Package conflicts found:")) + + if !config.UseAsk { + fmt.Println(bold(red(arrow)), bold("You will have to confirm these when installing")) + } + for name, pkgs := range conflicts { str := red(bold(smallArrow)) + " Installing " + cyan(name) + " will remove:" for pkg := range pkgs { @@ -178,7 +183,7 @@ func (dp *depPool) CheckConflicts() error { fmt.Println() } - return nil + return conflicts, nil } type missing struct { diff --git a/install.go b/install.go index b890bf6a..52464eda 100644 --- a/install.go +++ b/install.go @@ -116,7 +116,7 @@ func install(parser *arguments) error { return fmt.Errorf(bold(red(arrow)) + " Refusing to install AUR Packages as root, Aborting.") } - err = dp.CheckConflicts() + conflicts, err := dp.CheckConflicts() if err != nil { return err } @@ -279,17 +279,12 @@ func install(parser *arguments) error { } } - //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) + err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible, conflicts) if err != nil { return err } @@ -745,7 +740,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco return } -func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg.PKGBUILD, parser *arguments, incompatible stringSet) error { +func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg.PKGBUILD, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { for _, pkg := range do.Aur { dir := filepath.Join(config.BuildDir, pkg.PackageBase) built := true @@ -807,6 +802,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg arguments.clearTargets() arguments.op = "U" arguments.delArg("confirm") + arguments.delArg("noconfirm") arguments.delArg("c", "clean") arguments.delArg("q", "quiet") arguments.delArg("q", "quiet") @@ -814,6 +810,26 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg arguments.delArg("u", "sysupgrade") arguments.delArg("w", "downloadonly") + oldConfirm := config.NoConfirm + + //conflicts have been checked so answer y for them + if config.UseAsk { + ask, _ := strconv.Atoi(cmdArgs.globals["ask"]) + uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg + cmdArgs.globals["ask"] = fmt.Sprint(uask) + } else { + conflict := false + for _, split := range do.Bases[pkg.PackageBase] { + if _, ok := conflicts[split.Name]; ok { + conflict = true + } + } + + if !conflict { + config.NoConfirm = true + } + } + depArguments := makeArguments() depArguments.addArg("D", "asdeps") expArguments := makeArguments() @@ -850,8 +866,6 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg } } - oldConfirm := config.NoConfirm - config.NoConfirm = true err = passToPacman(arguments) if err != nil { return err From 67817e2a19fb9905227d36baadcd8632764a6c8c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 23 Jun 2018 16:19:25 +0100 Subject: [PATCH 004/155] Return when no packages are to be installed. --- cmd.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd.go b/cmd.go index 67607085..b24d88f6 100644 --- a/cmd.go +++ b/cmd.go @@ -556,6 +556,10 @@ func numberMenu(pkgS []string, flags []string) (err error) { } } + if len(arguments.targets) == 0 { + return fmt.Errorf("There is nothing to do") + } + if config.SudoLoop { sudoLoopBackground() } From 3bdb5343218d99d40f8a449b887348611f6bdbfc Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 22 Jun 2018 14:44:38 +0100 Subject: [PATCH 005/155] Separate Pacman upgrade and AUR Upgrade by default Currently When performing a system upgrade, Yay will first refresh the database then perform the repo and AUR upgrade. This allows Yay to add some features such as better batch interaction, showing potential dependency problems before the upgrade starts and combined menus showing AUR and repo upgrades together. There has been discussion that this approach is a bad idea. The main issue people have is that the separation of the database refresh and the upgrade could lead to a partial upgrade if Yay fails between the two stages. Personally I do not like this argument, there are valid reasons to Yay to fail between these points. For example there may be dependency or conflict issues during the AUR upgrade. Yay can detect these before any installing actually starts and exit, just like how pacman will when there are dependency problems. If Yay does fail between these points, for the previously mentioned reasons or even a crash then a simple refresh will not cause a partial upgrade by itself. It is then the user's responsibility to either resolve these issues or instead perform an upgrade using pacman directly. My opinions aside, The discussions on the Arch wiki has reached a decision, this method is not recommended. So to follow the decided best practises this behaviour has been disabled by default. This behaviour can be toggled using the --[no]combinedupgrade flag It should be noted that Yay's upgrade menu will not show repo packages unless --combinedupgrade is used. --- cmd.go | 4 +++ config.go | 72 ++++++++++++++++++++++++++++-------------------------- install.go | 58 +++++++++++++++++++++++++++++++++++++++++-- main.go | 21 +++++++++++++--- 4 files changed, 115 insertions(+), 40 deletions(-) diff --git a/cmd.go b/cmd.go index 1ed66920..e2fe6d2d 100644 --- a/cmd.go +++ b/cmd.go @@ -345,6 +345,10 @@ func handleConfig(option, value string) bool { config.UseAsk = true case "nouseask": config.UseAsk = false + case "combinedupgrade": + config.CombinedUpgrade = true + case "nocombinedupgrade": + config.CombinedUpgrade = false case "a", "aur": mode = ModeAUR case "repo": diff --git a/config.go b/config.go index 18f47161..daff6461 100644 --- a/config.go +++ b/config.go @@ -35,41 +35,42 @@ const ( // Configuration stores yay's config. type Configuration struct { - BuildDir string `json:"buildDir"` - Editor string `json:"editor"` - EditorFlags string `json:"editorflags"` - MakepkgBin string `json:"makepkgbin"` - PacmanBin string `json:"pacmanbin"` - PacmanConf string `json:"pacmanconf"` - TarBin string `json:"tarbin"` - 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"` - GpgBin string `json:"gpgbin"` - GpgFlags string `json:"gpgflags"` - MFlags string `json:"mflags"` - SortBy string `json:"sortby"` - GitFlags string `json:"gitflags"` - RequestSplitN int `json:"requestsplitn"` - SearchMode int `json:"-"` - SortMode int `json:"sortmode"` - SudoLoop bool `json:"sudoloop"` - TimeUpdate bool `json:"timeupdate"` - NoConfirm bool `json:"-"` - Devel bool `json:"devel"` - CleanAfter bool `json:"cleanAfter"` - GitClone bool `json:"gitclone"` - Provides bool `json:"provides"` - PGPFetch bool `json:"pgpfetch"` - UpgradeMenu bool `json:"upgrademenu"` - CleanMenu bool `json:"cleanmenu"` - DiffMenu bool `json:"diffmenu"` - EditMenu bool `json:"editmenu"` - UseAsk bool `json:"useask"` + BuildDir string `json:"buildDir"` + Editor string `json:"editor"` + EditorFlags string `json:"editorflags"` + MakepkgBin string `json:"makepkgbin"` + PacmanBin string `json:"pacmanbin"` + PacmanConf string `json:"pacmanconf"` + TarBin string `json:"tarbin"` + 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"` + GpgBin string `json:"gpgbin"` + GpgFlags string `json:"gpgflags"` + MFlags string `json:"mflags"` + SortBy string `json:"sortby"` + GitFlags string `json:"gitflags"` + RequestSplitN int `json:"requestsplitn"` + SearchMode int `json:"-"` + SortMode int `json:"sortmode"` + SudoLoop bool `json:"sudoloop"` + TimeUpdate bool `json:"timeupdate"` + NoConfirm bool `json:"-"` + Devel bool `json:"devel"` + CleanAfter bool `json:"cleanAfter"` + GitClone bool `json:"gitclone"` + Provides bool `json:"provides"` + PGPFetch bool `json:"pgpfetch"` + UpgradeMenu bool `json:"upgrademenu"` + CleanMenu bool `json:"cleanmenu"` + DiffMenu bool `json:"diffmenu"` + EditMenu bool `json:"editmenu"` + CombinedUpgrade bool `json:"combinedupgrade"` + UseAsk bool `json:"useask"` } var version = "7.885" @@ -179,6 +180,7 @@ func defaultSettings(config *Configuration) { config.DiffMenu = true config.EditMenu = false config.UseAsk = false + config.CombinedUpgrade = false } // Editor returns the preferred system editor. diff --git a/install.go b/install.go index 52464eda..492c4282 100644 --- a/install.go +++ b/install.go @@ -22,7 +22,6 @@ func install(parser *arguments) error { var aurUp upSlice var repoUp upSlice - requestTargets := parser.copy().targets warnings := &aurWarnings{} removeMake := false @@ -39,9 +38,64 @@ func install(parser *arguments) error { remoteNamesCache := sliceToStringSet(remoteNames) localNamesCache := sliceToStringSet(localNames) + if mode == ModeAny || mode == ModeRepo { + if config.CombinedUpgrade { + if parser.existsArg("y", "refresh") { + arguments := parser.copy() + parser.delArg("y", "refresh") + arguments.delArg("u", "sysupgrade") + arguments.delArg("s", "search") + arguments.delArg("i", "info") + arguments.delArg("l", "list") + arguments.clearTargets() + err = passToPacman(arguments) + if err != nil { + return fmt.Errorf("Error installing repo packages") + } + } + } else if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(parser.targets) > 0 { + arguments := parser.copy() + targets := parser.targets + parser.clearTargets() + arguments.clearTargets() + + //seperate aur and repo targets + for _, target := range targets { + if localNamesCache.get(target) { + arguments.addTarget(target) + } else { + parser.addTarget(target) + } + } + + if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(arguments.targets) > 0 { + err = passToPacman(arguments) + if err != nil { + return fmt.Errorf("Error installing repo packages") + } + } + + //we may have done -Sy, our handle now has an old + //database. + err = initAlpmHandle() + if err != nil { + return err + } + + _, _, localNames, remoteNames, err = filterPackages() + if err != nil { + return err + } + + remoteNamesCache = sliceToStringSet(remoteNames) + localNamesCache = sliceToStringSet(localNames) + } + } + + requestTargets := parser.copy().targets + //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" diff --git a/main.go b/main.go index 17d6f819..3966d38e 100644 --- a/main.go +++ b/main.go @@ -159,9 +159,8 @@ func initAlpm() (err error) { alpmConf.GPGDir = value } - alpmHandle, err = alpmConf.CreateHandle() + err = initAlpmHandle() if err != nil { - err = fmt.Errorf("Unable to CreateHandle: %s", err) return } @@ -174,8 +173,24 @@ func initAlpm() (err error) { useColor = alpmConf.Options&alpm.ConfColor > 0 } - alpmHandle.SetQuestionCallback(questionCallback) + return +} +func initAlpmHandle() (err error) { + if alpmHandle != nil { + err = alpmHandle.Release() + if err != nil { + return err + } + } + + alpmHandle, err = alpmConf.CreateHandle() + if err != nil { + err = fmt.Errorf("Unable to CreateHandle: %s", err) + return + } + + alpmHandle.SetQuestionCallback(questionCallback) return } From 52f5c8878f605ed9cf15ecfd47f52297ea7faaf7 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 1 Jul 2018 11:59:25 +0100 Subject: [PATCH 006/155] Add native pacman completions Signed-off-by: Jguer --- completions/fish | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/completions/fish b/completions/fish index 72aea16a..0ee71621 100644 --- a/completions/fish +++ b/completions/fish @@ -115,6 +115,12 @@ complete -c $progname -n "not $noopt" -l noprovides -d 'Just look for packages b 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' +# Post V7.887 +complete -c $progname -n "not $noopt" -l useask -d 'Automatically resolce conflicts using pacmans ask flag' +complete -c $progname -n "not $noopt" -l nouseask -d 'Confirm conflicts manually during the install' +complete -c $progname -n "not $noopt" -l combinedUpgrade -d 'Refresh then perform the repo and AUR upgrade together' +complete -c $progname -n "not $noopt" -l nocombinedUpgrade -d 'Perform the repo upgrade and AUR upgrade separately' + # Yay options complete -c $progname -n $yayspecific -s c -l clean -d 'Remove unneeded dependencies' -f complete -c $progname -n $yayspecific -l gendb -d 'Generate development package DB' -f From a91dc9e55778a7b7f536a73439c45e0ad29f870b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 1 Jul 2018 04:23:19 +0100 Subject: [PATCH 007/155] Document --[no]useask and --[no]combinedupgrade --- cmd.go | 4 ++++ doc/yay.8 | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index e2fe6d2d..165c5bd8 100644 --- a/cmd.go +++ b/cmd.go @@ -94,6 +94,10 @@ Permanent configuration options: --noprovides Just look for packages by pkgname --pgpfetch Prompt to import PGP keys from PKGBUILDs --nopgpfetch Don't prompt to import PGP keys + --useask Automatically resolce conflicts using pacman's ask flag + --nouseask Confirm conflicts manually during the install + --combinedUpgrade Refresh then perform the repo and AUR upgrade together + --nocombinedUpgrade Perform the repo upgrade and AUR upgrade separately --sudoloop Loop sudo calls in the background to avoid timeout --nosudoloop Do not loop sudo calls in the background diff --git a/doc/yay.8 b/doc/yay.8 index 4a359041..75010690 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -1,5 +1,5 @@ '\" t -.TH "YAY" "8" "2018\-06\-04" "Yay v7\&.885+" "Yay Manual" +.TH "YAY" "8" "2018\-07\-01" "Yay v7\&.887+" "Yay Manual" .nh .ad l .SH "NAME" @@ -437,6 +437,39 @@ failiure unless using options such as \fB\-\-skippgpcheck\fR or a customized gpg config\%. .RE .PP +\fB\-\-useask\fR +.RS 4 +Use pacman's --ask flag to automatically confirm package conflicts\&. Yay lists +conflicts ahead of time\&. It is possible thay Yay does not detect +a conflict\&. Causing a package to be removed without the user's confimation\&. +Although this is very unlikley\&. +.RE +.PP +\fB\-\-nouseask\fR +.RS 4 +Manually resolve package conflicts during the install. Packages which do not +conflict will not need to be confimed manually\&. +.RE +.PP +\fB\-\-combinedupgrade\fR +.RS 4 +During sysupgrade, Yay will first perform a refresh, then show +its combined menu of repo and AUR packages that will be upgraded\&. Then after +reviewing the pkgbuilds, the repo and AUR upgrade will start with no need +for manual intervention\&. + +If Yay exits for any reason After the refresh without upgrading\&. It is then +the user's responsibility to either resolve the reason Yay exited or run +a sysupgrade through pacman directly\&. +.RE +.PP +\fB\-\-nocombinedupgrade\fR +.RS 4 +During sysupgrade, Pacman \-Syu will be called, then the AUR upgrade will +start\&. This means the upgrade menu and pkgbuild review will be performed +after the sysupgrade has finished\&. +.RE +.PP \fB\-\-rebuild\fR .RS 4 Always build target packages even when a copy is available in cache\&. From 89b5a1b7986233ef4b63489b071555ae0f5cd4d5 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 1 Jul 2018 14:53:48 +0100 Subject: [PATCH 008/155] Fix invalid uppercasing in flags Signed-off-by: Jguer --- cmd.go | 4 ++-- completions/fish | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd.go b/cmd.go index 165c5bd8..55f440e1 100644 --- a/cmd.go +++ b/cmd.go @@ -96,8 +96,8 @@ Permanent configuration options: --nopgpfetch Don't prompt to import PGP keys --useask Automatically resolce conflicts using pacman's ask flag --nouseask Confirm conflicts manually during the install - --combinedUpgrade Refresh then perform the repo and AUR upgrade together - --nocombinedUpgrade Perform the repo upgrade and AUR upgrade separately + --combinedupgrade Refresh then perform the repo and AUR upgrade together + --nocombinedupgrade Perform the repo upgrade and AUR upgrade separately --sudoloop Loop sudo calls in the background to avoid timeout --nosudoloop Do not loop sudo calls in the background diff --git a/completions/fish b/completions/fish index 0ee71621..cdba63e1 100644 --- a/completions/fish +++ b/completions/fish @@ -118,8 +118,8 @@ complete -c $progname -n "not $noopt" -l nopgpfetch -d 'Do not prompt to import # Post V7.887 complete -c $progname -n "not $noopt" -l useask -d 'Automatically resolce conflicts using pacmans ask flag' complete -c $progname -n "not $noopt" -l nouseask -d 'Confirm conflicts manually during the install' -complete -c $progname -n "not $noopt" -l combinedUpgrade -d 'Refresh then perform the repo and AUR upgrade together' -complete -c $progname -n "not $noopt" -l nocombinedUpgrade -d 'Perform the repo upgrade and AUR upgrade separately' +complete -c $progname -n "not $noopt" -l combinedupgrade -d 'Refresh then perform the repo and AUR upgrade together' +complete -c $progname -n "not $noopt" -l nocombinedupgrade -d 'Perform the repo upgrade and AUR upgrade separately' # Yay options complete -c $progname -n $yayspecific -s c -l clean -d 'Remove unneeded dependencies' -f From 4f1a46eed86be51aa6fc659f05a50611ddadb089 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 1 Jul 2018 17:21:54 +0100 Subject: [PATCH 009/155] Add bash and zsh completion for new flags --- cmd.go | 2 +- completions/bash | 3 ++- completions/zsh | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd.go b/cmd.go index 55f440e1..63fbf694 100644 --- a/cmd.go +++ b/cmd.go @@ -94,7 +94,7 @@ Permanent configuration options: --noprovides Just look for packages by pkgname --pgpfetch Prompt to import PGP keys from PKGBUILDs --nopgpfetch Don't prompt to import PGP keys - --useask Automatically resolce conflicts using pacman's ask flag + --useask Automatically resolve conflicts using pacman's ask flag --nouseask Confirm conflicts manually during the install --combinedupgrade Refresh then perform the repo and AUR upgrade together --nocombinedupgrade Perform the repo upgrade and AUR upgrade separately diff --git a/completions/bash b/completions/bash index 64fd5558..45c92c76 100644 --- a/completions/bash +++ b/completions/bash @@ -77,7 +77,8 @@ _yay() { 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') + useask nouseask combinedupgrade nocombinedupgrade 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 d1df34a1..0ccbc406 100644 --- a/completions/zsh +++ b/completions/zsh @@ -86,6 +86,10 @@ _pacman_opts_common=( '--noprovides[Just look for packages by pkgname]' '--pgpfetch[Prompt to import PGP keys from PKGBUILDs]' "--nopgpfetch[Don't prompt to import PGP keys]" + "--useask[Automatically resolve conflicts using pacman's ask flag]" + '--nouseask[Confirm conflicts manually during the install]' + '--combinedupgrade[Refresh then perform the repo and AUR upgrade together]' + '--nocombinedupgrade[Perform the repo upgrade and AUR upgrade separately]' '--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 fef91ab37170cde9c76cbd4e98a56d75b88aa4a5 Mon Sep 17 00:00:00 2001 From: "Daniel Wendler (@cassandra)" Date: Mon, 2 Jul 2018 14:15:57 +0200 Subject: [PATCH 010/155] run pacman -Qk(k) as root fixes #525 --- parser.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/parser.go b/parser.go index 8a2ce936..1b8c2eca 100644 --- a/parser.go +++ b/parser.go @@ -136,6 +136,9 @@ func (parser *arguments) needRoot() bool { } return false case "Q", "query": + if parser.existsArg("k", "check") { + return true + } return false case "R", "remove": return true From 6eded7c4a3e310f3e126d5ce435568e3dea6c577 Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Mon, 2 Jul 2018 14:26:51 +0300 Subject: [PATCH 011/155] Support commas in parserNumberMenu --- parser.go | 7 +++++-- parser_test.go | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 8a2ce936..e9d99c60 100644 --- a/parser.go +++ b/parser.go @@ -8,6 +8,7 @@ import ( "os" "strconv" "strings" + "unicode" ) // A basic set implementation for strings. @@ -613,7 +614,7 @@ func (parser *arguments) parseCommandLine() (err error) { return } -//parses input for number menus +//parses input for number menus splitted by spaces or commas //supports individual selection: 1 2 3 4 //supports range selections: 1-4 10-20 //supports negation: ^1 ^1-4 @@ -629,7 +630,9 @@ func parseNumberMenu(input string) (intRanges, intRanges, stringSet, stringSet) otherInclude := make(stringSet) otherExclude := make(stringSet) - words := strings.Fields(input) + words := strings.FieldsFunc(input, func(c rune) bool { + return unicode.IsSpace(c) || c == ',' + }) for _, word := range words { var num1 int diff --git a/parser_test.go b/parser_test.go index 5aa57c67..b0c18c9c 100644 --- a/parser_test.go +++ b/parser_test.go @@ -65,6 +65,7 @@ func TestParseNumberMenu(t *testing.T) { "abort all none", "a-b ^a-b ^abort", "1\t2 3 4\t\t \t 5", + "1 2,3, 4, 5,6 ,7 ,8", "", " \t ", "A B C D E", @@ -78,6 +79,7 @@ func TestParseNumberMenu(t *testing.T) { {intRanges{}, intRanges{}, makeStringSet("abort", "all", "none"), make(stringSet)}, {intRanges{}, intRanges{}, makeStringSet("a-b"), makeStringSet("abort", "a-b")}, {intRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5)}, intRanges{}, make(stringSet), make(stringSet)}, + {intRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5), makeIntRange(6, 6), makeIntRange(7, 7), makeIntRange(8, 8)}, intRanges{}, make(stringSet), make(stringSet)}, {intRanges{}, intRanges{}, make(stringSet), make(stringSet)}, {intRanges{}, intRanges{}, make(stringSet), make(stringSet)}, {intRanges{}, intRanges{}, makeStringSet("a", "b", "c", "d", "e"), make(stringSet)}, From 43c52c69d2fec513aad33b082330a1665611ae34 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 3 Jul 2018 13:42:13 +0100 Subject: [PATCH 012/155] Also remove -u when not doing combined upgrade When not doing combined upgrade we do pacman -Syu early. So there is no need to use -u when installing repo dependencies of AUR packages. --- install.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/install.go b/install.go index 492c4282..85bc02b8 100644 --- a/install.go +++ b/install.go @@ -160,6 +160,10 @@ func install(parser *arguments) error { } if len(dp.Aur) == 0 { + if !config.CombinedUpgrade { + return nil + } + parser.op = "S" parser.delArg("y", "refresh") parser.options["ignore"] = arguments.options["ignore"] @@ -294,6 +298,10 @@ func install(parser *arguments) error { } } + if !config.CombinedUpgrade { + arguments.delArg("u", "sysupgrade") + } + if len(arguments.targets) > 0 || arguments.existsArg("u") { err := passToPacman(arguments) if err != nil { From b46b111c079a42f8f0014649ec884eceb12f0489 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 4 Jul 2018 15:29:54 +0100 Subject: [PATCH 013/155] Support source URLs that contain ? Since pacman 5.1 makepkg supports ? to signal some stuffg in a similar way to #. Cut this out so URLs with ? no longer fail. --- vcs.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcs.go b/vcs.go index 857185d3..7e6d7266 100644 --- a/vcs.go +++ b/vcs.go @@ -97,6 +97,8 @@ func parseSource(source string) (url string, branch string, protocols []string) branch = "HEAD" } + url = strings.Split(url, "?")[0] + return } From d627df728801b2e682711ef3d13925003499c86d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 5 Jul 2018 01:55:12 +0100 Subject: [PATCH 014/155] Support source URLs that contain ? again Turns out the query part of a source url can be dirrectly after the URL or after the # fragment. So the branch needs to be stripped too. --- vcs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/vcs.go b/vcs.go index 7e6d7266..6ede0ff3 100644 --- a/vcs.go +++ b/vcs.go @@ -98,6 +98,7 @@ func parseSource(source string) (url string, branch string, protocols []string) } url = strings.Split(url, "?")[0] + branch = strings.Split(branch, "?")[0] return } From 8dd0d97ae047dc624dd0461ab586144faab500d4 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 5 Jul 2018 22:20:18 +0100 Subject: [PATCH 015/155] Properley seprate aur and repo targets. When not doing combined upgrade the repo targets need to be extracted for the early pacman call. --- install.go | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/install.go b/install.go index 85bc02b8..6895eb25 100644 --- a/install.go +++ b/install.go @@ -59,12 +59,44 @@ func install(parser *arguments) error { parser.clearTargets() arguments.clearTargets() - //seperate aur and repo targets - for _, target := range targets { - if localNamesCache.get(target) { - arguments.addTarget(target) - } else { - parser.addTarget(target) + syncDb, err := alpmHandle.SyncDbs() + if err != nil { + return err + } + + if mode == ModeRepo { + arguments.targets = targets + } else { + alpmHandle.SetQuestionCallback(func(alpm.QuestionAny) {}) + //seperate aur and repo targets + for _, _target := range targets { + target := toTarget(_target) + + if target.Db == "aur" { + parser.addTarget(_target) + continue + } + + var singleDb *alpm.Db + + if target.Db != "" { + singleDb, err = alpmHandle.SyncDbByName(target.Db) + if err != nil { + return err + } + fmt.Println(singleDb) + fmt.Println(target.DepString()) + _, err = singleDb.PkgCache().FindSatisfier(target.DepString()) + fmt.Println("herererrrrrr", err) + } else { + _, err = syncDb.FindSatisfier(target.DepString()) + } + + if err == nil { + arguments.addTarget(_target) + } else { + parser.addTarget(_target) + } } } From dcaf1e5595d7ca8550f7c80abb0093ca17ab1b87 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 6 Jul 2018 15:24:03 +0100 Subject: [PATCH 016/155] Fix -Y and remove debug messages --- install.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/install.go b/install.go index 6895eb25..9db18c86 100644 --- a/install.go +++ b/install.go @@ -55,6 +55,7 @@ func install(parser *arguments) error { } } else if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(parser.targets) > 0 { arguments := parser.copy() + arguments.op = "S" targets := parser.targets parser.clearTargets() arguments.clearTargets() @@ -84,10 +85,7 @@ func install(parser *arguments) error { if err != nil { return err } - fmt.Println(singleDb) - fmt.Println(target.DepString()) _, err = singleDb.PkgCache().FindSatisfier(target.DepString()) - fmt.Println("herererrrrrr", err) } else { _, err = syncDb.FindSatisfier(target.DepString()) } From 24379373728e308f1b4aee603b353b26412bfc15 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 12 Jul 2018 11:12:12 +0100 Subject: [PATCH 017/155] Show nothing to do message for nocombinedupgrade --- install.go | 1 + 1 file changed, 1 insertion(+) diff --git a/install.go b/install.go index 9db18c86..bd7c0c30 100644 --- a/install.go +++ b/install.go @@ -191,6 +191,7 @@ func install(parser *arguments) error { if len(dp.Aur) == 0 { if !config.CombinedUpgrade { + fmt.Println("There is nothing to do") return nil } From f8e84658c02ac566354ec0c03c3d18bc29fef8fe Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 16 Jul 2018 11:35:25 +0100 Subject: [PATCH 018/155] Major version update --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d2fd34fa..cd5991b0 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ PREFIX := /usr DESTDIR := ifndef VERSION -MAJORVERSION := 7 +MAJORVERSION := 8 MINORVERSION ?= $(shell git rev-list --count master) endif VERSION := ${MAJORVERSION}.${MINORVERSION} From b1fb1b9656b8079ba99c07a4a31ccfe77f29de81 Mon Sep 17 00:00:00 2001 From: J Guerreiro Date: Mon, 16 Jul 2018 12:06:29 +0100 Subject: [PATCH 019/155] Add flagged out of date FAQ closes #545 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 52131ae7..8c5f18cc 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,8 @@ Currently yay Depends on: `yay -{OPERATION} --aur` `yay -{OPERATION} --repo` +* `Out Of Date AUR Packages`message is displayed, why doesn't `yay` update them? +This means the package has been flagged out of date on the AUR but author has not updated the `PKGBUILD` yet. ## Examples of Custom Operations * `yay ` presents package selection menu From d6b862357d3a495f2b778657c3c1f5235b11f53e Mon Sep 17 00:00:00 2001 From: Anna Date: Mon, 16 Jul 2018 15:28:18 +0100 Subject: [PATCH 020/155] Replace gopkgbuild with go-srcinfo (#528) * Prefer vercmp over gopkgbuild * Replace gopkgbuild with go-srcinfo --- Gopkg.lock | 14 +- Gopkg.toml | 2 +- depCheck.go | 1 - install.go | 26 +- keys.go | 6 +- keys_test.go | 26 +- upgrade.go | 88 +-- vcs.go | 8 +- .../go-srcinfo}/LICENSE | 0 .../Morganamilo/go-srcinfo/line_error.go | 38 ++ .../Morganamilo/go-srcinfo/parser.go | 310 +++++++++ .../Morganamilo/go-srcinfo/printsrcinfo.go | 155 +++++ .../Morganamilo/go-srcinfo/srcinfo.go | 215 ++++++ .../github.com/mikkeloscar/gopkgbuild/lex.go | 283 -------- .../mikkeloscar/gopkgbuild/pkgbuild.go | 625 ------------------ .../mikkeloscar/gopkgbuild/version.go | 324 --------- 16 files changed, 797 insertions(+), 1324 deletions(-) rename vendor/github.com/{mikkeloscar/gopkgbuild => Morganamilo/go-srcinfo}/LICENSE (100%) create mode 100644 vendor/github.com/Morganamilo/go-srcinfo/line_error.go create mode 100644 vendor/github.com/Morganamilo/go-srcinfo/parser.go create mode 100644 vendor/github.com/Morganamilo/go-srcinfo/printsrcinfo.go create mode 100644 vendor/github.com/Morganamilo/go-srcinfo/srcinfo.go delete mode 100644 vendor/github.com/mikkeloscar/gopkgbuild/lex.go delete mode 100644 vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go delete mode 100644 vendor/github.com/mikkeloscar/gopkgbuild/version.go diff --git a/Gopkg.lock b/Gopkg.lock index 1f3275b6..0281eb12 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + name = "github.com/Morganamilo/go-srcinfo" + packages = ["."] + revision = "368edc79b2c53cd9c065818fd4e65843ef3e9e11" + [[projects]] branch = "master" name = "github.com/jguer/go-alpm" @@ -13,15 +19,9 @@ packages = ["."] revision = "837b260b8e90895c45737e2e72313fe5bce6f2c4" -[[projects]] - branch = "master" - name = "github.com/mikkeloscar/gopkgbuild" - packages = ["."] - revision = "2bb4f1f1db67f81fe50f9c1c4ad9db4f20fd6b22" - [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "456465ee334310996a51a2282bf4cfe9f6269db508479c962474d61a4ce0a08c" + inputs-digest = "2a7c6ddb680b62cd3f3cf47a0dfdad617e4a42e29204c75ecf5be3271feda5e1" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 18b0e91f..82d4ef9c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -13,4 +13,4 @@ [[constraint]] branch = "master" - name = "github.com/mikkeloscar/gopkgbuild" + name = "github.com/Morganamilo/go-srcinfo" diff --git a/depCheck.go b/depCheck.go index 3ed42150..81ef7947 100644 --- a/depCheck.go +++ b/depCheck.go @@ -6,7 +6,6 @@ import ( "sync" alpm "github.com/jguer/go-alpm" - // gopkg "github.com/mikkeloscar/gopkgbuild" ) func (dp *depPool) checkInnerConflict(name string, conflict string, conflicts mapStringSet) { diff --git a/install.go b/install.go index bd7c0c30..70cb7cff 100644 --- a/install.go +++ b/install.go @@ -8,9 +8,9 @@ import ( "strconv" "strings" + gosrc "github.com/Morganamilo/go-srcinfo" alpm "github.com/jguer/go-alpm" rpc "github.com/mikkeloscar/aur" - gopkg "github.com/mikkeloscar/gopkgbuild" ) // Install handles package installs @@ -25,7 +25,7 @@ func install(parser *arguments) error { warnings := &aurWarnings{} removeMake := false - srcinfosStale := make(map[string]*gopkg.PKGBUILD) + srcinfosStale := make(map[string]*gosrc.Srcinfo) //remotenames: names of all non repo packages on the system _, _, localNames, remoteNames, err := filterPackages() @@ -407,7 +407,7 @@ func install(parser *arguments) error { return nil } -func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) (stringSet, error) { +func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) (stringSet, error) { incompatible := make(stringSet) alpmArch, err := alpmHandle.Arch() if err != nil { @@ -711,14 +711,14 @@ func editPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { return nil } -func parseSRCINFOFiles(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) error { +func parseSRCINFOFiles(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) error { for k, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) - pkgbuild, err := gopkg.ParseSRCINFO(filepath.Join(dir, ".SRCINFO")) + pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { return fmt.Errorf("%s: %s", pkg.Name, err) } @@ -729,14 +729,14 @@ func parseSRCINFOFiles(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bas return nil } -func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) { +func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) { for k, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) - pkgbuild, err := gopkg.ParseSRCINFO(filepath.Join(dir, ".SRCINFO")) + pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { fmt.Printf("cannot parse %s skipping: %s\n", pkg.Name, err) continue @@ -752,15 +752,11 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { 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) + pkgbuild, err := gosrc.ParseFile(dir) if err == nil { - versionRPC, errR := gopkg.NewCompleteVersion(pkg.Version) - versionPKG, errP := gopkg.NewCompleteVersion(pkgbuild.Version()) - if errP == nil && errR == nil { - if !versionRPC.Newer(versionPKG) { - toSkip.set(pkg.PackageBase) - } + if alpm.VerCmp(pkgbuild.Version(), pkg.Version) > 0 { + toSkip.set(pkg.PackageBase) } } } @@ -833,7 +829,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco return } -func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gopkg.PKGBUILD, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { +func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { for _, pkg := range do.Aur { dir := filepath.Join(config.BuildDir, pkg.PackageBase) built := true diff --git a/keys.go b/keys.go index 43b52cc5..012b9e4e 100644 --- a/keys.go +++ b/keys.go @@ -7,8 +7,8 @@ import ( "os/exec" "strings" + gosrc "github.com/Morganamilo/go-srcinfo" rpc "github.com/mikkeloscar/aur" - gopkg "github.com/mikkeloscar/gopkgbuild" ) // pgpKeySet maps a PGP key with a list of PKGBUILDs that require it. @@ -41,7 +41,7 @@ func (set pgpKeySet) get(key string) bool { // checkPgpKeys iterates through the keys listed in the PKGBUILDs and if needed, // asks the user whether yay should try to import them. -func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) error { +func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) error { // Let's check the keys individually, and then we can offer to import // the problematic ones. problematic := make(pgpKeySet) @@ -51,7 +51,7 @@ func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[str for _, pkg := range pkgs { srcinfo := srcinfos[pkg.PackageBase] - for _, key := range srcinfo.Validpgpkeys { + for _, key := range srcinfo.ValidPGPKeys { // If key already marked as problematic, indicate the current // PKGBUILD requires it. if problematic.get(key) { diff --git a/keys_test.go b/keys_test.go index ab8e0560..d8717519 100644 --- a/keys_test.go +++ b/keys_test.go @@ -11,8 +11,8 @@ import ( "regexp" "testing" + gosrc "github.com/Morganamilo/go-srcinfo" rpc "github.com/mikkeloscar/aur" - gopkg "github.com/mikkeloscar/gopkgbuild" ) const ( @@ -124,6 +124,14 @@ func TestImportKeys(t *testing.T) { } } +func makeSrcinfo(pkgbase string, pgpkeys ...string) *gosrc.Srcinfo { + srcinfo := gosrc.Srcinfo{} + srcinfo.Pkgbase = pkgbase + srcinfo.ValidPGPKeys = pgpkeys + + return &srcinfo +} + func TestCheckPgpKeys(t *testing.T) { keyringDir, err := ioutil.TempDir("/tmp", "yay-test-keyring") if err != nil { @@ -139,7 +147,7 @@ func TestCheckPgpKeys(t *testing.T) { casetests := []struct { pkgs []*rpc.Pkg - srcinfos map[string]*gopkg.PKGBUILD + srcinfos map[string]*gosrc.Srcinfo bases map[string][]*rpc.Pkg wantError bool }{ @@ -147,7 +155,7 @@ func TestCheckPgpKeys(t *testing.T) { // 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner. { pkgs: []*rpc.Pkg{newPkg("cower")}, - srcinfos: map[string]*gopkg.PKGBUILD{"cower": {Pkgbase: "cower", Validpgpkeys: []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"cower": makeSrcinfo("cower", "487EACC08557AD082088DABA1EB2638FF56C0C53")}, bases: map[string][]*rpc.Pkg{"cower": {newPkg("cower")}}, wantError: false, }, @@ -156,7 +164,7 @@ func TestCheckPgpKeys(t *testing.T) { // B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg. { pkgs: []*rpc.Pkg{newPkg("libc++")}, - srcinfos: map[string]*gopkg.PKGBUILD{"libc++": {Pkgbase: "libc++", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"libc++": makeSrcinfo("libc++", "11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D")}, bases: map[string][]*rpc.Pkg{"libc++": {newPkg("libc++")}}, wantError: false, }, @@ -164,7 +172,7 @@ func TestCheckPgpKeys(t *testing.T) { // ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds. { pkgs: []*rpc.Pkg{newPkg("dummy-1"), newPkg("dummy-2")}, - srcinfos: map[string]*gopkg.PKGBUILD{"dummy-1": {Pkgbase: "dummy-1", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}, "dummy-2": {Pkgbase: "dummy-2", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"dummy-1": makeSrcinfo("dummy-1", "ABAF11C65A2970B130ABE3C479BE3E4300411886"), "dummy-2": makeSrcinfo("dummy-2", "ABAF11C65A2970B130ABE3C479BE3E4300411886")}, bases: map[string][]*rpc.Pkg{"dummy-1": {newPkg("dummy-1")}, "dummy-2": {newPkg("dummy-2")}}, wantError: false, }, @@ -174,21 +182,21 @@ func TestCheckPgpKeys(t *testing.T) { // C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey. { pkgs: []*rpc.Pkg{newPkg("dummy-3")}, - srcinfos: map[string]*gopkg.PKGBUILD{"dummy-3": {Pkgbase: "dummy-3", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"dummy-3": makeSrcinfo("dummy-3", "11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB")}, bases: map[string][]*rpc.Pkg{"dummy-3": {newPkg("dummy-3")}}, wantError: false, }, // Two dummy packages with existing keys. { pkgs: []*rpc.Pkg{newPkg("dummy-4"), newPkg("dummy-5")}, - srcinfos: map[string]*gopkg.PKGBUILD{"dummy-4": {Pkgbase: "dummy-4", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294"}}, "dummy-5": {Pkgbase: "dummy-5", Validpgpkeys: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"dummy-4": makeSrcinfo("dummy-4", "11E521D646982372EB577A1F8F0871F202119294"), "dummy-5": makeSrcinfo("dummy-5", "C52048C0C0748FEE227D47A2702353E0F7E48EDB")}, bases: map[string][]*rpc.Pkg{"dummy-4": {newPkg("dummy-4")}, "dummy-5": {newPkg("dummy-5")}}, wantError: false, }, // Dummy package with invalid key, should fail. { pkgs: []*rpc.Pkg{newPkg("dummy-7")}, - srcinfos: map[string]*gopkg.PKGBUILD{"dummy-7": {Pkgbase: "dummy-7", Validpgpkeys: []string{"THIS-SHOULD-FAIL"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"dummy-7": makeSrcinfo("dummy-7", "THIS-SHOULD-FAIL")}, bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}}, wantError: true, }, @@ -196,7 +204,7 @@ func TestCheckPgpKeys(t *testing.T) { // A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler. { pkgs: []*rpc.Pkg{newPkg("dummy-8")}, - srcinfos: map[string]*gopkg.PKGBUILD{"dummy-8": {Pkgbase: "dummy-8", Validpgpkeys: []string{"A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL"}}}, + srcinfos: map[string]*gosrc.Srcinfo{"dummy-8": makeSrcinfo("dummy-8", "A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL")}, bases: map[string][]*rpc.Pkg{"dummy-8": {newPkg("dummy-8")}}, wantError: true, }, diff --git a/upgrade.go b/upgrade.go index 4daac107..71fa8df5 100644 --- a/upgrade.go +++ b/upgrade.go @@ -9,7 +9,6 @@ import ( alpm "github.com/jguer/go-alpm" rpc "github.com/mikkeloscar/aur" - pkgb "github.com/mikkeloscar/gopkgbuild" ) // upgrade type describes a system upgrade. @@ -63,64 +62,49 @@ func (u upSlice) Less(i, j int) bool { } -func getVersionDiff(oldVersion, newversion string) (left, right string) { - old, errOld := pkgb.NewCompleteVersion(oldVersion) - new, errNew := pkgb.NewCompleteVersion(newversion) - - if errOld != nil { - left = red("Invalid Version") - } - if errNew != nil { - right = red("Invalid Version") +func getVersionDiff(oldVersion, newVersion string) (left, right string) { + if oldVersion == newVersion { + return oldVersion, newVersion } - if errOld == nil && errNew == nil { - oldVersion := old.String() - newVersion := new.String() + diffPosition := 0 - if oldVersion == newVersion { - return oldVersion, newVersion - } - - diffPosition := 0 - - checkWords := func(str string, index int, words ...string) bool { - for _, word := range words { - wordLength := len(word) - nextIndex := index + 1 - if (index < len(str)-wordLength) && - (str[nextIndex:(nextIndex+wordLength)] == word) { - return true - } - } - return false - } - - for index, char := range oldVersion { - charIsSpecial := !(unicode.IsLetter(char) || unicode.IsNumber(char)) - - if (index >= len(newVersion)) || (char != rune(newVersion[index])) { - if charIsSpecial { - diffPosition = index - } - break - } - - if charIsSpecial || - (((index == len(oldVersion)-1) || (index == len(newVersion)-1)) && - ((len(oldVersion) != len(newVersion)) || - (oldVersion[index] == newVersion[index]))) || - checkWords(oldVersion, index, "rc", "pre", "alpha", "beta") { - diffPosition = index + 1 + checkWords := func(str string, index int, words ...string) bool { + for _, word := range words { + wordLength := len(word) + nextIndex := index + 1 + if (index < len(str)-wordLength) && + (str[nextIndex:(nextIndex+wordLength)] == word) { + return true } } - - samePart := oldVersion[0:diffPosition] - - left = samePart + red(oldVersion[diffPosition:]) - right = samePart + green(newVersion[diffPosition:]) + return false } + for index, char := range oldVersion { + charIsSpecial := !(unicode.IsLetter(char) || unicode.IsNumber(char)) + + if (index >= len(newVersion)) || (char != rune(newVersion[index])) { + if charIsSpecial { + diffPosition = index + } + break + } + + if charIsSpecial || + (((index == len(oldVersion)-1) || (index == len(newVersion)-1)) && + ((len(oldVersion) != len(newVersion)) || + (oldVersion[index] == newVersion[index]))) || + checkWords(oldVersion, index, "rc", "pre", "alpha", "beta") { + diffPosition = index + 1 + } + } + + samePart := oldVersion[0:diffPosition] + + left = samePart + red(oldVersion[diffPosition:]) + right = samePart + green(newVersion[diffPosition:]) + return } diff --git a/vcs.go b/vcs.go index 6ede0ff3..e2e96288 100644 --- a/vcs.go +++ b/vcs.go @@ -9,8 +9,8 @@ import ( "strings" "time" + gosrc "github.com/Morganamilo/go-srcinfo" rpc "github.com/mikkeloscar/aur" - gopkg "github.com/mikkeloscar/gopkgbuild" ) // Info contains the last commit sha of a repo @@ -25,7 +25,7 @@ type shaInfo struct { // createDevelDB forces yay to create a DB of the existing development packages func createDevelDB() error { infoMap := make(map[string]*rpc.Pkg) - srcinfosStale := make(map[string]*gopkg.PKGBUILD) + srcinfosStale := make(map[string]*gosrc.Srcinfo) _, _, _, remoteNames, err := filterPackages() if err != nil { @@ -103,7 +103,7 @@ func parseSource(source string) (url string, branch string, protocols []string) return } -func updateVCSData(pkgName string, sources []string) { +func updateVCSData(pkgName string, sources []gosrc.ArchString) { if savedInfo == nil { savedInfo = make(vcsInfo) } @@ -111,7 +111,7 @@ func updateVCSData(pkgName string, sources []string) { info := make(shaInfos) for _, source := range sources { - url, branch, protocols := parseSource(source) + url, branch, protocols := parseSource(source.Value) if url == "" || branch == "" { continue } diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/LICENSE b/vendor/github.com/Morganamilo/go-srcinfo/LICENSE similarity index 100% rename from vendor/github.com/mikkeloscar/gopkgbuild/LICENSE rename to vendor/github.com/Morganamilo/go-srcinfo/LICENSE diff --git a/vendor/github.com/Morganamilo/go-srcinfo/line_error.go b/vendor/github.com/Morganamilo/go-srcinfo/line_error.go new file mode 100644 index 00000000..358344db --- /dev/null +++ b/vendor/github.com/Morganamilo/go-srcinfo/line_error.go @@ -0,0 +1,38 @@ +package srcinfo + +import ( + "fmt" +) + +// LineError is an error type that stores the line number at which an error +// occurred as well the full Line that cased the error and an error string. +type LineError struct { + LineNumber int // The line number at which the error occurred + Line string // The line that caused the error + ErrorStr string // An error string +} + +// Error Returns an error string in the format: +// "Line : : ". +func (le LineError) Error() string { + return fmt.Sprintf("Line %d: %s: %s", le.LineNumber, le.ErrorStr, le.Line) +} + +// Error Returns a new LineError +func Error(LineNumber int, Line string, ErrorStr string) *LineError { + return &LineError{ + LineNumber, + Line, + ErrorStr, + } +} + +// Errorf Returns a new LineError using the same formatting rules as +// fmt.Printf. +func Errorf(LineNumber int, Line string, ErrorStr string, args ...interface{}) *LineError { + return &LineError{ + LineNumber, + Line, + fmt.Sprintf(ErrorStr, args...), + } +} diff --git a/vendor/github.com/Morganamilo/go-srcinfo/parser.go b/vendor/github.com/Morganamilo/go-srcinfo/parser.go new file mode 100644 index 00000000..e2b331be --- /dev/null +++ b/vendor/github.com/Morganamilo/go-srcinfo/parser.go @@ -0,0 +1,310 @@ +package srcinfo + +import ( + "fmt" + "io/ioutil" + "strings" +) + +// parser is used to track our current state as we parse the srcinfo. +type parser struct { + // srcinfo is a Pointer to the Srcinfo we are currently building. + srcinfo *Srcinfo + + // seenPkgnames is a set of pkgnames we have seen + seenPkgnames map[string]struct{} +} + +func (psr *parser) currentPackage() (*Package, error) { + if psr.srcinfo.Pkgbase == "" { + return nil, fmt.Errorf("Not in pkgbase or pkgname") + } else if len(psr.srcinfo.Packages) == 0 { + return &psr.srcinfo.Package, nil + } else { + return &psr.srcinfo.Packages[len(psr.srcinfo.Packages) - 1], nil + } +} + +func (psr *parser) setHeaderOrField(key, value string) error { + pkgbase := &psr.srcinfo.PackageBase + + switch key { + case "pkgbase": + if psr.srcinfo.Pkgbase != "" { + return fmt.Errorf("key \"%s\" can not occur after pkgbase or pkgname", key) + } + + pkgbase.Pkgbase = value + return nil + case "pkgname": + if psr.srcinfo.Pkgbase == "" { + return fmt.Errorf("key \"%s\" can not occur before pkgbase", key) + } + if _, ok := psr.seenPkgnames[value]; ok { + return fmt.Errorf("pkgname \"%s\" can not occur more than once", value) + } + psr.seenPkgnames[value] = struct{}{} + + psr.srcinfo.Packages = append(psr.srcinfo.Packages, Package{Pkgname: value}) + return nil + } + + if psr.srcinfo.Pkgbase == "" { + return fmt.Errorf("key \"%s\" can not occur before pkgbase or pkgname", key) + } + + return psr.setField(key, value) +} + +func (psr *parser) setField(archKey, value string) error { + pkg, err := psr.currentPackage() + if err != nil { + return err + } + + pkgbase := &psr.srcinfo.PackageBase + key, arch := splitArchFromKey(archKey) + err = checkArch(psr.srcinfo.Arch, archKey, arch) + if err != nil { + return err + } + + if value == "" { + value = EmptyOverride + } + + // pkgbase only + not arch dependent + found := true + switch archKey { + case "pkgver": + pkgbase.Pkgver = value + case "pkgrel": + pkgbase.Pkgrel = value + case "epoch": + pkgbase.Epoch = value + case "validpgpkeys": + pkgbase.ValidPGPKeys = append(pkgbase.ValidPGPKeys, value) + case "noextract": + pkgbase.NoExtract = append(pkgbase.NoExtract, value) + default: + found = false + } + + if found { + if len(psr.srcinfo.Packages) > 0 { + return fmt.Errorf("key \"%s\" can not occur after pkgname", archKey) + } + + return nil + } + + // pkgbase only + arch dependent + found = true + switch key { + case "source": + pkgbase.Source = append(pkgbase.Source, ArchString{arch, value}) + case "md5sums": + pkgbase.MD5Sums = append(pkgbase.MD5Sums, ArchString{arch, value}) + case "sha1sums": + pkgbase.SHA1Sums = append(pkgbase.SHA1Sums, ArchString{arch, value}) + case "sha224sums": + pkgbase.SHA224Sums = append(pkgbase.SHA224Sums, ArchString{arch, value}) + case "sha256sums": + pkgbase.SHA256Sums = append(pkgbase.SHA256Sums, ArchString{arch, value}) + case "sha384sums": + pkgbase.SHA384Sums = append(pkgbase.SHA384Sums, ArchString{arch, value}) + case "sha512sums": + pkgbase.SHA512Sums = append(pkgbase.SHA512Sums, ArchString{arch, value}) + case "makedepends": + pkgbase.MakeDepends = append(pkgbase.MakeDepends, ArchString{arch, value}) + case "checkdepends": + pkgbase.CheckDepends = append(pkgbase.CheckDepends, ArchString{arch, value}) + default: + found = false + } + + if found { + if len(psr.srcinfo.Packages) > 0 { + return fmt.Errorf("key \"%s\" can not occur after pkgname", archKey) + } + + return nil + } + + // pkgbase or pkgname + not arch dependent + found = true + switch archKey { + case "pkgdesc": + pkg.Pkgdesc = value + case "url": + pkg.URL = value + case "license": + pkg.License = append(pkg.License, value) + case "install": + pkg.Install = value + case "changelog": + pkg.Changelog = value + case "groups": + pkg.Groups = append(pkg.Groups, value) + case "arch": + pkg.Arch = append(pkg.Arch, value) + case "backup": + pkg.Backup = append(pkg.Backup, value) + case "options": + pkg.Options = append(pkg.Options, value) + default: + found = false + } + + if found { + return nil + } + + // pkgbase or pkgname + arch dependent + switch key { + case "depends": + pkg.Depends = append(pkg.Depends, ArchString{arch, value}) + case "optdepends": + pkg.OptDepends = append(pkg.OptDepends, ArchString{arch, value}) + case "conflicts": + pkg.Conflicts = append(pkg.Conflicts, ArchString{arch, value}) + case "provides": + pkg.Provides = append(pkg.Provides, ArchString{arch, value}) + case "replaces": + pkg.Replaces = append(pkg.Replaces, ArchString{arch, value}) + default: + return fmt.Errorf("Unknown key: \"%s\"", archKey) + } + + return nil +} + +func parse(data string) (*Srcinfo, error) { + psr := &parser{ + &Srcinfo{}, + make(map[string]struct{}), + } + + lines := strings.Split(data, "\n") + + for n, line := range lines { + line = strings.TrimSpace(line) + + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + key, value, err := splitPair(line) + if err != nil { + return nil, Error(n+1, line, err.Error()) + } + + err = psr.setHeaderOrField(key, value) + if err != nil { + return nil, Error(n+1, line, err.Error()) + } + } + + if psr.srcinfo.Pkgbase == "" { + return nil, fmt.Errorf("No pkgbase field") + } + + if len(psr.srcinfo.Packages) == 0 { + return nil, fmt.Errorf("No pkgname field") + } + + if psr.srcinfo.Pkgver == "" { + return nil, fmt.Errorf("No pkgver field") + } + + if psr.srcinfo.Pkgrel == "" { + return nil, fmt.Errorf("No pkgrel field") + } + + if len(psr.srcinfo.Arch) == 0 { + return nil, fmt.Errorf("No arch field") + } + + return psr.srcinfo, nil +} + +// splitPair splits a key value string in the form of "key = value", +// whitespace being ignored. The key and the value is returned. +func splitPair(line string) (string, string, error) { + split := strings.SplitN(line, "=", 2) + + if len(split) != 2 { + return "", "", fmt.Errorf("Line does not contain =") + } + + key := strings.TrimSpace(split[0]) + value := strings.TrimSpace(split[1]) + + if key == "" { + return "", "", fmt.Errorf("Key is empty") + } + + return key, value, nil +} + +// splitArchFromKey splits up architecture dependent field names, separating +// the field name from the architecture they depend on. +func splitArchFromKey(key string) (string, string) { + split := strings.SplitN(key, "_", 2) + if len(split) == 2 { + return split[0], split[1] + } + + return split[0], "" +} + +// checkArg checks that the arch from an arch dependent string is actually +// defined inside of the srcinfo and speicifly disallows the arch "any" as it +// is not a real arch +func checkArch(arches []string, key string, arch string) error { + if arch == "" { + return nil + } + + if arch == "any" { + return fmt.Errorf("Invalid key \"%s\" arch \"%s\" is not allowed", key, arch) + } + + for _, a := range arches { + if a == arch { + return nil + } + } + + return fmt.Errorf("Invalid key \"%s\" unsupported arch \"%s\"", key, arch) +} + +// ParseFile parses a srcinfo file as specified by path. +func ParseFile(path string) (*Srcinfo, error) { + file, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("Unable to read file: %s: %s", path, err.Error()) + } + + return Parse(string(file)) +} + +// Parse parses a srcinfo in string form. Parsing will fail if: +// A srcinfo does not contain all required fields +// The same pkgname is specified more then once +// arch is missing +// pkgver is mising +// pkgrel is missing +// An architecture specific field is defined for an architecture that does not exist +// An unknown key is specified +// An empty value is specified +// +// Required fields are: +// pkgbase +// pkname +// arch +// pkgrel +// pkgver +func Parse(data string) (*Srcinfo, error) { + return parse(data) +} diff --git a/vendor/github.com/Morganamilo/go-srcinfo/printsrcinfo.go b/vendor/github.com/Morganamilo/go-srcinfo/printsrcinfo.go new file mode 100644 index 00000000..fc26287c --- /dev/null +++ b/vendor/github.com/Morganamilo/go-srcinfo/printsrcinfo.go @@ -0,0 +1,155 @@ +package srcinfo + +import ( + "bytes" +) + +func appendHeader(buffer *bytes.Buffer, key string, value string) { + if value == "" { + return + } + + buffer.WriteString(key + " = " + value + "\n") +} + +func appendValue(buffer *bytes.Buffer, key string, value string) { + if value == "" { + return + } + + if value == EmptyOverride { + value = "" + } + + buffer.WriteString("\t" + key + " = " + value + "\n") +} + +func appendMultiValue(buffer *bytes.Buffer, key string, values []string) { + for _, value := range values { + if value == EmptyOverride { + value = "" + } + + buffer.WriteString("\t" + key + " = " + value + "\n") + } +} + +func appendMultiArchValue(buffer *bytes.Buffer, key string, values []ArchString) { + for _, value := range values { + if value.Value == EmptyOverride { + value.Value = "" + } + + if value.Arch == "" { + buffer.WriteString("\t" + key + " = " + value.Value + "\n") + } else { + buffer.WriteString("\t" + key + "_" + value.Arch + " = " + value.Value + "\n") + } + } +} + +//String generates a string that should be similar to the srcinfo data used to +//create this Srcinfo struct. Fields will be printed in order and with the same +//whitespcae rules that `makepkg --printsrcinfo` uses. +// +// The order of each global field is as follows: +// pkgdesc +// pkgver +// pkgrel +// epoch +// url +// install +// changelog +// arch +// groups +// license +// checkdepends +// makedepends +// depends +// optdepends +// provides +// conflicts +// replaces +// noextract +// options +// backup +// source +// validpgpkeys +// md5suns +// sha1sums +// sha224sums +// sha256sums +// sha384sums +// sha512sums +// +// The order of each overwritten field is as follows: +// pkgdesc +// url +// install +// changelog +// arch +// groups +// license +// checkdepends +// depends +// optdepends +// provides +// conflicts +// replaces +// options +// backup +func (si *Srcinfo) String() string { + var buffer bytes.Buffer + + appendHeader(&buffer, "pkgbase", si.Pkgbase) + + appendValue(&buffer, "pkgdesc", si.Pkgdesc) + appendValue(&buffer, "pkgver", si.Pkgver) + appendValue(&buffer, "pkgrel", si.Pkgrel) + appendValue(&buffer, "epoch", si.Epoch) + appendValue(&buffer, "url", si.URL) + appendValue(&buffer, "install", si.Install) + appendValue(&buffer, "changelog", si.Changelog) + appendMultiValue(&buffer, "arch", si.Arch) + appendMultiValue(&buffer, "groups", si.Groups) + appendMultiValue(&buffer, "license", si.License) + appendMultiArchValue(&buffer, "checkdepends", si.CheckDepends) + appendMultiArchValue(&buffer, "makedepends", si.MakeDepends) + appendMultiArchValue(&buffer, "depends", si.Depends) + appendMultiArchValue(&buffer, "optdepends", si.OptDepends) + appendMultiArchValue(&buffer, "provides", si.Provides) + appendMultiArchValue(&buffer, "conflicts", si.Conflicts) + appendMultiArchValue(&buffer, "replaces", si.Replaces) + appendMultiValue(&buffer, "noextract", si.NoExtract) + appendMultiValue(&buffer, "options", si.Options) + appendMultiValue(&buffer, "backup", si.Backup) + appendMultiValue(&buffer, "validpgpkeys", si.ValidPGPKeys) + appendMultiArchValue(&buffer, "source", si.Source) + appendMultiArchValue(&buffer, "md5sums", si.MD5Sums) + appendMultiArchValue(&buffer, "sha1sums", si.SHA1Sums) + appendMultiArchValue(&buffer, "sha224sums", si.SHA224Sums) + appendMultiArchValue(&buffer, "sha256sums", si.SHA256Sums) + appendMultiArchValue(&buffer, "sha384sums", si.SHA384Sums) + appendMultiArchValue(&buffer, "sha512sums", si.SHA512Sums) + + for n, pkg := range si.Packages { + appendHeader(&buffer, "\npkgname", si.Packages[n].Pkgname) + + appendValue(&buffer, "pkgdesc", pkg.Pkgdesc) + appendValue(&buffer, "url", pkg.URL) + appendValue(&buffer, "install", pkg.Install) + appendValue(&buffer, "changelog", pkg.Changelog) + appendMultiValue(&buffer, "arch", pkg.Arch) + appendMultiValue(&buffer, "groups", pkg.Groups) + appendMultiValue(&buffer, "license", pkg.License) + appendMultiArchValue(&buffer, "depends", pkg.Depends) + appendMultiArchValue(&buffer, "optdepends", pkg.OptDepends) + appendMultiArchValue(&buffer, "provides", pkg.Provides) + appendMultiArchValue(&buffer, "conflicts", pkg.Conflicts) + appendMultiArchValue(&buffer, "replaces", pkg.Replaces) + appendMultiValue(&buffer, "options", pkg.Options) + appendMultiValue(&buffer, "backup", pkg.Backup) + } + + return buffer.String() +} diff --git a/vendor/github.com/Morganamilo/go-srcinfo/srcinfo.go b/vendor/github.com/Morganamilo/go-srcinfo/srcinfo.go new file mode 100644 index 00000000..59decab8 --- /dev/null +++ b/vendor/github.com/Morganamilo/go-srcinfo/srcinfo.go @@ -0,0 +1,215 @@ +// Package srcinfo is a parser for srcinfo files. Typically generated by +// makepkg, part of the pacman package manager. +// +// Split packages and architecture dependent fields are fully supported. +// +// This Package aimes to parse srcinfos but not interpret them in any way. +// All values are fundamentally strings, other tools should be used for +// things such as dependency parsing, validity checking etc. +package srcinfo + +import ( + "fmt" +) + +// ArchString describes string values that may be architecture dependent. +// For Example depends_x86_64. +// If Arch is an empty string then the field is not architecture dependent. +type ArchString struct { + Arch string // Architecture name + Value string // Value +} + +// Package describes the fields of a pkgbuild that may be overwritten by +// in build_ function. +type Package struct { + Pkgname string + Pkgdesc string + Arch []string + URL string + License []string + Groups []string + Depends []ArchString + OptDepends []ArchString + Provides []ArchString + Conflicts []ArchString + Replaces []ArchString + Backup []string + Options []string + Install string + Changelog string +} + +// PackageBase describes the fields of a pkgbuild that may not be overwritten +// in package_ function. +type PackageBase struct { + Pkgbase string + Pkgver string + Pkgrel string + Epoch string + Source []ArchString + ValidPGPKeys []string + NoExtract []string + MD5Sums []ArchString + SHA1Sums []ArchString + SHA224Sums []ArchString + SHA256Sums []ArchString + SHA384Sums []ArchString + SHA512Sums []ArchString + MakeDepends []ArchString + CheckDepends []ArchString +} + +// Srcinfo represents a full srcinfo. All global fields are defined here while +// fields overwritten in the package_ function are defined in the +// Packages field. +// +// Note: The Packages field only contains the values that each package +// overrides, global fields will be missing. A Package containing both global +// and overwritten fields can be generated using the SplitPackage function. +type Srcinfo struct { + PackageBase // Fields that only apply to the package base + Package // Fields that apply to the package globally + Packages []Package // Fields for each package this package base contains +} + +// EmptyOverride is used to signal when a value has been overridden with an +// empty value. An empty ovrride is when a value is defined in the pkgbuild but +// then overridden inside the package function to be empty. +// +// For example "pkgdesc=''" is an empty override on the pkgdesc which would +// lead to the line "pkgdesc=" in the srcinfo. +// +// This value is used internally to store empty overrides, mainly to avoid +// using string pointers. It is possible to check for empty overrides using +// the Packages slice in Packagebase. +// +// During normal use with the SplitPackage function this value will be +// converted back to an empty string, or removed entirely for slice values. +// This means the this value can be completley ignored unless you are +// explicitly looking for empty overrides. +const EmptyOverride = "\x00" + +// Version formats a version string from the epoch, pkgver and pkgrel of the +// srcinfo. In the format [epoch:]pkgver-pkgrel. +func (si *Srcinfo) Version() string { + if si.Epoch == "" { + return si.Pkgver + "-" + si.Pkgrel + } + + return si.Epoch + ":" + si.Pkgver + "-" + si.Pkgrel +} + +// SplitPackages generates a splice of all packages that are part of this +// srcinfo. This is equivalent to calling SplitPackage on every pkgname. +func (si *Srcinfo) SplitPackages() []*Package { + pkgs := make([]*Package, 0, len(si.Packages)) + + for _, pkg := range si.Packages { + pkgs = append(pkgs, mergeSplitPackage(&si.Package, &pkg)) + } + + return pkgs +} + +// SplitPackage generates a Package that contains all fields that the specified +// pkgname has. But will fall back on global fields if they are not defined in +// the Package. +// +// Note slice values will be passed by reference, it is not recommended you +// modify this struct after it is returned. +func (si *Srcinfo) SplitPackage(pkgname string) (*Package, error) { + for n := range si.Packages { + if si.Packages[n].Pkgname == pkgname { + return mergeSplitPackage(&si.Package, &si.Packages[n]), nil + } + } + + return nil, fmt.Errorf("Package \"%s\" is not part of the package base \"%s\"", pkgname, si.Pkgbase) +} + +func mergeArchSlice(global, override []ArchString) []ArchString { + overridden := make(map[string]struct{}) + merged := make([]ArchString, 0, len(override)) + + for _, v := range override { + overridden[v.Arch] = struct{}{} + if v.Value == EmptyOverride { + continue + } + merged = append(merged, v) + } + + for _, v := range global { + if _, ok := overridden[v.Arch]; !ok { + merged = append(merged, v) + } + } + + return merged +} + +func mergeSplitPackage(base, split *Package) *Package { + pkg := &Package{} + *pkg = *base + + pkg.Pkgname = split.Pkgname + + if split.Pkgdesc != "" { + pkg.Pkgdesc = split.Pkgdesc + } + + if len(split.Arch) != 0 { + pkg.Arch = split.Arch + } + + if split.URL != "" { + pkg.URL = split.URL + } + + if len(split.License) != 0 { + pkg.License = split.License + } + + if len(split.Groups) != 0 { + pkg.Groups = split.Groups + } + + if len(split.Depends) != 0 { + pkg.Depends = mergeArchSlice(pkg.Depends, split.Depends) + } + + if len(split.OptDepends) != 0 { + pkg.OptDepends = mergeArchSlice(pkg.OptDepends, split.OptDepends) + } + + if len(split.Provides) != 0 { + pkg.Provides = mergeArchSlice(pkg.Provides, split.Provides) + } + + if len(split.Conflicts) != 0 { + pkg.Conflicts = mergeArchSlice(pkg.Conflicts, split.Conflicts) + } + + if len(split.Replaces) != 0 { + pkg.Replaces = mergeArchSlice(pkg.Replaces, split.Replaces) + } + + if len(split.Backup) != 0 { + pkg.Backup = split.Backup + } + + if len(split.Options) != 0 { + pkg.Options = split.Options + } + + if split.Changelog != "" { + pkg.Changelog = split.Changelog + } + + if split.Install != "" { + pkg.Install = split.Install + } + + return pkg +} diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/lex.go b/vendor/github.com/mikkeloscar/gopkgbuild/lex.go deleted file mode 100644 index dd2d429f..00000000 --- a/vendor/github.com/mikkeloscar/gopkgbuild/lex.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// based on the lexer from: src/pkg/text/template/parse/lex.go (golang source) - -package pkgbuild - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" -) - -// pos is a position in input being scanned -type pos int - -type item struct { - typ itemType - pos pos - val string -} - -func (i item) String() string { - switch { - case i.typ == itemEOF: - return "EOF" - case i.typ == itemError: - return i.val - case len(i.val) > 10: - return fmt.Sprintf("%.10q...", i.val) - } - return fmt.Sprintf("%q", i.val) -} - -type itemType int - -const ( - itemError itemType = iota - itemEOF - itemVariable - itemValue - itemEndSplit - // PKGBUILD variables - itemPkgname // pkgname variable - itemPkgver // pkgver variable - itemPkgrel // pkgrel variable - itemPkgdir // pkgdir variable - itemEpoch // epoch variable - itemPkgbase // pkgbase variable - itemPkgdesc // pkgdesc variable - itemArch // arch variable - itemURL // url variable - itemLicense // license variable - itemGroups // groups variable - itemDepends // depends variable - itemOptdepends // optdepends variable - itemMakedepends // makedepends variable - itemCheckdepends // checkdepends variable - itemProvides // provides variable - itemConflicts // conflicts variable - itemReplaces // replaces variable - itemBackup // backup variable - itemOptions // options variable - itemInstall // install variable - itemChangelog // changelog variable - itemSource // source variable - itemNoextract // noextract variable - itemMd5sums // md5sums variable - itemSha1sums // sha1sums variable - itemSha224sums // sha224sums variable - itemSha256sums // sha256sums variable - itemSha384sums // sha384sums variable - itemSha512sums // sha512sums variable - itemValidpgpkeys // validpgpkeys variable -) - -// PKGBUILD variables -var variables = map[string]itemType{ - "pkgname": itemPkgname, - "pkgver": itemPkgver, - "pkgrel": itemPkgrel, - "pkgdir": itemPkgdir, - "epoch": itemEpoch, - "pkgbase": itemPkgbase, - "pkgdesc": itemPkgdesc, - "arch": itemArch, - "url": itemURL, - "license": itemLicense, - "groups": itemGroups, - "depends": itemDepends, - "optdepends": itemOptdepends, - "makedepends": itemMakedepends, - "checkdepends": itemCheckdepends, - "provides": itemProvides, - "conflicts": itemConflicts, - "replaces": itemReplaces, - "backup": itemBackup, - "options": itemOptions, - "install": itemInstall, - "changelog": itemChangelog, - "source": itemSource, - "noextract": itemNoextract, - "md5sums": itemMd5sums, - "sha1sums": itemSha1sums, - "sha224sums": itemSha224sums, - "sha256sums": itemSha256sums, - "sha384sums": itemSha384sums, - "sha512sums": itemSha512sums, - "validpgpkeys": itemValidpgpkeys, -} - -const eof = -1 - -// stateFn represents the state of the scanner as a function that returns the next state -type stateFn func(*lexer) stateFn - -// lexer holds the state of the scanner -type lexer struct { - input string - state stateFn - pos pos - start pos - width pos - lastPos pos - items chan item // channel of scanned items -} - -// next returns the next rune in the input -func (l *lexer) next() rune { - if int(l.pos) >= len(l.input) { - l.width = 0 - return eof - } - r, w := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = pos(w) - l.pos += l.width - return r -} - -// peek returns but does not consume the next rune in the input -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// backup steps back one rune. Can only be called once per call of next -func (l *lexer) backup() { - l.pos -= l.width -} - -// emit passes an item back to the client -func (l *lexer) emit(t itemType) { - l.items <- item{t, l.start, l.input[l.start:l.pos]} - l.start = l.pos -} - -// ignore skips over the pending input before this point -func (l *lexer) ignore() { - l.start = l.pos -} - -// errorf returns an error token and terminates the scan by passing -// back a nil pointer that will be the next state, terminating l.nextItem. -func (l *lexer) errorf(format string, args ...interface{}) stateFn { - l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} - return nil -} - -// nextItem returns the next item from the input. -func (l *lexer) nextItem() item { - item := <-l.items - l.lastPos = item.pos - return item -} - -func lex(input string) *lexer { - l := &lexer{ - input: input, - items: make(chan item), - } - go l.run() - return l -} - -func (l *lexer) run() { - for l.state = lexEnv; l.state != nil; { - l.state = l.state(l) - } -} - -func lexEnv(l *lexer) stateFn { - var r rune - for { - switch r = l.next(); { - case r == eof: - l.emit(itemEOF) - return nil - case isAlphaNumericUnderscore(r): - return lexVariable - case r == '\n': - buffer := l.input[l.start:l.pos] - if buffer == "\n" { - if l.peek() == '\n' { - l.next() - l.emit(itemEndSplit) - } - l.ignore() - } - case r == '\t': - l.ignore() - case r == ' ': - l.ignore() - case r == '#': - return lexComment - default: - l.errorf("unable to parse character: %c", r) - } - } -} - -func lexComment(l *lexer) stateFn { - for { - switch l.next() { - case '\n': - l.ignore() - return lexEnv - case eof: - l.emit(itemEOF) - return nil - } - } -} - -func lexVariable(l *lexer) stateFn { - for { - switch r := l.next(); { - case isAlphaNumericUnderscore(r): - // absorb - case r == ' ' && l.peek() == '=': - l.backup() - variable := l.input[l.start:l.pos] - - // strip arch from source_arch like constructs - witharch := strings.SplitN(variable, "_", 2) - if len(witharch) == 2 { - variable = witharch[0] - } - - if _, ok := variables[variable]; ok { - l.emit(variables[variable]) - // TODO to cut off ' = ' - l.next() - l.next() - l.next() - l.ignore() - return lexValue - } - return l.errorf("invalid variable: %s", variable) - default: - pattern := l.input[l.start:l.pos] - return l.errorf("invalid pattern: %s", pattern) - } - } -} - -func lexValue(l *lexer) stateFn { - for { - switch l.next() { - case '\n': - l.backup() - l.emit(itemValue) - return lexEnv - } - } -} - -// isAlphaNumericUnderscore reports whether r is an alphabetic, digit, or underscore. -func isAlphaNumericUnderscore(r rune) bool { - return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) -} diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go b/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go deleted file mode 100644 index ac267f7f..00000000 --- a/vendor/github.com/mikkeloscar/gopkgbuild/pkgbuild.go +++ /dev/null @@ -1,625 +0,0 @@ -package pkgbuild - -import ( - "bytes" - "fmt" - "io/ioutil" - "strconv" - "strings" -) - -// Dependency describes a dependency with min and max version, if any. -type Dependency struct { - Name string // dependency name - MinVer *CompleteVersion // min version - sgt bool // defines if min version is strictly greater than - MaxVer *CompleteVersion // max version - slt bool // defines if max version is strictly less than -} - -// Restrict merges two dependencies together into a new dependency where the -// conditions of both a and b are met -func (a *Dependency) Restrict(b *Dependency) *Dependency { - newDep := &Dependency{ - Name: a.Name, - } - - if a.MaxVer != nil || b.MaxVer != nil { - newDep.MaxVer = &CompleteVersion{} - - if a.MaxVer == nil { - *newDep.MaxVer = *b.MaxVer - newDep.slt = b.slt - } else if b.MaxVer == nil { - *newDep.MaxVer = *a.MaxVer - newDep.slt = a.slt - } else { - cmpMax := a.MaxVer.cmp(b.MaxVer) - if cmpMax >= 1 { - *newDep.MaxVer = *b.MaxVer - newDep.slt = b.slt - } else if cmpMax <= -1 { - *newDep.MaxVer = *a.MaxVer - newDep.slt = a.slt - } else if cmpMax == 0 { - if len(a.MaxVer.Pkgrel) > len(b.MaxVer.Pkgrel) { - *newDep.MaxVer = *a.MaxVer - } else { - *newDep.MaxVer = *b.MaxVer - } - if a.slt != b.slt { - newDep.slt = true - } else { - newDep.slt = a.slt - } - } - } - } - - if a.MinVer != nil || b.MinVer != nil { - newDep.MinVer = &CompleteVersion{} - - if a.MinVer == nil { - *newDep.MinVer = *b.MinVer - newDep.sgt = b.slt - } else if b.MinVer == nil { - *newDep.MinVer = *a.MinVer - newDep.sgt = a.sgt - } else { - cmpMin := a.MinVer.cmp(b.MinVer) - if cmpMin >= 1 { - *newDep.MinVer = *a.MinVer - newDep.sgt = a.sgt - } else if cmpMin <= -1 { - *newDep.MinVer = *b.MinVer - newDep.sgt = b.sgt - } else if cmpMin == 0 { - if len(a.MinVer.Pkgrel) > len(b.MinVer.Pkgrel) { - *newDep.MinVer = *a.MinVer - } else { - *newDep.MinVer = *b.MinVer - } - if a.sgt != b.sgt { - newDep.sgt = true - } else { - newDep.sgt = a.sgt - } - } - } - } - - return newDep -} - -func (dep *Dependency) String() string { - str := "" - greaterThan := ">" - lessThan := "<" - - if !dep.sgt { - greaterThan = ">=" - } - - if !dep.slt { - lessThan = "<=" - } - - if dep.MinVer != nil { - str += dep.Name + greaterThan + dep.MinVer.String() - - if dep.MaxVer != nil { - str += " " - } - } - - if dep.MaxVer != nil { - str += dep.Name + lessThan + dep.MaxVer.String() - } - - return str -} - -// PKGBUILD is a struct describing a parsed PKGBUILD file. -// Required fields are: -// pkgname -// pkgver -// pkgrel -// arch -// (license) - not required but recommended -// -// parsing a PKGBUILD file without these fields will fail -type PKGBUILD struct { - Pkgnames []string - Pkgver Version // required - Pkgrel Version // required - Pkgdir string - Epoch int - Pkgbase string - Pkgdesc string - Arch []string // required - URL string - License []string // recommended - Groups []string - Depends []*Dependency - Optdepends []string - Makedepends []*Dependency - Checkdepends []*Dependency - Provides []string - Conflicts []string - Replaces []string - Backup []string - Options []string - Install string - Changelog string - Source []string - Noextract []string - Md5sums []string - Sha1sums []string - Sha224sums []string - Sha256sums []string - Sha384sums []string - Sha512sums []string - Validpgpkeys []string -} - -// Newer is true if p has a higher version number than p2 -func (p *PKGBUILD) Newer(p2 *PKGBUILD) bool { - if p.Epoch < p2.Epoch { - return false - } - - if p.Pkgver.bigger(p2.Pkgver) { - return true - } - - if p2.Pkgver.bigger(p.Pkgver) { - return false - } - - return p.Pkgrel > p2.Pkgrel -} - -// Older is true if p has a smaller version number than p2 -func (p *PKGBUILD) Older(p2 *PKGBUILD) bool { - if p.Epoch < p2.Epoch { - return true - } - - if p2.Pkgver.bigger(p.Pkgver) { - return true - } - - if p.Pkgver.bigger(p2.Pkgver) { - return false - } - - return p.Pkgrel < p2.Pkgrel -} - -// Version returns the full version of the PKGBUILD (including epoch and rel) -func (p *PKGBUILD) Version() string { - if p.Epoch > 0 { - return fmt.Sprintf("%d:%s-%s", p.Epoch, p.Pkgver, p.Pkgrel) - } - - return fmt.Sprintf("%s-%s", p.Pkgver, p.Pkgrel) -} - -// CompleteVersion returns a Complete version struct including version, rel and -// epoch. -func (p *PKGBUILD) CompleteVersion() CompleteVersion { - return CompleteVersion{ - Version: p.Pkgver, - Epoch: uint8(p.Epoch), - Pkgrel: p.Pkgrel, - } -} - -// BuildDepends is Depends, MakeDepends and CheckDepends combined. -func (p *PKGBUILD) BuildDepends() []*Dependency { - // TODO real merge - deps := make([]*Dependency, len(p.Depends)+len(p.Makedepends)+len(p.Checkdepends)) - - deps = append(p.Depends, p.Makedepends...) - deps = append(deps, p.Checkdepends...) - - return deps -} - -// IsDevel returns true if package contains devel packages (-{bzr,git,svn,hg}) -// TODO: more robust check. -func (p *PKGBUILD) IsDevel() bool { - for _, name := range p.Pkgnames { - if strings.HasSuffix(name, "-git") { - return true - } - - if strings.HasSuffix(name, "-svn") { - return true - } - - if strings.HasSuffix(name, "-hg") { - return true - } - - if strings.HasSuffix(name, "-bzr") { - return true - } - } - - return false -} - -// MustParseSRCINFO must parse the .SRCINFO given by path or it will panic -func MustParseSRCINFO(path string) *PKGBUILD { - pkgbuild, err := ParseSRCINFO(path) - if err != nil { - panic(err) - } - return pkgbuild -} - -// ParseSRCINFO parses .SRCINFO file given by path. -// This is a safe alternative to ParsePKGBUILD given that a .SRCINFO file is -// available -func ParseSRCINFO(path string) (*PKGBUILD, error) { - f, err := ioutil.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("unable to read file: %s, %s", path, err.Error()) - } - - return parsePKGBUILD(string(f)) -} - -// ParseSRCINFOContent parses a .SRCINFO formatted byte slice. -// This is a safe alternative to ParsePKGBUILD given that the .SRCINFO content -// is available -func ParseSRCINFOContent(content []byte) (*PKGBUILD, error) { - return parsePKGBUILD(string(content)) -} - -// parse a PKGBUILD and check that the required fields has a non-empty value -func parsePKGBUILD(input string) (*PKGBUILD, error) { - pkgb, err := parse(input) - if err != nil { - return nil, err - } - - if !validPkgver(string(pkgb.Pkgver)) { - return nil, fmt.Errorf("invalid pkgver: %s", pkgb.Pkgver) - } - - if len(pkgb.Arch) == 0 { - return nil, fmt.Errorf("Arch missing") - } - - if len(pkgb.Pkgnames) == 0 { - return nil, fmt.Errorf("missing pkgname") - } - - for _, name := range pkgb.Pkgnames { - if !validPkgname(name) { - return nil, fmt.Errorf("invalid pkgname: %s", name) - } - } - - return pkgb, nil -} - -// parses a SRCINFO formatted PKGBUILD -func parse(input string) (*PKGBUILD, error) { - var pkgbuild *PKGBUILD - var next item - - lexer := lex(input) -Loop: - for { - token := lexer.nextItem() - - // strip arch from source_arch like constructs - witharch := strings.SplitN(token.val, "_", 2) - if len(witharch) == 2 { - found := false - for _, arch := range pkgbuild.Arch { - if arch == witharch[1] { - token.val = witharch[0] - found = true - break - } - } - - if !found { - return nil, fmt.Errorf("unsupported arch for variable: %s", token.val) - } - } - - switch token.typ { - case itemPkgbase: - next = lexer.nextItem() - pkgbuild = &PKGBUILD{Epoch: 0, Pkgbase: next.val} - case itemPkgname: - next = lexer.nextItem() - pkgbuild.Pkgnames = append(pkgbuild.Pkgnames, next.val) - case itemPkgver: - next = lexer.nextItem() - version, err := parseVersion(next.val) - if err != nil { - return nil, err - } - pkgbuild.Pkgver = version - case itemPkgrel: - next = lexer.nextItem() - rel, err := parseVersion(next.val) - if err != nil { - return nil, err - } - pkgbuild.Pkgrel = rel - case itemPkgdir: - next = lexer.nextItem() - pkgbuild.Pkgdir = next.val - case itemEpoch: - next = lexer.nextItem() - epoch, err := strconv.ParseInt(next.val, 10, 0) - if err != nil { - return nil, err - } - - if epoch < 0 { - return nil, fmt.Errorf("invalid epoch: %d", epoch) - } - pkgbuild.Epoch = int(epoch) - case itemPkgdesc: - next = lexer.nextItem() - pkgbuild.Pkgdesc = next.val - case itemArch: - next = lexer.nextItem() - pkgbuild.Arch = append(pkgbuild.Arch, next.val) - case itemURL: - next = lexer.nextItem() - pkgbuild.URL = next.val - case itemLicense: - next = lexer.nextItem() - pkgbuild.License = append(pkgbuild.License, next.val) - case itemGroups: - next = lexer.nextItem() - pkgbuild.Groups = append(pkgbuild.Groups, next.val) - case itemDepends: - next = lexer.nextItem() - deps, err := parseDependency(next.val, pkgbuild.Depends) - if err != nil { - return nil, err - } - pkgbuild.Depends = deps - case itemOptdepends: - next = lexer.nextItem() - pkgbuild.Optdepends = append(pkgbuild.Optdepends, next.val) - case itemMakedepends: - next = lexer.nextItem() - deps, err := parseDependency(next.val, pkgbuild.Makedepends) - if err != nil { - return nil, err - } - pkgbuild.Makedepends = deps - case itemCheckdepends: - next = lexer.nextItem() - deps, err := parseDependency(next.val, pkgbuild.Checkdepends) - if err != nil { - return nil, err - } - pkgbuild.Checkdepends = deps - case itemProvides: - next = lexer.nextItem() - pkgbuild.Provides = append(pkgbuild.Provides, next.val) - case itemConflicts: - next = lexer.nextItem() - pkgbuild.Conflicts = append(pkgbuild.Conflicts, next.val) - case itemReplaces: - next = lexer.nextItem() - pkgbuild.Replaces = append(pkgbuild.Replaces, next.val) - case itemBackup: - next = lexer.nextItem() - pkgbuild.Backup = append(pkgbuild.Backup, next.val) - case itemOptions: - next = lexer.nextItem() - pkgbuild.Options = append(pkgbuild.Options, next.val) - case itemInstall: - next = lexer.nextItem() - pkgbuild.Install = next.val - case itemChangelog: - next = lexer.nextItem() - pkgbuild.Changelog = next.val - case itemSource: - next = lexer.nextItem() - pkgbuild.Source = append(pkgbuild.Source, next.val) - case itemNoextract: - next = lexer.nextItem() - pkgbuild.Noextract = append(pkgbuild.Noextract, next.val) - case itemMd5sums: - next = lexer.nextItem() - pkgbuild.Md5sums = append(pkgbuild.Md5sums, next.val) - case itemSha1sums: - next = lexer.nextItem() - pkgbuild.Sha1sums = append(pkgbuild.Sha1sums, next.val) - case itemSha224sums: - next = lexer.nextItem() - pkgbuild.Sha224sums = append(pkgbuild.Sha224sums, next.val) - case itemSha256sums: - next = lexer.nextItem() - pkgbuild.Sha256sums = append(pkgbuild.Sha256sums, next.val) - case itemSha384sums: - next = lexer.nextItem() - pkgbuild.Sha384sums = append(pkgbuild.Sha384sums, next.val) - case itemSha512sums: - next = lexer.nextItem() - pkgbuild.Sha512sums = append(pkgbuild.Sha512sums, next.val) - case itemValidpgpkeys: - next = lexer.nextItem() - pkgbuild.Validpgpkeys = append(pkgbuild.Validpgpkeys, next.val) - case itemEndSplit: - case itemError: - return nil, fmt.Errorf(token.val) - case itemEOF: - break Loop - default: - return nil, fmt.Errorf("invalid variable: %s", token.val) - } - } - return pkgbuild, nil -} - -// parse and validate a version string -func parseVersion(s string) (Version, error) { - if validPkgver(s) { - return Version(s), nil - } - - return "", fmt.Errorf("invalid version string: %s", s) -} - -// check if name is a valid pkgname format -func validPkgname(name string) bool { - if len(name) < 1 { - return false - } - - if name[0] == '-' { - return false - } - - for _, r := range name { - if !isValidPkgnameChar(r) { - return false - } - } - - return true -} - -// check if version is a valid pkgver format -func validPkgver(version string) bool { - if len(version) < 1 { - return false - } - - if !isAlphaNumeric(rune(version[0])) { - return false - } - - for _, r := range version[1:] { - if !isValidPkgverChar(r) { - return false - } - } - - return true -} - -// ParseDeps parses a string slice of dependencies into a slice of Dependency -// objects. -func ParseDeps(deps []string) ([]*Dependency, error) { - var err error - dependencies := make([]*Dependency, 0) - - for _, dep := range deps { - dependencies, err = parseDependency(dep, dependencies) - if err != nil { - return nil, err - } - } - - return dependencies, nil -} - -// parse dependency with possible version restriction -func parseDependency(dep string, deps []*Dependency) ([]*Dependency, error) { - var name string - var dependency *Dependency - index := -1 - - if dep == "" { - return deps, nil - } - - if dep[0] == '-' { - return nil, fmt.Errorf("invalid dependency name") - } - - i := 0 - for _, c := range dep { - if !isValidPkgnameChar(c) { - break - } - i++ - } - - // check if the dependency has been set before - name = dep[0:i] - for n, d := range deps { - if d.Name == name { - index = n - break - } - } - - dependency = &Dependency{ - Name: name, - sgt: false, - slt: false, - } - - if len(dep) != len(name) { - var eq bytes.Buffer - for _, c := range dep[i:] { - if c == '<' || c == '>' || c == '=' { - i++ - eq.WriteRune(c) - continue - } - break - } - - version, err := NewCompleteVersion(dep[i:]) - if err != nil { - return nil, err - } - - switch eq.String() { - case "=": - dependency.MinVer = version - dependency.MaxVer = version - case "<=": - dependency.MaxVer = version - case ">=": - dependency.MinVer = version - case "<": - dependency.MaxVer = version - dependency.slt = true - case ">": - dependency.MinVer = version - dependency.sgt = true - } - } - - if index == -1 { - deps = append(deps, dependency) - } else { - deps[index] = deps[index].Restrict(dependency) - } - - return deps, nil -} - -// isLowerAlpha reports whether c is a lowercase alpha character -func isLowerAlpha(c rune) bool { - return 'a' <= c && c <= 'z' -} - -// check if c is a valid pkgname char -func isValidPkgnameChar(c rune) bool { - return isAlphaNumeric(c) || c == '@' || c == '.' || c == '_' || c == '+' || c == '-' -} - -// check if c is a valid pkgver char -func isValidPkgverChar(c rune) bool { - return isAlphaNumeric(c) || c == '_' || c == '+' || c == '.' || c == '~' -} diff --git a/vendor/github.com/mikkeloscar/gopkgbuild/version.go b/vendor/github.com/mikkeloscar/gopkgbuild/version.go deleted file mode 100644 index 1695377d..00000000 --- a/vendor/github.com/mikkeloscar/gopkgbuild/version.go +++ /dev/null @@ -1,324 +0,0 @@ -package pkgbuild - -import ( - "fmt" - "strconv" - "strings" - "unicode" -) - -// Version string -type Version string - -type CompleteVersion struct { - Version Version - Epoch uint8 - Pkgrel Version -} - -func (c *CompleteVersion) String() string { - str := "" - - if c.Epoch > 0 { - str = fmt.Sprintf("%d:", c.Epoch) - } - - str = fmt.Sprintf("%s%s", str, c.Version) - - if c.Pkgrel != "" { - str = fmt.Sprintf("%s-%s", str, c.Pkgrel) - } - - return str -} - -// NewCompleteVersion creates a CompleteVersion including basic version, epoch -// and rel from string -func NewCompleteVersion(s string) (*CompleteVersion, error) { - var err error - epoch := 0 - rel := Version("") - - // handle possible epoch - versions := strings.Split(s, ":") - if len(versions) > 2 { - return nil, fmt.Errorf("invalid version format: %s", s) - } - - if len(versions) > 1 { - epoch, err = strconv.Atoi(versions[0]) - if err != nil { - return nil, err - } - } - - // handle possible rel - versions = strings.Split(versions[len(versions)-1], "-") - if len(versions) > 2 { - return nil, fmt.Errorf("invalid version format: %s", s) - } - - if len(versions) > 1 { - rel = Version(versions[1]) - } - - // finally check that the actual version is valid - if validPkgver(versions[0]) { - return &CompleteVersion{ - Version: Version(versions[0]), - Epoch: uint8(epoch), - Pkgrel: rel, - }, nil - } - - return nil, fmt.Errorf("invalid version format: %s", s) -} - -// 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 -func (a *CompleteVersion) Newer(b *CompleteVersion) bool { - return a.cmp(b) == 1 -} - -// Equal returns true if a is equal to the argument version -func (a *CompleteVersion) Equal(b *CompleteVersion) bool { - return a.cmp(b) == 0 -} - -// Satisfies tests whether or not version fits inside the bounds specified by -// dep -func (version *CompleteVersion) Satisfies(dep *Dependency) bool { - var cmpMax int8 - var cmpMin int8 - - if dep.MaxVer != nil { - cmpMax = version.cmp(dep.MaxVer) - if cmpMax == 1 { - return false - } - - if cmpMax == 0 && dep.slt { - return false - } - } - - if dep.MinVer != nil { - if dep.MaxVer == dep.MinVer { - cmpMin = cmpMax - } else { - cmpMin = version.cmp(dep.MinVer) - } - if cmpMin == -1 { - return false - } - - if cmpMin == 0 && dep.sgt { - return false - } - } - - return true -} - -// Compare a to b: -// return 1: a is newer than b -// 0: a and b are the same version -// -1: b is newer than a -func (a *CompleteVersion) cmp(b *CompleteVersion) int8 { - if a.Epoch > b.Epoch { - return 1 - } - - if a.Epoch < b.Epoch { - return -1 - } - - if a.Version.bigger(b.Version) { - return 1 - } - - if b.Version.bigger(a.Version) { - return -1 - } - - if a.Pkgrel == "" || b.Pkgrel == "" { - return 0 - } - - if a.Pkgrel.bigger(b.Pkgrel) { - return 1 - } - - if b.Pkgrel.bigger(a.Pkgrel) { - return -1 - } - - return 0 -} - -// Compare alpha and numeric segments of two versions. -// return 1: a is newer than b -// 0: a and b are the same version -// -1: b is newer than a -// -// This is based on the rpmvercmp function used in libalpm -// https://projects.archlinux.org/pacman.git/tree/lib/libalpm/version.c -func rpmvercmp(av, bv Version) int { - if av == bv { - return 0 - } - a, b := []rune(string(av)), []rune(string(bv)) - - var one, two, ptr1, ptr2 int - var isNum bool - one, two, ptr1, ptr2 = 0, 0, 0, 0 - - // loop through each version segment of a and b and compare them - for len(a) > one && len(b) > two { - for len(a) > one && !isAlphaNumeric(a[one]) { - one++ - } - for len(b) > two && !isAlphaNumeric(b[two]) { - two++ - } - - // if we ran to the end of either, we are finished with the loop - if !(len(a) > one && len(b) > two) { - break - } - - // if the seperator lengths were different, we are also finished - if one-ptr1 != two-ptr2 { - if one-ptr1 < two-ptr2 { - return -1 - } - return 1 - } - - ptr1 = one - ptr2 = two - - // grab first completely alpha or completely numeric segment - // leave one and two pointing to the start of the alpha or numeric - // segment and walk ptr1 and ptr2 to end of segment - if isDigit(a[ptr1]) { - for len(a) > ptr1 && isDigit(a[ptr1]) { - ptr1++ - } - for len(b) > ptr2 && isDigit(b[ptr2]) { - ptr2++ - } - isNum = true - } else { - for len(a) > ptr1 && isAlpha(a[ptr1]) { - ptr1++ - } - for len(b) > ptr2 && isAlpha(b[ptr2]) { - ptr2++ - } - isNum = false - } - - // take care of the case where the two version segments are - // different types: one numeric, the other alpha (i.e. empty) - // numeric segments are always newer than alpha segments - if two == ptr2 { - if isNum { - return 1 - } - return -1 - } - - if isNum { - // we know this part of the strings only contains digits - // so we can ignore the error value since it should - // always be nil - as, _ := strconv.ParseInt(string(a[one:ptr1]), 10, 0) - bs, _ := strconv.ParseInt(string(b[two:ptr2]), 10, 0) - - // whichever number has more digits wins - if as > bs { - return 1 - } - if as < bs { - return -1 - } - } else { - cmp := alphaCompare(a[one:ptr1], b[two:ptr2]) - if cmp < 0 { - return -1 - } - if cmp > 0 { - return 1 - } - } - - // advance one and two to next segment - one = ptr1 - two = ptr2 - } - - // this catches the case where all numeric and alpha segments have - // compared identically but the segment separating characters were - // different - if len(a) <= one && len(b) <= two { - return 0 - } - - // the final showdown. we never want a remaining alpha string to - // beat an empty string. the logic is a bit weird, but: - // - if one is empty and two is not an alpha, two is newer. - // - if one is an alpha, two is newer. - // - otherwise one is newer. - if (len(a) <= one && !isAlpha(b[two])) || len(a) > one && isAlpha(a[one]) { - return -1 - } - return 1 -} - -// alphaCompare compares two alpha version segments and will return a positive -// value if a is bigger than b and a negative if b is bigger than a else 0 -func alphaCompare(a, b []rune) int8 { - if string(a) == string(b) { - return 0 - } - - i := 0 - for len(a) > i && len(b) > i && a[i] == b[i] { - i++ - } - - if len(a) == i && len(b) > i { - return -1 - } - - if len(b) == i { - return 1 - } - - return int8(a[i]) - int8(b[i]) -} - -// check if version number v is bigger than v2 -func (v Version) bigger(v2 Version) bool { - return rpmvercmp(v, v2) == 1 -} - -// isAlphaNumeric reports whether c is an alpha character or digit -func isAlphaNumeric(c rune) bool { - return isDigit(c) || isAlpha(c) -} - -// isAlpha reports whether c is an alpha character -func isAlpha(c rune) bool { - return unicode.IsLetter(c) -} - -// isDigit reports whether d is an ASCII digit -func isDigit(d rune) bool { - return unicode.IsDigit(d) -} From f3635cd14d8d5f8652590fb3666fc66d734028e6 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 16 Jul 2018 17:03:39 +0100 Subject: [PATCH 021/155] Fix group installs for --nocombinedupgrade --- install.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/install.go b/install.go index 70cb7cff..00a736e3 100644 --- a/install.go +++ b/install.go @@ -93,6 +93,12 @@ func install(parser *arguments) error { if err == nil { arguments.addTarget(_target) } else { + _, err := syncDb.PkgCachebyGroup(target.Name) + if err == nil { + arguments.addTarget(_target) + continue + } + parser.addTarget(_target) } } From 6b30e17b67369194cd030057cdbf66bd7b5bbdf8 Mon Sep 17 00:00:00 2001 From: Ema Panz Date: Tue, 17 Jul 2018 16:49:47 +0200 Subject: [PATCH 022/155] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 8c5f18cc..35a3efaa 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,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) + +* Yay is not asking to select packages during install (issue [#554](https://github.com/Jguer/yay/issues/554)) + + The default behavior was changed from [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) (see: [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)). + To restore such behavior use the `--combinedupgrade`. + Note: this causes [native pacman](https://wiki.archlinux.org/index.php/AUR_helpers) to become partial. * Sometimes diffs are printed to the terminal and other times they are pages via less. How do I fix this? @@ -102,6 +108,7 @@ Currently yay Depends on: * `Out Of Date AUR Packages`message is displayed, why doesn't `yay` update them? This means the package has been flagged out of date on the AUR but author has not updated the `PKGBUILD` yet. + ## Examples of Custom Operations * `yay ` presents package selection menu From 686e1baaf4c52e478da70cd2a392031bedfd48cd Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 16 Jul 2018 16:24:57 +0100 Subject: [PATCH 023/155] Update readme, depreciate -Pu and -Pn --- README.md | 2 +- cmd.go | 2 -- doc/yay.8 | 6 ++---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 35a3efaa..ae140dbb 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ are built into Yay at build time. They do not need to be installed separately. Currently yay Depends on: * https://github.com/Jguer/go-alpm -* https://github.com/mikkeloscar/gopkgbuild +* https://github.com/Morganamilo/go-srcinfo * https://github.com/mikkeloscar/aur ## Frequently Asked Questions diff --git a/cmd.go b/cmd.go index 63fbf694..7eb44539 100644 --- a/cmd.go +++ b/cmd.go @@ -109,9 +109,7 @@ Print specific options: -c --complete Used for completions -d --defaultconfig Print default yay configuration -g --config Print current yay configuration - -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: diff --git a/doc/yay.8 b/doc/yay.8 index 75010690..33f51d85 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -118,8 +118,7 @@ Print current yay configuration\&. .PP \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\&. +Depreciated, use \fByay -Qu\fR and \fBwl -l\fR instead\%. .RE .PP \fB\-s \-\-stats\fR @@ -131,8 +130,7 @@ be displayed\&. .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\&. +Depreciated, use \fByay -Qu\fR instead\%. .RE .PP \fB\-w \-\-news\fR From 46d09f8ab75996969f49d2b13a9b2cb66c276caf Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 17 Jul 2018 22:07:20 +0100 Subject: [PATCH 024/155] Fixup FAQ Section --- README.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ae140dbb..f468d761 100644 --- a/README.md +++ b/README.md @@ -84,30 +84,28 @@ Currently yay Depends on: ## Frequently Asked Questions -* Yay does not display colored output. How do I fix it? +### 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) - -* Yay is not asking to select packages during install (issue [#554](https://github.com/Jguer/yay/issues/554)) +### Yay is not prompting to skip packages during sysupgrade (issue [#554](https://github.com/Jguer/yay/issues/554)) The default behavior was changed from [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) (see: [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)). To restore such behavior use the `--combinedupgrade`. Note: this causes [native pacman](https://wiki.archlinux.org/index.php/AUR_helpers) to become partial. -* 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`. +### Sometimes diffs are printed to the terminal and other times they are paged 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`. -* Yay is not asking me to edit PKGBUILDS and I don't like diff menu! What do? +### 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` +### Only act on AUR packages or only on repo packages? + `yay -{OPERATION} --aur` + `yay -{OPERATION} --repo` -* `Out Of Date AUR Packages`message is displayed, why doesn't `yay` update them? -This means the package has been flagged out of date on the AUR but author has not updated the `PKGBUILD` yet. +### `Out Of Date AUR Packages` message is displayed, why doesn't `yay` update them? + This means the package has been flagged out of date on the AUR but maintainer has not updated the `PKGBUILD` yet. ## Examples of Custom Operations From 9602d4bc799aadb5c86446ea23a2bd99a45f358c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 17 Jul 2018 22:36:01 +0100 Subject: [PATCH 025/155] Fix typo --- doc/yay.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index 33f51d85..dbc3c383 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -118,7 +118,7 @@ Print current yay configuration\&. .PP \fB\-n \-\-numberupgrades\fR .RS 4 -Depreciated, use \fByay -Qu\fR and \fBwl -l\fR instead\%. +Deprecated, use \fByay -Qu\fR and \fBwl -l\fR instead\%. .RE .PP \fB\-s \-\-stats\fR @@ -130,7 +130,7 @@ be displayed\&. .PP \fB\-u \-\-upgrades\fR .RS 4 -Depreciated, use \fByay -Qu\fR instead\%. +Deprecated, use \fByay -Qu\fR instead\%. .RE .PP \fB\-w \-\-news\fR From d4d36397fe8fd38a089ad356537126995d1b4939 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 17 Jul 2018 22:54:13 +0100 Subject: [PATCH 026/155] Show .install files with pkgbuilds when editing --- install.go | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/install.go b/install.go index 00a736e3..2110419e 100644 --- a/install.go +++ b/install.go @@ -259,6 +259,12 @@ func install(parser *arguments) error { return err } + //initial srcinfo parse before pkgver() bump + err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) + if err != nil { + return err + } + var toDiff []*rpc.Pkg var toEdit []*rpc.Pkg @@ -270,7 +276,7 @@ func install(parser *arguments) error { } if len(toDiff) > 0 { - err = showPkgBuildDiffs(toDiff, do.Bases, cloned) + err = showPkgBuildDiffs(toDiff, srcinfosStale, do.Bases, cloned) if err != nil { return err } @@ -300,7 +306,7 @@ func install(parser *arguments) error { } if len(toEdit) > 0 { - err = editPkgBuilds(toEdit, do.Bases) + err = editPkgBuilds(toEdit, srcinfosStale, do.Bases) if err != nil { return err } @@ -317,12 +323,6 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - //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 @@ -651,7 +651,7 @@ func cleanBuilds(pkgs []*rpc.Pkg) { } } -func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stringSet) error { +func showPkgBuildDiffs(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg, cloned stringSet) error { for _, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) if shouldUseGit(dir) { @@ -684,6 +684,12 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri } else { editor, editorArgs := editor() editorArgs = append(editorArgs, filepath.Join(dir, "PKGBUILD")) + for _, splitPkg := range srcinfos[pkg.PackageBase].SplitPackages() { + if splitPkg.Install != "" { + editorArgs = append(editorArgs, filepath.Join(dir, splitPkg.Install)) + } + } + editcmd := exec.Command(editor, editorArgs...) editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr err := editcmd.Run() @@ -696,11 +702,17 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri return nil } -func editPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { +func editPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) 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")) + + for _, splitPkg := range srcinfos[pkg.PackageBase].SplitPackages() { + if splitPkg.Install != "" { + pkgbuilds = append(pkgbuilds, filepath.Join(dir, splitPkg.Install)) + } + } } if len(pkgbuilds) > 0 { From a576dbc1fdd60bdd3d875427f0a1b16646093951 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 17:31:22 +0100 Subject: [PATCH 027/155] Mention --save in --combinedupgrade FAQ --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f468d761..47cf8a73 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,10 @@ Currently yay Depends on: Make sure you have the `Color` option in your `/etc/pacman.conf` [#123](https://github.com/Jguer/yay/issues/123) ### Yay is not prompting to skip packages during sysupgrade (issue [#554](https://github.com/Jguer/yay/issues/554)) - The default behavior was changed from [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) (see: [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)). - To restore such behavior use the `--combinedupgrade`. + The default behavior was changed after [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) + (see: [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)). + To restore such behavior use `--combinedupgrade`. This can also be + permanently enabled by appending `--save`. Note: this causes [native pacman](https://wiki.archlinux.org/index.php/AUR_helpers) to become partial. ### Sometimes diffs are printed to the terminal and other times they are paged via less. How do I fix this? From 6313c14382104277bfaf9a39d2aa8bdfdaa2f626 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 17:38:41 +0100 Subject: [PATCH 028/155] Add editing pkgbuild dependencies to the FAQ --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 47cf8a73..43152740 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,11 @@ Currently yay Depends on: ### `Out Of Date AUR Packages` message is displayed, why doesn't `yay` update them? This means the package has been flagged out of date on the AUR but maintainer has not updated the `PKGBUILD` yet. +### Yay doesn't install dependencies added to PKGBUILD during installation. + Yay resolves all dependencies ahead of time. You are free to edit the + PKGBUILD in anyway but any problems you cause are your own and should not be + reported unless they can be reproduced with the original PKGBUILD. + ## Examples of Custom Operations * `yay ` presents package selection menu From 526cec70ed8174b0b5618beef5d029966570bfa2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 17:39:54 +0100 Subject: [PATCH 029/155] Fix typo in man page --- doc/yay.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/yay.8 b/doc/yay.8 index dbc3c383..7c822a97 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -118,7 +118,7 @@ Print current yay configuration\&. .PP \fB\-n \-\-numberupgrades\fR .RS 4 -Deprecated, use \fByay -Qu\fR and \fBwl -l\fR instead\%. +Deprecated, use \fByay -Qu\fR and \fBwc -l\fR instead\%. .RE .PP \fB\-s \-\-stats\fR From 473a2de22530a05504c2674fcbd5281e40c4d226 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 18:37:28 +0100 Subject: [PATCH 030/155] Refactor pssToFoo() functions Previously each call to an external command had two functions. PassToFoo() and PassToFooCapture(). These functions are always similar and end up with duplicated code. So instead have the passToFoo() functions return the cmd itself and create small helper functions show() and capture() which will run the command and either forward it to std{out,err,in} or capture the output Also the saveVCSInfo() function which was called after every makepkg call is now only called after the pacman -U succeeds. --- clean.go | 6 +-- cmd.go | 130 ++++++++++++---------------------------------------- download.go | 23 ++++------ install.go | 34 ++++++++------ query.go | 2 +- 5 files changed, 62 insertions(+), 133 deletions(-) diff --git a/clean.go b/clean.go index d4bd4836..39f2cca5 100644 --- a/clean.go +++ b/clean.go @@ -49,7 +49,7 @@ func cleanRemove(pkgNames []string) (err error) { arguments := makeArguments() arguments.addArg("R") arguments.addTarget(pkgNames...) - err = passToPacman(arguments) + err = show(passToPacman(arguments)) return err } @@ -67,7 +67,7 @@ func syncClean(parser *arguments) error { } } - err := passToPacman(parser) + err := show(passToPacman(parser)) if err != nil { return err } @@ -185,7 +185,7 @@ func cleanUntracked() error { dir := filepath.Join(config.BuildDir, file.Name()) if shouldUseGit(dir) { - err = passToGit(dir, "clean", "-fx") + err = show(passToGit(dir, "clean", "-fx")) if err != nil { return err } diff --git a/cmd.go b/cmd.go index 7eb44539..6300fd51 100644 --- a/cmd.go +++ b/cmd.go @@ -175,9 +175,9 @@ func handleCmd() (err error) { case "V", "version": handleVersion() case "D", "database": - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) case "F", "files": - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) case "Q", "query": err = handleQuery() case "R", "remove": @@ -185,9 +185,9 @@ func handleCmd() (err error) { case "S", "sync": err = handleSync() case "T", "deptest": - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) case "U", "upgrade": - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) case "G", "getpkgbuild": err = handleGetpkgbuild() case "P", "print": @@ -209,7 +209,7 @@ func handleQuery() error { if cmdArgs.existsArg("u", "upgrades") { err = printUpdateList(cmdArgs) } else { - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) } return err @@ -221,7 +221,7 @@ func handleHelp() error { return nil } - return passToPacman(cmdArgs) + return show(passToPacman(cmdArgs)) } //this function should only set config options @@ -436,7 +436,7 @@ func handleSync() (err error) { arguments.delArg("i", "info") arguments.delArg("l", "list") arguments.clearTargets() - err = passToPacman(arguments) + err = show(passToPacman(arguments)) if err != nil { return } @@ -453,9 +453,9 @@ func handleSync() (err error) { } else if cmdArgs.existsArg("c", "clean") { err = syncClean(cmdArgs) } else if cmdArgs.existsArg("l", "list") { - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) } else if cmdArgs.existsArg("c", "clean") { - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) } else if cmdArgs.existsArg("i", "info") { err = syncInfo(targets) } else if cmdArgs.existsArg("u", "sysupgrade") { @@ -469,7 +469,7 @@ func handleSync() (err error) { func handleRemove() (err error) { removeVCSPackage(cmdArgs.targets) - err = passToPacman(cmdArgs) + err = show(passToPacman(cmdArgs)) return } @@ -579,41 +579,29 @@ func numberMenu(pkgS []string, flags []string) (err error) { return err } -// passToPacman outsources execution to pacman binary without modifications. -func passToPacman(args *arguments) error { - var cmd *exec.Cmd - argArr := make([]string, 0) - - if args.needRoot() { - argArr = append(argArr, "sudo") - } - - argArr = append(argArr, config.PacmanBin) - argArr = append(argArr, cmdArgs.formatGlobals()...) - argArr = append(argArr, args.formatArgs()...) - if config.NoConfirm { - argArr = append(argArr, "--noconfirm") - } - - argArr = append(argArr, "--") - - argArr = append(argArr, args.targets...) - - cmd = exec.Command(argArr[0], argArr[1:]...) - +func show(cmd *exec.Cmd) error { cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr err := cmd.Run() - if err != nil { return fmt.Errorf("") } return nil } -//passToPacman but return the output instead of showing the user -func passToPacmanCapture(args *arguments) (string, string, error) { +func capture(cmd *exec.Cmd) (string, string, error) { var outbuf, errbuf bytes.Buffer - var cmd *exec.Cmd + + cmd.Stdout = &outbuf + cmd.Stderr = &errbuf + err := cmd.Run() + stdout := outbuf.String() + stderr := errbuf.String() + + return stdout, stderr, err +} + +// passToPacman outsources execution to pacman binary without modifications. +func passToPacman(args *arguments) *exec.Cmd { argArr := make([]string, 0) if args.needRoot() { @@ -631,40 +619,11 @@ func passToPacmanCapture(args *arguments) (string, string, error) { argArr = append(argArr, args.targets...) - cmd = exec.Command(argArr[0], argArr[1:]...) - cmd.Stdout = &outbuf - cmd.Stderr = &errbuf - - err := cmd.Run() - stdout := outbuf.String() - stderr := errbuf.String() - - return stdout, stderr, err + return exec.Command(argArr[0], argArr[1:]...) } // passToMakepkg outsources execution to makepkg binary without modifications. -func passToMakepkg(dir string, args ...string) (err error) { - - if config.NoConfirm { - args = append(args) - } - - mflags := strings.Fields(config.MFlags) - 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 - err = cmd.Run() - if err == nil { - _ = saveVCSInfo() - } - return -} - -func passToMakepkgCapture(dir string, args ...string) (string, string, error) { - var outbuf, errbuf bytes.Buffer - +func passToMakepkg(dir string, args ...string) *exec.Cmd { if config.NoConfirm { args = append(args) } @@ -674,21 +633,10 @@ func passToMakepkgCapture(dir string, args ...string) (string, string, error) { cmd := exec.Command(config.MakepkgBin, args...) cmd.Dir = dir - cmd.Stdout = &outbuf - cmd.Stderr = &errbuf - - err := cmd.Run() - stdout := outbuf.String() - stderr := errbuf.String() - - if err == nil { - _ = saveVCSInfo() - } - - return stdout, stderr, err + return cmd } -func passToGit(dir string, _args ...string) (err error) { +func passToGit(dir string, _args ...string) *exec.Cmd { gitflags := strings.Fields(config.GitFlags) args := []string{"-C", dir} args = append(args, gitflags...) @@ -696,25 +644,5 @@ func passToGit(dir string, _args ...string) (err error) { cmd := exec.Command(config.GitBin, args...) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - 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 + return cmd } diff --git a/download.go b/download.go index 4b25a02f..c6ba74b4 100644 --- a/download.go +++ b/download.go @@ -45,19 +45,14 @@ func downloadFile(path string, url string) (err error) { } func gitHasDiff(path string, name string) (bool, error) { - stdout, stderr, err := passToGitCapture(filepath.Join(path, name), "rev-parse", "HEAD") + stdout, stderr, err := capture(passToGit(filepath.Join(path, name), "rev-parse", "HEAD", "HEAD@{upstream}")) if err != nil { return false, fmt.Errorf("%s%s", stderr, err) } - 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) + lines := strings.Split(stdout, "\n") + head := lines[0] + upstream := lines[1] return head != upstream, nil } @@ -65,7 +60,7 @@ func gitHasDiff(path string, name string) (bool, 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) + err = show(passToGit(path, "clone", url, name)) if err != nil { return false, fmt.Errorf("error cloning %s", name) } @@ -75,7 +70,7 @@ func gitDownload(url string, path string, name string) (bool, error) { return false, fmt.Errorf("error reading %s", filepath.Join(path, name, ".git")) } - err = passToGit(filepath.Join(path, name), "fetch") + err = show(passToGit(filepath.Join(path, name), "fetch")) if err != nil { return false, fmt.Errorf("error fetching %s", name) } @@ -84,12 +79,12 @@ func gitDownload(url string, path string, name string) (bool, error) { } func gitMerge(url string, path string, name string) error { - err := passToGit(filepath.Join(path, name), "reset", "--hard", "HEAD") + err := show(passToGit(filepath.Join(path, name), "reset", "--hard", "HEAD")) if err != nil { return fmt.Errorf("error resetting %s", name) } - err = passToGit(filepath.Join(path, name), "merge", "--no-edit", "--ff") + err = show(passToGit(filepath.Join(path, name), "merge", "--no-edit", "--ff")) if err != nil { return fmt.Errorf("error merging %s", name) } @@ -98,7 +93,7 @@ func gitMerge(url string, path string, name string) error { } func gitDiff(path string, name string) error { - err := passToGit(filepath.Join(path, name), "diff", "HEAD..HEAD@{upstream}") + err := show(passToGit(filepath.Join(path, name), "diff", "HEAD..HEAD@{upstream}")) return err } diff --git a/install.go b/install.go index 2110419e..c7a3842d 100644 --- a/install.go +++ b/install.go @@ -48,7 +48,7 @@ func install(parser *arguments) error { arguments.delArg("i", "info") arguments.delArg("l", "list") arguments.clearTargets() - err = passToPacman(arguments) + err = show(passToPacman(arguments)) if err != nil { return fmt.Errorf("Error installing repo packages") } @@ -105,7 +105,7 @@ func install(parser *arguments) error { } if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(arguments.targets) > 0 { - err = passToPacman(arguments) + err = show(passToPacman(arguments)) if err != nil { return fmt.Errorf("Error installing repo packages") } @@ -204,7 +204,7 @@ func install(parser *arguments) error { parser.op = "S" parser.delArg("y", "refresh") parser.options["ignore"] = arguments.options["ignore"] - return passToPacman(parser) + return show(passToPacman(parser)) } if len(dp.Aur) > 0 && 0 == os.Geteuid() { @@ -340,7 +340,7 @@ func install(parser *arguments) error { } if len(arguments.targets) > 0 || arguments.existsArg("u") { - err := passToPacman(arguments) + err := show(passToPacman(arguments)) if err != nil { return fmt.Errorf("Error installing repo packages") } @@ -364,14 +364,14 @@ func install(parser *arguments) error { } if len(depArguments.targets) > 0 { - _, stderr, err := passToPacmanCapture(depArguments) + _, stderr, err := capture(passToPacman(depArguments)) if err != nil { return fmt.Errorf("%s%s", stderr, err) } } if len(expArguments.targets) > 0 { - _, stderr, err := passToPacmanCapture(expArguments) + _, stderr, err := capture(passToPacman(expArguments)) if err != nil { return fmt.Errorf("%s%s", stderr, err) } @@ -398,7 +398,7 @@ func install(parser *arguments) error { oldValue := config.NoConfirm config.NoConfirm = true - err = passToPacman(removeArguments) + err = show(passToPacman(removeArguments)) config.NoConfirm = oldValue if err != nil { @@ -449,7 +449,7 @@ nextpkg: } func parsePackageList(dir string) (map[string]string, string, error) { - stdout, stderr, err := passToMakepkgCapture(dir, "--packagelist") + stdout, stderr, err := capture(passToMakepkg(dir, "--packagelist")) if err != nil { return nil, "", fmt.Errorf("%s%s", stderr, err) @@ -677,7 +677,7 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, base } else { args = append(args, "--color=never") } - err := passToGit(dir, args...) + err := show(passToGit(dir, args...)) if err != nil { return err } @@ -838,7 +838,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco args = append(args, "--ignorearch") } - err = passToMakepkg(dir, args...) + err = show(passToMakepkg(dir, args...)) if err != nil { return fmt.Errorf("Error downloading sources: %s", cyan(formatPkgbase(pkg, bases))) } @@ -861,7 +861,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc } //pkgver bump - err := passToMakepkg(dir, args...) + err := show(passToMakepkg(dir, args...)) if err != nil { return fmt.Errorf("Error making: %s", pkg.Name) } @@ -899,7 +899,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc args = append(args, "--ignorearch") } - err := passToMakepkg(dir, args...) + err := show(passToMakepkg(dir, args...)) if err != nil { return fmt.Errorf("Error making: %s", pkg.Name) } @@ -973,17 +973,23 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc } } - err = passToPacman(arguments) + err = show(passToPacman(arguments)) if err != nil { return err } + for _, pkg := range do.Bases[pkg.PackageBase] { updateVCSData(pkg.Name, srcinfo.Source) } + err = saveVCSInfo() + if err != nil { + fmt.Println(err) + } + if len(depArguments.targets) > 0 { - _, stderr, err := passToPacmanCapture(depArguments) + _, stderr, err := capture(passToPacman(depArguments)) if err != nil { return fmt.Errorf("%s%s", stderr, err) } diff --git a/query.go b/query.go index 8ead0b79..7c57d103 100644 --- a/query.go +++ b/query.go @@ -229,7 +229,7 @@ func syncInfo(pkgS []string) (err error) { arguments := cmdArgs.copy() arguments.clearTargets() arguments.addTarget(repoS...) - err = passToPacman(arguments) + err = show(passToPacman(arguments)) if err != nil { return From 8427dc3804126fdd26eb375642187996d601e692 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 18:48:46 +0100 Subject: [PATCH 031/155] Move passToFoo() functions to their own file --- cmd.go | 70 -------------------------------------------------- exec.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ install.go | 1 - 3 files changed, 75 insertions(+), 71 deletions(-) create mode 100644 exec.go diff --git a/cmd.go b/cmd.go index 6300fd51..63614c64 100644 --- a/cmd.go +++ b/cmd.go @@ -2,12 +2,10 @@ package main import ( "bufio" - "bytes" "fmt" "os" "os/exec" "strconv" - "strings" "time" ) @@ -578,71 +576,3 @@ func numberMenu(pkgS []string, flags []string) (err error) { return err } - -func show(cmd *exec.Cmd) error { - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - err := cmd.Run() - if err != nil { - return fmt.Errorf("") - } - return nil -} - -func capture(cmd *exec.Cmd) (string, string, error) { - var outbuf, errbuf bytes.Buffer - - cmd.Stdout = &outbuf - cmd.Stderr = &errbuf - err := cmd.Run() - stdout := outbuf.String() - stderr := errbuf.String() - - return stdout, stderr, err -} - -// passToPacman outsources execution to pacman binary without modifications. -func passToPacman(args *arguments) *exec.Cmd { - argArr := make([]string, 0) - - if args.needRoot() { - argArr = append(argArr, "sudo") - } - - argArr = append(argArr, config.PacmanBin) - argArr = append(argArr, cmdArgs.formatGlobals()...) - argArr = append(argArr, args.formatArgs()...) - if config.NoConfirm { - argArr = append(argArr, "--noconfirm") - } - - argArr = append(argArr, "--") - - argArr = append(argArr, args.targets...) - - return exec.Command(argArr[0], argArr[1:]...) -} - -// passToMakepkg outsources execution to makepkg binary without modifications. -func passToMakepkg(dir string, args ...string) *exec.Cmd { - if config.NoConfirm { - args = append(args) - } - - mflags := strings.Fields(config.MFlags) - args = append(args, mflags...) - - cmd := exec.Command(config.MakepkgBin, args...) - cmd.Dir = dir - return cmd -} - -func passToGit(dir string, _args ...string) *exec.Cmd { - gitflags := strings.Fields(config.GitFlags) - args := []string{"-C", dir} - args = append(args, gitflags...) - args = append(args, _args...) - - cmd := exec.Command(config.GitBin, args...) - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - return cmd -} diff --git a/exec.go b/exec.go new file mode 100644 index 00000000..f97cbab9 --- /dev/null +++ b/exec.go @@ -0,0 +1,75 @@ +package main + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "strings" +) + +func show(cmd *exec.Cmd) error { + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr + err := cmd.Run() + if err != nil { + return fmt.Errorf("") + } + return nil +} + +func capture(cmd *exec.Cmd) (string, string, error) { + var outbuf, errbuf bytes.Buffer + + cmd.Stdout = &outbuf + cmd.Stderr = &errbuf + err := cmd.Run() + stdout := outbuf.String() + stderr := errbuf.String() + + return stdout, stderr, err +} + +func passToPacman(args *arguments) *exec.Cmd { + argArr := make([]string, 0) + + if args.needRoot() { + argArr = append(argArr, "sudo") + } + + argArr = append(argArr, config.PacmanBin) + argArr = append(argArr, cmdArgs.formatGlobals()...) + argArr = append(argArr, args.formatArgs()...) + if config.NoConfirm { + argArr = append(argArr, "--noconfirm") + } + + argArr = append(argArr, "--") + + argArr = append(argArr, args.targets...) + + return exec.Command(argArr[0], argArr[1:]...) +} + +func passToMakepkg(dir string, args ...string) *exec.Cmd { + if config.NoConfirm { + args = append(args) + } + + mflags := strings.Fields(config.MFlags) + args = append(args, mflags...) + + cmd := exec.Command(config.MakepkgBin, args...) + cmd.Dir = dir + return cmd +} + +func passToGit(dir string, _args ...string) *exec.Cmd { + gitflags := strings.Fields(config.GitFlags) + args := []string{"-C", dir} + args = append(args, gitflags...) + args = append(args, _args...) + + cmd := exec.Command(config.GitBin, args...) + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr + return cmd +} diff --git a/install.go b/install.go index c7a3842d..62ab6338 100644 --- a/install.go +++ b/install.go @@ -978,7 +978,6 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc return err } - for _, pkg := range do.Bases[pkg.PackageBase] { updateVCSData(pkg.Name, srcinfo.Source) } From 474cc56f8d77acc70ab7df264d15beea0a05cc91 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 18:51:57 +0100 Subject: [PATCH 032/155] Use passToGit() in getCommit() --- vcs.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/vcs.go b/vcs.go index e2e96288..139656e3 100644 --- a/vcs.go +++ b/vcs.go @@ -1,11 +1,9 @@ package main import ( - "bytes" "encoding/json" "fmt" "os" - "os/exec" "strings" "time" @@ -136,13 +134,9 @@ func updateVCSData(pkgName string, sources []gosrc.ArchString) { func getCommit(url string, branch string, protocols []string) string { for _, protocol := range protocols { - var outbuf bytes.Buffer - - cmd := exec.Command(config.GitBin, "ls-remote", protocol+"://"+url, branch) - cmd.Stdout = &outbuf + cmd := passToGit("ls-remote", protocol+"://"+url, branch) cmd.Env = append(cmd.Env, "GIT_TERMINAL_PROMPT=0") - - err := cmd.Start() + stdout, _, err := capture(cmd) if err != nil { continue } @@ -161,7 +155,6 @@ func getCommit(url string, branch string, protocols []string) string { continue } - stdout := outbuf.String() split := strings.Fields(stdout) if len(split) < 2 { From 257653047bd3edfa07352dc7817a50e110a05ce1 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 18:56:40 +0100 Subject: [PATCH 033/155] Move sudoloop code to exec.go --- cmd.go | 27 --------------------------- exec.go | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/cmd.go b/cmd.go index 63614c64..929b333a 100644 --- a/cmd.go +++ b/cmd.go @@ -4,9 +4,7 @@ import ( "bufio" "fmt" "os" - "os/exec" "strconv" - "time" ) var cmdArgs = makeArguments() @@ -118,31 +116,6 @@ If no arguments are provided 'yay -Syu' will be performed If no operation is provided -Y will be assumed`) } -func sudoLoopBackground() { - updateSudo() - go sudoLoop() -} - -func sudoLoop() { - for { - updateSudo() - time.Sleep(298 * time.Second) - } -} - -func updateSudo() { - for { - cmd := exec.Command("sudo", "-v") - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - err := cmd.Run() - if err != nil { - fmt.Println(err) - } else { - break - } - } -} - func handleCmd() (err error) { for option, value := range cmdArgs.options { if handleConfig(option, value) { diff --git a/exec.go b/exec.go index f97cbab9..b7249ccf 100644 --- a/exec.go +++ b/exec.go @@ -6,6 +6,7 @@ import ( "os" "os/exec" "strings" + "time" ) func show(cmd *exec.Cmd) error { @@ -29,6 +30,29 @@ func capture(cmd *exec.Cmd) (string, string, error) { return stdout, stderr, err } +func sudoLoopBackground() { + updateSudo() + go sudoLoop() +} + +func sudoLoop() { + for { + updateSudo() + time.Sleep(298 * time.Second) + } +} + +func updateSudo() { + for { + err := show(exec.Command("sudo", "-v")) + if err != nil { + fmt.Println(err) + } else { + break + } + } +} + func passToPacman(args *arguments) *exec.Cmd { argArr := make([]string, 0) From 0196a47ad25c6eaebcca18217cf094d4f8128768 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 19:53:17 +0100 Subject: [PATCH 034/155] Refactor combinedupgrade code --- install.go | 185 ++++++++++++++++++++++++++--------------------------- 1 file changed, 92 insertions(+), 93 deletions(-) diff --git a/install.go b/install.go index 62ab6338..79d32b6e 100644 --- a/install.go +++ b/install.go @@ -27,107 +27,37 @@ func install(parser *arguments) error { removeMake := false srcinfosStale := make(map[string]*gosrc.Srcinfo) - //remotenames: names of all non repo packages on the system + if mode == ModeAny || mode == ModeRepo { + if config.CombinedUpgrade { + if parser.existsArg("y", "refresh") { + err = earlyRefresh(parser) + if err != nil { + return fmt.Errorf("Error refreshing databases") + } + } + } else if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(parser.targets) > 0 { + err = earlyPacmanCall(parser) + if err != nil { + return err + } + } + } + + //we may have done -Sy, our handle now has an old + //database. + err = initAlpmHandle() + if err != nil { + return err + } + _, _, localNames, remoteNames, err := filterPackages() if err != nil { return err } - //cache as a stringset. maybe make it return a string set in the first - //place remoteNamesCache := sliceToStringSet(remoteNames) localNamesCache := sliceToStringSet(localNames) - if mode == ModeAny || mode == ModeRepo { - if config.CombinedUpgrade { - if parser.existsArg("y", "refresh") { - arguments := parser.copy() - parser.delArg("y", "refresh") - arguments.delArg("u", "sysupgrade") - arguments.delArg("s", "search") - arguments.delArg("i", "info") - arguments.delArg("l", "list") - arguments.clearTargets() - err = show(passToPacman(arguments)) - if err != nil { - return fmt.Errorf("Error installing repo packages") - } - } - } else if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(parser.targets) > 0 { - arguments := parser.copy() - arguments.op = "S" - targets := parser.targets - parser.clearTargets() - arguments.clearTargets() - - syncDb, err := alpmHandle.SyncDbs() - if err != nil { - return err - } - - if mode == ModeRepo { - arguments.targets = targets - } else { - alpmHandle.SetQuestionCallback(func(alpm.QuestionAny) {}) - //seperate aur and repo targets - for _, _target := range targets { - target := toTarget(_target) - - if target.Db == "aur" { - parser.addTarget(_target) - continue - } - - var singleDb *alpm.Db - - if target.Db != "" { - singleDb, err = alpmHandle.SyncDbByName(target.Db) - if err != nil { - return err - } - _, err = singleDb.PkgCache().FindSatisfier(target.DepString()) - } else { - _, err = syncDb.FindSatisfier(target.DepString()) - } - - if err == nil { - arguments.addTarget(_target) - } else { - _, err := syncDb.PkgCachebyGroup(target.Name) - if err == nil { - arguments.addTarget(_target) - continue - } - - parser.addTarget(_target) - } - } - } - - if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(arguments.targets) > 0 { - err = show(passToPacman(arguments)) - if err != nil { - return fmt.Errorf("Error installing repo packages") - } - } - - //we may have done -Sy, our handle now has an old - //database. - err = initAlpmHandle() - if err != nil { - return err - } - - _, _, localNames, remoteNames, err = filterPackages() - if err != nil { - return err - } - - remoteNamesCache = sliceToStringSet(remoteNames) - localNamesCache = sliceToStringSet(localNames) - } - } - requestTargets := parser.copy().targets //create the arguments to pass for the repo install @@ -413,6 +343,75 @@ func install(parser *arguments) error { return nil } +func inRepos(syncDb alpm.DbList, pkg string) bool { + target := toTarget(pkg) + + if target.Db == "aur" { + return false + } else if target.Db != "" { + return true + } + + _, err := syncDb.FindSatisfier(target.DepString()) + if err == nil { + return true + } + + _, err = syncDb.PkgCachebyGroup(target.Name) + if err == nil { + return true + } + + return false +} + +func earlyPacmanCall(parser *arguments) error { + arguments := parser.copy() + arguments.op = "S" + targets := parser.targets + parser.clearTargets() + arguments.clearTargets() + + syncDb, err := alpmHandle.SyncDbs() + if err != nil { + return err + } + + if mode == ModeRepo { + arguments.targets = targets + } else { + alpmHandle.SetQuestionCallback(func(alpm.QuestionAny) {}) + //seperate aur and repo targets + for _, target := range targets { + if inRepos(syncDb, target) { + arguments.addTarget(target) + } else { + parser.addTarget(target) + } + } + } + + if parser.existsArg("y", "refresh") || parser.existsArg("u", "sysupgrade") || len(arguments.targets) > 0 { + err = show(passToPacman(arguments)) + if err != nil { + return fmt.Errorf("Error installing repo packages") + } + } + + return nil +} + +func earlyRefresh(parser *arguments) error { + arguments := parser.copy() + parser.delArg("y", "refresh") + arguments.delArg("u", "sysupgrade") + arguments.delArg("s", "search") + arguments.delArg("i", "info") + arguments.delArg("l", "list") + arguments.clearTargets() + return show(passToPacman(arguments)) +} + func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) (stringSet, error) { incompatible := make(stringSet) alpmArch, err := alpmHandle.Arch() From 1d443c0d40eba95d7b402d7deb7fc310e17fe3d0 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 20:52:30 +0100 Subject: [PATCH 035/155] Merge GIT_TERMINAL_PROMPT with the current env --- vcs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcs.go b/vcs.go index 139656e3..1dd34ac0 100644 --- a/vcs.go +++ b/vcs.go @@ -135,7 +135,7 @@ func updateVCSData(pkgName string, sources []gosrc.ArchString) { func getCommit(url string, branch string, protocols []string) string { for _, protocol := range protocols { cmd := passToGit("ls-remote", protocol+"://"+url, branch) - cmd.Env = append(cmd.Env, "GIT_TERMINAL_PROMPT=0") + cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0") stdout, _, err := capture(cmd) if err != nil { continue From d1146de6d54fbae4a6979e43b504b34f6883b8a8 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 19 Jul 2018 22:19:24 +0100 Subject: [PATCH 036/155] Show tar diffs as diffs instead of editing When looking at diffs of packages downloaded as tar achives actually show a diff instead of opening the files in the ediror. This diff is against /var/empty so it is not that useful. In realiy this is an excuse to move the srcinfo parsing back down to after the git merge. Viewing the build files in the editor requires the .srcinfos to be parsed to know what .install files are used. Now viewing diffs does not need the srcinfos so they can be moved to after we git merge. Before now the srcinfo would have been of the previous version. This is not much of a problem because we don't really use the srcinfo for much. Checking the arch and pgpkeys which never really change. Recently libc++ changed their pgp keys and yay missed that because it parsed the old srcinfo without the new keys. Viewing a proper diff for tars can be tossed on the todo by doing something along the lines of: mv pkg{,.old} diff pkg{,.old} rm -rf pkg.old But I doubt there are many people out there using tar so it's not much of an issue. --- install.go | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/install.go b/install.go index 79d32b6e..11e302d2 100644 --- a/install.go +++ b/install.go @@ -189,12 +189,6 @@ func install(parser *arguments) error { return err } - //initial srcinfo parse before pkgver() bump - err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) - if err != nil { - return err - } - var toDiff []*rpc.Pkg var toEdit []*rpc.Pkg @@ -206,7 +200,7 @@ func install(parser *arguments) error { } if len(toDiff) > 0 { - err = showPkgBuildDiffs(toDiff, srcinfosStale, do.Bases, cloned) + err = showPkgBuildDiffs(toDiff, do.Bases, cloned) if err != nil { return err } @@ -228,6 +222,12 @@ func install(parser *arguments) error { return err } + //initial srcinfo parse before pkgver() bump + err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) + if err != nil { + return err + } + if config.EditMenu { pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) toEdit, err = editNumberMenu(do.Aur, do.Bases, remoteNamesCache) @@ -650,7 +650,7 @@ func cleanBuilds(pkgs []*rpc.Pkg) { } } -func showPkgBuildDiffs(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg, cloned stringSet) 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) { @@ -681,20 +681,15 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, base return err } } else { - editor, editorArgs := editor() - editorArgs = append(editorArgs, filepath.Join(dir, "PKGBUILD")) - for _, splitPkg := range srcinfos[pkg.PackageBase].SplitPackages() { - if splitPkg.Install != "" { - editorArgs = append(editorArgs, filepath.Join(dir, splitPkg.Install)) - } - } - - 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) + args := []string{"diff"} + if useColor { + args = append(args, "--color=always") + } else { + args = append(args, "--color=never") } + args = append(args, "--no-index", "/var/empty", dir) + // git always returns 1. why? I have no idea + show(passToGit(dir, args...)) } } From 900dfd1851f1591503c8f07607e84640c303188d Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Fri, 20 Jul 2018 00:36:06 +0300 Subject: [PATCH 037/155] Make output more similar to `pacman`s Before: * Empty line after `Searching AUR` * `There is` starts with capital letter without space before ``` > yay --combinedupgrade -Syu :: Synchronizing package databases... core is up to date extra is up to date community is up to date multilib is up to date :: Searching databases for updates... :: Searching AUR for updates... :: Starting full system upgrade... there is nothing to do > yay --nocombinedupgrade -Syu :: Synchronizing package databases... core is up to date extra is up to date community is up to date multilib is up to date :: Starting full system upgrade... there is nothing to do :: Searching databases for updates... :: Searching AUR for updates... There is nothing to do ``` After: ``` > yay --combinedupgrade -Syu :: Synchronizing package databases... core is up to date extra is up to date community is up to date multilib is up to date :: Searching databases for updates... :: Searching AUR for updates... :: Starting full system upgrade... there is nothing to do > yay --nocombinedupgrade -Syu :: Synchronizing package databases... core is up to date extra is up to date community is up to date multilib is up to date :: Starting full system upgrade... there is nothing to do :: Searching databases for updates... :: Searching AUR for updates... there is nothing to do ``` --- install.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/install.go b/install.go index 79d32b6e..60060a44 100644 --- a/install.go +++ b/install.go @@ -106,8 +106,6 @@ func install(parser *arguments) error { arguments.options["ignore"] = ignoreStr } - fmt.Println() - for pkg := range aurUp { parser.addTarget(pkg) } @@ -127,7 +125,7 @@ func install(parser *arguments) error { if len(dp.Aur) == 0 { if !config.CombinedUpgrade { - fmt.Println("There is nothing to do") + fmt.Println(" there is nothing to do") return nil } @@ -160,7 +158,7 @@ func install(parser *arguments) error { } if len(do.Aur) == 0 && len(arguments.targets) == 0 && (!parser.existsArg("u", "sysupgrade") || mode == ModeAUR) { - fmt.Println("There is nothing to do") + fmt.Println(" there is nothing to do") return nil } From b5b6928803747c2121d2a23d85b6e5e1d8036d47 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 20 Jul 2018 18:59:12 +0100 Subject: [PATCH 038/155] Fix devel updates Commit 474cc56f8d77acc70ab7df264d15beea0a05cc91 refactored the getCommit() function to use the standard passToGit() and capture() functions. Unlike every other external call, here we use .Wait() and kill the command after 5 seconds. This was missed and ended up breaking the function. So instead don't use capture but the manual .Wait() call. passToGit() is still used. --- vcs.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vcs.go b/vcs.go index 1dd34ac0..4b6cef70 100644 --- a/vcs.go +++ b/vcs.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/json" "fmt" "os" @@ -134,9 +135,13 @@ func updateVCSData(pkgName string, sources []gosrc.ArchString) { func getCommit(url string, branch string, protocols []string) string { for _, protocol := range protocols { - cmd := passToGit("ls-remote", protocol+"://"+url, branch) + var outbuf bytes.Buffer + + cmd := passToGit("", "ls-remote", protocol+"://"+url, branch) + cmd.Stdout = &outbuf cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0") - stdout, _, err := capture(cmd) + + err := cmd.Start() if err != nil { continue } @@ -155,6 +160,7 @@ func getCommit(url string, branch string, protocols []string) string { continue } + stdout := outbuf.String() split := strings.Fields(stdout) if len(split) < 2 { From 1d17940ce98bce15ddb3cfb7e1c6104085808981 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 20 Jul 2018 20:42:47 +0100 Subject: [PATCH 039/155] Abort ealy when there's conflicts with --noconfirm When using --nouseask, manual intervention is needed to resolve conflicts. When also useing --noconfirm the install will always fail. So abort early, before trying to install any AUR packages. --- depCheck.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/depCheck.go b/depCheck.go index 81ef7947..01b6cccd 100644 --- a/depCheck.go +++ b/depCheck.go @@ -180,6 +180,10 @@ func (dp *depPool) CheckConflicts() (mapStringSet, error) { } fmt.Println() + + if config.NoConfirm && !config.UseAsk { + return nil, fmt.Errorf("Package conflicts can not be resolved with noconfirm, aborting") + } } return conflicts, nil From ec48698f3544c3227577638bf19e00043cb9102a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 21 Jul 2018 14:20:00 +0100 Subject: [PATCH 040/155] Add --{no,ask}removemake --- cmd.go | 6 ++++++ config.go | 2 ++ install.go | 6 +++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index 929b333a..b77a91f3 100644 --- a/cmd.go +++ b/cmd.go @@ -326,6 +326,12 @@ func handleConfig(option, value string) bool { mode = ModeAUR case "repo": mode = ModeRepo + case "removemake": + config.RemoveMake = "yes" + case "noremovemake": + config.RemoveMake = "no" + case "askremovemake": + config.RemoveMake = "ask" default: return false } diff --git a/config.go b/config.go index daff6461..04dd9a40 100644 --- a/config.go +++ b/config.go @@ -54,6 +54,7 @@ type Configuration struct { MFlags string `json:"mflags"` SortBy string `json:"sortby"` GitFlags string `json:"gitflags"` + RemoveMake string `json:"removemake"` RequestSplitN int `json:"requestsplitn"` SearchMode int `json:"-"` SortMode int `json:"sortmode"` @@ -173,6 +174,7 @@ func defaultSettings(config *Configuration) { config.AnswerDiff = "" config.AnswerEdit = "" config.AnswerUpgrade = "" + config.RemoveMake = "ask" config.GitClone = true config.Provides = true config.UpgradeMenu = true diff --git a/install.go b/install.go index abdf8686..c4185b50 100644 --- a/install.go +++ b/install.go @@ -166,7 +166,11 @@ func install(parser *arguments) error { fmt.Println() if do.HasMake() { - if !continueTask("Remove make dependencies after install?", "yY") { + if config.RemoveMake == "yes" { + removeMake = true + } else if config.RemoveMake == "no" { + removeMake = false + } else if !continueTask("Remove make dependencies after install?", "yY") { removeMake = true } } From f9972da763fdbf9f8cc94c10b74be958ab75bda2 Mon Sep 17 00:00:00 2001 From: J Guerreiro Date: Sat, 21 Jul 2018 16:18:19 +0100 Subject: [PATCH 041/155] Wait for db.lck to become available before starting a db operation (#573) * Wait for db.lck to become available before starting a db operation * Fix err!=nil issues and avoid spamming users * Remove redundant cases * Remove return --- exec.go | 20 ++++++++++++++++++++ parser.go | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/exec.go b/exec.go index b7249ccf..2a97ae3c 100644 --- a/exec.go +++ b/exec.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "os/exec" + "path/filepath" "strings" "time" ) @@ -53,6 +54,22 @@ func updateSudo() { } } +// waitLock will lock yay checking the status of db.lck until it does not exist +func waitLock() { + if _, err := os.Stat(filepath.Join(alpmConf.DBPath, "db.lck")); err != nil { + return + } + + fmt.Println(bold(yellow(smallArrow)), "db.lck is present. Waiting... ") + + for { + time.Sleep(3 * time.Second) + if _, err := os.Stat(filepath.Join(alpmConf.DBPath, "db.lck")); err != nil { + return + } + } +} + func passToPacman(args *arguments) *exec.Cmd { argArr := make([]string, 0) @@ -71,6 +88,9 @@ func passToPacman(args *arguments) *exec.Cmd { argArr = append(argArr, args.targets...) + if args.needWait() { + waitLock() + } return exec.Command(argArr[0], argArr[1:]...) } diff --git a/parser.go b/parser.go index d4f444b0..3c7d51e5 100644 --- a/parser.go +++ b/parser.go @@ -144,12 +144,6 @@ func (parser *arguments) needRoot() bool { case "R", "remove": return true case "S", "sync": - if parser.existsArg("y", "refresh") { - return true - } - if parser.existsArg("u", "sysupgrade") { - return true - } if parser.existsArg("s", "search") { return false } @@ -177,6 +171,50 @@ func (parser *arguments) needRoot() bool { } } +//needWait checks if waitLock() should be called before calling pacman +func (parser *arguments) needWait() bool { + if parser.existsArg("h", "help") { + return false + } + + if parser.existsArg("p", "print") { + return false + } + + switch parser.op { + case "D", "database": + return true + case "F", "files": + if parser.existsArg("y", "refresh") { + return true + } + return false + case "R", "remove": + return true + case "S", "sync": + if parser.existsArg("y", "refresh") { + return true + } + if parser.existsArg("u", "sysupgrade") { + return true + } + if parser.existsArg("s", "search") { + return false + } + if parser.existsArg("l", "list") { + return false + } + if parser.existsArg("i", "info") { + return false + } + return true + case "U", "upgrade": + return true + default: + return false + } +} + func (parser *arguments) addOP(op string) (err error) { if parser.op != "" { err = fmt.Errorf("only one operation may be used at a time") From 253d162b5b5820e5c764fcfc86cf74ccc7890242 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 21 Jul 2018 17:36:16 +0100 Subject: [PATCH 042/155] Remove unused code, fix typo for -g flag As it turns out, the times you need root also tend to be the time you need to manipulate the database. So the needWait() function can be removed and repllaced by needRoot() --- cmd.go | 18 +++-------------- exec.go | 5 +++-- parser.go | 58 ++++--------------------------------------------------- 3 files changed, 10 insertions(+), 71 deletions(-) diff --git a/cmd.go b/cmd.go index b77a91f3..7b872661 100644 --- a/cmd.go +++ b/cmd.go @@ -405,20 +405,6 @@ func handleYogurt() (err error) { func handleSync() (err error) { targets := cmdArgs.targets - if cmdArgs.existsArg("y", "refresh") { - arguments := cmdArgs.copy() - cmdArgs.delArg("y", "refresh") - arguments.delArg("u", "sysupgrade") - arguments.delArg("s", "search") - arguments.delArg("i", "info") - arguments.delArg("l", "list") - arguments.clearTargets() - err = show(passToPacman(arguments)) - if err != nil { - return - } - } - if cmdArgs.existsArg("s", "search") { if cmdArgs.existsArg("q", "quiet") { config.SearchMode = Minimal @@ -431,7 +417,7 @@ func handleSync() (err error) { err = syncClean(cmdArgs) } else if cmdArgs.existsArg("l", "list") { err = show(passToPacman(cmdArgs)) - } else if cmdArgs.existsArg("c", "clean") { + } else if cmdArgs.existsArg("g", "groups") { err = show(passToPacman(cmdArgs)) } else if cmdArgs.existsArg("i", "info") { err = syncInfo(targets) @@ -439,6 +425,8 @@ func handleSync() (err error) { err = install(cmdArgs) } else if len(cmdArgs.targets) > 0 { err = install(cmdArgs) + } else if cmdArgs.existsArg("y", "refresh") { + err = show(passToPacman(cmdArgs)) } return diff --git a/exec.go b/exec.go index 2a97ae3c..76040641 100644 --- a/exec.go +++ b/exec.go @@ -60,11 +60,12 @@ func waitLock() { return } - fmt.Println(bold(yellow(smallArrow)), "db.lck is present. Waiting... ") + fmt.Print(bold(yellow(smallArrow)), " db.lck is present. Waiting...") for { time.Sleep(3 * time.Second) if _, err := os.Stat(filepath.Join(alpmConf.DBPath, "db.lck")); err != nil { + fmt.Println() return } } @@ -88,7 +89,7 @@ func passToPacman(args *arguments) *exec.Cmd { argArr = append(argArr, args.targets...) - if args.needWait() { + if args.needRoot() { waitLock() } return exec.Command(argArr[0], argArr[1:]...) diff --git a/parser.go b/parser.go index 3c7d51e5..34f3f5a0 100644 --- a/parser.go +++ b/parser.go @@ -127,9 +127,10 @@ func (parser *arguments) needRoot() bool { } switch parser.op { - case "V", "version": - return false case "D", "database": + if parser.existsArg("k", "check") { + return false + } return true case "F", "files": if parser.existsArg("y", "refresh") { @@ -150,58 +151,7 @@ func (parser *arguments) needRoot() bool { if parser.existsArg("l", "list") { return false } - if parser.existsArg("i", "info") { - return false - } - return true - case "T", "deptest": - return false - case "U", "upgrade": - return true - - // yay specific - case "Y", "yay": - return false - case "P", "print": - return false - case "G", "getpkgbuild": - return false - default: - return false - } -} - -//needWait checks if waitLock() should be called before calling pacman -func (parser *arguments) needWait() bool { - if parser.existsArg("h", "help") { - return false - } - - if parser.existsArg("p", "print") { - return false - } - - switch parser.op { - case "D", "database": - return true - case "F", "files": - if parser.existsArg("y", "refresh") { - return true - } - return false - case "R", "remove": - return true - case "S", "sync": - if parser.existsArg("y", "refresh") { - return true - } - if parser.existsArg("u", "sysupgrade") { - return true - } - if parser.existsArg("s", "search") { - return false - } - if parser.existsArg("l", "list") { + if parser.existsArg("g", "groups") { return false } if parser.existsArg("i", "info") { From a5a9afd6813cf77624d1d25d57a2b6f62d77c6e6 Mon Sep 17 00:00:00 2001 From: Alad Wenter Date: Sun, 22 Jul 2018 01:04:22 +0200 Subject: [PATCH 043/155] yay.8: fix typo in --nopgpfetch --- doc/yay.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/yay.8 b/doc/yay.8 index 7c822a97..befb697a 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -428,7 +428,7 @@ Prompt to import unknown PGP keys from the \fBvalidpgpkeys\fR field of each PKGBUILD. .RE .PP -\fB\-\-pgpfetch\fR +\fB\-\-nopgpfetch\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 From e28f4f3431c2f00b53190bc26ecaacfb34ea2256 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 22 Jul 2018 00:46:55 +0100 Subject: [PATCH 044/155] Refactor continueTask() The main reason behind this is for future localisation. yes and no can be set to the localized equivalent and it should just work. This Refactor also changes the function in ways which make it much less confusing. The param is no longer reversed and changed to a boolean. Before you had to pass in Yy to get a default of no and vice versa. The function now retuens false for no and true for yes. Before it would return true if the default option was choosen. --- clean.go | 4 ++-- config.go | 36 +++++++++++++++++++----------------- install.go | 8 ++++---- keys.go | 2 +- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/clean.go b/clean.go index 39f2cca5..74ccb132 100644 --- a/clean.go +++ b/clean.go @@ -82,7 +82,7 @@ func syncClean(parser *arguments) error { fmt.Println() fmt.Printf("Build directory: %s\n", config.BuildDir) - if continueTask(question, "nN") { + if continueTask(question, true) { err = cleanAUR(keepInstalled, keepCurrent, removeAll) } @@ -90,7 +90,7 @@ func syncClean(parser *arguments) error { return err } - if continueTask("Do you want to remove ALL untracked AUR files?", "nN") { + if continueTask("Do you want to remove ALL untracked AUR files?", true) { err = cleanUntracked() } diff --git a/config.go b/config.go index 04dd9a40..06eee594 100644 --- a/config.go +++ b/config.go @@ -241,31 +241,33 @@ func editor() (string, []string) { // ContinueTask prompts if user wants to continue task. //If NoConfirm is set the action will continue without user input. -func continueTask(s string, def string) (cont bool) { +func continueTask(s string, cont bool) bool { if config.NoConfirm { - return true - } - var postFix string - - if def == "nN" { - postFix = " [Y/n] " - } else { - postFix = " [y/N] " + return cont } var response string + var postFix string + yes := "yes" + no := "no" + y := string([]rune(yes)[0]) + n := string([]rune(no)[0]) + + if cont { + postFix = fmt.Sprintf(" [%s/%s] ", strings.ToUpper(y), n) + } else { + postFix = fmt.Sprintf(" [%s/%s] ", y, strings.ToUpper(n)) + } + fmt.Print(bold(green(arrow)+" "+s), bold(postFix)) - n, err := fmt.Scanln(&response) - if err != nil || n == 0 { - return true + len, err := fmt.Scanln(&response) + if err != nil || len == 0 { + return cont } - if response == string(def[0]) || response == string(def[1]) { - return false - } - - return true + response = strings.ToLower(response) + return response == yes || response == y } func getInput(defaultValue string) (string, error) { diff --git a/install.go b/install.go index c4185b50..b47bc7e4 100644 --- a/install.go +++ b/install.go @@ -170,7 +170,7 @@ func install(parser *arguments) error { removeMake = true } else if config.RemoveMake == "no" { removeMake = false - } else if !continueTask("Remove make dependencies after install?", "yY") { + } else if continueTask("Remove make dependencies after install?", false) { removeMake = true } } @@ -213,7 +213,7 @@ func install(parser *arguments) error { oldValue := config.NoConfirm config.NoConfirm = false fmt.Println() - if !continueTask(bold(green("Proceed with install?")), "nN") { + if !continueTask(bold(green("Proceed with install?")), true) { return fmt.Errorf("Aborting due to user") } config.NoConfirm = oldValue @@ -249,7 +249,7 @@ func install(parser *arguments) error { oldValue := config.NoConfirm config.NoConfirm = false fmt.Println() - if !continueTask(bold(green("Proceed with install?")), "nN") { + if !continueTask(bold(green("Proceed with install?")), true) { return fmt.Errorf("Aborting due to user") } config.NoConfirm = oldValue @@ -441,7 +441,7 @@ nextpkg: fmt.Println() - if !continueTask("Try to build them anyway?", "nN") { + if !continueTask("Try to build them anyway?", true) { return nil, fmt.Errorf("Aborting due to user") } } diff --git a/keys.go b/keys.go index 012b9e4e..89fe3666 100644 --- a/keys.go +++ b/keys.go @@ -80,7 +80,7 @@ func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[str fmt.Println() fmt.Println(str) - if continueTask(bold(green("Import?")), "nN") { + if continueTask(bold(green("Import?")), true) { return importKeys(problematic.toSlice()) } From 0ebaa8a7501352a397f42afa39c7dd910a8cf4fd Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 00:13:34 +0100 Subject: [PATCH 045/155] Don't print nothing to do every time When using nocombinedupgrade "there is nothing to do" is printed when insinstalling repo packages. This is because as far as AUR installer is concerned, there is nothing to do. Instead only print that when doing a sysupgrade. --- install.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.go b/install.go index b47bc7e4..6d11e80e 100644 --- a/install.go +++ b/install.go @@ -125,7 +125,9 @@ func install(parser *arguments) error { if len(dp.Aur) == 0 { if !config.CombinedUpgrade { - fmt.Println(" there is nothing to do") + if parser.existsArg("u", "sysupgrade") { + fmt.Println(" there is nothing to do") + } return nil } From 562a21fb4d4685576c0f18ba40bbd789469c4ca7 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 02:49:45 +0100 Subject: [PATCH 046/155] Support --aur/--repo with -Sc --- clean.go | 13 ++++++++++--- parser.go | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/clean.go b/clean.go index 74ccb132..49706b1b 100644 --- a/clean.go +++ b/clean.go @@ -54,6 +54,7 @@ func cleanRemove(pkgNames []string) (err error) { } func syncClean(parser *arguments) error { + var err error keepInstalled := false keepCurrent := false @@ -67,9 +68,15 @@ func syncClean(parser *arguments) error { } } - err := show(passToPacman(parser)) - if err != nil { - return err + if mode == ModeRepo || mode == ModeAny { + err = show(passToPacman(parser)) + if err != nil { + return err + } + } + + if !(mode == ModeAUR || mode == ModeAny) { + return nil } var question string diff --git a/parser.go b/parser.go index 34f3f5a0..276726bb 100644 --- a/parser.go +++ b/parser.go @@ -157,6 +157,9 @@ func (parser *arguments) needRoot() bool { if parser.existsArg("i", "info") { return false } + if parser.existsArg("c", "clean") && mode == ModeAUR { + return false + } return true case "U", "upgrade": return true From b3a53d613d270e8f62db688cfc1503399570e4e8 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 13:04:07 +0100 Subject: [PATCH 047/155] Update vendored dependencies --- Gopkg.lock | 2 +- vendor/github.com/mikkeloscar/aur/aur.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Gopkg.lock b/Gopkg.lock index 0281eb12..c3f4ee22 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -17,7 +17,7 @@ branch = "master" name = "github.com/mikkeloscar/aur" packages = ["."] - revision = "837b260b8e90895c45737e2e72313fe5bce6f2c4" + revision = "2980c04ca5c926b2cb7c4ac3ac8dc0b7f70d29ba" [solve-meta] analyzer-name = "dep" diff --git a/vendor/github.com/mikkeloscar/aur/aur.go b/vendor/github.com/mikkeloscar/aur/aur.go index 6e0a804a..778ea1e1 100644 --- a/vendor/github.com/mikkeloscar/aur/aur.go +++ b/vendor/github.com/mikkeloscar/aur/aur.go @@ -41,6 +41,7 @@ type Pkg struct { Provides []string `json:"Provides"` Replaces []string `json:"Replaces"` OptDepends []string `json:"OptDepends"` + Groups []string `json:"Groups"` License []string `json:"License"` Keywords []string `json:"Keywords"` } From 523c471a456547861935dce4b6e01be8bfb7e8e7 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 01:48:36 +0100 Subject: [PATCH 048/155] Add extra fields to -Si[i] --- print.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/print.go b/print.go index 3f571a27..bc162bb0 100644 --- a/print.go +++ b/print.go @@ -275,9 +275,12 @@ func printInfoValue(str, value string) { func PrintInfo(a *rpc.Pkg) { printInfoValue("Repository", "aur") printInfoValue("Name", a.Name) + printInfoValue("Keywords", strings.Join(a.Keywords, " ")) printInfoValue("Version", a.Version) printInfoValue("Description", a.Description) printInfoValue("URL", a.URL) + printInfoValue("AUR URL", baseURL+"/packages/"+a.Name) + printInfoValue("Groups", strings.Join(a.Groups, " ")) printInfoValue("Licenses", strings.Join(a.License, " ")) printInfoValue("Provides", strings.Join(a.Provides, " ")) printInfoValue("Depends On", strings.Join(a.Depends, " ")) @@ -288,12 +291,22 @@ func PrintInfo(a *rpc.Pkg) { printInfoValue("Maintainer", a.Maintainer) printInfoValue("Votes", fmt.Sprintf("%d", a.NumVotes)) printInfoValue("Popularity", fmt.Sprintf("%f", a.Popularity)) + printInfoValue("First Submitted", formatTime(a.FirstSubmitted)) + printInfoValue("Last Modified", formatTime(a.LastModified)) + if a.OutOfDate != 0 { printInfoValue("Out-of-date", "Yes ["+formatTime(a.OutOfDate)+"]") } else { printInfoValue("Out-of-date", "No") } + if cmdArgs.existsDouble("i") { + printInfoValue("ID", fmt.Sprintf("%d", a.ID)) + printInfoValue("Package Base ID", fmt.Sprintf("%d", a.PackageBaseID)) + printInfoValue("Package Base", a.PackageBase) + printInfoValue("Snapshot URL", baseURL+a.URLPath) + } + fmt.Println() } From 7c74dc5dec8c73a3de7a1cd45a7dcd3d45e51bbf Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 01:49:54 +0100 Subject: [PATCH 049/155] Use none for empty fields --- print.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/print.go b/print.go index bc162bb0..2f2f27c7 100644 --- a/print.go +++ b/print.go @@ -268,6 +268,10 @@ func printDownloads(repoName string, length int, packages string) { } func printInfoValue(str, value string) { + if value == "" { + value = "None" + } + fmt.Printf(bold("%-16s%s")+" %s\n", str, ":", value) } From 4af671afac8d5c29ed609248181ddcaa6a27260a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 18 Jul 2018 00:53:53 +0100 Subject: [PATCH 050/155] Add --[no]makepkgconf --- cmd.go | 4 ++++ config.go | 2 ++ exec.go | 4 ++++ parser.go | 2 ++ 4 files changed, 12 insertions(+) diff --git a/cmd.go b/cmd.go index 929b333a..bc06a886 100644 --- a/cmd.go +++ b/cmd.go @@ -273,6 +273,10 @@ func handleConfig(option, value string) bool { config.EditorFlags = value case "makepkg": config.MakepkgBin = value + case "makepkgconf": + config.MakepkgConf = value + case "nomakepkgconf": + config.MakepkgConf = "" case "pacman": config.PacmanBin = value case "tar": diff --git a/config.go b/config.go index daff6461..ac950069 100644 --- a/config.go +++ b/config.go @@ -39,6 +39,7 @@ type Configuration struct { Editor string `json:"editor"` EditorFlags string `json:"editorflags"` MakepkgBin string `json:"makepkgbin"` + MakepkgConf string `json:"makepkgconf"` PacmanBin string `json:"pacmanbin"` PacmanConf string `json:"pacmanconf"` TarBin string `json:"tarbin"` @@ -152,6 +153,7 @@ func defaultSettings(config *Configuration) { config.EditorFlags = "" config.Devel = false config.MakepkgBin = "makepkg" + config.MakepkgConf = "" config.NoConfirm = false config.PacmanBin = "pacman" config.PGPFetch = true diff --git a/exec.go b/exec.go index b7249ccf..b70a72f6 100644 --- a/exec.go +++ b/exec.go @@ -82,6 +82,10 @@ func passToMakepkg(dir string, args ...string) *exec.Cmd { mflags := strings.Fields(config.MFlags) args = append(args, mflags...) + if config.MakepkgConf != "" { + args = append(args, "--config", config.MakepkgConf) + } + cmd := exec.Command(config.MakepkgBin, args...) cmd.Dir = dir return cmd diff --git a/parser.go b/parser.go index d4f444b0..c11d8cbd 100644 --- a/parser.go +++ b/parser.go @@ -461,6 +461,8 @@ func hasParam(arg string) bool { return true case "makepkg": return true + case "makepkgconf": + return true case "pacman": return true case "tar": From c4fec3dad05423755fded0394f22deed0a0aea65 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 25 Jul 2018 03:45:34 +0100 Subject: [PATCH 051/155] Wrap -Sp Currently we do not handle -Sp, this leads to yay trying a proper install and failing. So instead pass it to pacman and exit. Ideally we would extend -Sp to include AUR packages but for now don't bother. --- cmd.go | 2 ++ parser.go | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cmd.go b/cmd.go index a1204aa0..c0f1f0e4 100644 --- a/cmd.go +++ b/cmd.go @@ -417,6 +417,8 @@ func handleSync() (err error) { } err = syncSearch(targets) + } else if cmdArgs.existsArg("p", "print", "print-format") { + err = show(passToPacman(cmdArgs)) } else if cmdArgs.existsArg("c", "clean") { err = syncClean(cmdArgs) } else if cmdArgs.existsArg("l", "list") { diff --git a/parser.go b/parser.go index cd91c68f..8fef7a8f 100644 --- a/parser.go +++ b/parser.go @@ -122,10 +122,6 @@ func (parser *arguments) needRoot() bool { return false } - if parser.existsArg("p", "print") { - return false - } - switch parser.op { case "D", "database": if parser.existsArg("k", "check") { @@ -145,6 +141,12 @@ func (parser *arguments) needRoot() bool { case "R", "remove": return true case "S", "sync": + if parser.existsArg("y", "refresh") { + return true + } + if parser.existsArg("p", "print", "print-format") { + return false + } if parser.existsArg("s", "search") { return false } From e6c2f6f3e344d82a3302ee7349cb3be6fbfa1ad2 Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Wed, 25 Jul 2018 12:24:06 +0200 Subject: [PATCH 052/155] Fixed typos and improved punctuation consistency in README --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 43152740..4a826e1c 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ 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), [apacman](https://github.com/oshazard/apacman) and [pacaur](https://github.com/rmarquis/pacaur): -* Have almost no dependencies. -* Provide an interface for pacman. -* Have yaourt like search. +* Have almost no dependencies +* Provide an interface for pacman +* Have yaourt-like search * Minimize user input -* Know when git packages are due for an upgrade. +* Know when git packages are due for an upgrade ## Features @@ -23,7 +23,7 @@ Yay was created with a few objectives in mind and based on the design of [yaourt * Ask all questions first and then start building * 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. +* The binary has no dependencies that pacman doesn't already have * Advanced dependency solving * Remove make dependencies at the end of the build process @@ -107,11 +107,12 @@ Currently yay Depends on: `yay -{OPERATION} --repo` ### `Out Of Date AUR Packages` message is displayed, why doesn't `yay` update them? - This means the package has been flagged out of date on the AUR but maintainer has not updated the `PKGBUILD` yet. + This means the package has been flagged out of date on the AUR, but its + maintainer has not yet updated the `PKGBUILD`. ### Yay doesn't install dependencies added to PKGBUILD during installation. Yay resolves all dependencies ahead of time. You are free to edit the - PKGBUILD in anyway but any problems you cause are your own and should not be + PKGBUILD in any way, but any problems you cause are your own and should not be reported unless they can be reproduced with the original PKGBUILD. ## Examples of Custom Operations From 0b9e10e6975ebf9c9c74751dcab541f09b5a1237 Mon Sep 17 00:00:00 2001 From: J Guerreiro Date: Thu, 26 Jul 2018 12:05:50 +0100 Subject: [PATCH 053/155] Demote FAQ question headers Prevent FAQs from screaming at you --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4a826e1c..c227244f 100644 --- a/README.md +++ b/README.md @@ -84,33 +84,33 @@ Currently yay Depends on: ## Frequently Asked Questions -### Yay does not display colored output. How do I fix it? +#### 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) -### Yay is not prompting to skip packages during sysupgrade (issue [#554](https://github.com/Jguer/yay/issues/554)) +#### Yay is not prompting to skip packages during sysupgrade (issue [#554](https://github.com/Jguer/yay/issues/554)) The default behavior was changed after [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) (see: [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)). To restore such behavior use `--combinedupgrade`. This can also be permanently enabled by appending `--save`. Note: this causes [native pacman](https://wiki.archlinux.org/index.php/AUR_helpers) to become partial. -### Sometimes diffs are printed to the terminal and other times they are paged via less. How do I fix this? +#### Sometimes diffs are printed to the terminal and other times they are paged 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`. -### Yay is not asking me to edit PKGBUILDS and I don't like diff menu! What do? +#### 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? +#### Only act on AUR packages or only on repo packages? `yay -{OPERATION} --aur` `yay -{OPERATION} --repo` -### `Out Of Date AUR Packages` message is displayed, why doesn't `yay` update them? +#### `Out Of Date AUR Packages` message is displayed, why doesn't `yay` update them? This means the package has been flagged out of date on the AUR, but its maintainer has not yet updated the `PKGBUILD`. -### Yay doesn't install dependencies added to PKGBUILD during installation. +#### Yay doesn't install dependencies added to PKGBUILD during installation. Yay resolves all dependencies ahead of time. You are free to edit the PKGBUILD in any way, but any problems you cause are your own and should not be reported unless they can be reproduced with the original PKGBUILD. From 9c882614a38899568b38d9b9662bc83527652791 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 14:16:12 +0100 Subject: [PATCH 054/155] Rework completion Bash seperates on whitespace, so the fish completion file actually works for bash and zsh. So remove the concept of shells entirley and just use the singular aur_sh.cache file. If for some reason output without the repository data is needed, the user could always just pipe it into awk like so `yay -Pc | awk '{print $1}'`. Or perhaps a --quiet option could be added where yay will strip the output itself. The completion cache now updates when installing AUR packages. This is done as a goroutine with no wait groups. This ensures the program will never hang if there is a problem. The completion is stil updated during -Pc but as long as an AUR package has been installed recently it should not need to update. The cache will now also wait 7 days instead of 2 before refreshing. A refresh can be forced using -Pcc. --- cmd.go | 9 +++------ completions.go | 52 ++++++++++++++++++++------------------------------ install.go | 2 ++ 3 files changed, 26 insertions(+), 37 deletions(-) diff --git a/cmd.go b/cmd.go index a1204aa0..cfa67211 100644 --- a/cmd.go +++ b/cmd.go @@ -361,13 +361,10 @@ func handlePrint() (err error) { err = printUpdateList(cmdArgs) case cmdArgs.existsArg("w", "news"): err = printNewsFeed() + case cmdArgs.existsDouble("c", "complete"): + complete(true) case cmdArgs.existsArg("c", "complete"): - switch { - case cmdArgs.existsArg("f", "fish"): - complete("fish") - default: - complete("sh") - } + complete(false) case cmdArgs.existsArg("s", "stats"): err = localStatistics() default: diff --git a/completions.go b/completions.go index 68bad132..ba52d702 100644 --- a/completions.go +++ b/completions.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "fmt" "io" "net/http" "os" @@ -13,7 +12,7 @@ import ( ) //CreateAURList creates a new completion file -func createAURList(out *os.File, shell string) (err error) { +func createAURList(out *os.File) (err error) { resp, err := http.Get("https://aur.archlinux.org/packages.gz") if err != nil { return err @@ -24,22 +23,15 @@ func createAURList(out *os.File, shell string) (err error) { scanner.Scan() for scanner.Scan() { - fmt.Print(scanner.Text()) out.WriteString(scanner.Text()) - if shell == "fish" { - fmt.Print("\tAUR\n") - out.WriteString("\tAUR\n") - } else { - fmt.Print("\n") - out.WriteString("\n") - } + out.WriteString("\tAUR\n") } return nil } //CreatePackageList appends Repo packages to completion cache -func createRepoList(out *os.File, shell string) (err error) { +func createRepoList(out *os.File) (err error) { dbList, err := alpmHandle.SyncDbs() if err != nil { return @@ -47,15 +39,8 @@ func createRepoList(out *os.File, shell string) (err error) { _ = dbList.ForEach(func(db alpm.Db) error { _ = db.PkgCache().ForEach(func(pkg alpm.Package) error { - fmt.Print(pkg.Name()) out.WriteString(pkg.Name()) - if shell == "fish" { - fmt.Print("\t" + pkg.DB().Name() + "\n") - out.WriteString("\t" + pkg.DB().Name() + "\n") - } else { - fmt.Print("\n") - out.WriteString("\n") - } + out.WriteString("\t" + pkg.DB().Name() + "\n") return nil }) return nil @@ -63,33 +48,38 @@ func createRepoList(out *os.File, shell string) (err error) { return nil } -// Complete provides completion info for shells -func complete(shell string) error { - var path string - - if shell == "fish" { - path = filepath.Join(cacheHome, "aur_fish"+".cache") - } else { - path = filepath.Join(cacheHome, "aur_sh"+".cache") - } +func updateCompletion(force bool) error { + path := filepath.Join(cacheHome, "completion.cache") info, err := os.Stat(path) - if os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { + if os.IsNotExist(err) || time.Since(info.ModTime()).Hours() >= 7*24 || force { os.MkdirAll(filepath.Dir(path), 0755) out, errf := os.Create(path) if errf != nil { return errf } - if createAURList(out, shell) != nil { + if createAURList(out) != nil { defer os.Remove(path) } - erra := createRepoList(out, shell) + erra := createRepoList(out) out.Close() return erra } + return nil +} + +// Complete provides completion info for shells +func complete(force bool) error { + path := filepath.Join(cacheHome, "completion.cache") + + err := updateCompletion(force) + if err != nil { + return err + } + in, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644) if err != nil { return err diff --git a/install.go b/install.go index 6d11e80e..ed068ecd 100644 --- a/install.go +++ b/install.go @@ -312,6 +312,8 @@ func install(parser *arguments) error { } } + go updateCompletion(false) + err = downloadPkgBuildsSources(do.Aur, do.Bases, incompatible) if err != nil { return err From bc6028348b8ffdb6be78c79eee1dafafd3e9b4d2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 14:42:43 +0100 Subject: [PATCH 055/155] Make the completion refresh time configurable The default setting is 7 days. The user can specify a different time in days. -1 can be set to never refresh while 0 can be used to always refresh. --- cmd.go | 5 ++++ completions.go | 2 +- config.go | 78 ++++++++++++++++++++++++++------------------------ parser.go | 2 ++ 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/cmd.go b/cmd.go index cfa67211..5dffe1aa 100644 --- a/cmd.go +++ b/cmd.go @@ -221,6 +221,11 @@ func handleConfig(option, value string) bool { config.SortMode = TopDown case "bottomup": config.SortMode = BottomUp + case "completioninterval": + n, err := strconv.Atoi(value) + if err == nil { + config.CompletionInterval = n + } case "sortby": config.SortBy = value case "noconfirm": diff --git a/completions.go b/completions.go index ba52d702..2a83f2ff 100644 --- a/completions.go +++ b/completions.go @@ -52,7 +52,7 @@ func updateCompletion(force bool) error { path := filepath.Join(cacheHome, "completion.cache") info, err := os.Stat(path) - if os.IsNotExist(err) || time.Since(info.ModTime()).Hours() >= 7*24 || force { + if os.IsNotExist(err) || (config.CompletionInterval != -1 && time.Since(info.ModTime()).Hours() >= float64(config.CompletionInterval*24)) || force { os.MkdirAll(filepath.Dir(path), 0755) out, errf := os.Create(path) if errf != nil { diff --git a/config.go b/config.go index 06be4bdb..cff3e77d 100644 --- a/config.go +++ b/config.go @@ -35,44 +35,45 @@ const ( // Configuration stores yay's config. type Configuration struct { - BuildDir string `json:"buildDir"` - Editor string `json:"editor"` - EditorFlags string `json:"editorflags"` - MakepkgBin string `json:"makepkgbin"` - MakepkgConf string `json:"makepkgconf"` - PacmanBin string `json:"pacmanbin"` - PacmanConf string `json:"pacmanconf"` - TarBin string `json:"tarbin"` - 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"` - GpgBin string `json:"gpgbin"` - GpgFlags string `json:"gpgflags"` - MFlags string `json:"mflags"` - SortBy string `json:"sortby"` - GitFlags string `json:"gitflags"` - RemoveMake string `json:"removemake"` - RequestSplitN int `json:"requestsplitn"` - SearchMode int `json:"-"` - SortMode int `json:"sortmode"` - SudoLoop bool `json:"sudoloop"` - TimeUpdate bool `json:"timeupdate"` - NoConfirm bool `json:"-"` - Devel bool `json:"devel"` - CleanAfter bool `json:"cleanAfter"` - GitClone bool `json:"gitclone"` - Provides bool `json:"provides"` - PGPFetch bool `json:"pgpfetch"` - UpgradeMenu bool `json:"upgrademenu"` - CleanMenu bool `json:"cleanmenu"` - DiffMenu bool `json:"diffmenu"` - EditMenu bool `json:"editmenu"` - CombinedUpgrade bool `json:"combinedupgrade"` - UseAsk bool `json:"useask"` + BuildDir string `json:"buildDir"` + Editor string `json:"editor"` + EditorFlags string `json:"editorflags"` + MakepkgBin string `json:"makepkgbin"` + MakepkgConf string `json:"makepkgconf"` + PacmanBin string `json:"pacmanbin"` + PacmanConf string `json:"pacmanconf"` + TarBin string `json:"tarbin"` + 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"` + GpgBin string `json:"gpgbin"` + GpgFlags string `json:"gpgflags"` + MFlags string `json:"mflags"` + SortBy string `json:"sortby"` + GitFlags string `json:"gitflags"` + RemoveMake string `json:"removemake"` + RequestSplitN int `json:"requestsplitn"` + SearchMode int `json:"-"` + SortMode int `json:"sortmode"` + CompletionInterval int `json:"completionrefreshtime"` + SudoLoop bool `json:"sudoloop"` + TimeUpdate bool `json:"timeupdate"` + NoConfirm bool `json:"-"` + Devel bool `json:"devel"` + CleanAfter bool `json:"cleanAfter"` + GitClone bool `json:"gitclone"` + Provides bool `json:"provides"` + PGPFetch bool `json:"pgpfetch"` + UpgradeMenu bool `json:"upgrademenu"` + CleanMenu bool `json:"cleanmenu"` + DiffMenu bool `json:"diffmenu"` + EditMenu bool `json:"editmenu"` + CombinedUpgrade bool `json:"combinedupgrade"` + UseAsk bool `json:"useask"` } var version = "7.885" @@ -163,6 +164,7 @@ func defaultSettings(config *Configuration) { config.MFlags = "" config.GitFlags = "" config.SortMode = BottomUp + config.CompletionInterval = 7 config.SortBy = "votes" config.SudoLoop = false config.TarBin = "bsdtar" diff --git a/parser.go b/parser.go index cd91c68f..9090b35a 100644 --- a/parser.go +++ b/parser.go @@ -472,6 +472,8 @@ func hasParam(arg string) bool { return true case "answerupgrade": return true + case "completioninterval": + return true case "sortby": return true default: From 2f975c71573d99b5425fdab2f63b44a5398653a5 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 26 Jul 2018 13:58:51 +0100 Subject: [PATCH 056/155] Update vendored dependencies --- Gopkg.lock | 4 +- vendor/github.com/jguer/go-alpm/callbacks.c | 2 +- vendor/github.com/jguer/go-alpm/callbacks.go | 10 ++-- vendor/github.com/jguer/go-alpm/conf.go | 27 ++++++++++ vendor/github.com/jguer/go-alpm/db.go | 25 +++++++++ vendor/github.com/jguer/go-alpm/enums.go | 39 +++++++++++++- vendor/github.com/jguer/go-alpm/sync.go | 27 ++++++++++ vendor/github.com/jguer/go-alpm/trans.go | 54 ++++++++++++++++++++ vendor/github.com/jguer/go-alpm/types.go | 8 +++ vendor/github.com/mikkeloscar/aur/aur.go | 4 +- 10 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 vendor/github.com/jguer/go-alpm/sync.go create mode 100644 vendor/github.com/jguer/go-alpm/trans.go diff --git a/Gopkg.lock b/Gopkg.lock index c3f4ee22..ba84f576 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,13 +11,13 @@ branch = "master" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "1114f773cdfb05f577438f7a0538eccabc9cf012" + revision = "c3ee958efac942186012cc67de8fe5e7a5b3685d" [[projects]] branch = "master" name = "github.com/mikkeloscar/aur" packages = ["."] - revision = "2980c04ca5c926b2cb7c4ac3ac8dc0b7f70d29ba" + revision = "f998dbf94dc47ef839c76740efeb673d3459be1f" [solve-meta] analyzer-name = "dep" diff --git a/vendor/github.com/jguer/go-alpm/callbacks.c b/vendor/github.com/jguer/go-alpm/callbacks.c index e36a4295..857506dc 100644 --- a/vendor/github.com/jguer/go-alpm/callbacks.c +++ b/vendor/github.com/jguer/go-alpm/callbacks.c @@ -9,7 +9,7 @@ #include #include -void logCallback(uint16_t level, char *cstring); +void logCallback(alpm_loglevel_t level, char *cstring); void questionCallback(alpm_question_t *question); void go_alpm_log_cb(alpm_loglevel_t level, const char *fmt, va_list arg) { diff --git a/vendor/github.com/jguer/go-alpm/callbacks.go b/vendor/github.com/jguer/go-alpm/callbacks.go index 0078e58a..66467930 100644 --- a/vendor/github.com/jguer/go-alpm/callbacks.go +++ b/vendor/github.com/jguer/go-alpm/callbacks.go @@ -9,7 +9,7 @@ package alpm /* #include #include -void logCallback(uint16_t level, char *cstring); +void logCallback(alpm_loglevel_t level, char *cstring); void go_alpm_log_cb(alpm_loglevel_t level, const char *fmt, va_list arg); void go_alpm_set_logging(alpm_handle_t *handle); void go_alpm_set_question(alpm_handle_t *handle); @@ -20,12 +20,12 @@ import ( "unsafe" ) -type logCallbackSig func(uint16, string) +type logCallbackSig func(LogLevel, string) type questionCallbackSig func(QuestionAny) var DefaultLogLevel = LogWarning -func DefaultLogCallback(lvl uint16, s string) { +func DefaultLogCallback(lvl LogLevel, s string) { if lvl <= DefaultLogLevel { print("go-alpm: ", s) } @@ -35,8 +35,8 @@ var log_callback logCallbackSig var question_callback questionCallbackSig //export logCallback -func logCallback(level uint16, cstring *C.char) { - log_callback(level, C.GoString(cstring)) +func logCallback(level C.alpm_loglevel_t, cstring *C.char) { + log_callback(LogLevel(level), C.GoString(cstring)) } //export questionCallback diff --git a/vendor/github.com/jguer/go-alpm/conf.go b/vendor/github.com/jguer/go-alpm/conf.go index 18033239..62284726 100644 --- a/vendor/github.com/jguer/go-alpm/conf.go +++ b/vendor/github.com/jguer/go-alpm/conf.go @@ -69,6 +69,7 @@ type PacmanConfig struct { type RepoConfig struct { Name string SigLevel SigLevel + Usage Usage Servers []string } @@ -197,6 +198,24 @@ lineloop: case "SigLevel": // TODO: implement SigLevel parsing. continue lineloop + case "Usage": + for _, usage := range line.Values { + switch usage { + case "Sync": + curRepo.Usage |= UsageSync + case "Search": + curRepo.Usage |= UsageSearch + case "Install": + curRepo.Usage |= UsageInstall + case "Upgrade": + curRepo.Usage |= UsageUpgrade + case "All": + curRepo.Usage |= UsageAll + default: + err = fmt.Errorf("unknown option at line %d: %s", rdr.Lineno, line.Name) + break lineloop + } + } case "Server": curRepo.Servers = append(curRepo.Servers, line.Values...) continue lineloop @@ -261,6 +280,13 @@ lineloop: conf.CacheDir = []string{"/var/cache/pacman/pkg/"} //should only be set if the config does not specify this } + for n, _ := range conf.Repos { + repo := &conf.Repos[n] + if repo.Usage == 0 { + repo.Usage = UsageAll + } + } + return conf, err } @@ -316,6 +342,7 @@ func (conf *PacmanConfig) CreateHandle() (*Handle, error) { repoconf.Servers[i] = addr } db.SetServers(repoconf.Servers) + db.SetUsage(repoconf.Usage) } } diff --git a/vendor/github.com/jguer/go-alpm/db.go b/vendor/github.com/jguer/go-alpm/db.go index 214984de..1295e26a 100644 --- a/vendor/github.com/jguer/go-alpm/db.go +++ b/vendor/github.com/jguer/go-alpm/db.go @@ -117,6 +117,11 @@ func (db Db) SetServers(servers []string) { } } +// SetUsage sets the Usage of the database +func (db Db) SetUsage(usage Usage) { + C.alpm_db_set_usage(db.ptr, C.int(usage)) +} + // PkgByName searches a package in db. func (db Db) PkgByName(name string) (*Package, error) { cName := C.CString(name) @@ -151,3 +156,23 @@ func (db Db) PkgCache() PackageList { pkgcache := (*list)(unsafe.Pointer(C.alpm_db_get_pkgcache(db.ptr))) return PackageList{pkgcache, db.handle} } + +func (db Db) Search(targets []string) PackageList { + needles := &C.alpm_list_t{} + head := needles + needles.data = unsafe.Pointer(C.CString(targets[0])) + + for _, str := range targets[1:] { + needles.next = &C.alpm_list_t{} + needles = needles.next + needles.data = unsafe.Pointer(C.CString(str)) + } + + pkglist := (*list)(unsafe.Pointer(C.alpm_db_search(db.ptr, needles))) + + for needles = head; needles != nil; needles = needles.next { + C.free(needles.data) + } + + return PackageList{pkglist, db.handle} +} diff --git a/vendor/github.com/jguer/go-alpm/enums.go b/vendor/github.com/jguer/go-alpm/enums.go index 3c692bc1..cb32b500 100644 --- a/vendor/github.com/jguer/go-alpm/enums.go +++ b/vendor/github.com/jguer/go-alpm/enums.go @@ -89,9 +89,11 @@ const ( SigStatusKeyDisabled ) +type LogLevel uint16 + // Logging levels. const ( - LogError uint16 = 1 << iota + LogError LogLevel = 1 << iota LogWarning LogDebug LogFunction @@ -118,3 +120,38 @@ const ( ValidationSignature ValidationUnkown Validation = 0 ) + +type Usage int + +const ( + UsageSync Usage = 1 << iota + UsageSearch + UsageInstall + UsageUpgrade + UsageAll = (1 << 4) - 1 +) + +type TransFlag int + +const ( + TransFlagNoDeps TransFlag = 1 << iota + TransFlagForce + TransFlagNoSave + TransFlagNoDepVersion + TransFlagCascade + TransFlagRecurse + // 7 is missing + _ + TransFlagDbOnly + TransFlagAllDeps + TransFlagDownloadOnly + TransFlagNoScriptlets + // 12 is missing + _ + TransFlagNoConflicts + TransFlagNeeded + TransFlagAllExplicit + TransFlagUnneeded + TransFlagRecurseAll + TransFlagNoLock +) diff --git a/vendor/github.com/jguer/go-alpm/sync.go b/vendor/github.com/jguer/go-alpm/sync.go new file mode 100644 index 00000000..d5e4ebab --- /dev/null +++ b/vendor/github.com/jguer/go-alpm/sync.go @@ -0,0 +1,27 @@ +// db.go - Functions for database handling. +// +// Copyright (c) 2013 The go-alpm Authors +// +// MIT Licensed. See LICENSE for details. + +package alpm + +/* +#include +*/ +import "C" + +func (h *Handle) SyncSysupgrade(enableDowngrade bool) error { + intEnableDowngrade := C.int(0) + + if enableDowngrade { + intEnableDowngrade = C.int(1) + } + + ret := C.alpm_sync_sysupgrade(h.ptr, intEnableDowngrade) + if ret != 0 { + return h.LastError() + } + + return nil +} diff --git a/vendor/github.com/jguer/go-alpm/trans.go b/vendor/github.com/jguer/go-alpm/trans.go new file mode 100644 index 00000000..92d5a740 --- /dev/null +++ b/vendor/github.com/jguer/go-alpm/trans.go @@ -0,0 +1,54 @@ +// db.go - Functions for database handling. +// +// Copyright (c) 2013 The go-alpm Authors +// +// MIT Licensed. See LICENSE for details. + +package alpm + +/* +#include +*/ +import "C" + +import ( + "unsafe" +) + +func (h *Handle) TransInit(flags TransFlag) error { + ret := C.alpm_trans_init(h.ptr, C.int(flags)) + if ret != 0 { + return h.LastError() + } + + return nil +} + +func (h *Handle) TransRelease() error { + ret := C.alpm_trans_release(h.ptr) + if ret != 0 { + return h.LastError() + } + + return nil +} + +func (h *Handle) TransGetAdd() PackageList { + pkgs := C.alpm_trans_get_add(h.ptr) + return PackageList{(*list)(unsafe.Pointer(pkgs)), *h} +} + +func (h *Handle) TransGetRemove() PackageList { + pkgs := C.alpm_trans_get_remove(h.ptr) + return PackageList{(*list)(unsafe.Pointer(pkgs)), *h} +} + +func (h *Handle) TransGetFalgs() (TransFlag, error) { + flags := C.alpm_trans_get_flags(h.ptr) + + if flags == -1 { + return -1, h.LastError() + } + + return TransFlag(flags), nil +} diff --git a/vendor/github.com/jguer/go-alpm/types.go b/vendor/github.com/jguer/go-alpm/types.go index 91390550..351a21ee 100644 --- a/vendor/github.com/jguer/go-alpm/types.go +++ b/vendor/github.com/jguer/go-alpm/types.go @@ -192,6 +192,14 @@ func (question QuestionAny) QuestionSelectProvider() (QuestionSelectProvider, er return QuestionSelectProvider{}, fmt.Errorf("Can not convert to QuestionInstallIgnorepkg") } +func (question QuestionAny) QuestionReplace() (QuestionReplace, error) { + if question.Type() == QuestionTypeReplacePkg { + return *(*QuestionReplace)(unsafe.Pointer(&question)), nil + } + + return QuestionReplace{}, fmt.Errorf("Can not convert to QuestionReplace") +} + func (question QuestionInstallIgnorepkg) SetInstall(install bool) { if install { question.ptr.install = 1 diff --git a/vendor/github.com/mikkeloscar/aur/aur.go b/vendor/github.com/mikkeloscar/aur/aur.go index 778ea1e1..46db9391 100644 --- a/vendor/github.com/mikkeloscar/aur/aur.go +++ b/vendor/github.com/mikkeloscar/aur/aur.go @@ -2,7 +2,7 @@ package aur import ( "encoding/json" - "fmt" + "errors" "net/http" "net/url" ) @@ -62,7 +62,7 @@ func get(values url.Values) ([]Pkg, error) { } if len(result.Error) > 0 { - return nil, fmt.Errorf(result.Error) + return nil, errors.New(result.Error) } return result.Results, nil From 3180c66f394e3e025fb49e9004a0eec388cd8204 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 24 Jul 2018 22:00:33 +0100 Subject: [PATCH 057/155] Use alpm's built in searching for -Ss This allows us to support the usage option in pacman.conf This also speeds up the searching --- query.go | 49 +++++++++++++------------------------------------ 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/query.go b/query.go index 7c57d103..6abdd3a4 100644 --- a/query.go +++ b/query.go @@ -260,46 +260,23 @@ func queryRepo(pkgInputN []string) (s repoQuery, n int, err error) { return } - // BottomUp functions - initL := func(len int) int { - if config.SortMode == TopDown { - return 0 + dbList.ForEach(func(db alpm.Db) error { + if len(pkgInputN) == 0 { + pkgs := db.PkgCache() + s = append(s, pkgs.Slice()...) + } else { + pkgs := db.Search(pkgInputN) + s = append(s, pkgs.Slice()...) } - return len - 1 - } - compL := func(len int, i int) bool { - if config.SortMode == TopDown { - return i < len + return nil + }) + + if config.SortMode == BottomUp { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] } - return i > -1 - } - finalL := func(i int) int { - if config.SortMode == TopDown { - return i + 1 - } - return i - 1 } - dbS := dbList.Slice() - lenDbs := len(dbS) - for f := initL(lenDbs); compL(lenDbs, f); f = finalL(f) { - pkgS := dbS[f].PkgCache().Slice() - lenPkgs := len(pkgS) - for i := initL(lenPkgs); compL(lenPkgs, i); i = finalL(i) { - match := true - for _, pkgN := range pkgInputN { - if !(strings.Contains(pkgS[i].Name(), pkgN) || strings.Contains(strings.ToLower(pkgS[i].Description()), pkgN)) { - match = false - break - } - } - - if match { - n++ - s = append(s, pkgS[i]) - } - } - } return } From f4aa7f79337fe777b9be04d44b35d4308da59a95 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 25 Jul 2018 02:04:17 +0100 Subject: [PATCH 058/155] Use alpm_sync_sysupgrade for uprepo This allows us to support the Upgrade Usage option as well as relying on alpm's logic instead of coming up with out own. It is possible that this could lead to showing replaces in the upgrade menu. --- upgrade.go | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/upgrade.go b/upgrade.go index 71fa8df5..5e81ccaf 100644 --- a/upgrade.go +++ b/upgrade.go @@ -297,23 +297,38 @@ func printLocalNewerThanAUR( // upRepo gathers local packages and checks if they have new versions. // Output: Upgrade type package list. func upRepo(local []alpm.Package) (upSlice, error) { - dbList, err := alpmHandle.SyncDbs() - if err != nil { - return nil, err - } - slice := upSlice{} - for _, pkg := range local { - newPkg := pkg.NewVersion(dbList) - if newPkg != nil { - if pkg.ShouldIgnore() { - printIgnoringPackage(pkg, newPkg.Version()) - } else { - slice = append(slice, upgrade{pkg.Name(), newPkg.DB().Name(), pkg.Version(), newPkg.Version()}) - } - } + localDB, err := alpmHandle.LocalDb() + if err != nil { + return slice, err } + + err = alpmHandle.TransInit(alpm.TransFlagNoLock) + if err != nil { + return slice, err + } + + defer alpmHandle.TransRelease() + + alpmHandle.SyncSysupgrade(cmdArgs.existsDouble("u", "sysupgrade")) + alpmHandle.TransGetAdd().ForEach(func(pkg alpm.Package) error { + localPkg, err := localDB.PkgByName(pkg.Name()) + localVer := "-" + + if err == nil { + localVer = localPkg.Version() + } + + slice = append(slice, upgrade{ + pkg.Name(), + pkg.DB().Name(), + localVer, + pkg.Version(), + }) + return nil + }) + return slice, nil } From a592d1aa87912939dd3e2524b4b66285b206b893 Mon Sep 17 00:00:00 2001 From: Jguer Date: Fri, 27 Jul 2018 12:16:21 +0100 Subject: [PATCH 059/155] Add completions to fish for series 900 Signed-off-by: Jguer --- completions/fish | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/completions/fish b/completions/fish index cdba63e1..e9a84928 100644 --- a/completions/fish +++ b/completions/fish @@ -8,7 +8,7 @@ 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) -set -l listall "(yay -Pcf)" +set -l listall "(yay -Pc)" set -l listrepos "(__fish_print_pacman_repos)" set -l listgroups "(pacman -Sg)\t'Package Group'" set -l listpacman "(__fish_print_packages)" @@ -110,17 +110,25 @@ complete -c $progname -n "not $noopt" -l noeditmenu -d 'Do not edit/view PKGBUIL 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 provides -d 'Look for matching providers 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' # Post V7.887 -complete -c $progname -n "not $noopt" -l useask -d 'Automatically resolce conflicts using pacmans ask flag' +complete -c $progname -n "not $noopt" -l useask -d 'Automatically resolve conflicts using pacmans ask flag' complete -c $progname -n "not $noopt" -l nouseask -d 'Confirm conflicts manually during the install' complete -c $progname -n "not $noopt" -l combinedupgrade -d 'Refresh then perform the repo and AUR upgrade together' complete -c $progname -n "not $noopt" -l nocombinedupgrade -d 'Perform the repo upgrade and AUR upgrade separately' +#Post V8.976 +complete -c $progname -n "not $noopt" -l nomakepkgconf -d 'Use default makepkg.conf' +complete -c $progname -n "not $noopt" -l makepkgconf -d 'Use custom makepkg.conf location' +complete -c $progname -n "not $noopt" -l removemake -d 'Remove make deps after install' +complete -c $progname -n "not $noopt" -l askremovemake -d 'Ask to remove make deps after install' +complete -c $progname -n "not $noopt" -l noremovemake -d 'Do not remove make deps after install' +complete -c $progname -n "not $noopt" -l completioninterval -d 'Refresh interval for completion cache' + # Yay options complete -c $progname -n $yayspecific -s c -l clean -d 'Remove unneeded dependencies' -f complete -c $progname -n $yayspecific -l gendb -d 'Generate development package DB' -f From a54b9496701d77e7e05585008847677c5945b1f5 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 28 Jul 2018 03:45:04 +0100 Subject: [PATCH 060/155] Show alpm version with -V --- cmd.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index b95e3faa..7d8d508d 100644 --- a/cmd.go +++ b/cmd.go @@ -5,6 +5,8 @@ import ( "fmt" "os" "strconv" + + alpm "github.com/jguer/go-alpm" ) var cmdArgs = makeArguments() @@ -349,7 +351,7 @@ func handleConfig(option, value string) bool { } func handleVersion() { - fmt.Printf("yay v%s\n", version) + fmt.Printf("yay v%s - libalpm v%s\n", version, alpm.Version()) } func handlePrint() (err error) { From a61eb0d568dd189040c5daafddf0f68111793237 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 28 Jul 2018 16:12:49 +0100 Subject: [PATCH 061/155] Use no-progress when cloning packages The output is annoying and takes up many lines. All AUR packages clone extremley fast anyway, making the progress unneeded. --- download.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/download.go b/download.go index c6ba74b4..0f6a9281 100644 --- a/download.go +++ b/download.go @@ -60,7 +60,7 @@ func gitHasDiff(path string, name string) (bool, error) { func gitDownload(url string, path string, name string) (bool, error) { _, err := os.Stat(filepath.Join(path, name, ".git")) if os.IsNotExist(err) { - err = show(passToGit(path, "clone", url, name)) + err = show(passToGit(path, "clone", "--no-progress", url, name)) if err != nil { return false, fmt.Errorf("error cloning %s", name) } From 5ce740068ec082adf1a8dc10c9d8103945832fa3 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 28 Jul 2018 19:51:19 +0100 Subject: [PATCH 062/155] Always pass PacmanConf to pacman Normaly we only pass --config to pacman if the user specifies it on the command line. Otherwise we let pacman use it's default config location. If the user has changed pacmanconf in Yay's config file then this could cause a miss match between the config we use to init alpm and the config pacman is using. --- cmd.go | 14 ++------------ exec.go | 2 +- main.go | 7 ++----- parser.go | 20 +++++++++++++++++--- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/cmd.go b/cmd.go index 7d8d508d..526a0922 100644 --- a/cmd.go +++ b/cmd.go @@ -119,18 +119,6 @@ If no operation is provided -Y will be assumed`) } func handleCmd() (err error) { - for option, value := range cmdArgs.options { - if handleConfig(option, value) { - cmdArgs.delArg(option) - } - } - - for option, value := range cmdArgs.globals { - if handleConfig(option, value) { - cmdArgs.delArg(option) - } - } - if shouldSaveConfig { config.saveConfig() } @@ -232,6 +220,8 @@ func handleConfig(option, value string) bool { config.SortBy = value case "noconfirm": config.NoConfirm = true + case "config": + config.PacmanConf = value case "redownload": config.ReDownload = "yes" case "redownloadall": diff --git a/exec.go b/exec.go index dd5b1e88..394f59b4 100644 --- a/exec.go +++ b/exec.go @@ -85,8 +85,8 @@ func passToPacman(args *arguments) *exec.Cmd { argArr = append(argArr, "--noconfirm") } + argArr = append(argArr, "--config", config.PacmanConf) argArr = append(argArr, "--") - argArr = append(argArr, args.targets...) if args.needRoot() { diff --git a/main.go b/main.go index 3966d38e..57d5101b 100644 --- a/main.go +++ b/main.go @@ -109,11 +109,6 @@ func initAlpm() (err error) { var exists bool //var double bool - value, _, exists = cmdArgs.getArg("config") - if exists { - config.PacmanConf = value - } - alpmConf, err = readAlpmConfig(config.PacmanConf) if err != nil { err = fmt.Errorf("Unable to read Pacman conf: %s", err) @@ -223,6 +218,8 @@ func main() { goto cleanup } + cmdArgs.extractYayOptions() + err = initVCS() if err != nil { fmt.Println(err) diff --git a/parser.go b/parser.go index 780c0292..c45d4a4e 100644 --- a/parser.go +++ b/parser.go @@ -593,10 +593,10 @@ func (parser *arguments) parseCommandLine() (err error) { parser.op = "Y" } - if cmdArgs.existsArg("-") { + if parser.existsArg("-") { var file *os.File - err = cmdArgs.parseStdin() - cmdArgs.delArg("-") + err = parser.parseStdin() + parser.delArg("-") if err != nil { return @@ -614,6 +614,20 @@ func (parser *arguments) parseCommandLine() (err error) { return } +func (parser *arguments) extractYayOptions() { + for option, value := range parser.options { + if handleConfig(option, value) { + parser.delArg(option) + } + } + + for option, value := range parser.globals { + if handleConfig(option, value) { + parser.delArg(option) + } + } +} + //parses input for number menus splitted by spaces or commas //supports individual selection: 1 2 3 4 //supports range selections: 1-4 10-20 From b4c102a17ac6e6051f71c01852076d36afcc551d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 30 Jul 2018 01:16:36 +0100 Subject: [PATCH 063/155] Split stdin on new line Pacman 5.1 changed the stdin seperation from whitespace to newline. To maintain corectness we should also do this. --- parser.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/parser.go b/parser.go index c45d4a4e..1517c155 100644 --- a/parser.go +++ b/parser.go @@ -1,10 +1,10 @@ package main import ( + "bufio" "bytes" "fmt" "html" - "io" "os" "strconv" "strings" @@ -537,21 +537,15 @@ func (parser *arguments) parseLongOption(arg string, param string) (usedNext boo return } -func (parser *arguments) parseStdin() (err error) { - for { - var target string - _, err = fmt.Scan(&target) +func (parser *arguments) parseStdin() error { + scanner := bufio.NewScanner(os.Stdin) + scanner.Split(bufio.ScanLines) - if err != nil { - if err == io.EOF { - err = nil - } - - return - } - - parser.addTarget(target) + for scanner.Scan() { + parser.addTarget(scanner.Text()) } + + return os.Stdin.Close() } func (parser *arguments) parseCommandLine() (err error) { From 8e1e935d7e5ffb71deafe3c28bff6cc56d8fd8fa Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 28 Jul 2018 04:01:55 +0100 Subject: [PATCH 064/155] Update man page --- doc/yay.8 | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index befb697a..fc9557f6 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -210,6 +210,17 @@ The command to use for \fBgpg\fR calls. This can be a command in The pacman config file to use\&. .RE .PP +\fB\-\-makepkgconf \fR +.RS 4 +The config file for makepkg to use\%. If this is not set then the default +config file will be used\&. +.RE +.PP +\fB\-\-nomakepkgconf\fR +.RS 4 +Reset the makepkg config file back to its default\&. +.RE +.PP \fB\-\-requestsplitn \fR .RS 4 The maximum amount of packages to request per AUR query\&. The higher the @@ -218,6 +229,13 @@ AUR query will cause an error\&. This should only make a noticeable difference with very large requests (>500) packages\&. .RE .PP +\fB\-\-completioninterval \fR +.RS 4 +Time in days to refresh the completion cache\&. Setting this to 0 will cause +the cache to be refreshed every time, while setting this to -1 will cause the +cache to never be refreshed\&. +.RE +.PP \fB\-\-sortby \fR .RS 4 Sort AUR results by a specific field during search\&. @@ -324,6 +342,21 @@ Do not show the edit menu\&. Do not show the upgrade menu\&. .RE .PP +\fB\-\-askremovemake\fR +.RS 4 +Ask to remove makedepends after installing packages\&. +.RE +.PP +\fB\-\-removemake\fR +.RS 4 +Remove makedepends after installing packages\&. +.RE +.PP +\fB\-\-noremovemake\fR +.RS 4 +Do not remove makedepends after installing packages\&. +.RE +.PP \fB\-\-topdown\fR .RS 4 Display repository packages first and then AUR packages\&. @@ -579,8 +612,9 @@ The cache directory is \fI$XDG_CACHE_HOME/yay/\fR\&. if \fB$XDG_CACHE_HOME\fR is unset, the cache directory will fall back to \fI$HOME/.cache/yay\fR\&. .PP -\fIaur_\fR holds a list of of all packages, including the AUR, -for shell completion\&. The completion files are refreshed every 48 hours\&. +\fIcompletion.cache\fR holds a list of of all packages, including the AUR, +for shell completion\&. By default the completion files are refreshed every +7 days\&. .PP \fIvcs.json\fR tracks VCS packages and the latest commit of each source. If any of these commits change the package will be upgraded during a devel update. From 4841642c2141317b14496ef0430f6b9991361231 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 28 Jul 2018 04:49:15 +0100 Subject: [PATCH 065/155] Rework manpage Give the manpage a cleaner and easier to read and maintain structure. This refacotrs the raw groff, the formatted output should apear very similar. --- doc/yay.8 | 1077 ++++++++++++++++++++++++----------------------------- 1 file changed, 491 insertions(+), 586 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index fc9557f6..dde5a504 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -1,654 +1,559 @@ -'\" t -.TH "YAY" "8" "2018\-07\-01" "Yay v7\&.887+" "Yay Manual" +'\ t +.TH "YAY" "8" "2018\-07\-01" "Yay v8.972+" "Yay Manual" .nh .ad l -.SH "NAME" +.SH NAME yay \- AUR Helper written in go -.SH "SYNOPSIS" -.sp + +.SH SYNOPSIS \fIyay\fR [options] [targets] .sp \fIyay\fR .sp \fIyay\fR -.SH "DESCRIPTION" -.sp -Yay is a Pacman wrapper with AUR support\&. It passes options to Makepkg and -Pacman after resolving packages to install/upgrade\&. -.sp -This manpage only covers options unique to Yay\&. For other options see -\fBpacman(8)\fR\&. -.SH "YAY OPERATIONS" -.PP -\fB\-Y, \-\-yay\fR -.RS 4 -Perform yay specific operations\&. This is the default if no other operation is -selected\&. + +.SH DESCRIPTION +Yay is a Pacman wrapper with AUR support. It passes options to Makepkg and +Pacman after resolving packages to install/upgrade. + +This manpage only covers options unique to Yay. For other options see +\fBpacman(8)\fR. + +.SH YAY OPERATIONS +.TP +.B \-Y, \-\-yay +Perform yay specific operations. This is the default if no other operation is +selected. + +.TP +.B \-P, \-\-print +Perform yay specific print operations. + +.TP +.B \-G, \-\-getpkgbuild +Downloads PKGBUILD from ABS or AUR. + .RE -.PP -\fB\-P, \-\-print\fR -.RS 4 -Perform yay specific print operations\&. -.RE -.PP -\fB\-G, \-\-getpkgbuild\fR -.RS 4 -Downloads PKGBUILD from ABS or AUR\&. -.RE -.PP -If no arguments are provided 'yay \-Syu' will be performed\&. -.RE -.PP -If no operation is selected \-Y will be assumed\&. -.SH "EXTENDED PACMAN OPERATIONS" -.PP -\fB\-S, \-Si, \-Ss, \-Su, \-Sc, \-Qu\fR -.RS 4 -These operations are extended to support both AUR and repo packages\&. -.RE -.PP -\fB\-Sc\fR -.RS 4 +If no arguments are provided 'yay \-Syu' will be performed. + +If no operation is selected \-Y will be assumed. + +.SH EXTENDED PACMAN OPERATIONS +.TP +.B \-S, \-Si, \-Ss, \-Su, \-Sc, \-Qu +These operations are extended to support both AUR and repo packages. + +.TP +.B \-Sc Yay will also clean cached AUR package and any untracked Files in the -cache\&. Untracked files cleaning only works for packages downloaded -using gitclone\&. Cleaning untracked files will wipe any downloaded -sources or built packages but will keep already downloaded vcs sources\&. -.RE -.PP -\fB\-R\fR -.RS 4 -Yay will also remove cached data about devel packages\&. -.RE -.SH "NEW OPTIONS" -.PP -\fB \-\-repo\fR -.RS 4 -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\&. Additionally Actions such as -sysupgrade will only act on AUR packages\&. +cache. Untracked files cleaning only works for packages downloaded +using gitclone. Cleaning untracked files will wipe any downloaded +sources or built packages but will keep already downloaded vcs sources. + +.TP +.B \-R +Yay will also remove cached data about devel packages. + +.SH NEW OPTIONS +.TP +.B \-\-repo +Assume all targets are from the repositories. Additionally Actions such as +sysupgrade will only act on repository packages. + +.TP +.B \-a, \-\-aur +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 -packages\&. -.RE -.SH "YAY OPTIONS (APPLY TO \-Y AND \-\-YAY)" -.PP -\fB\fR -.RS 4 +packages. + +.SH YAY OPTIONS (APPLY TO \-Y AND \-\-YAY) + +.TP +.B Displays a list of packages matching the search terms and prompts the user on -which packages to install (yogurt mode)\&. -.RE -.PP -\fB \-\-gendb\fR -.RS 4 -Generate development package database\&. Tracks the latest commit for each -development package, when there is a new commit Yay will know to update\&. This +which packages to install (yogurt mode). + +.TP +.B \-\-gendb +Generate development package database. Tracks the latest commit for each +development package, when there is a new commit Yay will know to update. This is done per package whenever a package is synced. This option should only be used when migrating to Yay from another AUR helper. -.RE -.PP -\fB\-c \-\-clean\fR -.RS 4 -Remove unneeded dependencies\&. -.RE -.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 -and is not intended to be used directly by the user\&. -.RE -.PP -\fB\-f \-\-fish\fR -.RS 4 -During complete adjust the output for the fish shell\&. -.RE -.PP -\fB\-d \-\-defaultconfig\fR -.RS 4 -Print default yay configuration\&. -.RE -.PP -\fB\-g \-\-config\fR -.RS 4 -Print current yay configuration\&. -.RE -.PP -\fB\-n \-\-numberupgrades\fR -.RS 4 + +.TP +.B \-c, \-\-clean +Remove unneeded dependencies. + +.SH PRINT OPTIONS (APPLY TO \-P AND \-\-PRINT) +.TP +.B \-c, \-\-complete +Print a list of all AUR and repo packages. This is to allow shell completion +and is not intended to be used directly by the user. + +.TP +.B \-f, \-\-fish +During complete adjust the output for the fish shell. + +.TP +.B \-d, \-\-defaultconfig +Print default yay configuration. + +.TP +.B \-g, \-\-config +Print current yay configuration. + +.TP +.B \-n, \-\-numberupgrades Deprecated, use \fByay -Qu\fR and \fBwc -l\fR instead\%. -.RE -.PP -\fB\-s \-\-stats\fR -.RS 4 -Displays information about installed packages and system health\&. If there are + +.TP +.B \-s, \-\-stats +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 -be displayed\&. -.RE -.PP -\fB\-u \-\-upgrades\fR -.RS 4 +be displayed. + +.TP +.B \-u, \-\-upgrades Deprecated, use \fByay -Qu\fR instead\%. -.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 -available news\&. -.RE -.PP -\fB\-q \-\-quiet\fR -.RS 4 -Only show titles when printing news\&. -.RE -.PP -.SH "PERMANENT CONFIGURATION SETTINGS" -.PP -\fB\-\-save\fR -.RS 4 -Causes the following options to be saved back to the config file\&. This + +.TP +.B \-w, \-\-news +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 +available news. + +.TP +.B \-q, \-\-quiet +Only show titles when printing news. + +.SH PERMANENT CONFIGURATION SETTINGS +.TP +.B \-\-save +Causes the following options to be saved back to the config file. This provides an easy way to change config options without directly editing the -file\&. -.RE -.PP -\fB\-\-builddir \fR -.RS 4 -Directory to use for Building AUR Packages\&. This directory is also used as -the AUR cache when deciding if Yay should should skip builds\&. -.RE -.PP -\fB\-\-editor \fR -.RS 4 -Editor to use when editing PKGBUILDs\&. If this is not set the \fBEDITOR\fR -environment variable will be checked, followed by \fBVISUAL\fR\&. If none of -these are set Yay will prompt the user for an editor\&. -.RE -.PP -\fB\-\-editorflags \fR -.RS 4 -Passes arguments to the editor\&. These flags get passed to every instance where +file. + +.TP +.B \-\-builddir +Directory to use for Building AUR Packages. This directory is also used as +the AUR cache when deciding if Yay should should skip builds. + +.TP +.B \-\-editor +Editor to use when editing PKGBUILDs. If this is not set the \fBEDITOR\fR +environment variable will be checked, followed by \fBVISUAL\fR. If none of +these are set Yay will prompt the user for an editor. + +.TP +.B \-\-editorflags +Passes arguments to the editor. These flags get passed to every instance where the editor is called by Yay. Arguments are split on whitespace before being passed to gpg. Multiple arguments may be passed by supplying a space separated list that is quoted by the shell. -.RE -.PP -\fB\-\-makepkg \fR -.RS 4 -The command to use for \fBmakepkg\fR calls. This can be a command in -\fBPATH\fR or an absolute path to the file\&. -.RE -.PP -\fB\-\-pacman \fR -.RS 4 -The command to use for \fBpacman\fR calls. This can be a command in -\fBPATH\fR or an absolute path to the file\&. -.RE -.PP -\fB\-\-tar \fR -.RS 4 -The command to use for \fBbsdtar\fR calls. This can be a command in -\fBPATH\fR or an absolute path to the file\&. -.RE -.PP -\fB\-\-git \fR -.RS 4 -The command to use for \fBgit\fR calls. This can be a command in -\fBPATH\fR or an absolute path to the file\&. -.RE -.PP -\fB\-\-gpg \fR -.RS 4 -The command to use for \fBgpg\fR calls. This can be a command in -\fBPATH\fR or an absolute path to the file\&. -.RE -.PP -\fB\-\-config \fR -.RS 4 -The pacman config file to use\&. -.RE -.PP -\fB\-\-makepkgconf \fR -.RS 4 -The config file for makepkg to use\%. If this is not set then the default -config file will be used\&. -.RE -.PP -\fB\-\-nomakepkgconf\fR -.RS 4 -Reset the makepkg config file back to its default\&. -.RE -.PP -\fB\-\-requestsplitn \fR -.RS 4 -The maximum amount of packages to request per AUR query\&. The higher the -number the faster AUR requests will be\&. Requesting too many packages in one -AUR query will cause an error\&. This should only make a noticeable difference -with very large requests (>500) packages\&. -.RE -.PP -\fB\-\-completioninterval \fR -.RS 4 -Time in days to refresh the completion cache\&. Setting this to 0 will cause -the cache to be refreshed every time, while setting this to -1 will cause the -cache to never be refreshed\&. -.RE -.PP -\fB\-\-sortby \fR -.RS 4 -Sort AUR results by a specific field during search\&. -.RE -.PP -\fB\-\-answerclean \fR -.RS 4 -Set a predetermined answer for the clean build 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\-\-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 -will be used instead of reading from standard input but will be treated exactly -the same when parsed\&. -.RE -.PP -\fB\-\-answerupgrade\fR -.RS 4 -Set a predetermined answer for the upgrade menu question\&. Selects which package -ranges or repos to omit for updades\&. This answer will be used instead of -reading from standard input but will be treated exactly the same\&. -.RE -.PP -\fB\-\-noanswerclean\fR -.RS 4 -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\&. -.RE -.PP -\fB\-\-noanswerupgrade\fR -.RS 4 -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\-\-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\&. +.TP +.B \-\-makepkg +The command to use for \fBmakepkg\fR calls. This can be a command in +\fBPATH\fR or an absolute path to the file. + +.TP +.B \-\-pacman +The command to use for \fBpacman\fR calls. This can be a command in +\fBPATH\fR or an absolute path to the file. + +.TP +.B \-\-tar +The command to use for \fBbsdtar\fR calls. This can be a command in +\fBPATH\fR or an absolute path to the file. + +.TP +.B \-\-git +The command to use for \fBgit\fR calls. This can be a command in +\fBPATH\fR or an absolute path to the file. + +.TP +.B \-\-gpg +The command to use for \fBgpg\fR calls. This can be a command in +\fBPATH\fR or an absolute path to the file. + +.TP +.B \-\-config +The pacman config file to use. + +.TP +.B \-\-makepkgconf +The config file for makepkg to use\%. If this is not set then the default +config file will be used. + +.TP +.B \-\-nomakepkgconf +Reset the makepkg config file back to its default. + +.TP +.B \-\-requestsplitn +The maximum amount of packages to request per AUR query. The higher the +number the faster AUR requests will be. Requesting too many packages in one +AUR query will cause an error. This should only make a noticeable difference +with very large requests (>500) packages. + +.TP +.B \-\-completioninterval +Time in days to refresh the completion cache. Setting this to 0 will cause +the cache to be refreshed every time, while setting this to -1 will cause the +cache to never be refreshed. + +.TP +.B \-\-sortby +Sort AUR results by a specific field during search. + +.TP +.B \-\-answerclean +Set a predetermined answer for the clean build menu question. This answer +will be used instead of reading from standard input but will be treated exactly +the same when parsed. + +.TP +.B \-\-answerdiff +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. + +.TP +.B \-\-answeredit +Set a predetermined answer for the edit pkgbuild menu question. This answer +will be used instead of reading from standard input but will be treated exactly +the same when parsed. + +.TP +.B \-\-answerupgrade +Set a predetermined answer for the upgrade menu question. Selects which package +ranges or repos to omit for updades. This answer will be used instead of +reading from standard input but will be treated exactly the same. + +.TP +.B \-\-noanswerclean +Unset the answer for the clean build menu. + +.TP +.B \-\-noanswerdiff +Unset the answer for the diff menu. + +.TP +.B \-\-noansweredit +Unset the answer for the edit pkgbuild menu. + +.TP +.B \-\-noanswerupgrade +Unset the answer for the upgrade menu. + +.TP +.B \-\-cleanmenu +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. + +.TP +.B \-\-diffmenu +Show the diff menu. This menu gives you the option to view diffs from +build files before building. + +.TP +.B \-\-editmenu +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. + +.TP +.B \-\-upgrademenu +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\&. -.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\-\-noupgrademenu\fR -.RS 4 -Do not show the upgrade menu\&. -.RE -.PP -\fB\-\-askremovemake\fR -.RS 4 -Ask to remove makedepends after installing packages\&. -.RE -.PP -\fB\-\-removemake\fR -.RS 4 -Remove makedepends after installing packages\&. -.RE -.PP -\fB\-\-noremovemake\fR -.RS 4 -Do not remove makedepends after installing packages\&. -.RE -.PP -\fB\-\-topdown\fR -.RS 4 -Display repository packages first and then AUR packages\&. -.RE -.PP -\fB\-\-bottomup\fR -.RS 4 -Show AUR packages first and then repository packages\&. -.RE -.PP -\fB\-\-devel\fR -.RS 4 -During sysupgrade also check AUR development packages for updates\&. Currently -only GitHub packages are supported\&. -.RE -.PP -\fB\-\-nodevel\fR -.RS 4 -Do not check for development packages updates during sysupgrade\&. -.RE -.PP -\fB\-\-gitclone\fR -.RS 4 -Use git to download and update PKGBUILDs\&. PKGBUILDs previously downloaded +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. + +.TP +.B \-\-nocleanmenu +Do not show the clean menu. + +.TP +.B \-\-nodiffmenu +Do not show the diff menu. + +.TP +.B \-\-noeditmenu +Do not show the edit menu. + +.TP +.B \-\-noupgrademenu +Do not show the upgrade menu. + +.TP +.B \-\-askremovemake +Ask to remove makedepends after installing packages. + +.TP +.B \-\-removemake +Remove makedepends after installing packages. + +.TP +.B \-\-noremovemake +Do not remove makedepends after installing packages. + +.TP +.B \-\-topdown +Display repository packages first and then AUR packages. + +.TP +.B \-\-bottomup +Show AUR packages first and then repository packages. + +.TP +.B \-\-devel +During sysupgrade also check AUR development packages for updates. Currently +only GitHub packages are supported. + +.TP +.B \-\-nodevel +Do not check for development packages updates during sysupgrade. + +.TP +.B \-\-gitclone +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.\&. -.RE -.PP -\fB\-\-nogitclone\fR -.RS 4 -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\&. -.RE -.PP -\fB\-\-noafterclean\fR -.RS 4 -Do not remove package sources after successful Install\&. -.RE -.PP -\fB\-\-timeupdate\fR -.RS 4 +built. Similarly, PKGBUILDs managed with git will continue to use git until +the package is clean built.. + +.TP +.B \-\-nogitclone +Download and update PKGBUILDs using tarballs. The above conditions about +previously installed packages still apply. + +.TP +.B \-\-showdiffs +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. + +.TP +.B \-\-noshowdiffs +Show diffs for build files. Files will be opened by the editor\%. + +.TP +.B \-\-afterclean +Remove package sources after successful Install. + +.TP +.B \-\-noafterclean +Do not remove package sources after successful Install. + +.TP +.B \-\-timeupdate During sysupgrade also compare the build time of installed packages against -the last modification time of each package's AUR page\&. -.RE -.PP -\fB\-\-notimeupdate\fR -.RS 4 -Do not consider build times during sysupgrade\&. -.RE -.PP -\fB\-\-redownload\fR -.RS 4 -Always download pkgbuilds of targets even when a copy is available in cache\&. -.RE -.PP -\fB\-\-redownloadall\fR -.RS 4 +the last modification time of each package's AUR page. + +.TP +.B \-\-notimeupdate +Do not consider build times during sysupgrade. + +.TP +.B \-\-redownload +Always download pkgbuilds of targets even when a copy is available in cache. + +.TP +.B \-\-redownloadall Always download pkgbuilds of all AUR packages even when a copy is available -in cache\&. -.RE -.PP -\fB\-\-noredownload\fR -.RS 4 +in cache. + +.TP +.B \-\-noredownload 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 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 appear\&. -.RE -.PP -\fB\-\-pgpfetch\fR -.RS 4 +newer than the AUR's version use that instead of downloading a new one. + +.TP +.B \-\-provides +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 noticeable. + +.TP +.B \-\-noprovides +Do not look for matching providers when searching for AUR packages. If +multiple providers happen to be found the menu will still appear. + +.TP +.B \-\-pgpfetch Prompt to import unknown PGP keys from the \fBvalidpgpkeys\fR field of each PKGBUILD. -.RE -.PP -\fB\-\-nopgpfetch\fR -.RS 4 -Do not prompt to import unknown PGP keys\&. This is likley to cause a build + +.TP +.B \-\-nopgpfetch +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\-\-useask\fR -.RS 4 -Use pacman's --ask flag to automatically confirm package conflicts\&. Yay lists -conflicts ahead of time\&. It is possible thay Yay does not detect -a conflict\&. Causing a package to be removed without the user's confimation\&. -Although this is very unlikley\&. -.RE -.PP -\fB\-\-nouseask\fR -.RS 4 -Manually resolve package conflicts during the install. Packages which do not -conflict will not need to be confimed manually\&. -.RE -.PP -\fB\-\-combinedupgrade\fR -.RS 4 -During sysupgrade, Yay will first perform a refresh, then show -its combined menu of repo and AUR packages that will be upgraded\&. Then after -reviewing the pkgbuilds, the repo and AUR upgrade will start with no need -for manual intervention\&. -If Yay exits for any reason After the refresh without upgrading\&. It is then +.TP +.B \-\-useask +Use pacman's --ask flag to automatically confirm package conflicts. Yay lists +conflicts ahead of time. It is possible thay Yay does not detect +a conflict. Causing a package to be removed without the user's confimation. +Although this is very unlikley. + +.TP +.B \-\-nouseask +Manually resolve package conflicts during the install. Packages which do not +conflict will not need to be confimed manually. + +.TP +.B \-\-combinedupgrade +During sysupgrade, Yay will first perform a refresh, then show +its combined menu of repo and AUR packages that will be upgraded. Then after +reviewing the pkgbuilds, the repo and AUR upgrade will start with no need +for manual intervention. + +If Yay exits for any reason After the refresh without upgrading. It is then the user's responsibility to either resolve the reason Yay exited or run -a sysupgrade through pacman directly\&. -.RE -.PP -\fB\-\-nocombinedupgrade\fR -.RS 4 +a sysupgrade through pacman directly. + +.TP +.B \-\-nocombinedupgrade During sysupgrade, Pacman \-Syu will be called, then the AUR upgrade will -start\&. This means the upgrade menu and pkgbuild review will be performed -after the sysupgrade has finished\&. -.RE -.PP -\fB\-\-rebuild\fR -.RS 4 -Always build target packages even when a copy is available in cache\&. -.RE -.PP -\fB\-\-rebuildall\fR -.RS 4 +start. This means the upgrade menu and pkgbuild review will be performed +after the sysupgrade has finished. + +.TP +.B \-\-rebuild +Always build target packages even when a copy is available in cache. + +.TP +.B \-\-rebuildall Always build all AUR packages even when a copy is available -in cache\&. -.RE -.PP -\fB\-\-rebuildtree\fR -.RS 4 +in cache. + +.TP +.B \-\-rebuildtree When installing an AUR package rebuild and reinstall all of its AUR dependencies recursivley, even the ones already installed. This flag allows you to easily rebuild packages against your current system's libraries if they have become incompatible. -.RE -.PP -\fB\-\-norebuild\fR -.RS 4 + +.TP +.B \-\-norebuild When building packages if the package is found in cache and is an equal version -to the one wanted skip the package build and use the existing package\&. -.RE -.PP -\fB\-\-mflags \fR -.RS 4 -Passes arguments to makepkg\&. These flags get passed to every instance where +to the one wanted skip the package build and use the existing package. + +.TP +.B \-\-mflags +Passes arguments to makepkg. These flags get passed to every instance where makepkg is called by Yay. Arguments are split on whitespace before being passed to makepkg. Multiple arguments may be passed by supplying a space separated list that is quoted by the shell. -.RE -.PP -\fB\-\-gpgflags \fR -.RS 4 -Passes arguments to gpg\&. These flags get passed to every instance where + +.TP +.B \-\-gpgflags +Passes arguments to gpg. These flags get passed to every instance where gpg is called by Yay. Arguments are split on whitespace before being passed to gpg. Multiple arguments may be passed by supplying a space separated list that is quoted by the shell. -.RE -.PP -\fB\-\-sudoloop\fR -.RS 4 + +.TP +.B \-\-sudoloop Loop sudo calls in the background to prevent sudo from timing out during long -builds\&. -.RE -.PP -\fB\-\-nosudoloop\fR -.RS 4 -Do not loop sudo calls in the background\&. -.RE -.SH "EXAMPLES" -.PP +builds. + +.TP +.B \-\-nosudoloop +Do not loop sudo calls in the background. + +.SH EXAMPLES +.TP yay \fIfoo\fR -.RS 4 -Search and install from the repos and the \fBAUR\fR\ using yogurt mode\&. -.RE -.PP +Search and install from the repos and the \fBAUR\fR\ using yogurt mode. + +.TP yay \-Syu -.RS 4 -Update package list and upgrade all currently installed repo and \fBAUR\fR\&. -.RE -.PP +Update package list and upgrade all currently installed repo and \fBAUR\fR. + +.TP yay \-S \fIfoo\fR -.RS 4 -Installs package \fIfoo\fR from the repos or the \fBAUR\fR\&. -.RE -.PP +Installs package \fIfoo\fR from the repos or the \fBAUR\fR. + +.TP yay \-Ss \fIfoo\fR -.RS 4 -Searches for package \fIfoo\fR on the repos or the \fBAUR\fR\&. -.RE -.PP +Searches for package \fIfoo\fR on the repos or the \fBAUR\fR. + +.TP yay \-Si \fIfoo\fR -.RS 4 -Gets information about package \fIfoo\fR from the repos or the \fBAUR\fR\&. -.RE -.PP +Gets information about package \fIfoo\fR from the repos or the \fBAUR\fR. + +.TP yay \-S \fIfoo\fR \-\-mflags "\-\-skipchecksums \-\-skippgpcheck" -.RS 4 -Installs \fIfoo\fR while skipping checksums and pgp checks\&. -.RE -.PP +Installs \fIfoo\fR while skipping checksums and pgp checks. + +.TP yay \-\-devel \-\-save -.RS 4 -Sets devel to true in the config\&. -.RE -.PP +Sets devel to true in the config. + +.TP yay \-P \-\-stats -.RS 4 -Shows statistics for installed packages and system health\&. -.RE -.SH "FILES" -.sp -\fBCONFIG DIRECTORY\fR -.RS 4 -The config directory is \fI$XDG_CONFIG_HOME/yay/\fR\&. if +Shows statistics for installed packages and system health. + +.SH FILES +.TP +.B CONFIG DIRECTORY +The config directory is \fI$XDG_CONFIG_HOME/yay/\fR. if \fB$XDG_CONFIG_HOME\fR is unset, the config directory will fall back to -\fI$HOME/.config/yay\fR\&. -.PP -\fIconfig.json\fR\& Is used to store all of Yay's config options\&. Editing +\fI$HOME/.config/yay\fR. + +\fIconfig.json\fR Is used to store all of Yay's config options. Editing this file should be done through Yay, using the options -mentioned in \fBPERMANENT CONFIGURATION SETTINGS\fR\&. -.RE -.PP -\fBCACHE DIRECTORY\fR -.RS 4 -The cache directory is \fI$XDG_CACHE_HOME/yay/\fR\&. if +mentioned in \fBPERMANENT CONFIGURATION SETTINGS\fR. + +.TP +.B CACHE DIRECTORY +The cache directory is \fI$XDG_CACHE_HOME/yay/\fR. if \fB$XDG_CACHE_HOME\fR is unset, the cache directory will fall back to -\fI$HOME/.cache/yay\fR\&. -.PP +\fI$HOME/.cache/yay\fR. + \fIcompletion.cache\fR holds a list of of all packages, including the AUR, -for shell completion\&. By default the completion files are refreshed every -7 days\&. -.PP +for shell completion. By default the completion files are refreshed every +7 days. + \fIvcs.json\fR tracks VCS packages and the latest commit of each source. If any of these commits change the package will be upgraded during a devel update. -.RE -.PP -\fBBUILD DIRECTORY\fR -.RS 4 + +.TP +.B BUILD DIRECTORY Unless otherwise set this should be the same as \fBCACHE DIRECTORY\fR. This directory is used to store downloaded AUR Packages as well as any source files -and built packages from those packages\&. -.RE -.PP -\fBPACMAN.CONF\fR -.RS 4 +and built packages from those packages. + +.TP +.B PACMAN.CONF 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 -pacman options\&. -.PP -Notably \fBDatabases\fR, \fBColor\fR and \fB*Path/*Dir\fR options are used\&. -.RE -.PP -.SH "SEE ALSO" -.sp -\fBmakepkg\fR(8) -\fBPKGBUILD\fR(5) -\fBpacman\fR(8) -\fBpacman\&.conf\fR(5) -.PP -See the arch wiki at https://wiki\&.archlinux\&.org/index\&.php/Arch_User_Repository for more info on the \fBAUR\fR\&. -.SH "BUGS" -.PP -Please report bugs to our GitHub page https://github\&.com/Jguer/yay -.SH "AUTHORS" -.sp -Jguer +pacman options. + +Notably: \fBDatabases\fR, \fBColor\fR and \fB*Path/*Dir\fR options are used. + +.SH SEE ALSO +.BR makepkg (8), +.BR makepkg.conf (5), +.BR PKGBUILD (5), +.BR pacman (8), +.BR pacman.conf (5) + +See the arch wiki at https://wiki.archlinux.org/index.php/Arch_User_Repository for more info on the \fBAUR\fR. + +.SH BUGS +Please report bugs to our GitHub page https://github.com/Jguer/yay + +.SH AUTHORS +Jguer .br -Morgana +Anna From 6fe17ad0c18680db6d376b94f5861ffd385a7cfe Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 28 Jul 2018 13:40:07 +0100 Subject: [PATCH 066/155] Update usage --- cmd.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index 526a0922..3cb3ef82 100644 --- a/cmd.go +++ b/cmd.go @@ -40,7 +40,7 @@ Permanent configuration options: --save Causes the following options to be saved back to the config file when used - --builddir Directory to use for building AUR Packages + --builddir Directory used to download and run PKBUILDS --editor Editor to use when editing PKGBUILDs --editorflags Pass arguments to editor --makepkg makepkg command to use @@ -52,8 +52,11 @@ Permanent configuration options: --gpg gpg command to use --gpgflags Pass arguments to gpg --config pacman.conf file to use + --makepkgconf makepkg.conf file to use + --nomakepkgconf Use the default makepkg.conf --requestsplitn Max amount of packages to query per AUR request + --completioninterval Time in days to to refresh completion cache --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 @@ -71,6 +74,9 @@ Permanent configuration options: --nodiffmenu Don't show diffs for build files --noeditmenu Don't edit/view PKGBUILDS --noupgrademenu Don't show the upgrade menu + --askremovemake Ask to remove makedepends after install + --removemake Remove makedepends after install + --noremovemake Don't remove makedepends after install --afterclean Remove package sources after successful install --noafterclean Do not remove package sources after successful build From 0503753185104daa34e8165ec250c0f524ce4eb4 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 29 Jul 2018 15:39:13 +0100 Subject: [PATCH 067/155] Remove --[no]showdiffs and merge the text --- doc/yay.8 | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index dde5a504..a67bec60 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -258,6 +258,10 @@ downloaded build files from Yay's cache before redownloing a fresh copy. Show the diff menu. This menu gives you the option to view diffs from build files before building. +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. + .TP .B \-\-editmenu Show the edit menu. This menu gives you the option to edit or view PKGBUILDs @@ -334,16 +338,6 @@ the package is clean built.. Download and update PKGBUILDs using tarballs. The above conditions about previously installed packages still apply. -.TP -.B \-\-showdiffs -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. - -.TP -.B \-\-noshowdiffs -Show diffs for build files. Files will be opened by the editor\%. - .TP .B \-\-afterclean Remove package sources after successful Install. From 2a60dd7052cdeff93a1dfcd025e7438d9d9b3271 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 30 Jul 2018 14:14:16 +0100 Subject: [PATCH 068/155] Remove unneeded variables --- cmd.go | 9 ++++----- download.go | 2 +- install.go | 28 ++++++++++++++-------------- upgrade.go | 7 +++---- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/cmd.go b/cmd.go index 526a0922..29fd9aab 100644 --- a/cmd.go +++ b/cmd.go @@ -392,10 +392,8 @@ func handleGetpkgbuild() (err error) { } func handleYogurt() (err error) { - options := cmdArgs.formatArgs() - config.SearchMode = NumberMenu - err = numberMenu(cmdArgs.targets, options) + err = numberMenu(cmdArgs.targets) return } @@ -439,7 +437,7 @@ func handleRemove() (err error) { } // NumberMenu presents a CLI for selecting packages to install. -func numberMenu(pkgS []string, flags []string) (err error) { +func numberMenu(pkgS []string) (err error) { pkgS = removeInvalidTargets(pkgS) var aurErr error var repoErr error @@ -532,7 +530,8 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(arguments.targets) == 0 { - return fmt.Errorf("There is nothing to do") + fmt.Println("There is nothing to do") + return nil } if config.SudoLoop { diff --git a/download.go b/download.go index 0f6a9281..acd6fe77 100644 --- a/download.go +++ b/download.go @@ -78,7 +78,7 @@ func gitDownload(url string, path string, name string) (bool, error) { return false, nil } -func gitMerge(url string, path string, name string) error { +func gitMerge(path string, name string) error { err := show(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 ed068ecd..7fe0fbd2 100644 --- a/install.go +++ b/install.go @@ -179,7 +179,7 @@ func install(parser *arguments) error { if config.CleanMenu { askClean := pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) - toClean, err := cleanNumberMenu(do.Aur, do.Bases, remoteNamesCache, askClean) + toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean) if err != nil { return err } @@ -198,7 +198,7 @@ func install(parser *arguments) error { if config.DiffMenu { pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) - toDiff, err = diffNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache) if err != nil { return err } @@ -234,13 +234,13 @@ func install(parser *arguments) error { if config.EditMenu { pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) - toEdit, err = editNumberMenu(do.Aur, do.Bases, remoteNamesCache) + toEdit, err = editNumberMenu(do.Aur, remoteNamesCache) if err != nil { return err } if len(toEdit) > 0 { - err = editPkgBuilds(toEdit, srcinfosStale, do.Bases) + err = editPkgBuilds(toEdit, srcinfosStale) if err != nil { return err } @@ -257,7 +257,7 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - incompatible, err = getIncompatible(do.Aur, srcinfosStale, do.Bases) + incompatible, err = getIncompatible(do.Aur, srcinfosStale) if err != nil { return err } @@ -418,7 +418,7 @@ func earlyRefresh(parser *arguments) error { return show(passToPacman(arguments)) } -func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) (stringSet, error) { +func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) (stringSet, error) { incompatible := make(stringSet) alpmArch, err := alpmHandle.Arch() if err != nil { @@ -513,7 +513,7 @@ func pkgbuildNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed return askClean } -func cleanNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet, hasClean bool) ([]*rpc.Pkg, error) { +func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rpc.Pkg, error) { toClean := make([]*rpc.Pkg, 0) if !hasClean { @@ -576,15 +576,15 @@ func cleanNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed str 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 editNumberMenu(pkgs []*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { + return editDiffNumberMenu(pkgs, installed, false) } -func diffNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { - return editDiffNumberMenu(pkgs, bases, installed, true) +func diffNumberMenu(pkgs []*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { + return editDiffNumberMenu(pkgs, installed, true) } -func editDiffNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet, diff bool) ([]*rpc.Pkg, error) { +func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc.Pkg, error) { toEdit := make([]*rpc.Pkg, 0) var editInput string var err error @@ -702,7 +702,7 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri return nil } -func editPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) error { +func editPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) error { pkgbuilds := make([]string, 0, len(pkgs)) for _, pkg := range pkgs { dir := filepath.Join(config.BuildDir, pkg.PackageBase) @@ -786,7 +786,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(config.BuildDir, pkg.PackageBase) if err != nil { return err } diff --git a/upgrade.go b/upgrade.go index 71fa8df5..e3bfc958 100644 --- a/upgrade.go +++ b/upgrade.go @@ -120,7 +120,6 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { var repoErr error var aurErr error - var develErr error pkgdata := make(map[string]*rpc.Pkg) @@ -145,7 +144,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { fmt.Println(bold(cyan("::") + bold(" Checking development packages..."))) wg.Add(1) go func() { - develUp, develErr = upDevel(remote) + develUp = upDevel(remote) wg.Done() }() } @@ -156,7 +155,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { printLocalNewerThanAUR(remote, pkgdata) errs := make([]string, 0) - for _, e := range []error{repoErr, aurErr, develErr} { + for _, e := range []error{repoErr, aurErr} { if e != nil { errs = append(errs, e.Error()) } @@ -184,7 +183,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { return aurUp, repoUp, err } -func upDevel(remote []alpm.Package) (toUpgrade upSlice, err error) { +func upDevel(remote []alpm.Package) (toUpgrade upSlice) { toUpdate := make([]alpm.Package, 0) toRemove := make([]string, 0) From f9d8d61524081bd426207fdd6f5a0f80f3fd941a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 30 Jul 2018 14:21:49 +0100 Subject: [PATCH 069/155] Upbade bash completions --- completions/bash | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/completions/bash b/completions/bash index 45c92c76..55fb095f 100644 --- a/completions/bash +++ b/completions/bash @@ -77,7 +77,8 @@ _yay() { sortby answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff noansweredit noanswerupgrade cleanmenu diffmenu editmenu upgrademenu nocleanmenu nodiffmenu noupgrademenu provides noprovides pgpfetch nopgpfetch - useask nouseask combinedupgrade nocombinedupgrade root verbose aur repo' + useask nouseask combinedupgrade nocombinedupgrade root verbose aur repo makepkgconf + nomakepkgconf askremovemake removemake noremovemake completioninterval' 'a b d h q r v') core=('database files help query remove sync upgrade version' 'D F Q R S U V h') From 05587c3a1cc784f04a8981ea31f991cb7049c93d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 30 Jul 2018 14:28:14 +0100 Subject: [PATCH 070/155] Update zsh completion --- completions/zsh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/completions/zsh b/completions/zsh index 0ccbc406..8d005f44 100644 --- a/completions/zsh +++ b/completions/zsh @@ -33,6 +33,10 @@ _pacman_opts_common=( {-v,--verbose}'[Be more verbose]' '--cachedir[Alternate package cache location]:cache_location:_files -/' '--config[An alternate configuration file]:config file:_files' + '--makepkgconf[makepkg.conf file to use]:config file:_files' + '--nomakepkgconf[Use the default makepkg.conf]' + '--requestsplitn[Max amount of packages to query per AUR request]:number' + '--completioninterval[Time in days to to refresh completion cache]:number' '--confirm[Always ask for confirmation]' '--debug[Display debug messages]' '--gpgdir[Set an alternate directory for GnuPG (instead of /etc/pacman.d/gnupg)]: :_files -/' @@ -68,6 +72,9 @@ _pacman_opts_common=( "--nodiffmenu[Don't show diffs for build files]" "--noeditmenu[Don't edit/view PKGBUILDS]" "--noupgrademenu[Don't show the upgrade menu]" + "--askremovemake[Ask to remove makedepends after install]" + "--removemake[Remove makedepends after install]" + "--noremovemake[Don't remove makedepends after install]" '--bottomup[Show AUR packages first]' '--topdown[Show repository packages first]' From 29f3e011eca4063635d4182a609f5e3b404a4e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=2E=20R=C3=B8dseth?= Date: Tue, 31 Jul 2018 10:42:17 +0200 Subject: [PATCH 071/155] Only minor changes --- callbacks.go | 117 +++++++++++++++++----------------- clean.go | 24 +++---- cmd.go | 127 +++++++++++++++++-------------------- config.go | 2 +- main.go | 176 ++++++++++++++++++++------------------------------- 5 files changed, 198 insertions(+), 248 deletions(-) diff --git a/callbacks.go b/callbacks.go index 1b55a0f6..972971a0 100644 --- a/callbacks.go +++ b/callbacks.go @@ -10,78 +10,79 @@ import ( ) func questionCallback(question alpm.QuestionAny) { - qi, err := question.QuestionInstallIgnorepkg() - if err == nil { + if qi, err := question.QuestionInstallIgnorepkg(); err == nil { qi.SetInstall(true) } qp, err := question.QuestionSelectProvider() - if err == nil { - size := 0 + if err != nil { + return + } - qp.Providers(alpmHandle).ForEach(func(pkg alpm.Package) error { - size++ - return nil - }) + size := 0 - fmt.Print(bold(cyan(":: "))) - str := bold(fmt.Sprintf(bold("There are %d providers available for %s:"), size, qp.Dep())) + qp.Providers(alpmHandle).ForEach(func(pkg alpm.Package) error { + size++ + return nil + }) - size = 1 - var db string + fmt.Print(bold(cyan(":: "))) + str := bold(fmt.Sprintf(bold("There are %d providers available for %s:"), size, qp.Dep())) - qp.Providers(alpmHandle).ForEach(func(pkg alpm.Package) error { - thisDb := pkg.DB().Name() + size = 1 + var db string - if db != thisDb { - db = thisDb - str += bold(cyan("\n:: ")) + bold("Repository "+db+"\n ") - } - str += fmt.Sprintf("%d) %s ", size, pkg.Name()) - size++ - return nil - }) + qp.Providers(alpmHandle).ForEach(func(pkg alpm.Package) error { + thisDb := pkg.DB().Name() - fmt.Println(str) + if db != thisDb { + db = thisDb + str += bold(cyan("\n:: ")) + bold("Repository "+db+"\n ") + } + str += fmt.Sprintf("%d) %s ", size, pkg.Name()) + size++ + return nil + }) - for { - fmt.Print("\nEnter a number (default=1): ") + fmt.Println(str) - if config.NoConfirm { - fmt.Println() - break - } + for { + fmt.Print("\nEnter a number (default=1): ") - 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) == "" { - break - } - - 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 - } - - qp.SetUseIndex(num - 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) == "" { + break + } + + 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 + } + + qp.SetUseIndex(num - 1) + break } } diff --git a/clean.go b/clean.go index 49706b1b..f8e743b2 100644 --- a/clean.go +++ b/clean.go @@ -14,8 +14,7 @@ func removeVCSPackage(pkgs []string) { updated := false for _, pkgName := range pkgs { - _, ok := savedInfo[pkgName] - if ok { + if _, ok := savedInfo[pkgName]; ok { delete(savedInfo, pkgName) updated = true } @@ -34,10 +33,10 @@ func cleanDependencies(removeOptional bool) error { } if len(hanging) != 0 { - err = cleanRemove(hanging) + return cleanRemove(hanging) } - return err + return nil } // CleanRemove sends a full removal command to pacman with the pkgName slice @@ -49,8 +48,8 @@ func cleanRemove(pkgNames []string) (err error) { arguments := makeArguments() arguments.addArg("R") arguments.addTarget(pkgNames...) - err = show(passToPacman(arguments)) - return err + + return show(passToPacman(arguments)) } func syncClean(parser *arguments) error { @@ -69,8 +68,7 @@ func syncClean(parser *arguments) error { } if mode == ModeRepo || mode == ModeAny { - err = show(passToPacman(parser)) - if err != nil { + if err = show(passToPacman(parser)); err != nil { return err } } @@ -86,8 +84,7 @@ func syncClean(parser *arguments) error { question = "Do you want to remove all other AUR packages from cache?" } - fmt.Println() - fmt.Printf("Build directory: %s\n", config.BuildDir) + fmt.Printf("\nBuild directory: %s\n", config.BuildDir) if continueTask(question, true) { err = cleanAUR(keepInstalled, keepCurrent, removeAll) @@ -98,10 +95,10 @@ func syncClean(parser *arguments) error { } if continueTask("Do you want to remove ALL untracked AUR files?", true) { - err = cleanUntracked() + return cleanUntracked() } - return err + return nil } func cleanAUR(keepInstalled, keepCurrent, removeAll bool) error { @@ -192,8 +189,7 @@ func cleanUntracked() error { dir := filepath.Join(config.BuildDir, file.Name()) if shouldUseGit(dir) { - err = show(passToGit(dir, "clean", "-fx")) - if err != nil { + if err = show(passToGit(dir, "clean", "-fx")); err != nil { return err } } diff --git a/cmd.go b/cmd.go index cb9eede8..4284813c 100644 --- a/cmd.go +++ b/cmd.go @@ -171,15 +171,10 @@ func handleCmd() (err error) { } func handleQuery() error { - var err error - if cmdArgs.existsArg("u", "upgrades") { - err = printUpdateList(cmdArgs) - } else { - err = show(passToPacman(cmdArgs)) + return printUpdateList(cmdArgs) } - - return err + return show(passToPacman(cmdArgs)) } func handleHelp() error { @@ -187,7 +182,6 @@ func handleHelp() error { usage() return nil } - return show(passToPacman(cmdArgs)) } @@ -289,8 +283,7 @@ func handleConfig(option, value string) bool { case "gpg": config.GpgBin = value case "requestsplitn": - n, err := strconv.Atoi(value) - if err == nil && n > 0 { + if n, err := strconv.Atoi(value); err == nil && n > 0 { config.RequestSplitN = n } case "sudoloop": @@ -340,9 +333,10 @@ func handleConfig(option, value string) bool { case "askremovemake": config.RemoveMake = "ask" default: + // the option was not handled by the switch return false } - + // the option was successfully handled by the switch return true } @@ -373,35 +367,33 @@ func handlePrint() (err error) { default: err = nil } - return err } -func handleYay() (err error) { +func handleYay() error { //_, options, targets := cmdArgs.formatArgs() if cmdArgs.existsArg("gendb") { - err = createDevelDB() - } else if cmdArgs.existsDouble("c") { - err = cleanDependencies(true) - } else if cmdArgs.existsArg("c", "clean") { - err = cleanDependencies(false) - } else if len(cmdArgs.targets) > 0 { - err = handleYogurt() + return createDevelDB() } - - return + if cmdArgs.existsDouble("c") { + return cleanDependencies(true) + } + if cmdArgs.existsArg("c", "clean") { + return cleanDependencies(false) + } + if len(cmdArgs.targets) > 0 { + return handleYogurt() + } + return nil } -func handleGetpkgbuild() (err error) { - err = getPkgbuilds(cmdArgs.targets) - return +func handleGetpkgbuild() error { + return getPkgbuilds(cmdArgs.targets) } -func handleYogurt() (err error) { +func handleYogurt() error { config.SearchMode = NumberMenu - err = numberMenu(cmdArgs.targets) - - return + return numberMenu(cmdArgs.targets) } func handleSync() (err error) { @@ -413,44 +405,50 @@ func handleSync() (err error) { } else { config.SearchMode = Detailed } - - err = syncSearch(targets) - } else if cmdArgs.existsArg("p", "print", "print-format") { - err = show(passToPacman(cmdArgs)) - } else if cmdArgs.existsArg("c", "clean") { - err = syncClean(cmdArgs) - } else if cmdArgs.existsArg("l", "list") { - err = show(passToPacman(cmdArgs)) - } else if cmdArgs.existsArg("g", "groups") { - err = show(passToPacman(cmdArgs)) - } else if cmdArgs.existsArg("i", "info") { - err = syncInfo(targets) - } else if cmdArgs.existsArg("u", "sysupgrade") { - err = install(cmdArgs) - } else if len(cmdArgs.targets) > 0 { - err = install(cmdArgs) - } else if cmdArgs.existsArg("y", "refresh") { - err = show(passToPacman(cmdArgs)) + return syncSearch(targets) } - - return + if cmdArgs.existsArg("p", "print", "print-format") { + return show(passToPacman(cmdArgs)) + } + if cmdArgs.existsArg("c", "clean") { + return syncClean(cmdArgs) + } + if cmdArgs.existsArg("l", "list") { + return show(passToPacman(cmdArgs)) + } + if cmdArgs.existsArg("g", "groups") { + return show(passToPacman(cmdArgs)) + } + if cmdArgs.existsArg("i", "info") { + return syncInfo(targets) + } + if cmdArgs.existsArg("u", "sysupgrade") { + return install(cmdArgs) + } + if len(cmdArgs.targets) > 0 { + return install(cmdArgs) + } + if cmdArgs.existsArg("y", "refresh") { + return show(passToPacman(cmdArgs)) + } + return nil } -func handleRemove() (err error) { +func handleRemove() error { removeVCSPackage(cmdArgs.targets) - err = show(passToPacman(cmdArgs)) - return + return show(passToPacman(cmdArgs)) } // NumberMenu presents a CLI for selecting packages to install. func numberMenu(pkgS []string) (err error) { + var ( + aurErr, repoErr error + aq aurQuery + pq repoQuery + lenaq, lenpq int + ) + 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) @@ -492,12 +490,11 @@ func numberMenu(pkgS []string) (err error) { fmt.Print(bold(green(arrow + " "))) reader := bufio.NewReader(os.Stdin) - numberBuf, overflow, err := reader.ReadLine() + numberBuf, overflow, err := reader.ReadLine() if err != nil { return err } - if overflow { return fmt.Errorf("Input too long") } @@ -513,10 +510,7 @@ func numberMenu(pkgS []string) (err error) { target = i + 1 } - if isInclude && include.get(target) { - arguments.addTarget(pkg.DB().Name() + "/" + pkg.Name()) - } - if !isInclude && !exclude.get(target) { + if (isInclude && include.get(target)) || (!isInclude && !exclude.get(target)) { arguments.addTarget(pkg.DB().Name() + "/" + pkg.Name()) } } @@ -527,10 +521,7 @@ func numberMenu(pkgS []string) (err error) { target = i + 1 + len(pq) } - if isInclude && include.get(target) { - arguments.addTarget("aur/" + pkg.Name) - } - if !isInclude && !exclude.get(target) { + if (isInclude && include.get(target)) || (!isInclude && !exclude.get(target)) { arguments.addTarget("aur/" + pkg.Name) } } diff --git a/config.go b/config.go index cff3e77d..6b84665c 100644 --- a/config.go +++ b/config.go @@ -118,7 +118,7 @@ var alpmConf alpm.PacmanConfig var alpmHandle *alpm.Handle // Mode is used to restrict yay to AUR or repo only modes -var mode targetMode = ModeAny +var mode = ModeAny func readAlpmConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { file, err := os.Open(pacmanconf) diff --git a/main.go b/main.go index 57d5101b..cb49db01 100644 --- a/main.go +++ b/main.go @@ -45,43 +45,43 @@ func setPaths() error { return nil } -func initConfig() (err error) { +func initConfig() error { defaultSettings(&config) - if _, err = os.Stat(configFile); os.IsNotExist(err) { + if _, err := os.Stat(configFile); os.IsNotExist(err) { err = os.MkdirAll(filepath.Dir(configFile), 0755) if err != nil { err = fmt.Errorf("Unable to create config directory:\n%s\n"+ "The error was:\n%s", filepath.Dir(configFile), err) - return + return err } // Save the default config if nothing is found config.saveConfig() - } else { - cfile, errf := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) - if errf != nil { - fmt.Printf("Error reading config: %s\n", err) - } else { - defer cfile.Close() - decoder := json.NewDecoder(cfile) - err = decoder.Decode(&config) - if err != nil { - fmt.Println("Loading default Settings.\nError reading config:", - 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 - } - } + return err + } + + cfile, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + fmt.Printf("Error reading config: %s\n", err) + return err + } + defer cfile.Close() + + decoder := json.NewDecoder(cfile) + if err := decoder.Decode(&config); err != nil { + fmt.Println("Loading default Settings.\nError reading config:", err) + defaultSettings(&config) + return err + } + + if _, err := os.Stat(config.BuildDir); os.IsNotExist(err) { + if err = os.MkdirAll(config.BuildDir, 0755); err != nil { + return fmt.Errorf("Unable to create BuildDir directory:\n%s\n"+ + "The error was:\n%s", config.BuildDir, err) } } - return + return nil } func initVCS() (err error) { @@ -92,22 +92,20 @@ func initVCS() (err error) { "The error was:\n%s", filepath.Dir(configFile), err) return } - } else { - vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) - if err == nil { - defer vfile.Close() - decoder := json.NewDecoder(vfile) - _ = decoder.Decode(&savedInfo) - } + return } - - return + vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) + if err == nil { + defer vfile.Close() + decoder := json.NewDecoder(vfile) + _ = decoder.Decode(&savedInfo) + } + return err } func initAlpm() (err error) { var value string var exists bool - //var double bool alpmConf, err = readAlpmConfig(config.PacmanConf) if err != nil { @@ -171,93 +169,57 @@ func initAlpm() (err error) { return } -func initAlpmHandle() (err error) { +func initAlpmHandle() error { if alpmHandle != nil { - err = alpmHandle.Release() - if err != nil { + if err := alpmHandle.Release(); err != nil { return err } } - - alpmHandle, err = alpmConf.CreateHandle() - if err != nil { - err = fmt.Errorf("Unable to CreateHandle: %s", err) - return + var err error + if alpmHandle, err = alpmConf.CreateHandle(); err != nil { + return fmt.Errorf("Unable to CreateHandle: %s", err) } alpmHandle.SetQuestionCallback(questionCallback) - return + return nil +} + +func cleanup() { + if alpmHandle != nil { + temp := alpmHandle + // set alpmHandle to nil to avoid entering this + // branch of code again, at cleanup time. + alpmHandle = nil + must(temp.Release()) + } +} + +// must outputs the error if there is one, +// then calls cleanup() and ends the program with exit code 1. +// If err == nil, no action is taken. +func must(err error) { + if err != nil { + fmt.Fprintln(os.Stderr, err) + cleanup() + os.Exit(1) + } } func main() { - var status int - var err error - - if 0 == os.Geteuid() { + if os.Geteuid() == 0 { fmt.Println("Please avoid running yay as root/sudo.") } - err = cmdArgs.parseCommandLine() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } + // Ensure release of alpmHandle + defer cleanup() - err = setPaths() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } - - err = initConfig() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } + must(cmdArgs.parseCommandLine()) + must(setPaths()) + must(initConfig()) cmdArgs.extractYayOptions() - err = initVCS() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - - } - - err = initAlpm() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } - - err = handleCmd() - if err != nil { - if err.Error() != "" { - fmt.Println(err) - } - - status = 1 - goto cleanup - } - -cleanup: - //cleanup - //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 - - if alpmHandle != nil { - err = alpmHandle.Release() - if err != nil { - fmt.Println(err) - status = 1 - } - } - - os.Exit(status) + must(initVCS()) + must(initAlpm()) + must(handleCmd()) } From 345fd552f051eb6c5e6f0c34e27fc20b8e0c2d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=2E=20R=C3=B8dseth?= Date: Tue, 31 Jul 2018 13:08:54 +0200 Subject: [PATCH 072/155] Use main.go from the master branch --- main.go | 176 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 107 insertions(+), 69 deletions(-) diff --git a/main.go b/main.go index cb49db01..57d5101b 100644 --- a/main.go +++ b/main.go @@ -45,43 +45,43 @@ func setPaths() error { return nil } -func initConfig() error { +func initConfig() (err error) { defaultSettings(&config) - if _, err := os.Stat(configFile); os.IsNotExist(err) { + if _, err = os.Stat(configFile); os.IsNotExist(err) { err = os.MkdirAll(filepath.Dir(configFile), 0755) if err != nil { err = fmt.Errorf("Unable to create config directory:\n%s\n"+ "The error was:\n%s", filepath.Dir(configFile), err) - return err + return } // Save the default config if nothing is found config.saveConfig() - return err - } - - cfile, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) - if err != nil { - fmt.Printf("Error reading config: %s\n", err) - return err - } - defer cfile.Close() - - decoder := json.NewDecoder(cfile) - if err := decoder.Decode(&config); err != nil { - fmt.Println("Loading default Settings.\nError reading config:", err) - defaultSettings(&config) - return err - } - - if _, err := os.Stat(config.BuildDir); os.IsNotExist(err) { - if err = os.MkdirAll(config.BuildDir, 0755); err != nil { - return fmt.Errorf("Unable to create BuildDir directory:\n%s\n"+ - "The error was:\n%s", config.BuildDir, err) + } else { + cfile, errf := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) + if errf != nil { + fmt.Printf("Error reading config: %s\n", err) + } else { + defer cfile.Close() + decoder := json.NewDecoder(cfile) + err = decoder.Decode(&config) + if err != nil { + fmt.Println("Loading default Settings.\nError reading config:", + 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 + } + } } } - return nil + return } func initVCS() (err error) { @@ -92,20 +92,22 @@ func initVCS() (err error) { "The error was:\n%s", filepath.Dir(configFile), err) return } - return + } else { + vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) + if err == nil { + defer vfile.Close() + decoder := json.NewDecoder(vfile) + _ = decoder.Decode(&savedInfo) + } } - vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) - if err == nil { - defer vfile.Close() - decoder := json.NewDecoder(vfile) - _ = decoder.Decode(&savedInfo) - } - return err + + return } func initAlpm() (err error) { var value string var exists bool + //var double bool alpmConf, err = readAlpmConfig(config.PacmanConf) if err != nil { @@ -169,57 +171,93 @@ func initAlpm() (err error) { return } -func initAlpmHandle() error { +func initAlpmHandle() (err error) { if alpmHandle != nil { - if err := alpmHandle.Release(); err != nil { + err = alpmHandle.Release() + if err != nil { return err } } - var err error - if alpmHandle, err = alpmConf.CreateHandle(); err != nil { - return fmt.Errorf("Unable to CreateHandle: %s", err) + + alpmHandle, err = alpmConf.CreateHandle() + if err != nil { + err = fmt.Errorf("Unable to CreateHandle: %s", err) + return } alpmHandle.SetQuestionCallback(questionCallback) - return nil -} - -func cleanup() { - if alpmHandle != nil { - temp := alpmHandle - // set alpmHandle to nil to avoid entering this - // branch of code again, at cleanup time. - alpmHandle = nil - must(temp.Release()) - } -} - -// must outputs the error if there is one, -// then calls cleanup() and ends the program with exit code 1. -// If err == nil, no action is taken. -func must(err error) { - if err != nil { - fmt.Fprintln(os.Stderr, err) - cleanup() - os.Exit(1) - } + return } func main() { - if os.Geteuid() == 0 { + var status int + var err error + + if 0 == os.Geteuid() { fmt.Println("Please avoid running yay as root/sudo.") } - // Ensure release of alpmHandle - defer cleanup() + err = cmdArgs.parseCommandLine() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + } - must(cmdArgs.parseCommandLine()) - must(setPaths()) - must(initConfig()) + err = setPaths() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + } + + err = initConfig() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + } cmdArgs.extractYayOptions() - must(initVCS()) - must(initAlpm()) - must(handleCmd()) + err = initVCS() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + + } + + err = initAlpm() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + } + + err = handleCmd() + if err != nil { + if err.Error() != "" { + fmt.Println(err) + } + + status = 1 + goto cleanup + } + +cleanup: + //cleanup + //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 + + if alpmHandle != nil { + err = alpmHandle.Release() + if err != nil { + fmt.Println(err) + status = 1 + } + } + + os.Exit(status) } From e9d0b8bee68d28c35789eb99651af9ffc8a25fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=2E=20R=C3=B8dseth?= Date: Tue, 31 Jul 2018 13:10:51 +0200 Subject: [PATCH 073/155] Refactor a named return Ref: https://github.com/Jguer/yay/pull/601/files/29f3e011eca4063635d4182a609f5e3b404a4e7d#diff-0cf3d18277fde705f1a4eb69fddfefc1L407 --- cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd.go b/cmd.go index 4284813c..c0061355 100644 --- a/cmd.go +++ b/cmd.go @@ -396,7 +396,7 @@ func handleYogurt() error { return numberMenu(cmdArgs.targets) } -func handleSync() (err error) { +func handleSync() error { targets := cmdArgs.targets if cmdArgs.existsArg("s", "search") { From 95bcea8f4054600b30d4804daa69926f93676304 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 31 Jul 2018 16:58:49 +0100 Subject: [PATCH 074/155] Ensure devel packages exist when updating --- upgrade.go | 64 +++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/upgrade.go b/upgrade.go index e3bfc958..15537cf9 100644 --- a/upgrade.go +++ b/upgrade.go @@ -121,7 +121,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { var repoErr error var aurErr error - pkgdata := make(map[string]*rpc.Pkg) + aurdata := make(map[string]*rpc.Pkg) if mode == ModeAny || mode == ModeRepo { fmt.Println(bold(cyan("::") + bold(" Searching databases for updates..."))) @@ -134,25 +134,34 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { 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..."))) + var _aurdata []*rpc.Pkg + _aurdata, aurErr = aurInfo(remoteNames, warnings) + if aurErr == nil { + for _, pkg := range _aurdata { + aurdata[pkg.Name] = pkg + } + wg.Add(1) go func() { - develUp = upDevel(remote) + aurUp, aurErr = upAUR(remote, aurdata) wg.Done() }() + + if config.Devel { + fmt.Println(bold(cyan("::") + bold(" Checking development packages..."))) + wg.Add(1) + go func() { + develUp = upDevel(remote, aurdata) + wg.Done() + }() + } } } wg.Wait() - printLocalNewerThanAUR(remote, pkgdata) + printLocalNewerThanAUR(remote, aurdata) errs := make([]string, 0) for _, e := range []error{repoErr, aurErr} { @@ -183,7 +192,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { return aurUp, repoUp, err } -func upDevel(remote []alpm.Package) (toUpgrade upSlice) { +func upDevel(remote []alpm.Package, aurdata map[string]*rpc.Pkg) (toUpgrade upSlice) { toUpdate := make([]alpm.Package, 0) toRemove := make([]string, 0) @@ -195,12 +204,14 @@ func upDevel(remote []alpm.Package) (toUpgrade upSlice) { defer wg.Done() if e.needsUpdate() { - for _, pkg := range remote { - if pkg.Name() == vcsName { - mux1.Lock() - toUpdate = append(toUpdate, pkg) - mux1.Unlock() - return + if _, ok := aurdata[vcsName]; ok { + for _, pkg := range remote { + if pkg.Name() == vcsName { + mux1.Lock() + toUpdate = append(toUpdate, pkg) + mux1.Unlock() + return + } } } @@ -231,22 +242,11 @@ func upDevel(remote []alpm.Package) (toUpgrade upSlice) { // upAUR gathers foreign packages and checks if they have new versions. // Output: Upgrade type package list. -func upAUR( - remote []alpm.Package, remoteNames []string, - pkgdata map[string]*rpc.Pkg, warnings *aurWarnings) (upSlice, error) { - +func upAUR(remote []alpm.Package, aurdata map[string]*rpc.Pkg) (upSlice, error) { toUpgrade := make(upSlice, 0) - _pkgdata, err := aurInfo(remoteNames, warnings) - if err != nil { - return nil, err - } - - for _, pkg := range _pkgdata { - pkgdata[pkg.Name] = pkg - } for _, pkg := range remote { - aurPkg, ok := pkgdata[pkg.Name()] + aurPkg, ok := aurdata[pkg.Name()] if !ok { continue } @@ -274,9 +274,9 @@ func printIgnoringPackage(pkg alpm.Package, newPkgVersion string) { } func printLocalNewerThanAUR( - remote []alpm.Package, pkgdata map[string]*rpc.Pkg) { + remote []alpm.Package, aurdata map[string]*rpc.Pkg) { for _, pkg := range remote { - aurPkg, ok := pkgdata[pkg.Name()] + aurPkg, ok := aurdata[pkg.Name()] if !ok { continue } From 42a74c41c53181d632424b58e36772074cf2d106 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 26 Jul 2018 13:35:19 +0100 Subject: [PATCH 075/155] Show alpm warnings --- callbacks.go | 9 +++++++++ main.go | 1 + 2 files changed, 10 insertions(+) diff --git a/callbacks.go b/callbacks.go index 1b55a0f6..5d0bd22d 100644 --- a/callbacks.go +++ b/callbacks.go @@ -85,3 +85,12 @@ func questionCallback(question alpm.QuestionAny) { } } } + +func logCallback(level alpm.LogLevel, str string) { + switch level { + case alpm.LogWarning: + fmt.Print(bold(yellow(smallArrow)), " ", str) + case alpm.LogError: + fmt.Print(bold(red(smallArrow)), " ", str) + } +} diff --git a/main.go b/main.go index 3966d38e..1c1ec4b7 100644 --- a/main.go +++ b/main.go @@ -191,6 +191,7 @@ func initAlpmHandle() (err error) { } alpmHandle.SetQuestionCallback(questionCallback) + alpmHandle.SetLogCallback(logCallback) return } From dfe7738d6e873a84b82472dbbea526abc641445f Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 31 Jul 2018 00:19:21 +0100 Subject: [PATCH 076/155] Use pacman like text for ignorepkg and newerpkg Now that we are using alpm to fetch packages it generates these mesages and we can not control the format. So change out format to match. --- upgrade.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/upgrade.go b/upgrade.go index 5e81ccaf..39d1e448 100644 --- a/upgrade.go +++ b/upgrade.go @@ -268,10 +268,11 @@ func upAUR( 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)) + fmt.Printf("%s %s: ignoring package upgrade (%s => %s)\n", + yellow(bold(smallArrow)), + cyan(pkg.Name()), + left, right, + ) } func printLocalNewerThanAUR( @@ -284,12 +285,12 @@ func printLocalNewerThanAUR( 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)) + if !isDevelName(pkg.Name()) && alpm.VerCmp(pkg.Version(), aurPkg.Version) > 0 { + fmt.Printf("%s %s: local (%s) is newer than AUR (%s)\n", + yellow(bold(smallArrow)), + cyan(pkg.Name()), + left, right, + ) } } } From 06a45bad59d4d2c698312865c570292c7542a2e8 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 31 Jul 2018 01:56:41 +0100 Subject: [PATCH 077/155] Don't return length with queryRepo --- cmd.go | 3 ++- query.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd.go b/cmd.go index b95e3faa..7be8e6ee 100644 --- a/cmd.go +++ b/cmd.go @@ -461,7 +461,8 @@ func numberMenu(pkgS []string, flags []string) (err error) { lenaq = len(aq) } if mode == ModeRepo || mode == ModeAny { - pq, lenpq, repoErr = queryRepo(pkgS) + pq, repoErr = queryRepo(pkgS) + lenpq = len(pq) if repoErr != nil { return err } diff --git a/query.go b/query.go index 6abdd3a4..bcf0d455 100644 --- a/query.go +++ b/query.go @@ -169,7 +169,7 @@ func syncSearch(pkgS []string) (err error) { aq, aurErr = narrowSearch(pkgS, true) } if mode == ModeRepo || mode == ModeAny { - pq, _, repoErr = queryRepo(pkgS) + pq, repoErr = queryRepo(pkgS) if repoErr != nil { return err } @@ -254,7 +254,7 @@ func syncInfo(pkgS []string) (err error) { } // Search handles repo searches. Creates a RepoSearch struct. -func queryRepo(pkgInputN []string) (s repoQuery, n int, err error) { +func queryRepo(pkgInputN []string) (s repoQuery, err error) { dbList, err := alpmHandle.SyncDbs() if err != nil { return From d9823e4230715c0d51a614320602ca31bdb44830 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 30 Jul 2018 04:38:06 +0100 Subject: [PATCH 078/155] Error on unkown args This is simply implemented by looking up against all the args. No conflicts are checked such as using -Ss and -Si at the same time or using -u with -D. --- parser.go | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) diff --git a/parser.go b/parser.go index 1517c155..88855802 100644 --- a/parser.go +++ b/parser.go @@ -181,6 +181,10 @@ func (parser *arguments) addOP(op string) (err error) { } func (parser *arguments) addParam(option string, arg string) (err error) { + if !isArg(option) { + return fmt.Errorf("invalid option '%s'", option) + } + if isOp(option) { err = parser.addOP(option) return @@ -340,6 +344,277 @@ func formatArg(arg string) string { return arg } +func isArg(arg string) bool { + switch arg { + case "D", "database": + return true + case "Q", "query": + return true + case "R", "remove": + return true + case "S", "sync": + return true + case "T", "deptest": + return true + case "U", "upgrade": + return true + case "F", "files": + return true + case "V", "version": + return true + case "h", "help": + return true + case "Y", "yay": + return true + case "P", "print": + return true + case "G", "getpkgbuild": + return true + case "b", "dbpath": + return true + case "r", "root": + return true + case "v", "verbose": + return true + case "arch": + return true + case "cachedir": + return true + case "color": + return true + case "config": + return true + case "debug": + return true + case "gpgdir": + return true + case "hookdir": + return true + case "logfile": + return true + case "noconfirm": + return true + case "confirm": + return true + case "disabledownloadtimeout": + return true + case "sysroot": + return true + case "d", "nodeps": + return true + case "assumeinstalled": + return true + case "dbonly": + return true + case "noprogressbar": + return true + case "noscriptlet": + return true + case "p": + return true + case "printformat": + return true + case "asdeps": + return true + case "asexplicit": + return true + case "ignore": + return true + case "ignoregroup": + return true + case "needed": + return true + case "overwrite": + return true + case "force": + return true + case "c", "changelog": + return true + case "deps": + return true + case "e", "explicit": + return true + case "g", "groups": + return true + case "i", "info": + return true + case "k", "check": + return true + case "l", "list": + return true + case "m", "foreign": + return true + case "n", "native": + return true + case "o", "owns": + return true + case "file": + return true + case "q", "quiet": + return true + case "s", "search": + return true + case "t", "unrequired": + return true + case "u", "upgrades": + return true + case "cascade": + return true + case "nosave": + return true + case "recursive": + return true + case "unneeded": + return true + case "clean": + return true + case "sysupgrade": + return true + case "w", "downloadonly": + return true + case "y", "refresh": + return true + case "x", "regex": + return true + case "machinereadable": + return true + + //yay options + case "save": + return true + case "afterclean": + return true + case "noafterclean": + return true + case "devel": + return true + case "nodevel": + return true + case "timeupdate": + return true + case "notimeupdate": + return true + case "topdown": + return true + case "bottomup": + return true + case "completioninterval": + return true + case "sortby": + return true + case "redownload": + return true + case "redownloadall": + return true + case "noredownload": + return true + case "rebuild": + return true + case "rebuildall": + return true + case "rebuildtree": + return true + case "norebuild": + return true + case "answerclean": + return true + case "noanswerclean": + return true + case "answerdiff": + return true + case "noanswerdiff": + return true + case "answeredit": + return true + case "noansweredit": + return true + case "answerupgrade": + return true + case "noanswerupgrade": + return true + case "gitclone": + return true + case "nogitclone": + return true + case "gpgflags": + return true + case "mflags": + return true + case "gitflags": + return true + case "builddir": + return true + case "editor": + return true + case "editorflags": + return true + case "makepkg": + return true + case "makepkgconf": + return true + case "nomakepkgconf": + return true + case "pacman": + return true + case "tar": + return true + case "git": + return true + case "gpg": + return true + case "requestsplitn": + return true + case "sudoloop": + return true + case "nosudoloop": + return true + case "provides": + return true + case "noprovides": + return true + case "pgpfetch": + return true + case "nopgpfetch": + return true + case "upgrademenu": + return true + case "noupgrademenu": + return true + case "cleanmenu": + return true + case "nocleanmenu": + return true + case "diffmenu": + return true + case "nodiffmenu": + return true + case "editmenu": + return true + case "noeditmenu": + return true + case "useask": + return true + case "nouseask": + return true + case "combinedupgrade": + return true + case "nocombinedupgrade": + return true + case "a", "aur": + return true + case "repo": + return true + case "removemake": + return true + case "noremovemake": + return true + case "askremovemake": + return true + default: + return false + } +} + func isOp(op string) bool { switch op { case "V", "version": From 4e67c1e88694279025745763991a4423234b5125 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 30 Jul 2018 04:49:17 +0100 Subject: [PATCH 079/155] Simlify huge case statments Instead of having true in every case, rely on the lack of fallthrough causing the default not to trigger. Moved handleConfig to parser.go --- cmd.go | 156 ------------------------ parser.go | 352 ++++++++++++++++++++++++------------------------------ 2 files changed, 158 insertions(+), 350 deletions(-) diff --git a/cmd.go b/cmd.go index b085f772..3784692d 100644 --- a/cmd.go +++ b/cmd.go @@ -4,7 +4,6 @@ import ( "bufio" "fmt" "os" - "strconv" alpm "github.com/jguer/go-alpm" ) @@ -185,161 +184,6 @@ func handleHelp() error { return show(passToPacman(cmdArgs)) } -//this function should only set config options -//but currently still uses the switch left over from old code -//eventually this should be refactored out further -//my current plan is to have yay specific operations in its own operator -//e.g. yay -Y --gendb -//e.g yay -Yg -func handleConfig(option, value string) bool { - switch option { - case "save": - shouldSaveConfig = true - case "afterclean": - config.CleanAfter = true - case "noafterclean": - config.CleanAfter = false - case "devel": - config.Devel = true - case "nodevel": - config.Devel = false - case "timeupdate": - config.TimeUpdate = true - case "notimeupdate": - config.TimeUpdate = false - case "topdown": - config.SortMode = TopDown - case "bottomup": - config.SortMode = BottomUp - case "completioninterval": - n, err := strconv.Atoi(value) - if err == nil { - config.CompletionInterval = n - } - case "sortby": - config.SortBy = value - case "noconfirm": - config.NoConfirm = true - case "config": - config.PacmanConf = value - case "redownload": - config.ReDownload = "yes" - case "redownloadall": - config.ReDownload = "all" - case "noredownload": - config.ReDownload = "no" - case "rebuild": - config.ReBuild = "yes" - case "rebuildall": - config.ReBuild = "all" - case "rebuildtree": - config.ReBuild = "tree" - case "norebuild": - config.ReBuild = "no" - case "answerclean": - config.AnswerClean = value - case "noanswerclean": - config.AnswerClean = "" - case "answerdiff": - config.AnswerDiff = value - case "noanswerdiff": - config.AnswerDiff = "" - case "answeredit": - config.AnswerEdit = value - case "noansweredit": - config.AnswerEdit = "" - case "answerupgrade": - config.AnswerUpgrade = value - case "noanswerupgrade": - config.AnswerUpgrade = "" - case "gitclone": - config.GitClone = true - case "nogitclone": - config.GitClone = false - case "gpgflags": - config.GpgFlags = value - case "mflags": - config.MFlags = value - case "gitflags": - config.GitFlags = value - case "builddir": - config.BuildDir = value - case "editor": - config.Editor = value - case "editorflags": - config.EditorFlags = value - case "makepkg": - config.MakepkgBin = value - case "makepkgconf": - config.MakepkgConf = value - case "nomakepkgconf": - config.MakepkgConf = "" - case "pacman": - config.PacmanBin = value - case "tar": - config.TarBin = value - case "git": - config.GitBin = value - case "gpg": - config.GpgBin = value - case "requestsplitn": - if n, err := strconv.Atoi(value); err == nil && n > 0 { - config.RequestSplitN = n - } - case "sudoloop": - config.SudoLoop = true - case "nosudoloop": - config.SudoLoop = false - case "provides": - config.Provides = true - case "noprovides": - config.Provides = false - case "pgpfetch": - 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": - config.CleanMenu = false - case "diffmenu": - config.DiffMenu = true - case "nodiffmenu": - config.DiffMenu = false - case "editmenu": - config.EditMenu = true - case "noeditmenu": - config.EditMenu = false - case "useask": - config.UseAsk = true - case "nouseask": - config.UseAsk = false - case "combinedupgrade": - config.CombinedUpgrade = true - case "nocombinedupgrade": - config.CombinedUpgrade = false - case "a", "aur": - mode = ModeAUR - case "repo": - mode = ModeRepo - case "removemake": - config.RemoveMake = "yes" - case "noremovemake": - config.RemoveMake = "no" - case "askremovemake": - config.RemoveMake = "ask" - default: - // the option was not handled by the switch - return false - } - // the option was successfully handled by the switch - return true -} - func handleVersion() { fmt.Printf("yay v%s - libalpm v%s\n", version, alpm.Version()) } diff --git a/parser.go b/parser.go index 88855802..179048ec 100644 --- a/parser.go +++ b/parser.go @@ -347,415 +347,379 @@ func formatArg(arg string) string { func isArg(arg string) bool { switch arg { case "D", "database": - return true case "Q", "query": - return true case "R", "remove": - return true case "S", "sync": - return true case "T", "deptest": - return true case "U", "upgrade": - return true case "F", "files": - return true case "V", "version": - return true case "h", "help": - return true case "Y", "yay": - return true case "P", "print": - return true case "G", "getpkgbuild": - return true case "b", "dbpath": - return true case "r", "root": - return true case "v", "verbose": - return true case "arch": - return true case "cachedir": - return true case "color": - return true case "config": - return true case "debug": - return true case "gpgdir": - return true case "hookdir": - return true case "logfile": - return true case "noconfirm": - return true case "confirm": - return true case "disabledownloadtimeout": - return true case "sysroot": - return true case "d", "nodeps": - return true case "assumeinstalled": - return true case "dbonly": - return true case "noprogressbar": - return true case "noscriptlet": - return true case "p": - return true case "printformat": - return true case "asdeps": - return true case "asexplicit": - return true case "ignore": - return true case "ignoregroup": - return true case "needed": - return true case "overwrite": - return true case "force": - return true case "c", "changelog": - return true case "deps": - return true case "e", "explicit": - return true case "g", "groups": - return true case "i", "info": - return true case "k", "check": - return true case "l", "list": - return true case "m", "foreign": - return true case "n", "native": - return true case "o", "owns": - return true case "file": - return true case "q", "quiet": - return true case "s", "search": - return true case "t", "unrequired": - return true case "u", "upgrades": - return true case "cascade": - return true case "nosave": - return true case "recursive": - return true case "unneeded": - return true case "clean": - return true case "sysupgrade": - return true case "w", "downloadonly": - return true case "y", "refresh": - return true case "x", "regex": - return true case "machinereadable": - return true - //yay options case "save": - return true case "afterclean": - return true case "noafterclean": - return true case "devel": - return true case "nodevel": - return true case "timeupdate": - return true case "notimeupdate": - return true case "topdown": - return true case "bottomup": - return true case "completioninterval": - return true case "sortby": - return true case "redownload": - return true case "redownloadall": - return true case "noredownload": - return true case "rebuild": - return true case "rebuildall": - return true case "rebuildtree": - return true case "norebuild": - return true case "answerclean": - return true case "noanswerclean": - return true case "answerdiff": - return true case "noanswerdiff": - return true case "answeredit": - return true case "noansweredit": - return true case "answerupgrade": - return true case "noanswerupgrade": - return true case "gitclone": - return true case "nogitclone": - return true case "gpgflags": - return true case "mflags": - return true case "gitflags": - return true case "builddir": - return true case "editor": - return true case "editorflags": - return true case "makepkg": - return true case "makepkgconf": - return true case "nomakepkgconf": - return true case "pacman": - return true case "tar": - return true case "git": - return true case "gpg": - return true case "requestsplitn": - return true case "sudoloop": - return true case "nosudoloop": - return true case "provides": - return true case "noprovides": - return true case "pgpfetch": - return true case "nopgpfetch": - return true case "upgrademenu": - return true case "noupgrademenu": - return true case "cleanmenu": - return true case "nocleanmenu": - return true case "diffmenu": - return true case "nodiffmenu": - return true case "editmenu": - return true case "noeditmenu": - return true case "useask": - return true case "nouseask": - return true case "combinedupgrade": - return true case "nocombinedupgrade": - return true case "a", "aur": - return true case "repo": - return true case "removemake": - return true case "noremovemake": - return true case "askremovemake": - return true default: return false } + + return true +} + +func handleConfig(option, value string) bool { + switch option { + case "save": + shouldSaveConfig = true + case "afterclean": + config.CleanAfter = true + case "noafterclean": + config.CleanAfter = false + case "devel": + config.Devel = true + case "nodevel": + config.Devel = false + case "timeupdate": + config.TimeUpdate = true + case "notimeupdate": + config.TimeUpdate = false + case "topdown": + config.SortMode = TopDown + case "bottomup": + config.SortMode = BottomUp + case "completioninterval": + n, err := strconv.Atoi(value) + if err == nil { + config.CompletionInterval = n + } + case "sortby": + config.SortBy = value + case "noconfirm": + config.NoConfirm = true + case "config": + config.PacmanConf = value + case "redownload": + config.ReDownload = "yes" + case "redownloadall": + config.ReDownload = "all" + case "noredownload": + config.ReDownload = "no" + case "rebuild": + config.ReBuild = "yes" + case "rebuildall": + config.ReBuild = "all" + case "rebuildtree": + config.ReBuild = "tree" + case "norebuild": + config.ReBuild = "no" + case "answerclean": + config.AnswerClean = value + case "noanswerclean": + config.AnswerClean = "" + case "answerdiff": + config.AnswerDiff = value + case "noanswerdiff": + config.AnswerDiff = "" + case "answeredit": + config.AnswerEdit = value + case "noansweredit": + config.AnswerEdit = "" + case "answerupgrade": + config.AnswerUpgrade = value + case "noanswerupgrade": + config.AnswerUpgrade = "" + case "gitclone": + config.GitClone = true + case "nogitclone": + config.GitClone = false + case "gpgflags": + config.GpgFlags = value + case "mflags": + config.MFlags = value + case "gitflags": + config.GitFlags = value + case "builddir": + config.BuildDir = value + case "editor": + config.Editor = value + case "editorflags": + config.EditorFlags = value + case "makepkg": + config.MakepkgBin = value + case "makepkgconf": + config.MakepkgConf = value + case "nomakepkgconf": + config.MakepkgConf = "" + case "pacman": + config.PacmanBin = value + case "tar": + config.TarBin = value + case "git": + config.GitBin = value + case "gpg": + config.GpgBin = value + case "requestsplitn": + n, err := strconv.Atoi(value) + if err == nil && n > 0 { + config.RequestSplitN = n + } + case "sudoloop": + config.SudoLoop = true + case "nosudoloop": + config.SudoLoop = false + case "provides": + config.Provides = true + case "noprovides": + config.Provides = false + case "pgpfetch": + 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": + config.CleanMenu = false + case "diffmenu": + config.DiffMenu = true + case "nodiffmenu": + config.DiffMenu = false + case "editmenu": + config.EditMenu = true + case "noeditmenu": + config.EditMenu = false + case "useask": + config.UseAsk = true + case "nouseask": + config.UseAsk = false + case "combinedupgrade": + config.CombinedUpgrade = true + case "nocombinedupgrade": + config.CombinedUpgrade = false + case "a", "aur": + mode = ModeAUR + case "repo": + mode = ModeRepo + case "removemake": + config.RemoveMake = "yes" + case "noremovemake": + config.RemoveMake = "no" + case "askremovemake": + config.RemoveMake = "ask" + default: + return false + } + + return true } func isOp(op string) bool { switch op { case "V", "version": - return true case "D", "database": - return true case "F", "files": - return true case "Q", "query": - return true case "R", "remove": - return true case "S", "sync": - return true case "T", "deptest": - return true case "U", "upgrade": - return true - - // yay specific + // yay specific case "Y", "yay": - return true case "P", "print": - return true case "G", "getpkgbuild": - return true default: return false } + + return true } func isGlobal(op string) bool { switch op { case "b", "dbpath": - return true case "r", "root": - return true case "v", "verbose": - return true case "arch": - return true case "cachedir": - return true case "color": - return true case "config": - return true case "debug": - return true case "gpgdir": - return true case "hookdir": - return true case "logfile": - return true case "noconfirm": - return true case "confirm": - return true default: return false } + + return true } func hasParam(arg string) bool { switch arg { case "dbpath", "b": - return true case "root", "r": - return true case "sysroot": - return true case "config": - return true case "ignore": - return true case "assume-installed": - return true case "overwrite": - return true case "ask": - return true case "cachedir": - return true case "hookdir": - return true case "logfile": - return true case "ignoregroup": - return true case "arch": - return true case "print-format": - return true case "gpgdir": - return true case "color": - return true - //yay params case "mflags": - return true case "gpgflags": - return true case "gitflags": - return true case "builddir": - return true case "editor": - return true case "editorflags": - return true case "makepkg": - return true case "makepkgconf": - return true case "pacman": - return true case "tar": - return true case "git": - return true case "gpg": - return true case "requestsplitn": - return true case "answerclean": - return true case "answerdiff": - return true case "answeredit": - return true case "answerupgrade": - return true case "completioninterval": - return true case "sortby": - return true default: return false } + + return true } // Parses short hand options such as: From 97006ade19a215e61f4f07b7bf820a6d59d9d2ae Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 14:43:54 +0100 Subject: [PATCH 080/155] Support -r=foo syntax --- parser.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 179048ec..c582ab38 100644 --- a/parser.go +++ b/parser.go @@ -735,9 +735,16 @@ func (parser *arguments) parseShortOption(arg string, param string) (usedNext bo for k, _char := range arg { char := string(_char) - if hasParam(char) { - if k < len(arg)-2 { + if k < len(arg)-1 { + if arg[k+1] == '=' { err = parser.addParam(char, arg[k+2:]) + break + } + } + + if hasParam(char) { + if k < len(arg)-1 { + err = parser.addParam(char, arg[k+1:]) } else { usedNext = true err = parser.addParam(char, param) From 4a254303c53a7901c799e49ba81f1eda6876b084 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 15:21:01 +0100 Subject: [PATCH 081/155] Don't show .SRCINFO in diffs --- install.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.go b/install.go index 7fe0fbd2..f4b6dc45 100644 --- a/install.go +++ b/install.go @@ -676,7 +676,7 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri } } - args := []string{"diff", start + "..HEAD@{upstream}", "--src-prefix", dir + "/", "--dst-prefix", dir + "/"} + args := []string{"diff", start + "..HEAD@{upstream}", "--src-prefix", dir + "/", "--dst-prefix", dir + "/", "--", ".", ":(exclude).SRCINFO"} if useColor { args = append(args, "--color=always") } else { From db9ff186d67358659eac92d2c56d24b3d86233c2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 16:51:33 +0100 Subject: [PATCH 082/155] Accept - and -- options --- parser.go | 1 + 1 file changed, 1 insertion(+) diff --git a/parser.go b/parser.go index c582ab38..8093623f 100644 --- a/parser.go +++ b/parser.go @@ -346,6 +346,7 @@ func formatArg(arg string) string { func isArg(arg string) bool { switch arg { + case "-", "--": case "D", "database": case "Q", "query": case "R", "remove": From 08ac9036adff6223434ae21ce3ef99a0d7d71ea7 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 3 Aug 2018 23:15:01 +0100 Subject: [PATCH 083/155] Ensure AUR upgrades actually use the AUR Yay's dependency resolving takes provides into account. When upgrading AUR package 'foo', if a repo package provides 'foo' then yay would get confused and pull in the package providing 'foo' instead of the AUR package. This commit ensures AUR upgrades always exclusively check the AUR. --- install.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/install.go b/install.go index f4b6dc45..ccf05d5a 100644 --- a/install.go +++ b/install.go @@ -93,7 +93,8 @@ func install(parser *arguments) error { } for up := range aurUp { - requestTargets = append(requestTargets, up) + requestTargets = append(requestTargets, "aur/" + up) + parser.addTarget("aur/" + up) } value, _, exists := cmdArgs.getArg("ignore") @@ -105,10 +106,6 @@ func install(parser *arguments) error { } arguments.options["ignore"] = ignoreStr } - - for pkg := range aurUp { - parser.addTarget(pkg) - } } targets := sliceToStringSet(parser.targets) From de59b3911d763859f4796e52fc24f852040fe24c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 4 Aug 2018 14:22:49 +0100 Subject: [PATCH 084/155] Fix padding on time update --- upgrade.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/upgrade.go b/upgrade.go index a004cd50..81827449 100644 --- a/upgrade.go +++ b/upgrade.go @@ -64,7 +64,7 @@ func (u upSlice) Less(i, j int) bool { func getVersionDiff(oldVersion, newVersion string) (left, right string) { if oldVersion == newVersion { - return oldVersion, newVersion + return oldVersion + red(""), newVersion + green("") } diffPosition := 0 @@ -286,10 +286,10 @@ func printLocalNewerThanAUR( if !isDevelName(pkg.Name()) && alpm.VerCmp(pkg.Version(), aurPkg.Version) > 0 { fmt.Printf("%s %s: local (%s) is newer than AUR (%s)\n", - yellow(bold(smallArrow)), - cyan(pkg.Name()), - left, right, - ) + yellow(bold(smallArrow)), + cyan(pkg.Name()), + left, right, + ) } } } From 8d7ff22fed20c56bfe2bb8f118cc03b7cfe722ae Mon Sep 17 00:00:00 2001 From: Peter Dyer Date: Sun, 5 Aug 2018 00:25:27 +0100 Subject: [PATCH 085/155] Fix panic on invalid version strings --- dep.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dep.go b/dep.go index 3328331f..47c8c0a5 100644 --- a/dep.go +++ b/dep.go @@ -53,6 +53,10 @@ func splitDep(dep string) (string, string, string) { return match }) + if len(split) == 0 { + return "", "", "" + } + if len(split) == 1 { return split[0], "", "" } From 2d6fe95903ac118811d8f24a5fb3361de09e0114 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 21:58:03 +0100 Subject: [PATCH 086/155] Add yay specific args, drop conflicting args Replace -P/--print with -P/--show Replace --config with --currentconfig --- cmd.go | 4 ++-- parser.go | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd.go b/cmd.go index 3784692d..433ae0b4 100644 --- a/cmd.go +++ b/cmd.go @@ -156,7 +156,7 @@ func handleCmd() (err error) { err = show(passToPacman(cmdArgs)) case "G", "getpkgbuild": err = handleGetpkgbuild() - case "P", "print": + case "P", "show": err = handlePrint() case "Y", "--yay": err = handleYay() @@ -194,7 +194,7 @@ func handlePrint() (err error) { var tmpConfig Configuration defaultSettings(&tmpConfig) fmt.Printf("%v", tmpConfig) - case cmdArgs.existsArg("g", "config"): + case cmdArgs.existsArg("g", "currentconfig"): fmt.Printf("%v", config) case cmdArgs.existsArg("n", "numberupgrades"): err = printNumberOfUpdates() diff --git a/parser.go b/parser.go index 8093623f..5c3fa054 100644 --- a/parser.go +++ b/parser.go @@ -357,7 +357,7 @@ func isArg(arg string) bool { case "V", "version": case "h", "help": case "Y", "yay": - case "P", "print": + case "P", "show": case "G", "getpkgbuild": case "b", "dbpath": case "r", "root": @@ -479,6 +479,11 @@ func isArg(arg string) bool { case "removemake": case "noremovemake": case "askremovemake": + case "complete": + case "stats": + case "news": + case "gendb": + case "currentconfig": default: return false } @@ -647,7 +652,7 @@ func isOp(op string) bool { case "U", "upgrade": // yay specific case "Y", "yay": - case "P", "print": + case "P", "show": case "G", "getpkgbuild": default: return false From 5ef38c12bde2a85e8c89592f7b8a81dcce8b6512 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 22:01:41 +0100 Subject: [PATCH 087/155] Update usage and man page --- cmd.go | 4 ++-- doc/yay.8 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd.go b/cmd.go index 433ae0b4..738d1ea9 100644 --- a/cmd.go +++ b/cmd.go @@ -29,7 +29,7 @@ operations: New operations: yay {-Y --yay} [options] [package(s)] - yay {-P --print} [options] + yay {-P --show} [options] yay {-G --getpkgbuild} [package(s)] New options: @@ -111,7 +111,7 @@ Permanent configuration options: Print specific options: -c --complete Used for completions -d --defaultconfig Print default yay configuration - -g --config Print current yay configuration + -g --currentconfig Print current yay configuration -s --stats Display system package statistics -w --news Print arch news diff --git a/doc/yay.8 b/doc/yay.8 index a67bec60..137cc2a3 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -26,7 +26,7 @@ Perform yay specific operations. This is the default if no other operation is selected. .TP -.B \-P, \-\-print +.B \-P, \-\-show Perform yay specific print operations. .TP @@ -101,7 +101,7 @@ During complete adjust the output for the fish shell. Print default yay configuration. .TP -.B \-g, \-\-config +.B \-g, \-\-currentconfig Print current yay configuration. .TP From 8f3f4b7b980d8b959a5cafbb4a7192b67dd9645b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 5 Aug 2018 15:28:06 +0100 Subject: [PATCH 088/155] Give an example of how to update only AUR packages I've seen `yay -Syua` given as an example all over the place. I'm not sure if this is left over as a habbit from yaourt. In yay, -a restricts the upgrade to AUR packages ONLY while I believe in yaourt it means to also include the AUR. The problem with `yay -Syua` is that you are doing a database refresh and then only upgrading the AUR packages. Essencially: pacman -Sy && update-aur This is a recipy for partial upgrades. Either upgrade everything `yay -Syu` or just the AUR `yay -Sua`. --- doc/yay.8 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/yay.8 b/doc/yay.8 index a67bec60..2684a08c 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -473,6 +473,10 @@ Search and install from the repos and the \fBAUR\fR\ using yogurt mode. yay \-Syu Update package list and upgrade all currently installed repo and \fBAUR\fR. +.TP +yay \-Sua +Update all currently installed \fBAUR\fR packages. + .TP yay \-S \fIfoo\fR Installs package \fIfoo\fR from the repos or the \fBAUR\fR. From 746a541f7b437b60026ae1549ed64695701c71e4 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 5 Aug 2018 23:01:09 +0100 Subject: [PATCH 089/155] Update bash completion Update bash completion, based of the current pacman bash completion. Organized to try and keep the yay additions seperate from the main pacman stuff and unused functions removed. --- completions/bash | 50 +++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/completions/bash b/completions/bash index 55fb095f..7e2e31e7 100644 --- a/completions/bash +++ b/completions/bash @@ -1,4 +1,3 @@ -# vim:fdm=marker foldlevel=0 tabstop=2 shiftwidth=2 filetype=bash # This file is in the public domain. _arch_compgen() { @@ -28,19 +27,6 @@ _arch_incomp() { local r="\s-(-${1#* }\s|\w*${1% *})"; [[ $COMP_LINE =~ $r ]] } -_pacman_keyids() { - \pacman-key --list-keys 2>/dev/null | awk ' - $1 == "pub" { - # key id - split($2, a, "/"); print a[2] - } - $1 == "uid" { - # email - if (match($NF, /<[^>]+>/)) - print substr($NF, RSTART + 1, RLENGTH - 2) - }' -} - _pacman_pkg() { _arch_compgen "$( if [[ $2 ]]; then @@ -51,38 +37,46 @@ _pacman_pkg() { )" } +_yay_pkg() { + _arch_compgen "$(yay -Pc)" +} - +_pacman_repo_list() { + _arch_compgen "$(pacman-conf --repo-list)" +} _yay() { - local common core cur database prev query remove sync upgrade yays print o + local common core cur database files prev query remove sync upgrade o + local yays show COMPREPLY=() _get_comp_words_by_ref cur prev database=('asdeps asexplicit') files=('list machinereadable owns search refresh regex' 'l o s x y') - query=('changelog check deps explicit file foreign groups info list owns - search unrequired upgrades' 'c e g i k l m o p s t u') + query=('changelog check deps explicit file foreign groups info list native owns + search unrequired upgrades' 'c e g i k l m n o p s t u') remove=('cascade dbonly nodeps assume-installed nosave print recursive unneeded' 'c n p s u') sync=('asdeps asexplicit clean dbonly downloadonly force groups ignore ignoregroup info list needed nodeps assume-installed print refresh recursive search sysupgrade' '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 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 + noconfirm noprogressbar noscriptlet quiet root verbose + #yay stuff makepkg pacman tar git gpg gpgflags config requestsplitn sudoloop nosudoloop redownload noredownload redownloadall rebuild rebuildall rebuildtree norebuild sortby answerclean answerdiff answeredit answerupgrade noanswerclean noanswerdiff noansweredit noanswerupgrade cleanmenu diffmenu editmenu upgrademenu nocleanmenu nodiffmenu noupgrademenu provides noprovides pgpfetch nopgpfetch - useask nouseask combinedupgrade nocombinedupgrade root verbose aur repo makepkgconf - nomakepkgconf askremovemake removemake noremovemake completioninterval' - 'a b d h q r v') + useask nouseask combinedupgrade nocombinedupgrade aur repo makepkgconf + nomakepkgconf askremovemake removemake noremovemake completioninterval' + '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 + ##yay stuff + yays=('clean gendb' 'c') + print=('complete defaultconfig currentconfig stats news' 'c d g s w') + + for o in 'D database' 'F files' 'Q query' 'R remove' 'S sync' 'U upgrade' 'Y yays' 'P show'; do _arch_incomp "$o" && break done @@ -105,8 +99,8 @@ _yay() { _pacman_pkg Qq;; S) { _arch_incomp 'g groups' && _pacman_pkg Sg; } || - { _arch_incomp 'l list' && _arch_compgen "$(yay -Pc | \sort -u)"; } || - _arch_compgen "$(yay -Pc )";; + { _arch_incomp 'l list' && _pacman_repo_list; } || + _yay_pkg;; U) _pacman_file;; esac From 1aff6cada02ad659eb7c7effc3e2265df1f95955 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 5 Aug 2018 23:10:54 +0100 Subject: [PATCH 090/155] Don't complete packages for empty string --- completions/bash | 1 + 1 file changed, 1 insertion(+) diff --git a/completions/bash b/completions/bash index 7e2e31e7..39551ca1 100644 --- a/completions/bash +++ b/completions/bash @@ -38,6 +38,7 @@ _pacman_pkg() { } _yay_pkg() { + [ -z "$cur" ] && return _arch_compgen "$(yay -Pc)" } From 6b35f9ee2f4c2a95d80e80c2158c757bd93ffe9d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 8 Aug 2018 15:58:28 +0100 Subject: [PATCH 091/155] Revert "Support -r=foo syntax" This reverts commit 97006ade19a215e61f4f07b7bf820a6d59d9d2ae. But keepts the usr of k+1 and len(arg)-1 --- parser.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/parser.go b/parser.go index 5c3fa054..c6d3cc22 100644 --- a/parser.go +++ b/parser.go @@ -741,13 +741,6 @@ func (parser *arguments) parseShortOption(arg string, param string) (usedNext bo for k, _char := range arg { char := string(_char) - if k < len(arg)-1 { - if arg[k+1] == '=' { - err = parser.addParam(char, arg[k+2:]) - break - } - } - if hasParam(char) { if k < len(arg)-1 { err = parser.addParam(char, arg[k+1:]) From 16d4a2ca88c458584a1f1c7d511b79e432d4aa7d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 8 Aug 2018 16:03:39 +0100 Subject: [PATCH 092/155] Support = on long opts, not short opts --- parser.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parser.go b/parser.go index c6d3cc22..b4d22d5c 100644 --- a/parser.go +++ b/parser.go @@ -772,7 +772,10 @@ func (parser *arguments) parseLongOption(arg string, param string) (usedNext boo arg = arg[2:] - if hasParam(arg) { + split := strings.SplitN(arg, "=", 2) + if len(split) == 2 { + err = parser.addParam(split[0], split[1]) + } else if hasParam(arg) { err = parser.addParam(arg, param) usedNext = true } else { From 58240bdc3d8e5a31b5bc55ff6a07a618a1e5d77a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 16:05:43 +0100 Subject: [PATCH 093/155] Steal multierror from aurlib --- utils.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/utils.go b/utils.go index c9e9017e..3762dd56 100644 --- a/utils.go +++ b/utils.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "sync" "unicode" ) @@ -128,3 +129,36 @@ func removeInvalidTargets(targets []string) []string { return filteredTargets } + +type MultiError struct { + Errors []error + mux sync.Mutex +} + +func (err *MultiError) Error() string { + str := "" + + for _, e := range err.Errors { + str += e.Error() + } + + return str +} + +func (err *MultiError) Add(e error) { + if e == nil { + return + } + + err.mux.Lock() + err.Errors = append(err.Errors, e) + err.mux.Unlock() +} + +func (err *MultiError) Return() error { + if len(err.Errors) > 0 { + return err + } + + return nil +} From 8c2adaddb3aac75956eae60d51d45deb1ee7a33d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 16:11:37 +0100 Subject: [PATCH 094/155] Hide git output --- download.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/download.go b/download.go index acd6fe77..c1fafe91 100644 --- a/download.go +++ b/download.go @@ -60,9 +60,9 @@ func gitHasDiff(path string, name string) (bool, error) { func gitDownload(url string, path string, name string) (bool, error) { _, err := os.Stat(filepath.Join(path, name, ".git")) if os.IsNotExist(err) { - err = show(passToGit(path, "clone", "--no-progress", url, name)) + _, stderr, err := capture(passToGit(path, "clone", "--no-progress", url, name)) if err != nil { - return false, fmt.Errorf("error cloning %s", name) + return false, fmt.Errorf("error cloning %s: stderr", name, stderr) } return true, nil @@ -70,23 +70,23 @@ func gitDownload(url string, path string, name string) (bool, error) { return false, fmt.Errorf("error reading %s", filepath.Join(path, name, ".git")) } - err = show(passToGit(filepath.Join(path, name), "fetch")) + _, stderr, err := capture(passToGit(filepath.Join(path, name), "fetch")) if err != nil { - return false, fmt.Errorf("error fetching %s", name) + return false, fmt.Errorf("error fetching %s: %s", name, stderr) } return false, nil } func gitMerge(path string, name string) error { - err := show(passToGit(filepath.Join(path, name), "reset", "--hard", "HEAD")) + _, stderr, err := capture(passToGit(filepath.Join(path, name), "reset", "--hard", "HEAD")) if err != nil { - return fmt.Errorf("error resetting %s", name) + return fmt.Errorf("error resetting %s: %s", name, stderr) } - err = show(passToGit(filepath.Join(path, name), "merge", "--no-edit", "--ff")) + _, stderr, err = capture(passToGit(filepath.Join(path, name), "merge", "--no-edit", "--ff")) if err != nil { - return fmt.Errorf("error merging %s", name) + return fmt.Errorf("error merging %s: %s", name, stderr) } return nil From ff5ed12181d4d9da2c3ed5b4b15c0ce9b0ea32fa Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 16:49:30 +0100 Subject: [PATCH 095/155] Parallelize pkgbuild download --- install.go | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/install.go b/install.go index ccf05d5a..03c36f68 100644 --- a/install.go +++ b/install.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" gosrc "github.com/Morganamilo/go-srcinfo" alpm "github.com/jguer/go-alpm" @@ -770,7 +771,7 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { pkgbuild, err := gosrc.ParseFile(dir) if err == nil { - if alpm.VerCmp(pkgbuild.Version(), pkg.Version) > 0 { + if alpm.VerCmp(pkgbuild.Version(), pkg.Version) >= 0 { toSkip.set(pkg.PackageBase) } } @@ -795,35 +796,57 @@ func mergePkgBuilds(pkgs []*rpc.Pkg) error { func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) (stringSet, error) { cloned := make(stringSet) + downloaded := 0 + var wg sync.WaitGroup + var mux sync.Mutex + var errs MultiError + + download := func(k int, pkg *rpc.Pkg) { + defer wg.Done() - for k, pkg := range pkgs { if toSkip.get(pkg.PackageBase) { + mux.Lock() + downloaded++ str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) - continue + fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(pkg, bases))) + mux.Unlock() + return } - str := bold(cyan("::") + " Downloading PKGBUILD (%d/%d): %s\n") - - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) - if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { clone, err := gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) if err != nil { - return nil, err + errs.Add(err) + return } if clone { + mux.Lock() cloned.set(pkg.PackageBase) + mux.Unlock() } } else { err := downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) if err != nil { - return nil, err + errs.Add(err) + return } } + + mux.Lock() + downloaded++ + str := bold(cyan("::") + " Downloaded PKGBUILD (%d/%d): %s\n") + fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(pkg, bases))) + mux.Unlock() } - return cloned, nil + for k, pkg := range pkgs { + wg.Add(1) + go download(k, pkg) + } + + wg.Wait() + + return cloned, errs.Return() } func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) { From b3e647aee449dd5e5acc3bd467dd393c8818efa0 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 17:14:57 +0100 Subject: [PATCH 096/155] Use MultiError in other goroutines --- query.go | 9 +++------ upgrade.go | 33 ++++++++++++--------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/query.go b/query.go index bcf0d455..0ee90b2f 100644 --- a/query.go +++ b/query.go @@ -477,16 +477,13 @@ func aurInfo(names []string, warnings *aurWarnings) ([]*rpc.Pkg, error) { seen := make(map[string]int) var mux sync.Mutex var wg sync.WaitGroup - var err error + var errs MultiError makeRequest := func(n, max int) { defer wg.Done() tempInfo, requestErr := rpc.Info(names[n:max]) - if err != nil { - return - } + errs.Add(requestErr) if requestErr != nil { - err = requestErr return } mux.Lock() @@ -505,7 +502,7 @@ func aurInfo(names []string, warnings *aurWarnings) ([]*rpc.Pkg, error) { wg.Wait() - if err != nil { + if err := errs.Return(); err != nil { return info, err } diff --git a/upgrade.go b/upgrade.go index 81827449..3b739369 100644 --- a/upgrade.go +++ b/upgrade.go @@ -3,7 +3,6 @@ package main import ( "fmt" "sort" - "strings" "sync" "unicode" @@ -109,7 +108,7 @@ func getVersionDiff(oldVersion, newVersion string) (left, right string) { } // upList returns lists of packages to upgrade from each source. -func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { +func upList(warnings *aurWarnings) (upSlice, upSlice, error) { local, remote, _, remoteNames, err := filterPackages() if err != nil { return nil, nil, err @@ -117,9 +116,10 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { var wg sync.WaitGroup var develUp upSlice + var repoUp upSlice + var aurUp upSlice - var repoErr error - var aurErr error + var errs MultiError aurdata := make(map[string]*rpc.Pkg) @@ -127,7 +127,8 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { fmt.Println(bold(cyan("::") + bold(" Searching databases for updates..."))) wg.Add(1) go func() { - repoUp, repoErr = upRepo(local) + repoUp, err = upRepo(local) + errs.Add(err) wg.Done() }() } @@ -136,15 +137,17 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { fmt.Println(bold(cyan("::") + bold(" Searching AUR for updates..."))) var _aurdata []*rpc.Pkg - _aurdata, aurErr = aurInfo(remoteNames, warnings) - if aurErr == nil { + _aurdata, err = aurInfo(remoteNames, warnings) + errs.Add(err) + if err == nil { for _, pkg := range _aurdata { aurdata[pkg.Name] = pkg } wg.Add(1) go func() { - aurUp, aurErr = upAUR(remote, aurdata) + aurUp, err = upAUR(remote, aurdata) + errs.Add(err) wg.Done() }() @@ -163,18 +166,6 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { printLocalNewerThanAUR(remote, aurdata) - errs := make([]string, 0) - for _, e := range []error{repoErr, aurErr} { - if e != nil { - errs = append(errs, e.Error()) - } - } - - if len(errs) > 0 { - err = fmt.Errorf("%s", strings.Join(errs, "\n")) - return nil, nil, err - } - if develUp != nil { names := make(stringSet) for _, up := range develUp { @@ -189,7 +180,7 @@ func upList(warnings *aurWarnings) (aurUp upSlice, repoUp upSlice, err error) { aurUp = develUp } - return aurUp, repoUp, err + return aurUp, repoUp, errs.Return() } func upDevel(remote []alpm.Package, aurdata map[string]*rpc.Pkg) (toUpgrade upSlice) { From 161bc1a17a7207062779bb298c45fc8aff6fa008 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 22:55:48 +0100 Subject: [PATCH 097/155] Only check pkgbuild source protocols for vcs fetch The current check involves checking the entire source url for the word git. This can lead to yay asumming sources are git repos when they are not. For example: https://raw.githubusercontent.com/ryanoasis/nerd-fonts/v2.0.0/LICENSE/ Makepkg seems to also only respect the protocols. For example: https://github.com/jguer/yay will be fetched as a web page. git:// or git+https:// would be needed. Although this does not seem to work the way yay assumes. You can not simply + togther a bunch of protocols. For exaplle: git+http+https:// will not work, even though individually they do. git must also come first: https+git:// will not work either. Yay's method of spliting on each + is fine though, it works and I'm not going to worry about broken packages that do https+git:// or similar. --- vcs.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/vcs.go b/vcs.go index 4b6cef70..9ba31072 100644 --- a/vcs.go +++ b/vcs.go @@ -64,11 +64,6 @@ func createDevelDB() error { // parseSource returns the git url, default branch and protocols it supports func parseSource(source string) (url string, branch string, protocols []string) { - if !(strings.Contains(source, "git://") || - strings.Contains(source, ".git") || - strings.Contains(source, "git+https://")) { - return "", "", nil - } split := strings.Split(source, "::") source = split[len(split)-1] split = strings.SplitN(source, "://", 2) @@ -76,8 +71,20 @@ func parseSource(source string) (url string, branch string, protocols []string) if len(split) != 2 { return "", "", nil } - protocols = strings.Split(split[0], "+") + + git := false + for _, protocol := range protocols { + if protocol == "git" { + git = true + break + } + } + + if !git { + return "", "", nil + } + split = strings.SplitN(split[1], "#", 2) if len(split) == 2 { secondSplit := strings.SplitN(split[1], "=", 2) From 297bf31cdf79f10e12d5faa4664eb0cc1b760e9e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 23:07:36 +0100 Subject: [PATCH 098/155] Set GIT_TERMINAL_PROMPT=0 for clone and fetch --- download.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/download.go b/download.go index c1fafe91..ae8c38d6 100644 --- a/download.go +++ b/download.go @@ -60,7 +60,9 @@ func gitHasDiff(path string, name string) (bool, error) { func gitDownload(url string, path string, name string) (bool, error) { _, err := os.Stat(filepath.Join(path, name, ".git")) if os.IsNotExist(err) { - _, stderr, err := capture(passToGit(path, "clone", "--no-progress", url, name)) + cmd := passToGit(path, "clone", "--no-progress", url, name) + cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0") + _, stderr, err := capture(cmd) if err != nil { return false, fmt.Errorf("error cloning %s: stderr", name, stderr) } @@ -70,7 +72,9 @@ func gitDownload(url string, path string, name string) (bool, error) { return false, fmt.Errorf("error reading %s", filepath.Join(path, name, ".git")) } - _, stderr, err := capture(passToGit(filepath.Join(path, name), "fetch")) + cmd := passToGit(filepath.Join(path, name), "fetch") + cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0") + _, stderr, err := capture(cmd) if err != nil { return false, fmt.Errorf("error fetching %s: %s", name, stderr) } From 284c87afb6fd22b5877e2ba088cc9d8ee209abf5 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 23:30:48 +0100 Subject: [PATCH 099/155] Parallelize gendb --- install.go | 7 ++++++- vcs.go | 30 ++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/install.go b/install.go index 03c36f68..8ff93166 100644 --- a/install.go +++ b/install.go @@ -998,10 +998,15 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc return err } + var mux sync.Mutex + var wg sync.WaitGroup for _, pkg := range do.Bases[pkg.PackageBase] { - updateVCSData(pkg.Name, srcinfo.Source) + wg.Add(1) + go updateVCSData(pkg.Name, srcinfo.Source, &mux, &wg) } + wg.Wait() + err = saveVCSInfo() if err != nil { fmt.Println(err) diff --git a/vcs.go b/vcs.go index 9ba31072..2863cc01 100644 --- a/vcs.go +++ b/vcs.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "strings" + "sync" "time" gosrc "github.com/Morganamilo/go-srcinfo" @@ -23,6 +24,8 @@ type shaInfo struct { // createDevelDB forces yay to create a DB of the existing development packages func createDevelDB() error { + var mux sync.Mutex + var wg sync.WaitGroup infoMap := make(map[string]*rpc.Pkg) srcinfosStale := make(map[string]*gosrc.Srcinfo) @@ -53,12 +56,13 @@ func createDevelDB() error { } for _, pkg := range bases[pkg.PackageBase] { - updateVCSData(pkg.Name, pkgbuild.Source) + wg.Add(1) + go updateVCSData(pkg.Name, pkgbuild.Source, &mux, &wg) } } + wg.Wait() fmt.Println(bold(yellow(arrow) + bold(" GenDB finished. No packages were installed"))) - return err } @@ -109,22 +113,26 @@ func parseSource(source string) (url string, branch string, protocols []string) return } -func updateVCSData(pkgName string, sources []gosrc.ArchString) { +func updateVCSData(pkgName string, sources []gosrc.ArchString, mux *sync.Mutex, wg *sync.WaitGroup) { + defer wg.Done() + if savedInfo == nil { + mux.Lock() savedInfo = make(vcsInfo) + mux.Unlock() } info := make(shaInfos) - - for _, source := range sources { + checkSource := func(source gosrc.ArchString) { + defer wg.Done() url, branch, protocols := parseSource(source.Value) if url == "" || branch == "" { - continue + return } commit := getCommit(url, branch, protocols) if commit == "" { - continue + return } info[url] = shaInfo{ @@ -133,10 +141,16 @@ func updateVCSData(pkgName string, sources []gosrc.ArchString) { commit, } + mux.Lock() savedInfo[pkgName] = info - fmt.Println(bold(yellow(arrow)) + " Found git repo: " + cyan(url)) saveVCSInfo() + mux.Unlock() + } + + for _, source := range sources { + wg.Add(1) + go checkSource(source) } } From 2de67d1b24eab73840b919b566ae782830a3909b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 23:44:55 +0100 Subject: [PATCH 100/155] Show message for timed out vcs checks --- vcs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/vcs.go b/vcs.go index 2863cc01..f6abae19 100644 --- a/vcs.go +++ b/vcs.go @@ -173,6 +173,7 @@ func getCommit(url string, branch string, protocols []string) string { //Introduce a time out so this can not hang timer := time.AfterFunc(5*time.Second, func() { cmd.Process.Kill() + fmt.Println(bold(yellow(arrow)), "Timeout:", cyan(url)) }) err = cmd.Wait() From 602f386b03c59fb26982e9b554c54b82450f2ebf Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 3 Aug 2018 00:36:47 +0100 Subject: [PATCH 101/155] Loop over srcinfos instead of pkglist in gendb --- vcs.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/vcs.go b/vcs.go index f6abae19..ac897f19 100644 --- a/vcs.go +++ b/vcs.go @@ -49,15 +49,10 @@ func createDevelDB() error { downloadPkgBuilds(info, bases, toSkip) tryParsesrcinfosFile(info, srcinfosStale, bases) - for _, pkg := range info { - pkgbuild, ok := srcinfosStale[pkg.PackageBase] - if !ok { - continue - } - - for _, pkg := range bases[pkg.PackageBase] { + for _, pkgbuild := range srcinfosStale { + for _, pkg := range pkgbuild.Packages { wg.Add(1) - go updateVCSData(pkg.Name, pkgbuild.Source, &mux, &wg) + go updateVCSData(pkg.Pkgname, pkgbuild.Source, &mux, &wg) } } From 86ef1ec077c4c86faf8b4f8e350912462253d15d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 9 Aug 2018 17:01:29 +0100 Subject: [PATCH 102/155] Include info in the lock --- vcs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcs.go b/vcs.go index ac897f19..41569296 100644 --- a/vcs.go +++ b/vcs.go @@ -130,13 +130,13 @@ func updateVCSData(pkgName string, sources []gosrc.ArchString, mux *sync.Mutex, return } + mux.Lock() info[url] = shaInfo{ protocols, branch, commit, } - mux.Lock() savedInfo[pkgName] = info fmt.Println(bold(yellow(arrow)) + " Found git repo: " + cyan(url)) saveVCSInfo() From 8cb800c6d1a44dac28a050f2bfb767935927f10c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 9 Aug 2018 19:44:56 +0100 Subject: [PATCH 103/155] Dont change std{out,err,in} in passToGit This should be done in show instead --- exec.go | 1 - 1 file changed, 1 deletion(-) diff --git a/exec.go b/exec.go index 394f59b4..facecf71 100644 --- a/exec.go +++ b/exec.go @@ -119,6 +119,5 @@ func passToGit(dir string, _args ...string) *exec.Cmd { args = append(args, _args...) cmd := exec.Command(config.GitBin, args...) - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd } From 00f2cffc453bcf036f6d4a5d1623d90ac6d7797a Mon Sep 17 00:00:00 2001 From: Architekton Date: Sun, 12 Aug 2018 09:13:40 +1000 Subject: [PATCH 104/155] Remove redundant variable --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index cd5991b0..39bb7fb3 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,6 @@ endif VERSION := ${MAJORVERSION}.${MINORVERSION} LDFLAGS := -ldflags '-s -w -X main.version=${VERSION}' -GOFILES := $(shell ls *.go | grep -v /vendor/) ARCH := $(shell uname -m) PKGNAME := yay BINNAME := yay From 1739a88be2b8e74e9d95d927f2b860a1c3ed29e0 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 20:45:41 +0100 Subject: [PATCH 105/155] Refactor main function Move cleanup and error checking to their own functions. --- main.go | 93 +++++++++++++++++---------------------------------------- 1 file changed, 28 insertions(+), 65 deletions(-) diff --git a/main.go b/main.go index 0087a58b..11130977 100644 --- a/main.go +++ b/main.go @@ -190,75 +190,38 @@ func initAlpmHandle() (err error) { return } -func main() { - var status int - var err error +func exitOnError(err error) { + if err != nil { + if str := err.Error(); str != "" { + fmt.Println(str) + } + cleanup() + os.Exit(1) + } +} +func cleanup() int { + if alpmHandle != nil { + if err := alpmHandle.Release(); err != nil { + fmt.Println(err) + return 1 + } + } + + return 0 +} + +func main() { if 0 == os.Geteuid() { fmt.Println("Please avoid running yay as root/sudo.") } - err = cmdArgs.parseCommandLine() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } - - err = setPaths() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } - - err = initConfig() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } - + exitOnError(cmdArgs.parseCommandLine()) + exitOnError(setPaths()) + exitOnError(initConfig()) cmdArgs.extractYayOptions() - - err = initVCS() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - - } - - err = initAlpm() - if err != nil { - fmt.Println(err) - status = 1 - goto cleanup - } - - err = handleCmd() - if err != nil { - if err.Error() != "" { - fmt.Println(err) - } - - status = 1 - goto cleanup - } - -cleanup: - //cleanup - //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 - - if alpmHandle != nil { - err = alpmHandle.Release() - if err != nil { - fmt.Println(err) - status = 1 - } - } - - os.Exit(status) + exitOnError(initVCS()) + exitOnError(initAlpm()) + exitOnError(handleCmd()) + os.Exit(cleanup()) } From 2fac9c036fb938ccaa70652203e497ac8a9c8190 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 2 Aug 2018 21:36:42 +0100 Subject: [PATCH 106/155] Refactor main.go to use one liner if err checks --- main.go | 161 +++++++++++++++++++++++++------------------------------- 1 file changed, 73 insertions(+), 88 deletions(-) diff --git a/main.go b/main.go index 11130977..262bb054 100644 --- a/main.go +++ b/main.go @@ -45,98 +45,88 @@ func setPaths() error { return nil } -func initConfig() (err error) { +func initConfig() error { defaultSettings(&config) - if _, err = os.Stat(configFile); os.IsNotExist(err) { - err = os.MkdirAll(filepath.Dir(configFile), 0755) - if err != nil { - err = fmt.Errorf("Unable to create config directory:\n%s\n"+ + if _, err := os.Stat(configFile); os.IsNotExist(err) { + if err = os.MkdirAll(filepath.Dir(configFile), 0755); err != nil { + return fmt.Errorf("Unable to create config directory:\n%s\n"+ "The error was:\n%s", filepath.Dir(configFile), err) - return } // Save the default config if nothing is found - config.saveConfig() - } else { - cfile, errf := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) - if errf != nil { - fmt.Printf("Error reading config: %s\n", err) - } else { - defer cfile.Close() - decoder := json.NewDecoder(cfile) - err = decoder.Decode(&config) - if err != nil { - fmt.Println("Loading default Settings.\nError reading config:", - 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 - } - } - } + return config.saveConfig() + } else if err != nil { + return err } - return -} - -func initVCS() (err error) { - if _, err = os.Stat(vcsFile); os.IsNotExist(err) { - err = os.MkdirAll(filepath.Dir(vcsFile), 0755) - if err != nil { - err = fmt.Errorf("Unable to create vcs directory:\n%s\n"+ - "The error was:\n%s", filepath.Dir(configFile), err) - return - } - } else { - vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) - if err == nil { - defer vfile.Close() - decoder := json.NewDecoder(vfile) - _ = decoder.Decode(&savedInfo) - } - } - - return -} - -func initAlpm() (err error) { - var value string - var exists bool - //var double bool - - alpmConf, err = readAlpmConfig(config.PacmanConf) + cfile, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) if err != nil { - err = fmt.Errorf("Unable to read Pacman conf: %s", err) - return + return fmt.Errorf("Error reading config: %s\n", err) } - value, _, exists = cmdArgs.getArg("dbpath", "b") - if exists { + defer cfile.Close() + decoder := json.NewDecoder(cfile) + if err = decoder.Decode(&config); err != nil { + return fmt.Errorf("Error reading config: %s", + err) + } + + if _, err = os.Stat(config.BuildDir); os.IsNotExist(err) { + if err = os.MkdirAll(config.BuildDir, 0755); err != nil { + return fmt.Errorf("Unable to create BuildDir directory:\n%s\n"+ + "The error was:\n%s", config.BuildDir, err) + } + } + + return err +} + +func initVCS() error { + if _, err := os.Stat(vcsFile); os.IsNotExist(err) { + if err = os.MkdirAll(filepath.Dir(vcsFile), 0755); err != nil { + return fmt.Errorf("Unable to create vcs directory:\n%s\n"+ + "The error was:\n%s", filepath.Dir(configFile), err) + } + } else if err != nil { + return err + } + + vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) + if err != nil { + return err + } + + defer vfile.Close() + decoder := json.NewDecoder(vfile) + _ = decoder.Decode(&savedInfo) + + return nil +} + +func initAlpm() error { + var err error + + if alpmConf, err = readAlpmConfig(config.PacmanConf); err != nil { + return fmt.Errorf("Unable to read Pacman conf: %s", err) + } + + if value, _, exists := cmdArgs.getArg("dbpath", "b"); exists { alpmConf.DBPath = value } - value, _, exists = cmdArgs.getArg("root", "r") - if exists { + if value, _, exists := cmdArgs.getArg("root", "r"); exists { alpmConf.RootDir = value } - value, _, exists = cmdArgs.getArg("arch") - if exists { + if value, _, exists := cmdArgs.getArg("arch"); exists { alpmConf.Architecture = value } - value, _, exists = cmdArgs.getArg("ignore") - if exists { + if value, _, exists := cmdArgs.getArg("ignore"); exists { alpmConf.IgnorePkg = append(alpmConf.IgnorePkg, strings.Split(value, ",")...) } - value, _, exists = cmdArgs.getArg("ignoregroup") - if exists { + if value, _, exists := cmdArgs.getArg("ignoregroup"); exists { alpmConf.IgnoreGroup = append(alpmConf.IgnoreGroup, strings.Split(value, ",")...) } @@ -144,23 +134,19 @@ func initAlpm() (err error) { //current system does not allow duplicate arguments //but pacman allows multiple cachdirs to be passed //for now only handle one cache dir - value, _, exists = cmdArgs.getArg("cachdir") - if exists { + if value, _, exists := cmdArgs.getArg("cachdir"); exists { alpmConf.CacheDir = []string{value} } - value, _, exists = cmdArgs.getArg("gpgdir") - if exists { + if value, _, exists := cmdArgs.getArg("gpgdir"); exists { alpmConf.GPGDir = value } - err = initAlpmHandle() - if err != nil { - return + if err = initAlpmHandle(); err != nil { + return err } - value, _, _ = cmdArgs.getArg("color") - if value == "always" || value == "auto" { + if value, _, _ := cmdArgs.getArg("color"); value == "always" || value == "auto" { useColor = true } else if value == "never" { useColor = false @@ -168,26 +154,25 @@ func initAlpm() (err error) { useColor = alpmConf.Options&alpm.ConfColor > 0 } - return + return nil } -func initAlpmHandle() (err error) { +func initAlpmHandle() error { + var err error + if alpmHandle != nil { - err = alpmHandle.Release() - if err != nil { + if err := alpmHandle.Release(); err != nil { return err } } - alpmHandle, err = alpmConf.CreateHandle() - if err != nil { - err = fmt.Errorf("Unable to CreateHandle: %s", err) - return + if alpmHandle, err = alpmConf.CreateHandle(); err != nil { + return fmt.Errorf("Unable to CreateHandle: %s", err) } alpmHandle.SetQuestionCallback(questionCallback) alpmHandle.SetLogCallback(logCallback) - return + return nil } func exitOnError(err error) { From febccaef3a74aa07cc585dcd235390f5a0d77ee0 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 12 Aug 2018 02:40:43 +0100 Subject: [PATCH 107/155] Reorder main Split functions out into smaller, more simple chunks. Ensure the correct order of things. Before, initConfig() would also create config.BuildDirbefore the command line flags have been applied, so yay would try to mkdir what was in the config, ignoring the flag. --- main.go | 86 +++++++++++++++++++++++++++++++------------------------ parser.go | 1 + 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/main.go b/main.go index 262bb054..73cf2f4b 100644 --- a/main.go +++ b/main.go @@ -46,59 +46,67 @@ func setPaths() error { } func initConfig() error { - defaultSettings(&config) - - if _, err := os.Stat(configFile); os.IsNotExist(err) { - if err = os.MkdirAll(filepath.Dir(configFile), 0755); err != nil { - return fmt.Errorf("Unable to create config directory:\n%s\n"+ - "The error was:\n%s", filepath.Dir(configFile), err) - } - // Save the default config if nothing is found - return config.saveConfig() - } else if err != nil { - return err - } - - cfile, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644) - if err != nil { - return fmt.Errorf("Error reading config: %s\n", err) + cfile, err := os.Open(configFile) + if !os.IsNotExist(err) && err != nil { + return fmt.Errorf("Failed to open config file '%s': %s", configFile, err) } defer cfile.Close() - decoder := json.NewDecoder(cfile) - if err = decoder.Decode(&config); err != nil { - return fmt.Errorf("Error reading config: %s", - err) - } - - if _, err = os.Stat(config.BuildDir); os.IsNotExist(err) { - if err = os.MkdirAll(config.BuildDir, 0755); err != nil { - return fmt.Errorf("Unable to create BuildDir directory:\n%s\n"+ - "The error was:\n%s", config.BuildDir, err) + if !os.IsNotExist(err) { + decoder := json.NewDecoder(cfile) + if err = decoder.Decode(&config); err != nil { + return fmt.Errorf("Failed to read config '%s': %s", configFile, err) } } - return err + return nil } func initVCS() error { - if _, err := os.Stat(vcsFile); os.IsNotExist(err) { - if err = os.MkdirAll(filepath.Dir(vcsFile), 0755); err != nil { - return fmt.Errorf("Unable to create vcs directory:\n%s\n"+ - "The error was:\n%s", filepath.Dir(configFile), err) + vfile, err := os.Open(vcsFile) + if !os.IsNotExist(err) && err != nil { + return fmt.Errorf("Failed to open vcs file '%s': %s", vcsFile, err) + } + + defer vfile.Close() + if !os.IsNotExist(err) { + decoder := json.NewDecoder(vfile) + if err = decoder.Decode(&savedInfo); err != nil { + return fmt.Errorf("Failed to read vcs '%s': %s", vcsFile, err) + } + } + + return nil +} + +func initHomeDirs() error { + if _, err := os.Stat(configHome); os.IsNotExist(err) { + if err = os.MkdirAll(configHome, 0755); err != nil { + return fmt.Errorf("Failed to create config directory '%s': %s", configHome, err) } } else if err != nil { return err } - vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644) - if err != nil { + if _, err := os.Stat(cacheHome); os.IsNotExist(err) { + if err = os.MkdirAll(cacheHome, 0755); err != nil { + return fmt.Errorf("Failed to create cache directory '%s': %s", cacheHome, err) + } + } else if err != nil { return err } - defer vfile.Close() - decoder := json.NewDecoder(vfile) - _ = decoder.Decode(&savedInfo) + return nil +} + +func initBuildDir() error { + if _, err := os.Stat(config.BuildDir); os.IsNotExist(err) { + if err = os.MkdirAll(config.BuildDir, 0755); err != nil { + return fmt.Errorf("Failed to create BuildDir directory '%s': %s", config.BuildDir, err) + } + } else if err != nil { + return err + } return nil } @@ -201,10 +209,12 @@ func main() { fmt.Println("Please avoid running yay as root/sudo.") } - exitOnError(cmdArgs.parseCommandLine()) exitOnError(setPaths()) + defaultSettings(&config) + exitOnError(initHomeDirs()) exitOnError(initConfig()) - cmdArgs.extractYayOptions() + exitOnError(cmdArgs.parseCommandLine()) + exitOnError(initBuildDir()) exitOnError(initVCS()) exitOnError(initAlpm()) exitOnError(handleCmd()) diff --git a/parser.go b/parser.go index b4d22d5c..27b45589 100644 --- a/parser.go +++ b/parser.go @@ -853,6 +853,7 @@ func (parser *arguments) parseCommandLine() (err error) { os.Stdin = file } + cmdArgs.extractYayOptions() return } From 339a0146143c8a30b9b1e89a5426ac4c9805d57f Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 12 Aug 2018 04:11:34 +0100 Subject: [PATCH 108/155] Go back to using os.Getenv Most programs seem to take an empty string as being the same as unset. Even if they are technically different. This makes it easier to unset variables via `VARIABLE= yay --foo`. --- main.go | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/main.go b/main.go index 73cf2f4b..53a6db58 100644 --- a/main.go +++ b/main.go @@ -11,30 +11,18 @@ import ( ) func setPaths() error { - if _configHome, set := os.LookupEnv("XDG_CONFIG_HOME"); set { - if _configHome == "" { - return fmt.Errorf("XDG_CONFIG_HOME set but empty") - } - configHome = filepath.Join(_configHome, "yay") - } else if _configHome, set := os.LookupEnv("HOME"); set { - if _configHome == "" { - return fmt.Errorf("HOME set but empty") - } - configHome = filepath.Join(_configHome, ".config/yay") + if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" { + configHome = filepath.Join(configHome, "yay") + } else if configHome = os.Getenv("HOME"); configHome != "" { + configHome = filepath.Join(configHome, ".config/yay") } else { return fmt.Errorf("XDG_CONFIG_HOME and HOME unset") } - if _cacheHome, set := os.LookupEnv("XDG_CACHE_HOME"); set { - if _cacheHome == "" { - return fmt.Errorf("XDG_CACHE_HOME set but empty") - } - cacheHome = filepath.Join(_cacheHome, "yay") - } else if _cacheHome, set := os.LookupEnv("HOME"); set { - if _cacheHome == "" { - return fmt.Errorf("XDG_CACHE_HOME set but empty") - } - cacheHome = filepath.Join(_cacheHome, ".cache/yay") + if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" { + cacheHome = filepath.Join(cacheHome, "yay") + } else if cacheHome = os.Getenv("HOME"); cacheHome != "" { + cacheHome = filepath.Join(cacheHome, ".cache/yay") } else { return fmt.Errorf("XDG_CACHE_HOME and HOME unset") } From 3dc350d3acd7c9679d3ebd0f22e7441875b6ccf5 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 9 Aug 2018 22:28:27 +0100 Subject: [PATCH 109/155] Simplify formatPkgBase Only pass the packages belonging to the desired pkgbase. Before our entire list of every pkgbase had to be passed, as well as an example package from the base we are looking for. This lets use use formatPkgBase easier in other places outside of install. Many of the functions in install could also be simplified in a similar way, although that has not been done in this commit. --- install.go | 16 ++++++++-------- keys.go | 2 +- print.go | 7 ++++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/install.go b/install.go index 8ff93166..c67dc230 100644 --- a/install.go +++ b/install.go @@ -94,7 +94,7 @@ func install(parser *arguments) error { } for up := range aurUp { - requestTargets = append(requestTargets, "aur/" + up) + requestTargets = append(requestTargets, "aur/"+up) parser.addTarget("aur/" + up) } @@ -493,7 +493,7 @@ func pkgbuildNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed dir := filepath.Join(config.BuildDir, pkg.PackageBase) toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(pkgs)-n, - bold(formatPkgbase(pkg, bases))) + bold(formatPkgbase(bases[pkg.PackageBase]))) if installed.get(pkg.Name) { toPrint += bold(green(" (Installed)")) } @@ -669,7 +669,7 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri } if !hasDiff { - fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(pkg, bases)), bold("No changes -- skipping")) + fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(bases[pkg.PackageBase])), bold("No changes -- skipping")) continue } } @@ -732,7 +732,7 @@ func parseSRCINFOFiles(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, base dir := filepath.Join(config.BuildDir, pkg.PackageBase) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) + fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { @@ -750,7 +750,7 @@ func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, b dir := filepath.Join(config.BuildDir, pkg.PackageBase) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases))) + fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { @@ -808,7 +808,7 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri mux.Lock() downloaded++ str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") - fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(pkg, bases))) + fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) mux.Unlock() return } @@ -835,7 +835,7 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri mux.Lock() downloaded++ str := bold(cyan("::") + " Downloaded PKGBUILD (%d/%d): %s\n") - fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(pkg, bases))) + fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) mux.Unlock() } @@ -860,7 +860,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco err = show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error downloading sources: %s", cyan(formatPkgbase(pkg, bases))) + return fmt.Errorf("Error downloading sources: %s", cyan(formatPkgbase(bases[pkg.PackageBase]))) } } diff --git a/keys.go b/keys.go index 89fe3666..66583427 100644 --- a/keys.go +++ b/keys.go @@ -115,7 +115,7 @@ func formatKeysToImport(keys pgpKeySet, bases map[string][]*rpc.Pkg) (string, er for key, pkgs := range keys { pkglist := "" for _, pkg := range pkgs { - pkglist += formatPkgbase(pkg, bases) + " " + pkglist += formatPkgbase(bases[pkg.PackageBase]) + " " } pkglist = strings.TrimRight(pkglist, " ") buffer.WriteString(fmt.Sprintf("\n%s %s, required by: %s", yellow(bold(smallArrow)), cyan(key), cyan(pkglist))) diff --git a/print.go b/print.go index 2f2f27c7..15dc6ea1 100644 --- a/print.go +++ b/print.go @@ -143,11 +143,12 @@ func (s repoQuery) printSearch() { // Pretty print a set of packages from the same package base. // Packages foo and bar from a pkgbase named base would print like so: // base (foo bar) -func formatPkgbase(pkg *rpc.Pkg, bases map[string][]*rpc.Pkg) string { +func formatPkgbase(base []*rpc.Pkg) string { + pkg := base[0] str := pkg.PackageBase - if len(bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name { + if len(base) > 1 || pkg.PackageBase != pkg.Name { str2 := " (" - for _, split := range bases[pkg.PackageBase] { + for _, split := range base { str2 += split.Name + " " } str2 = str2[:len(str2)-1] + ")" From 43feb12c852c91ff932931b4a56d27183d9e545a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 10 Aug 2018 04:40:27 +0100 Subject: [PATCH 110/155] Merge handles.Aur and depOrder.Bases depOrder.Aur contains the order in which AUR packages are to be installed. While depOrder.bases contains the actual package data organized by pkgbase. deoOrder.AUR is kind of counterintuitive, as it only contains one package from each package base. For example if you were to install libc++{,abi,experimental}, depOrder.Aur would only contain one of those packages, which one actually being quite random. depOrder.Bases[pkg.Pkgbase] will then be looked up and everything under that slice would be installed. This means that the only real use depOrder.Aur has, is to give the pkgbase. So to cut out the middleman, lets merge .Aur and .Bases into a single field. Doing this has also heped to spot som subtle bugs: Fix subtle split package errors. The number menus now correctly list and respect (installed) for bases that have atleast one of their packages installed. Entering package names in number menus now always expects the pkgbase name instead of the random package which happened to make it into .Aur. --rebuild and --redownload correctly handles split packages. formatPkgbase is also used more. --- dep.go | 16 +-- depOrder.go | 43 +++++--- install.go | 279 +++++++++++++++++++++++++++++----------------------- keys.go | 33 +++---- print.go | 11 ++- vcs.go | 8 +- 6 files changed, 219 insertions(+), 171 deletions(-) diff --git a/dep.go b/dep.go index 47c8c0a5..8accb678 100644 --- a/dep.go +++ b/dep.go @@ -149,15 +149,15 @@ func splitDbFromName(pkg string) (string, string) { return "", split[0] } -func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { - bases := make(map[string][]*rpc.Pkg) - +func getBases(pkgs map[string]*rpc.Pkg) []Base { + basesMap := make(map[string]Base) 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) + basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg) + } + + bases := make([]Base, 0, len(basesMap)) + for _, base := range basesMap { + bases = append(bases, base) } return bases diff --git a/depOrder.go b/depOrder.go index bb3a5273..f1d0e4cb 100644 --- a/depOrder.go +++ b/depOrder.go @@ -5,35 +5,48 @@ import ( rpc "github.com/mikkeloscar/aur" ) +type Base []*rpc.Pkg + +func (b Base) Pkgbase() string { + return b[0].PackageBase +} + +func (b Base) Version() string { + return b[0].Version +} + +func (b Base) URLPath() string { + return b[0].URLPath +} + type depOrder struct { - Aur []*rpc.Pkg + Aur []Base Repo []*alpm.Package Runtime stringSet - Bases map[string][]*rpc.Pkg } func makeDepOrder() *depOrder { return &depOrder{ - make([]*rpc.Pkg, 0), + make([]Base, 0), make([]*alpm.Package, 0), make(stringSet), - make(map[string][]*rpc.Pkg), } } func getDepOrder(dp *depPool) *depOrder { do := makeDepOrder() + basesMap := make(map[string]Base) for _, target := range dp.Targets { dep := target.DepString() aurPkg := dp.Aur[dep] if aurPkg != nil && pkgSatisfies(aurPkg.Name, aurPkg.Version, dep) { - do.orderPkgAur(aurPkg, dp, true) + do.orderPkgAur(aurPkg, dp, basesMap, true) } aurPkg = dp.findSatisfierAur(dep) if aurPkg != nil { - do.orderPkgAur(aurPkg, dp, true) + do.orderPkgAur(aurPkg, dp, basesMap, true) } repoPkg := dp.findSatisfierRepo(dep) @@ -42,10 +55,14 @@ func getDepOrder(dp *depPool) *depOrder { } } + for _, base := range basesMap { + do.Aur = append(do.Aur, base) + } + return do } -func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { +func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, basesMap map[string]Base, runtime bool) { if runtime { do.Runtime.set(pkg.Name) } @@ -55,7 +72,7 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { for _, dep := range deps { aurPkg := dp.findSatisfierAur(dep) if aurPkg != nil { - do.orderPkgAur(aurPkg, dp, runtime && i == 0) + do.orderPkgAur(aurPkg, dp, basesMap, runtime && i == 0) } repoPkg := dp.findSatisfierRepo(dep) @@ -65,11 +82,7 @@ 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) + basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg) } func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { @@ -92,7 +105,7 @@ func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { func (do *depOrder) HasMake() bool { lenAur := 0 - for _, base := range do.Bases { + for _, base := range do.Aur { lenAur += len(base) } @@ -102,7 +115,7 @@ func (do *depOrder) HasMake() bool { func (do *depOrder) getMake() []string { makeOnly := make([]string, 0, len(do.Aur)+len(do.Repo)-len(do.Runtime)) - for _, base := range do.Bases { + for _, base := range do.Aur { for _, pkg := range base { if !do.Runtime.get(pkg.Name) { makeOnly = append(makeOnly, pkg.Name) diff --git a/install.go b/install.go index c67dc230..89beaa0c 100644 --- a/install.go +++ b/install.go @@ -11,7 +11,6 @@ import ( gosrc "github.com/Morganamilo/go-srcinfo" alpm "github.com/jguer/go-alpm" - rpc "github.com/mikkeloscar/aur" ) // Install handles package installs @@ -176,7 +175,7 @@ func install(parser *arguments) error { } if config.CleanMenu { - askClean := pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + askClean := pkgbuildNumberMenu(do.Aur, remoteNamesCache) toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean) if err != nil { return err @@ -186,23 +185,23 @@ func install(parser *arguments) error { } toSkip := pkgBuildsToSkip(do.Aur, targets) - cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) + cloned, err := downloadPkgBuilds(do.Aur, toSkip) if err != nil { return err } - var toDiff []*rpc.Pkg - var toEdit []*rpc.Pkg + var toDiff []Base + var toEdit []Base if config.DiffMenu { - pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + pkgbuildNumberMenu(do.Aur, remoteNamesCache) toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache) if err != nil { return err } if len(toDiff) > 0 { - err = showPkgBuildDiffs(toDiff, do.Bases, cloned) + err = showPkgBuildDiffs(toDiff, cloned) if err != nil { return err } @@ -225,13 +224,13 @@ func install(parser *arguments) error { } //initial srcinfo parse before pkgver() bump - err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases) + err = parseSRCINFOFiles(do.Aur, srcinfosStale) if err != nil { return err } if config.EditMenu { - pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) + pkgbuildNumberMenu(do.Aur, remoteNamesCache) toEdit, err = editNumberMenu(do.Aur, remoteNamesCache) if err != nil { return err @@ -255,13 +254,14 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } + //TODO: fix for split packages maybe? incompatible, err = getIncompatible(do.Aur, srcinfosStale) if err != nil { return err } if config.PGPFetch { - err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) + err = checkPgpKeys(do.Aur, srcinfosStale) if err != nil { return err } @@ -312,7 +312,7 @@ func install(parser *arguments) error { go updateCompletion(false) - err = downloadPkgBuildsSources(do.Aur, do.Bases, incompatible) + err = downloadPkgBuildsSources(do.Aur, incompatible) if err != nil { return err } @@ -416,7 +416,7 @@ func earlyRefresh(parser *arguments) error { return show(passToPacman(arguments)) } -func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) (stringSet, error) { +func getIncompatible(bases []Base, srcinfos map[string]*gosrc.Srcinfo) (stringSet, error) { incompatible := make(stringSet) alpmArch, err := alpmHandle.Arch() if err != nil { @@ -424,14 +424,14 @@ func getIncompatible(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) (strin } nextpkg: - for _, pkg := range pkgs { - for _, arch := range srcinfos[pkg.PackageBase].Arch { + for _, base := range bases { + for _, arch := range srcinfos[base.Pkgbase()].Arch { if arch == "any" || arch == alpmArch { continue nextpkg } } - incompatible.set(pkg.PackageBase) + incompatible.set(base.Pkgbase()) } if len(incompatible) > 0 { @@ -485,16 +485,23 @@ func parsePackageList(dir string) (map[string]string, string, error) { return pkgdests, version, nil } -func pkgbuildNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) bool { +func pkgbuildNumberMenu(bases []Base, installed stringSet) bool { toPrint := "" askClean := false - for n, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) + for n, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) - toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(pkgs)-n, - bold(formatPkgbase(bases[pkg.PackageBase]))) - if installed.get(pkg.Name) { + toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(bases)-n, + bold(formatPkgbase(base))) + + anyInstalled := false + for _, b := range base { + anyInstalled = anyInstalled || installed.get(b.Name) + } + + if anyInstalled { toPrint += bold(green(" (Installed)")) } @@ -511,8 +518,8 @@ func pkgbuildNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed return askClean } -func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rpc.Pkg, error) { - toClean := make([]*rpc.Pkg, 0) +func cleanNumberMenu(bases []Base, installed stringSet, hasClean bool) ([]Base, error) { + toClean := make([]Base, 0) if !hasClean { return toClean, nil @@ -534,38 +541,44 @@ func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rp } if !cOtherInclude.get("n") && !cOtherInclude.get("none") { - for i, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) + for i, base := range bases { + pkg := base.Pkgbase() + anyInstalled := false + for _, b := range base { + anyInstalled = anyInstalled || installed.get(b.Name) + } + + dir := filepath.Join(config.BuildDir, pkg) if _, err := os.Stat(dir); os.IsNotExist(err) { continue } - if !cIsInclude && cExclude.get(len(pkgs)-i) { + if !cIsInclude && cExclude.get(len(bases)-i) { continue } - if installed.get(pkg.Name) && (cOtherInclude.get("i") || cOtherInclude.get("installed")) { - toClean = append(toClean, pkg) + if anyInstalled && (cOtherInclude.get("i") || cOtherInclude.get("installed")) { + toClean = append(toClean, base) continue } - if !installed.get(pkg.Name) && (cOtherInclude.get("no") || cOtherInclude.get("notinstalled")) { - toClean = append(toClean, pkg) + if !anyInstalled && (cOtherInclude.get("no") || cOtherInclude.get("notinstalled")) { + toClean = append(toClean, base) continue } if cOtherInclude.get("a") || cOtherInclude.get("all") { - toClean = append(toClean, pkg) + toClean = append(toClean, base) continue } - if cIsInclude && (cInclude.get(len(pkgs)-i) || cOtherInclude.get(pkg.PackageBase)) { - toClean = append(toClean, pkg) + if cIsInclude && (cInclude.get(len(bases)-i) || cOtherInclude.get(pkg)) { + toClean = append(toClean, base) continue } - if !cIsInclude && (!cExclude.get(len(pkgs)-i) && !cOtherExclude.get(pkg.PackageBase)) { - toClean = append(toClean, pkg) + if !cIsInclude && (!cExclude.get(len(bases)-i) && !cOtherExclude.get(pkg)) { + toClean = append(toClean, base) continue } } @@ -574,16 +587,16 @@ func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rp return toClean, nil } -func editNumberMenu(pkgs []*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { - return editDiffNumberMenu(pkgs, installed, false) +func editNumberMenu(bases []Base, installed stringSet) ([]Base, error) { + return editDiffNumberMenu(bases, installed, false) } -func diffNumberMenu(pkgs []*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { - return editDiffNumberMenu(pkgs, installed, true) +func diffNumberMenu(bases []Base, installed stringSet) ([]Base, error) { + return editDiffNumberMenu(bases, installed, true) } -func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc.Pkg, error) { - toEdit := make([]*rpc.Pkg, 0) +func editDiffNumberMenu(bases []Base, installed stringSet, diff bool) ([]Base, error) { + toEdit := make([]Base, 0) var editInput string var err error @@ -613,32 +626,38 @@ func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc } if !eOtherInclude.get("n") && !eOtherInclude.get("none") { - for i, pkg := range pkgs { - if !eIsInclude && eExclude.get(len(pkgs)-i) { + for i, base := range bases { + pkg := base.Pkgbase() + anyInstalled := false + for _, b := range base { + anyInstalled = anyInstalled || installed.get(b.Name) + } + + if !eIsInclude && eExclude.get(len(bases)-i) { continue } - if installed.get(pkg.Name) && (eOtherInclude.get("i") || eOtherInclude.get("installed")) { - toEdit = append(toEdit, pkg) + if anyInstalled && (eOtherInclude.get("i") || eOtherInclude.get("installed")) { + toEdit = append(toEdit, base) continue } - if !installed.get(pkg.Name) && (eOtherInclude.get("no") || eOtherInclude.get("notinstalled")) { - toEdit = append(toEdit, pkg) + if !anyInstalled && (eOtherInclude.get("no") || eOtherInclude.get("notinstalled")) { + toEdit = append(toEdit, base) continue } if eOtherInclude.get("a") || eOtherInclude.get("all") { - toEdit = append(toEdit, pkg) + toEdit = append(toEdit, base) continue } - if eIsInclude && (eInclude.get(len(pkgs)-i) || eOtherInclude.get(pkg.PackageBase)) { - toEdit = append(toEdit, pkg) + if eIsInclude && (eInclude.get(len(bases)-i) || eOtherInclude.get(pkg)) { + toEdit = append(toEdit, base) } - if !eIsInclude && (!eExclude.get(len(pkgs)-i) && !eOtherExclude.get(pkg.PackageBase)) { - toEdit = append(toEdit, pkg) + if !eIsInclude && (!eExclude.get(len(bases)-i) && !eOtherExclude.get(pkg)) { + toEdit = append(toEdit, base) } } } @@ -646,30 +665,31 @@ func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc return toEdit, nil } -func cleanBuilds(pkgs []*rpc.Pkg) { - for i, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) - fmt.Printf(bold(cyan("::")+" Deleting (%d/%d): %s\n"), i+1, len(pkgs), cyan(dir)) +func cleanBuilds(bases []Base) { + for i, base := range bases { + dir := filepath.Join(config.BuildDir, base.Pkgbase()) + fmt.Printf(bold(cyan("::")+" Deleting (%d/%d): %s\n"), i+1, len(bases), cyan(dir)) os.RemoveAll(dir) } } -func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stringSet) error { - for _, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) +func showPkgBuildDiffs(bases []Base, cloned stringSet) error { + for _, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) if shouldUseGit(dir) { start := "HEAD" - if cloned.get(pkg.PackageBase) { + if cloned.get(pkg) { start = gitEmptyTree } else { - hasDiff, err := gitHasDiff(config.BuildDir, pkg.PackageBase) + hasDiff, err := gitHasDiff(config.BuildDir, pkg) if err != nil { return err } if !hasDiff { - fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(bases[pkg.PackageBase])), bold("No changes -- skipping")) + fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(base)), bold("No changes -- skipping")) continue } } @@ -700,13 +720,14 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri return nil } -func editPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) error { - pkgbuilds := make([]string, 0, len(pkgs)) - for _, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) +func editPkgBuilds(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { + pkgbuilds := make([]string, 0, len(bases)) + for _, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD")) - for _, splitPkg := range srcinfos[pkg.PackageBase].SplitPackages() { + for _, splitPkg := range srcinfos[pkg].SplitPackages() { if splitPkg.Install != "" { pkgbuilds = append(pkgbuilds, filepath.Join(dir, splitPkg.Install)) } @@ -727,52 +748,59 @@ func editPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) error { return nil } -func parseSRCINFOFiles(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) error { - for k, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) +func parseSRCINFOFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { + for k, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) + fmt.Printf(str, k+1, len(bases), cyan(formatPkgbase(base))) pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { - return fmt.Errorf("%s: %s", pkg.Name, err) + return fmt.Errorf("%s: %s", formatPkgbase(base), err) } - srcinfos[pkg.PackageBase] = pkgbuild + srcinfos[pkg] = pkgbuild } return nil } -func tryParsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) { - for k, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) +func tryParsesrcinfosFile(bases []Base, srcinfos map[string]*gosrc.Srcinfo) { + for k, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") - fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) + fmt.Printf(str, k+1, len(bases), cyan(formatPkgbase(base))) pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { - fmt.Printf("cannot parse %s skipping: %s\n", pkg.Name, err) + fmt.Printf("cannot parse %s skipping: %s\n", formatPkgbase(base), err) continue } - srcinfos[pkg.PackageBase] = pkgbuild + srcinfos[pkg] = pkgbuild } } -func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { +func pkgBuildsToSkip(bases []Base, targets stringSet) stringSet { toSkip := make(stringSet) - for _, pkg := range pkgs { - if config.ReDownload == "no" || (config.ReDownload == "yes" && !targets.get(pkg.Name)) { - dir := filepath.Join(config.BuildDir, pkg.PackageBase, ".SRCINFO") + for _, base := range bases { + isTarget := false + for _, pkg := range base { + isTarget = isTarget || targets.get(pkg.Name) + } + + if config.ReDownload == "no" || (config.ReDownload == "yes" && isTarget) { + dir := filepath.Join(config.BuildDir, base.Pkgbase(), ".SRCINFO") pkgbuild, err := gosrc.ParseFile(dir) if err == nil { - if alpm.VerCmp(pkgbuild.Version(), pkg.Version) >= 0 { - toSkip.set(pkg.PackageBase) + if alpm.VerCmp(pkgbuild.Version(), base.Version()) >= 0 { + toSkip.set(base.Pkgbase()) } } } @@ -781,10 +809,10 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet { return toSkip } -func mergePkgBuilds(pkgs []*rpc.Pkg) error { - for _, pkg := range pkgs { - if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - err := gitMerge(config.BuildDir, pkg.PackageBase) +func mergePkgBuilds(bases []Base) error { + for _, base := range bases { + if shouldUseGit(filepath.Join(config.BuildDir, base.Pkgbase())) { + err := gitMerge(config.BuildDir, base.Pkgbase()) if err != nil { return err } @@ -794,38 +822,39 @@ func mergePkgBuilds(pkgs []*rpc.Pkg) error { return nil } -func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stringSet) (stringSet, error) { +func downloadPkgBuilds(bases []Base, toSkip stringSet) (stringSet, error) { cloned := make(stringSet) downloaded := 0 var wg sync.WaitGroup var mux sync.Mutex var errs MultiError - download := func(k int, pkg *rpc.Pkg) { + download := func(k int, base Base) { defer wg.Done() + pkg := base.Pkgbase() - if toSkip.get(pkg.PackageBase) { + if toSkip.get(pkg) { mux.Lock() downloaded++ str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") - fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) + fmt.Printf(str, downloaded, len(bases), cyan(formatPkgbase(base))) mux.Unlock() return } - if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { - clone, err := gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) + if shouldUseGit(filepath.Join(config.BuildDir, pkg)) { + clone, err := gitDownload(baseURL+"/"+pkg+".git", config.BuildDir, pkg) if err != nil { errs.Add(err) return } if clone { mux.Lock() - cloned.set(pkg.PackageBase) + cloned.set(pkg) mux.Unlock() } } else { - err := downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) + err := downloadAndUnpack(baseURL+base.URLPath(), config.BuildDir) if err != nil { errs.Add(err) return @@ -835,13 +864,13 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri mux.Lock() downloaded++ str := bold(cyan("::") + " Downloaded PKGBUILD (%d/%d): %s\n") - fmt.Printf(str, downloaded, len(pkgs), cyan(formatPkgbase(bases[pkg.PackageBase]))) + fmt.Printf(str, downloaded, len(bases), cyan(formatPkgbase(base))) mux.Unlock() } - for k, pkg := range pkgs { + for k, base := range bases { wg.Add(1) - go download(k, pkg) + go download(k, base) } wg.Wait() @@ -849,18 +878,19 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri return cloned, errs.Return() } -func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) { - for _, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) +func downloadPkgBuildsSources(bases []Base, incompatible stringSet) (err error) { + for _, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) args := []string{"--verifysource", "-Ccf"} - if incompatible.get(pkg.PackageBase) { + if incompatible.get(pkg) { args = append(args, "--ignorearch") } err = show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error downloading sources: %s", cyan(formatPkgbase(bases[pkg.PackageBase]))) + return fmt.Errorf("Error downloading sources: %s", cyan(formatPkgbase(base))) } } @@ -868,22 +898,23 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, inco } func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { - for _, pkg := range do.Aur { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) + for _, base := range do.Aur { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) built := true - srcinfo := srcinfos[pkg.PackageBase] + srcinfo := srcinfos[pkg] args := []string{"--nobuild", "-fC"} - if incompatible.get(pkg.PackageBase) { + if incompatible.get(pkg) { args = append(args, "--ignorearch") } //pkgver bump err := show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error making: %s", pkg.Name) + return fmt.Errorf("Error making: %s", formatPkgbase(base)) } pkgdests, version, err := parsePackageList(dir) @@ -891,8 +922,12 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc return err } - if config.ReBuild == "no" || (config.ReBuild == "yes" && !dp.Explicit.get(pkg.Name)) { - for _, split := range do.Bases[pkg.PackageBase] { + isExplicit := false + for _, b := range base { + isExplicit = isExplicit || dp.Explicit.get(b.Name) + } + if config.ReBuild == "no" || (config.ReBuild == "yes" && isExplicit) { + for _, split := range base { pkgdest, ok := pkgdests[split.Name] if !ok { return fmt.Errorf("Could not find PKGDEST for: %s", split.Name) @@ -911,17 +946,17 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc if built { fmt.Println(bold(yellow(arrow)), - cyan(pkg.Name+"-"+version)+bold(" Already made -- skipping build")) + cyan(pkg+"-"+version)+bold(" Already made -- skipping build")) } else { args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} - if incompatible.get(pkg.PackageBase) { + if incompatible.get(pkg) { args = append(args, "--ignorearch") } err := show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error making: %s", pkg.Name) + return fmt.Errorf("Error making: %s", formatPkgbase(base)) } } @@ -946,7 +981,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc cmdArgs.globals["ask"] = fmt.Sprint(uask) } else { conflict := false - for _, split := range do.Bases[pkg.PackageBase] { + for _, split := range base { if _, ok := conflicts[split.Name]; ok { conflict = true } @@ -973,7 +1008,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc remoteNamesCache := sliceToStringSet(remoteNames) localNamesCache := sliceToStringSet(localNames) - for _, split := range do.Bases[pkg.PackageBase] { + for _, split := range base { pkgdest, ok := pkgdests[split.Name] if !ok { return fmt.Errorf("Could not find PKGDEST for: %s", split.Name) @@ -1000,7 +1035,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc var mux sync.Mutex var wg sync.WaitGroup - for _, pkg := range do.Bases[pkg.PackageBase] { + for _, pkg := range base { wg.Add(1) go updateVCSData(pkg.Name, srcinfo.Source, &mux, &wg) } @@ -1024,12 +1059,12 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc return nil } -func clean(pkgs []*rpc.Pkg) { - for _, pkg := range pkgs { - dir := filepath.Join(config.BuildDir, pkg.PackageBase) +func clean(bases []Base) { + for _, base := range bases { + dir := filepath.Join(config.BuildDir, base.Pkgbase()) fmt.Println(bold(green(arrow + - " CleanAfter enabled. Deleting " + pkg.Name + " source folder."))) + " CleanAfter enabled. Deleting " + base.Pkgbase() + " source folder."))) os.RemoveAll(dir) } } diff --git a/keys.go b/keys.go index 66583427..28e7fd35 100644 --- a/keys.go +++ b/keys.go @@ -8,12 +8,11 @@ import ( "strings" gosrc "github.com/Morganamilo/go-srcinfo" - rpc "github.com/mikkeloscar/aur" ) // pgpKeySet maps a PGP key with a list of PKGBUILDs that require it. // This is similar to stringSet, used throughout the code. -type pgpKeySet map[string][]*rpc.Pkg +type pgpKeySet map[string][]Base func (set pgpKeySet) toSlice() []string { slice := make([]string, 0, len(set)) @@ -23,14 +22,11 @@ func (set pgpKeySet) toSlice() []string { return slice } -func (set pgpKeySet) set(key string, p *rpc.Pkg) { +func (set pgpKeySet) set(key string, p Base) { // Using ToUpper to make sure keys with a different case will be // considered the same. upperKey := strings.ToUpper(key) - if _, exists := set[upperKey]; !exists { - set[upperKey] = []*rpc.Pkg{} - } - set[key] = append(set[key], p) + set[key] = append(set[upperKey], p) } func (set pgpKeySet) get(key string) bool { @@ -41,28 +37,29 @@ func (set pgpKeySet) get(key string) bool { // checkPgpKeys iterates through the keys listed in the PKGBUILDs and if needed, // asks the user whether yay should try to import them. -func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) error { +func checkPgpKeys(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { // Let's check the keys individually, and then we can offer to import // the problematic ones. problematic := make(pgpKeySet) args := append(strings.Fields(config.GpgFlags), "--list-keys") // Mapping all the keys. - for _, pkg := range pkgs { - srcinfo := srcinfos[pkg.PackageBase] + for _, base := range bases { + pkg := base.Pkgbase() + srcinfo := srcinfos[pkg] for _, key := range srcinfo.ValidPGPKeys { // If key already marked as problematic, indicate the current // PKGBUILD requires it. if problematic.get(key) { - problematic.set(key, pkg) + problematic.set(key, base) continue } cmd := exec.Command(config.GpgBin, append(args, key)...) err := cmd.Run() if err != nil { - problematic.set(key, pkg) + problematic.set(key, base) } } } @@ -72,7 +69,7 @@ func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[str return nil } - str, err := formatKeysToImport(problematic, bases) + str, err := formatKeysToImport(problematic) if err != nil { return err } @@ -104,7 +101,7 @@ func importKeys(keys []string) error { // formatKeysToImport receives a set of keys and returns a string containing the // question asking the user wants to import the problematic keys. -func formatKeysToImport(keys pgpKeySet, bases map[string][]*rpc.Pkg) (string, error) { +func formatKeysToImport(keys pgpKeySet) (string, error) { if len(keys) == 0 { return "", fmt.Errorf("%s No keys to import", bold(red(arrow+" Error:"))) } @@ -112,12 +109,12 @@ func formatKeysToImport(keys pgpKeySet, bases map[string][]*rpc.Pkg) (string, er var buffer bytes.Buffer buffer.WriteString(bold(green(arrow))) buffer.WriteString(bold(green(" PGP keys need importing:"))) - for key, pkgs := range keys { + for key, bases := range keys { pkglist := "" - for _, pkg := range pkgs { - pkglist += formatPkgbase(bases[pkg.PackageBase]) + " " + for _, base := range bases { + pkglist += formatPkgbase(base) + " " } - pkglist = strings.TrimRight(pkglist, " ") + pkglist = strings.TrimRight(pkglist, " ") buffer.WriteString(fmt.Sprintf("\n%s %s, required by: %s", yellow(bold(smallArrow)), cyan(key), cyan(pkglist))) } return buffer.String(), nil diff --git a/print.go b/print.go index 15dc6ea1..5b587637 100644 --- a/print.go +++ b/print.go @@ -211,18 +211,19 @@ func (do *depOrder) Print() { } } - for _, pkg := range do.Aur { - pkgStr := " " + pkg.PackageBase + "-" + pkg.Version + for _, base := range do.Aur { + pkg := base.Pkgbase() + pkgStr := " " + pkg + "-" + base[0].Version pkgStrMake := pkgStr push := false pushMake := false - if len(do.Bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name { + if len(base) > 1 || pkg != base[0].Name { pkgStr += " (" pkgStrMake += " (" - for _, split := range do.Bases[pkg.PackageBase] { + for _, split := range base { if do.Runtime.get(split.Name) { pkgStr += split.Name + " " aurLen++ @@ -236,7 +237,7 @@ func (do *depOrder) Print() { pkgStr = pkgStr[:len(pkgStr)-1] + ")" pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")" - } else if do.Runtime.get(pkg.Name) { + } else if do.Runtime.get(base[0].Name) { aurLen++ push = true } else { diff --git a/vcs.go b/vcs.go index 41569296..4afc536a 100644 --- a/vcs.go +++ b/vcs.go @@ -26,6 +26,7 @@ type shaInfo struct { func createDevelDB() error { var mux sync.Mutex var wg sync.WaitGroup + baseNames := make([]string, 0) infoMap := make(map[string]*rpc.Pkg) srcinfosStale := make(map[string]*gosrc.Srcinfo) @@ -40,14 +41,15 @@ func createDevelDB() error { } for _, pkg := range info { + baseNames = append(baseNames, pkg.PackageBase) infoMap[pkg.Name] = pkg } bases := getBases(infoMap) - toSkip := pkgBuildsToSkip(info, sliceToStringSet(remoteNames)) - downloadPkgBuilds(info, bases, toSkip) - tryParsesrcinfosFile(info, srcinfosStale, bases) + toSkip := pkgBuildsToSkip(bases, sliceToStringSet(remoteNames)) + downloadPkgBuilds(bases, toSkip) + tryParsesrcinfosFile(bases, srcinfosStale) for _, pkgbuild := range srcinfosStale { for _, pkg := range pkgbuild.Packages { From 29fdf23f50f33345208b7fcc6c68361650bba0f2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 11 Aug 2018 04:51:10 +0100 Subject: [PATCH 111/155] Remove unneeded code, consistent function names --- install.go | 68 ++++++++++++++++++------------------------------------ vcs.go | 9 +++----- 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/install.go b/install.go index 89beaa0c..139564bb 100644 --- a/install.go +++ b/install.go @@ -184,8 +184,8 @@ func install(parser *arguments) error { cleanBuilds(toClean) } - toSkip := pkgBuildsToSkip(do.Aur, targets) - cloned, err := downloadPkgBuilds(do.Aur, toSkip) + toSkip := pkgbuildsToSkip(do.Aur, targets) + cloned, err := downloadPkgbuilds(do.Aur, toSkip) if err != nil { return err } @@ -201,7 +201,7 @@ func install(parser *arguments) error { } if len(toDiff) > 0 { - err = showPkgBuildDiffs(toDiff, cloned) + err = showPkgbuildDiffs(toDiff, cloned) if err != nil { return err } @@ -218,13 +218,13 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - err = mergePkgBuilds(do.Aur) + err = mergePkgbuilds(do.Aur) if err != nil { return err } //initial srcinfo parse before pkgver() bump - err = parseSRCINFOFiles(do.Aur, srcinfosStale) + err = parseSrcinfoFiles(do.Aur, srcinfosStale, true) if err != nil { return err } @@ -237,7 +237,7 @@ func install(parser *arguments) error { } if len(toEdit) > 0 { - err = editPkgBuilds(toEdit, srcinfosStale) + err = editPkgbuilds(toEdit, srcinfosStale) if err != nil { return err } @@ -312,12 +312,12 @@ func install(parser *arguments) error { go updateCompletion(false) - err = downloadPkgBuildsSources(do.Aur, incompatible) + err = downloadPkgbuildsSources(do.Aur, incompatible) if err != nil { return err } - err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible, conflicts) + err = buildInstallPkgbuilds(dp, do, srcinfosStale, parser, incompatible, conflicts) if err != nil { return err } @@ -341,7 +341,7 @@ func install(parser *arguments) error { } if config.CleanAfter { - clean(do.Aur) + cleanBuilds(do.Aur) } return nil @@ -673,7 +673,7 @@ func cleanBuilds(bases []Base) { } } -func showPkgBuildDiffs(bases []Base, cloned stringSet) error { +func showPkgbuildDiffs(bases []Base, cloned stringSet) error { for _, base := range bases { pkg := base.Pkgbase() dir := filepath.Join(config.BuildDir, pkg) @@ -720,7 +720,7 @@ func showPkgBuildDiffs(bases []Base, cloned stringSet) error { return nil } -func editPkgBuilds(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { +func editPkgbuilds(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { pkgbuilds := make([]string, 0, len(bases)) for _, base := range bases { pkg := base.Pkgbase() @@ -748,7 +748,7 @@ func editPkgBuilds(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { return nil } -func parseSRCINFOFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { +func parseSrcinfoFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo, errIsFatal bool) error { for k, base := range bases { pkg := base.Pkgbase() dir := filepath.Join(config.BuildDir, pkg) @@ -758,7 +758,11 @@ func parseSRCINFOFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { - return fmt.Errorf("%s: %s", formatPkgbase(base), err) + if !errIsFatal { + fmt.Printf("failed to parse %s -- skipping: %s\n", formatPkgbase(base), err) + continue + } + return fmt.Errorf("failed to parse %s: %s", formatPkgbase(base), err) } srcinfos[pkg] = pkgbuild @@ -767,25 +771,7 @@ func parseSRCINFOFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { return nil } -func tryParsesrcinfosFile(bases []Base, srcinfos map[string]*gosrc.Srcinfo) { - for k, base := range bases { - pkg := base.Pkgbase() - dir := filepath.Join(config.BuildDir, pkg) - - str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") - fmt.Printf(str, k+1, len(bases), cyan(formatPkgbase(base))) - - pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) - if err != nil { - fmt.Printf("cannot parse %s skipping: %s\n", formatPkgbase(base), err) - continue - } - - srcinfos[pkg] = pkgbuild - } -} - -func pkgBuildsToSkip(bases []Base, targets stringSet) stringSet { +func pkgbuildsToSkip(bases []Base, targets stringSet) stringSet { toSkip := make(stringSet) for _, base := range bases { @@ -809,7 +795,7 @@ func pkgBuildsToSkip(bases []Base, targets stringSet) stringSet { return toSkip } -func mergePkgBuilds(bases []Base) error { +func mergePkgbuilds(bases []Base) error { for _, base := range bases { if shouldUseGit(filepath.Join(config.BuildDir, base.Pkgbase())) { err := gitMerge(config.BuildDir, base.Pkgbase()) @@ -822,7 +808,7 @@ func mergePkgBuilds(bases []Base) error { return nil } -func downloadPkgBuilds(bases []Base, toSkip stringSet) (stringSet, error) { +func downloadPkgbuilds(bases []Base, toSkip stringSet) (stringSet, error) { cloned := make(stringSet) downloaded := 0 var wg sync.WaitGroup @@ -878,7 +864,7 @@ func downloadPkgBuilds(bases []Base, toSkip stringSet) (stringSet, error) { return cloned, errs.Return() } -func downloadPkgBuildsSources(bases []Base, incompatible stringSet) (err error) { +func downloadPkgbuildsSources(bases []Base, incompatible stringSet) (err error) { for _, base := range bases { pkg := base.Pkgbase() dir := filepath.Join(config.BuildDir, pkg) @@ -897,7 +883,7 @@ func downloadPkgBuildsSources(bases []Base, incompatible stringSet) (err error) return } -func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { +func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { for _, base := range do.Aur { pkg := base.Pkgbase() dir := filepath.Join(config.BuildDir, pkg) @@ -1058,13 +1044,3 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc return nil } - -func clean(bases []Base) { - for _, base := range bases { - dir := filepath.Join(config.BuildDir, base.Pkgbase()) - - fmt.Println(bold(green(arrow + - " CleanAfter enabled. Deleting " + base.Pkgbase() + " source folder."))) - os.RemoveAll(dir) - } -} diff --git a/vcs.go b/vcs.go index 4afc536a..ce74b22c 100644 --- a/vcs.go +++ b/vcs.go @@ -26,7 +26,6 @@ type shaInfo struct { func createDevelDB() error { var mux sync.Mutex var wg sync.WaitGroup - baseNames := make([]string, 0) infoMap := make(map[string]*rpc.Pkg) srcinfosStale := make(map[string]*gosrc.Srcinfo) @@ -41,15 +40,13 @@ func createDevelDB() error { } for _, pkg := range info { - baseNames = append(baseNames, pkg.PackageBase) infoMap[pkg.Name] = pkg } bases := getBases(infoMap) - - toSkip := pkgBuildsToSkip(bases, sliceToStringSet(remoteNames)) - downloadPkgBuilds(bases, toSkip) - tryParsesrcinfosFile(bases, srcinfosStale) + toSkip := pkgbuildsToSkip(bases, sliceToStringSet(remoteNames)) + downloadPkgbuilds(bases, toSkip) + parseSrcinfoFiles(bases, srcinfosStale, false) for _, pkgbuild := range srcinfosStale { for _, pkg := range pkgbuild.Packages { From cd21298355173ffe248d97d4e464cb122f77158d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 11 Aug 2018 05:00:46 +0100 Subject: [PATCH 112/155] Return srcinfos instead of using it as a parameter Also, we do not do a pre and post pkgverbump pass anymore, so theres no need to name it stale. --- install.go | 22 +++++++++++----------- vcs.go | 5 ++--- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/install.go b/install.go index 139564bb..07cd3480 100644 --- a/install.go +++ b/install.go @@ -22,10 +22,10 @@ func install(parser *arguments) error { var aurUp upSlice var repoUp upSlice - warnings := &aurWarnings{} + var srcinfos map[string]*gosrc.Srcinfo + warnings := &aurWarnings{} removeMake := false - srcinfosStale := make(map[string]*gosrc.Srcinfo) if mode == ModeAny || mode == ModeRepo { if config.CombinedUpgrade { @@ -223,8 +223,7 @@ func install(parser *arguments) error { return err } - //initial srcinfo parse before pkgver() bump - err = parseSrcinfoFiles(do.Aur, srcinfosStale, true) + srcinfos, err = parseSrcinfoFiles(do.Aur, true) if err != nil { return err } @@ -237,7 +236,7 @@ func install(parser *arguments) error { } if len(toEdit) > 0 { - err = editPkgbuilds(toEdit, srcinfosStale) + err = editPkgbuilds(toEdit, srcinfos) if err != nil { return err } @@ -255,13 +254,13 @@ func install(parser *arguments) error { } //TODO: fix for split packages maybe? - incompatible, err = getIncompatible(do.Aur, srcinfosStale) + incompatible, err = getIncompatible(do.Aur, srcinfos) if err != nil { return err } if config.PGPFetch { - err = checkPgpKeys(do.Aur, srcinfosStale) + err = checkPgpKeys(do.Aur, srcinfos) if err != nil { return err } @@ -317,7 +316,7 @@ func install(parser *arguments) error { return err } - err = buildInstallPkgbuilds(dp, do, srcinfosStale, parser, incompatible, conflicts) + err = buildInstallPkgbuilds(dp, do, srcinfos, parser, incompatible, conflicts) if err != nil { return err } @@ -748,7 +747,8 @@ func editPkgbuilds(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error { return nil } -func parseSrcinfoFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo, errIsFatal bool) error { +func parseSrcinfoFiles(bases []Base, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) { + srcinfos := make(map[string]*gosrc.Srcinfo) for k, base := range bases { pkg := base.Pkgbase() dir := filepath.Join(config.BuildDir, pkg) @@ -762,13 +762,13 @@ func parseSrcinfoFiles(bases []Base, srcinfos map[string]*gosrc.Srcinfo, errIsFa fmt.Printf("failed to parse %s -- skipping: %s\n", formatPkgbase(base), err) continue } - return fmt.Errorf("failed to parse %s: %s", formatPkgbase(base), err) + return nil, fmt.Errorf("failed to parse %s: %s", formatPkgbase(base), err) } srcinfos[pkg] = pkgbuild } - return nil + return srcinfos, nil } func pkgbuildsToSkip(bases []Base, targets stringSet) stringSet { diff --git a/vcs.go b/vcs.go index ce74b22c..230b3fe2 100644 --- a/vcs.go +++ b/vcs.go @@ -27,7 +27,6 @@ func createDevelDB() error { var mux sync.Mutex var wg sync.WaitGroup infoMap := make(map[string]*rpc.Pkg) - srcinfosStale := make(map[string]*gosrc.Srcinfo) _, _, _, remoteNames, err := filterPackages() if err != nil { @@ -46,9 +45,9 @@ func createDevelDB() error { bases := getBases(infoMap) toSkip := pkgbuildsToSkip(bases, sliceToStringSet(remoteNames)) downloadPkgbuilds(bases, toSkip) - parseSrcinfoFiles(bases, srcinfosStale, false) + srcinfos, _ := parseSrcinfoFiles(bases, false) - for _, pkgbuild := range srcinfosStale { + for _, pkgbuild := range srcinfos { for _, pkg := range pkgbuild.Packages { wg.Add(1) go updateVCSData(pkg.Pkgname, pkgbuild.Source, &mux, &wg) From afee400662116637284299480c614dd7eb4f598b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 11 Aug 2018 05:21:06 +0100 Subject: [PATCH 113/155] Use formatPkgbase with getIncompatible There was a possibly that getIncompatible could be broken when working with split packages. After looking into it, this does not seem to be the case, as long as we only work with pkgbases. arch may be overriden inside of a package function. The global arch array may be 'any' but package_foo could say arch=('x86_64'). If you were running arm then should yay warn about this? I have decided the answer is no. This is because makepkg doesn't care. It would seem makepkg only checks the global arch array. This leads me to believe that the global array should contain a the required arch. Therefore the correct way to do the former example would be to declare the global arch as 'x86_64' and then override package_bar with 'any'. So all that we should do is properly use formatPkgbase to list all the packages under the base. --- install.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/install.go b/install.go index 07cd3480..808139ef 100644 --- a/install.go +++ b/install.go @@ -253,7 +253,6 @@ func install(parser *arguments) error { config.NoConfirm = oldValue } - //TODO: fix for split packages maybe? incompatible, err = getIncompatible(do.Aur, srcinfos) if err != nil { return err @@ -417,6 +416,7 @@ func earlyRefresh(parser *arguments) error { func getIncompatible(bases []Base, srcinfos map[string]*gosrc.Srcinfo) (stringSet, error) { incompatible := make(stringSet) + basesMap := make(map[string]Base) alpmArch, err := alpmHandle.Arch() if err != nil { return nil, err @@ -431,13 +431,14 @@ nextpkg: } incompatible.set(base.Pkgbase()) + basesMap[base.Pkgbase()] = base } if len(incompatible) > 0 { fmt.Println() fmt.Print(bold(yellow(arrow)) + " The following packages are not compatible with your architecture:") for pkg := range incompatible { - fmt.Print(" " + cyan(pkg)) + fmt.Print(" " + cyan(formatPkgbase(basesMap[pkg]))) } fmt.Println() From 40776fa18457854170400f771239868b8e2a6257 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 11 Aug 2018 05:39:24 +0100 Subject: [PATCH 114/155] implement formatPkgbase as Base.String Now that Base is its own type, it is much neater to have this as its stringer function. --- install.go | 22 +++++++++++----------- keys.go | 2 +- print.go | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/install.go b/install.go index 808139ef..3275e379 100644 --- a/install.go +++ b/install.go @@ -438,7 +438,7 @@ nextpkg: fmt.Println() fmt.Print(bold(yellow(arrow)) + " The following packages are not compatible with your architecture:") for pkg := range incompatible { - fmt.Print(" " + cyan(formatPkgbase(basesMap[pkg]))) + fmt.Print(" " + cyan((basesMap[pkg].String()))) } fmt.Println() @@ -494,7 +494,7 @@ func pkgbuildNumberMenu(bases []Base, installed stringSet) bool { dir := filepath.Join(config.BuildDir, pkg) toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(bases)-n, - bold(formatPkgbase(base))) + bold(base.String())) anyInstalled := false for _, b := range base { @@ -689,7 +689,7 @@ func showPkgbuildDiffs(bases []Base, cloned stringSet) error { } if !hasDiff { - fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(formatPkgbase(base)), bold("No changes -- skipping")) + fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(base.String()), bold("No changes -- skipping")) continue } } @@ -755,15 +755,15 @@ func parseSrcinfoFiles(bases []Base, errIsFatal bool) (map[string]*gosrc.Srcinfo dir := filepath.Join(config.BuildDir, pkg) str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") - fmt.Printf(str, k+1, len(bases), cyan(formatPkgbase(base))) + fmt.Printf(str, k+1, len(bases), cyan(base.String())) pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO")) if err != nil { if !errIsFatal { - fmt.Printf("failed to parse %s -- skipping: %s\n", formatPkgbase(base), err) + fmt.Printf("failed to parse %s -- skipping: %s\n", base.String(), err) continue } - return nil, fmt.Errorf("failed to parse %s: %s", formatPkgbase(base), err) + return nil, fmt.Errorf("failed to parse %s: %s", base.String(), err) } srcinfos[pkg] = pkgbuild @@ -824,7 +824,7 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet) (stringSet, error) { mux.Lock() downloaded++ str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") - fmt.Printf(str, downloaded, len(bases), cyan(formatPkgbase(base))) + fmt.Printf(str, downloaded, len(bases), cyan(base.String())) mux.Unlock() return } @@ -851,7 +851,7 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet) (stringSet, error) { mux.Lock() downloaded++ str := bold(cyan("::") + " Downloaded PKGBUILD (%d/%d): %s\n") - fmt.Printf(str, downloaded, len(bases), cyan(formatPkgbase(base))) + fmt.Printf(str, downloaded, len(bases), cyan(base.String())) mux.Unlock() } @@ -877,7 +877,7 @@ func downloadPkgbuildsSources(bases []Base, incompatible stringSet) (err error) err = show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error downloading sources: %s", cyan(formatPkgbase(base))) + return fmt.Errorf("Error downloading sources: %s", cyan(base.String())) } } @@ -901,7 +901,7 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc //pkgver bump err := show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error making: %s", formatPkgbase(base)) + return fmt.Errorf("Error making: %s", base.String()) } pkgdests, version, err := parsePackageList(dir) @@ -943,7 +943,7 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc err := show(passToMakepkg(dir, args...)) if err != nil { - return fmt.Errorf("Error making: %s", formatPkgbase(base)) + return fmt.Errorf("Error making: %s", base.String()) } } diff --git a/keys.go b/keys.go index 28e7fd35..968fda13 100644 --- a/keys.go +++ b/keys.go @@ -112,7 +112,7 @@ func formatKeysToImport(keys pgpKeySet) (string, error) { for key, bases := range keys { pkglist := "" for _, base := range bases { - pkglist += formatPkgbase(base) + " " + pkglist += base.String() + " " } pkglist = strings.TrimRight(pkglist, " ") buffer.WriteString(fmt.Sprintf("\n%s %s, required by: %s", yellow(bold(smallArrow)), cyan(key), cyan(pkglist))) diff --git a/print.go b/print.go index 5b587637..40284a8b 100644 --- a/print.go +++ b/print.go @@ -143,7 +143,7 @@ func (s repoQuery) printSearch() { // Pretty print a set of packages from the same package base. // Packages foo and bar from a pkgbase named base would print like so: // base (foo bar) -func formatPkgbase(base []*rpc.Pkg) string { +func (base Base) String() string { pkg := base[0] str := pkg.PackageBase if len(base) > 1 || pkg.PackageBase != pkg.Name { From b1ee03a7d8c9a8a7fb135c7db1d9c07302ddb62e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 11 Aug 2018 05:46:20 +0100 Subject: [PATCH 115/155] getBases now wants a slice instead of a map The one place this function is used, the caller converts its data to a map just to getBases will accept it. Instead just allow it to take the slice to begin with. --- dep.go | 2 +- vcs.go | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/dep.go b/dep.go index 8accb678..b3fae560 100644 --- a/dep.go +++ b/dep.go @@ -149,7 +149,7 @@ func splitDbFromName(pkg string) (string, string) { return "", split[0] } -func getBases(pkgs map[string]*rpc.Pkg) []Base { +func getBases(pkgs []*rpc.Pkg) []Base { basesMap := make(map[string]Base) for _, pkg := range pkgs { basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg) diff --git a/vcs.go b/vcs.go index 230b3fe2..53d949e2 100644 --- a/vcs.go +++ b/vcs.go @@ -10,7 +10,6 @@ import ( "time" gosrc "github.com/Morganamilo/go-srcinfo" - rpc "github.com/mikkeloscar/aur" ) // Info contains the last commit sha of a repo @@ -26,7 +25,6 @@ type shaInfo struct { func createDevelDB() error { var mux sync.Mutex var wg sync.WaitGroup - infoMap := make(map[string]*rpc.Pkg) _, _, _, remoteNames, err := filterPackages() if err != nil { @@ -38,11 +36,7 @@ func createDevelDB() error { return err } - for _, pkg := range info { - infoMap[pkg.Name] = pkg - } - - bases := getBases(infoMap) + bases := getBases(info) toSkip := pkgbuildsToSkip(bases, sliceToStringSet(remoteNames)) downloadPkgbuilds(bases, toSkip) srcinfos, _ := parseSrcinfoFiles(bases, false) From cba56c3f9e60f8091e43516932bd72e1d393285e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 00:16:04 +0100 Subject: [PATCH 116/155] Use downloadPkgbuilds for -G --- download.go | 53 +++++++++-------------------------------------------- install.go | 8 ++++---- vcs.go | 2 +- 3 files changed, 14 insertions(+), 49 deletions(-) diff --git a/download.go b/download.go index ae8c38d6..35283380 100644 --- a/download.go +++ b/download.go @@ -135,8 +135,11 @@ func getPkgbuilds(pkgs []string) error { } pkgs = removeInvalidTargets(pkgs) - aur, repo, err := packageSlices(pkgs) + info, err := aurInfoPrint(aur) + if err != nil { + return err + } if len(repo) > 0 { missing, err = getPkgbuildsfromABS(repo, wd) @@ -146,11 +149,13 @@ func getPkgbuilds(pkgs []string) error { } if len(aur) > 0 { - _missing, err := getPkgbuildsfromAUR(aur, wd) - if err != nil { + bases := getBases(info) + toSkip := pkgbuildsToSkip(bases, nil) + if _, err = downloadPkgbuilds(bases, toSkip, wd); err != nil { return err } - missing = missing || _missing + + missing = missing || len(aur) != len(info) } if missing { @@ -225,43 +230,3 @@ nextPkg: return } - -// GetPkgbuild downloads pkgbuild from the AUR. -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 missing, err - } - - for _, pkg := range aq { - 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 { - err = downloadAndUnpack(baseURL+aq[0].URLPath, dir) - } - - if err != nil { - fmt.Println(err) - } else { - fmt.Println(bold(yellow(arrow)), "Downloaded", cyan(pkg.PackageBase), "from AUR") - } - } - - if len(aq) != len(pkgs) { - missing = true - } - - return missing, err -} diff --git a/install.go b/install.go index 3275e379..42063d06 100644 --- a/install.go +++ b/install.go @@ -185,7 +185,7 @@ func install(parser *arguments) error { } toSkip := pkgbuildsToSkip(do.Aur, targets) - cloned, err := downloadPkgbuilds(do.Aur, toSkip) + cloned, err := downloadPkgbuilds(do.Aur, toSkip, config.BuildDir) if err != nil { return err } @@ -809,7 +809,7 @@ func mergePkgbuilds(bases []Base) error { return nil } -func downloadPkgbuilds(bases []Base, toSkip stringSet) (stringSet, error) { +func downloadPkgbuilds(bases []Base, toSkip stringSet, buildDir string) (stringSet, error) { cloned := make(stringSet) downloaded := 0 var wg sync.WaitGroup @@ -830,7 +830,7 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet) (stringSet, error) { } if shouldUseGit(filepath.Join(config.BuildDir, pkg)) { - clone, err := gitDownload(baseURL+"/"+pkg+".git", config.BuildDir, pkg) + clone, err := gitDownload(baseURL+"/"+pkg+".git", buildDir, pkg) if err != nil { errs.Add(err) return @@ -841,7 +841,7 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet) (stringSet, error) { mux.Unlock() } } else { - err := downloadAndUnpack(baseURL+base.URLPath(), config.BuildDir) + err := downloadAndUnpack(baseURL+base.URLPath(), buildDir) if err != nil { errs.Add(err) return diff --git a/vcs.go b/vcs.go index 53d949e2..584ed899 100644 --- a/vcs.go +++ b/vcs.go @@ -38,7 +38,7 @@ func createDevelDB() error { bases := getBases(info) toSkip := pkgbuildsToSkip(bases, sliceToStringSet(remoteNames)) - downloadPkgbuilds(bases, toSkip) + downloadPkgbuilds(bases, toSkip, config.BuildDir) srcinfos, _ := parseSrcinfoFiles(bases, false) for _, pkgbuild := range srcinfos { From a1edd09a52c68ba032b6d236c08e2351dd8efc78 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 04:06:27 +0100 Subject: [PATCH 117/155] Fixup getPkgbuildsFromABS Make it output more similary to downloadPkgbuilds. Refactor to remove all the indention. --- download.go | 113 ++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/download.go b/download.go index 35283380..d0af1861 100644 --- a/download.go +++ b/download.go @@ -8,6 +8,8 @@ import ( "os/exec" "path/filepath" "strings" + + alpm "github.com/jguer/go-alpm" ) // Decide what download method to use: @@ -136,6 +138,12 @@ func getPkgbuilds(pkgs []string) error { pkgs = removeInvalidTargets(pkgs) aur, repo, err := packageSlices(pkgs) + + for n := range aur { + _, pkg := splitDbFromName(aur[n]) + aur[n] = pkg + } + info, err := aurInfoPrint(aur) if err != nil { return err @@ -166,67 +174,70 @@ 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) (bool, error) { + missing := false dbList, err := alpmHandle.SyncDbs() if err != nil { - return + return missing, err } -nextPkg: - for _, pkgN := range pkgs { + for n, pkgN := range pkgs { pkgDb, name := splitDbFromName(pkgN) + var pkg *alpm.Package + var err error + var url string - for _, db := range dbList.Slice() { - if pkgDb != "" && db.Name() != pkgDb { - continue + if pkgDb != "" { + if db, err := alpmHandle.SyncDbByName(pkgDb); err == nil { + pkg, err = db.PkgByName(name) } - - pkg, err := db.PkgByName(name) - if err == nil { - var url string - name := pkg.Base() - if name == "" { - name = pkg.Name() + } else { + dbList.ForEach(func(db alpm.Db) error { + if pkg, err = db.PkgByName(name); err == nil { + return fmt.Errorf("") } - - if _, err := os.Stat(filepath.Join(path, name)); err == nil { - fmt.Println(bold(red(arrow)), bold(cyan(name)), "directory already exists") - continue nextPkg - } - - 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(pkgN, "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") - } - - continue nextPkg - } + return nil + }) } - fmt.Println(pkgN, "could not find package in database") - missing = true + if pkg == nil { + fmt.Println(name, "could not find package in database") + missing = true + continue + } + + name = pkg.Base() + if name == "" { + name = pkg.Name() + } + + if err = os.RemoveAll(filepath.Join(path, name)); err != nil { + fmt.Println(err) + continue + } + + switch pkg.DB().Name() { + case "core", "extra", "testing": + url = "https://git.archlinux.org/svntogit/packages.git/snapshot/packages/" + name + ".tar.gz" + case "community", "multilib", "community-testing", "multilib-testing": + url = "https://git.archlinux.org/svntogit/community.git/snapshot/packages/" + name + ".tar.gz" + default: + fmt.Println(name, "not in standard repositories") + continue + } + + if err = downloadAndUnpack(url, cacheHome); err != nil { + fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name())), bold(red(err.Error()))) + } + + err = exec.Command("mv", filepath.Join(cacheHome, "packages", name, "trunk"), filepath.Join(path, name)).Run() + if err != nil { + fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name())), bold(red(err.Error()))) + } else { + fmt.Printf(bold(cyan("::"))+" Downloaded PKGBUILD from ABS (%d/%d): %s\n", n+1, len(pkgs), cyan(pkg.Name())) + } } - if _, err := os.Stat(filepath.Join(cacheHome, "packages")); err == nil { - os.RemoveAll(filepath.Join(cacheHome, "packages")) - } - - return + err = os.RemoveAll(filepath.Join(cacheHome, "packages")) + return missing, err } From a8e4f18e6bbe90d403e0113ef83fbf185bba064c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 06:33:44 +0100 Subject: [PATCH 118/155] MultiError: add new lines between errors --- utils.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils.go b/utils.go index 3762dd56..28a48c09 100644 --- a/utils.go +++ b/utils.go @@ -139,10 +139,10 @@ func (err *MultiError) Error() string { str := "" for _, e := range err.Errors { - str += e.Error() + str += e.Error() + "\n" } - return str + return str[:len(str)-1] } func (err *MultiError) Add(e error) { From 8711562923408a97a4cbbc4de7f05f9245baa81b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 06:38:32 +0100 Subject: [PATCH 119/155] capture: strip whitespace on outputs --- exec.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exec.go b/exec.go index facecf71..0049af48 100644 --- a/exec.go +++ b/exec.go @@ -25,8 +25,8 @@ func capture(cmd *exec.Cmd) (string, string, error) { cmd.Stdout = &outbuf cmd.Stderr = &errbuf err := cmd.Run() - stdout := outbuf.String() - stderr := errbuf.String() + stdout := strings.TrimSpace(outbuf.String()) + stderr := strings.TrimSpace(errbuf.String()) return stdout, stderr, err } From e547173d42c90ee1ad7d1a253fd3c2916927c0cf Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 06:41:16 +0100 Subject: [PATCH 120/155] Use goroutines for fetching abs packages --- download.go | 83 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/download.go b/download.go index d0af1861..e1bcefad 100644 --- a/download.go +++ b/download.go @@ -8,6 +8,7 @@ import ( "os/exec" "path/filepath" "strings" + "sync" alpm "github.com/jguer/go-alpm" ) @@ -105,10 +106,10 @@ func gitDiff(path string, name string) error { } // DownloadAndUnpack downloads url tgz and extracts to path. -func downloadAndUnpack(url string, path string) (err error) { - err = os.MkdirAll(path, 0755) +func downloadAndUnpack(url string, path string) error { + err := os.MkdirAll(path, 0755) if err != nil { - return + return err } fileName := filepath.Base(url) @@ -118,15 +119,15 @@ func downloadAndUnpack(url string, path string) (err error) { err = downloadFile(tarLocation, url) if err != nil { - return + return err } - err = exec.Command(config.TarBin, "-xf", tarLocation, "-C", path).Run() + _, stderr, err := capture(exec.Command(config.TarBin, "-xf", tarLocation, "-C", path)) if err != nil { - return + return fmt.Errorf("%s", stderr) } - return + return nil } func getPkgbuilds(pkgs []string) error { @@ -175,17 +176,23 @@ func getPkgbuilds(pkgs []string) error { // GetPkgbuild downloads pkgbuild from the ABS. func getPkgbuildsfromABS(pkgs []string, path string) (bool, error) { - missing := false + var wg sync.WaitGroup + var mux sync.Mutex + var errs MultiError + names := make(map[string]string) + missing := make([]string, 0) + downloaded := 0 + dbList, err := alpmHandle.SyncDbs() if err != nil { - return missing, err + return false, err } - for n, pkgN := range pkgs { - pkgDb, name := splitDbFromName(pkgN) + for _, pkgN := range pkgs { var pkg *alpm.Package var err error var url string + pkgDb, name := splitDbFromName(pkgN) if pkgDb != "" { if db, err := alpmHandle.SyncDbByName(pkgDb); err == nil { @@ -201,8 +208,7 @@ func getPkgbuildsfromABS(pkgs []string, path string) (bool, error) { } if pkg == nil { - fmt.Println(name, "could not find package in database") - missing = true + missing = append(missing, name) continue } @@ -211,33 +217,52 @@ func getPkgbuildsfromABS(pkgs []string, path string) (bool, error) { name = pkg.Name() } - if err = os.RemoveAll(filepath.Join(path, name)); err != nil { - fmt.Println(err) - continue - } - switch pkg.DB().Name() { case "core", "extra", "testing": url = "https://git.archlinux.org/svntogit/packages.git/snapshot/packages/" + name + ".tar.gz" case "community", "multilib", "community-testing", "multilib-testing": url = "https://git.archlinux.org/svntogit/community.git/snapshot/packages/" + name + ".tar.gz" default: - fmt.Println(name, "not in standard repositories") + missing = append(missing, name) continue } - if err = downloadAndUnpack(url, cacheHome); err != nil { - fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name())), bold(red(err.Error()))) + if err = os.RemoveAll(filepath.Join(path, name)); err != nil { + fmt.Println(bold(red(smallArrow)), err) + continue } - err = exec.Command("mv", filepath.Join(cacheHome, "packages", name, "trunk"), filepath.Join(path, name)).Run() - if err != nil { - fmt.Println(bold(red(arrow)), bold(cyan(pkg.Name())), bold(red(err.Error()))) - } else { - fmt.Printf(bold(cyan("::"))+" Downloaded PKGBUILD from ABS (%d/%d): %s\n", n+1, len(pkgs), cyan(pkg.Name())) - } + names[name] = url } - err = os.RemoveAll(filepath.Join(cacheHome, "packages")) - return missing, err + if len(missing) != 0 { + fmt.Println(yellow(bold(smallArrow)), "Missing ABS packages: ", cyan(strings.Join(missing, " "))) + } + + download := func(pkg string, url string) { + defer wg.Done() + if err := downloadAndUnpack(url, cacheHome); err != nil { + errs.Add(fmt.Errorf("%s Failed to get pkgbuild: %s: %s", bold(red(arrow)), bold(cyan(pkg)), bold(red(err.Error())))) + return + } + + _, stderr, err := capture(exec.Command("mv", filepath.Join(cacheHome, "packages", pkg, "trunk"), filepath.Join(path, pkg))) + mux.Lock() + downloaded++ + if err != nil { + errs.Add(fmt.Errorf("%s Failed to move %s: %s", bold(red(arrow)), bold(cyan(pkg)), bold(red(string(stderr))))) + } else { + fmt.Printf(bold(cyan("::"))+" Downloaded PKGBUILD from ABS (%d/%d): %s\n", downloaded, len(names), cyan(pkg)) + } + mux.Unlock() + } + + for name, url := range names { + wg.Add(1) + go download(name, url) + } + + wg.Wait() + errs.Add(os.RemoveAll(filepath.Join(cacheHome, "packages"))) + return len(missing) != 0, errs.Return() } From 03fee7b7d5b7949655f378043ca770f001c7240d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 07:02:50 +0100 Subject: [PATCH 121/155] Expand -G documentation --- doc/yay.8 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index b0aa6584..7d558c76 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -31,7 +31,8 @@ Perform yay specific print operations. .TP .B \-G, \-\-getpkgbuild -Downloads PKGBUILD from ABS or AUR. +Downloads PKGBUILD from ABS or AUR. ABS pkgbuilds are always downloaded using +tarballs and taken from trunk. The ABS can only be used for Arch Linux repositories .RE If no arguments are provided 'yay \-Syu' will be performed. @@ -276,7 +277,7 @@ 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 +\fBWarning\fR: It is not recommended to skip updates from the repositories 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. From 907bf3a30e2dbce605b04cdcddea5a2e6d28aefd Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 17:32:40 +0100 Subject: [PATCH 122/155] skip build when package is up to date and --needed Before --needed was left purerly to pacman. The problem with this is that if a package is not in the cache, it will end up being build just for pacman to skip over the install. Now Yay will handle this and skip the build and install if --needed is used. The inital clone and pkgver bumb is still donw. --- install.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/install.go b/install.go index 42063d06..2146b63a 100644 --- a/install.go +++ b/install.go @@ -931,9 +931,23 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc built = false } + if cmdArgs.existsArg("needed") { + installed := true + for _, split := range base { + if alpmpkg, err := dp.LocalDb.PkgByName(split.Name); err != nil || alpmpkg.Version() != version { + installed = false + } + } + + if installed { + fmt.Println(cyan(pkg+"-"+version) + bold(" is up to date -- skipping")) + continue + } + } + if built { fmt.Println(bold(yellow(arrow)), - cyan(pkg+"-"+version)+bold(" Already made -- skipping build")) + cyan(pkg+"-"+version)+bold(" already made -- skipping build")) } else { args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} From aca65e743af6cb4ede3ef7d4f5970d5f1ace0e08 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 17:54:20 +0100 Subject: [PATCH 123/155] parsePackageList: include pkgrel in version --- install.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.go b/install.go index 2146b63a..565218e6 100644 --- a/install.go +++ b/install.go @@ -478,7 +478,7 @@ func parsePackageList(dir string) (map[string]string, string, error) { // 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], "-") + version = strings.Join(split[len(split)-3:len(split)-1], "-") pkgdests[pkgname] = line } From 0f324b37a66ff595b847c93f69085df1fce4004b Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 20:50:20 +0100 Subject: [PATCH 124/155] Only print the clean number menu when needed The input is only asked when needed, but the numbered package list was still printed either way. This fixes it so the list is not shown unless needed. --- install.go | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/install.go b/install.go index 42063d06..c9e36b7a 100644 --- a/install.go +++ b/install.go @@ -175,13 +175,15 @@ func install(parser *arguments) error { } if config.CleanMenu { - askClean := pkgbuildNumberMenu(do.Aur, remoteNamesCache) - toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean) - if err != nil { - return err - } + if anyExistInCache(do.Aur) { + askClean := pkgbuildNumberMenu(do.Aur, remoteNamesCache) + toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean) + if err != nil { + return err + } - cleanBuilds(toClean) + cleanBuilds(toClean) + } } toSkip := pkgbuildsToSkip(do.Aur, targets) @@ -485,6 +487,19 @@ func parsePackageList(dir string) (map[string]string, string, error) { return pkgdests, version, nil } +func anyExistInCache(bases []Base) bool { + for _, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) + + if _, err := os.Stat(dir); !os.IsNotExist(err) { + return true + } + } + + return false +} + func pkgbuildNumberMenu(bases []Base, installed stringSet) bool { toPrint := "" askClean := false From c0f73c4f31b32983103411cd3884352431f72302 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sat, 18 Aug 2018 20:57:39 +0100 Subject: [PATCH 125/155] Update vendored dependencies --- Gopkg.lock | 14 ++++++++++++-- vendor/github.com/jguer/go-alpm/db.go | 17 +++++------------ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index ba84f576..97953b93 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,25 +3,35 @@ [[projects]] branch = "master" + digest = "1:5f709618dc8a0ff9221d3685c95d69ed7d80ca94e58f3483f5d9bdefb4e6bb25" name = "github.com/Morganamilo/go-srcinfo" packages = ["."] + pruneopts = "NUT" revision = "368edc79b2c53cd9c065818fd4e65843ef3e9e11" [[projects]] branch = "master" + digest = "1:7681cb2a269451c1a0f781e1241ce0bd8e515d5e9a3b12f67fd768bafe08e682" name = "github.com/jguer/go-alpm" packages = ["."] - revision = "c3ee958efac942186012cc67de8fe5e7a5b3685d" + pruneopts = "NUT" + revision = "39edc7671fa431a0d14ba6e023f5f2290a86333b" [[projects]] branch = "master" + digest = "1:07c508c49b9c13cf582c2b986635d0acd11e113e0535fa4b147026e15bc64185" name = "github.com/mikkeloscar/aur" packages = ["."] + pruneopts = "NUT" revision = "f998dbf94dc47ef839c76740efeb673d3459be1f" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "2a7c6ddb680b62cd3f3cf47a0dfdad617e4a42e29204c75ecf5be3271feda5e1" + input-imports = [ + "github.com/Morganamilo/go-srcinfo", + "github.com/jguer/go-alpm", + "github.com/mikkeloscar/aur", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/jguer/go-alpm/db.go b/vendor/github.com/jguer/go-alpm/db.go index 1295e26a..8d9024ab 100644 --- a/vendor/github.com/jguer/go-alpm/db.go +++ b/vendor/github.com/jguer/go-alpm/db.go @@ -8,6 +8,7 @@ package alpm /* #include +#include */ import "C" @@ -158,21 +159,13 @@ func (db Db) PkgCache() PackageList { } func (db Db) Search(targets []string) PackageList { - needles := &C.alpm_list_t{} - head := needles - needles.data = unsafe.Pointer(C.CString(targets[0])) + var needles *C.alpm_list_t - for _, str := range targets[1:] { - needles.next = &C.alpm_list_t{} - needles = needles.next - needles.data = unsafe.Pointer(C.CString(str)) + for _, str := range targets { + needles = C.alpm_list_add(needles, unsafe.Pointer(C.CString(str))) } pkglist := (*list)(unsafe.Pointer(C.alpm_db_search(db.ptr, needles))) - - for needles = head; needles != nil; needles = needles.next { - C.free(needles.data) - } - + C.alpm_list_free(needles) return PackageList{pkglist, db.handle} } From 0454e8918b55f5bcb1b41aa0096458bfcef3f079 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 19 Aug 2018 05:05:16 +0100 Subject: [PATCH 126/155] Add --aururl --- config.go | 5 ++--- install.go | 4 ++-- main.go | 10 ++++++++++ parser.go | 4 ++++ print.go | 4 ++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/config.go b/config.go index 6b84665c..0148c8c8 100644 --- a/config.go +++ b/config.go @@ -35,6 +35,7 @@ const ( // Configuration stores yay's config. type Configuration struct { + AURURL string `json:"aururl"` BuildDir string `json:"buildDir"` Editor string `json:"editor"` EditorFlags string `json:"editorflags"` @@ -84,9 +85,6 @@ const configFileName string = "config.json" // vcsFileName holds the name of the vcs file. const vcsFileName string = "vcs.json" -// baseURL givers the AUR default address. -const baseURL string = "https://aur.archlinux.org" - // useColor enables/disables colored printing var useColor bool @@ -149,6 +147,7 @@ func (config *Configuration) saveConfig() error { } func defaultSettings(config *Configuration) { + config.AURURL = "https://aur.archlinux.org" config.BuildDir = cacheHome config.CleanAfter = false config.Editor = "" diff --git a/install.go b/install.go index 0ebc37e6..ecceb784 100644 --- a/install.go +++ b/install.go @@ -845,7 +845,7 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet, buildDir string) (stringS } if shouldUseGit(filepath.Join(config.BuildDir, pkg)) { - clone, err := gitDownload(baseURL+"/"+pkg+".git", buildDir, pkg) + clone, err := gitDownload(config.AURURL+"/"+pkg+".git", buildDir, pkg) if err != nil { errs.Add(err) return @@ -856,7 +856,7 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet, buildDir string) (stringS mux.Unlock() } } else { - err := downloadAndUnpack(baseURL+base.URLPath(), buildDir) + err := downloadAndUnpack(config.AURURL+base.URLPath(), buildDir) if err != nil { errs.Add(err) return diff --git a/main.go b/main.go index 53a6db58..5198abf8 100644 --- a/main.go +++ b/main.go @@ -4,10 +4,13 @@ import ( "encoding/json" "fmt" "os" + "path" "path/filepath" "strings" + "net/url" alpm "github.com/jguer/go-alpm" + rpc "github.com/mikkeloscar/aur" ) func setPaths() error { @@ -47,6 +50,13 @@ func initConfig() error { } } + url, err := url.Parse(config.AURURL) + if err != nil { + return err + } + url.Path = path.Join(url.Path, "") + rpc.AURURL = url.String() + "/rpc.php?" + return nil } diff --git a/parser.go b/parser.go index 27b45589..bc25a387 100644 --- a/parser.go +++ b/parser.go @@ -414,6 +414,7 @@ func isArg(arg string) bool { case "x", "regex": case "machinereadable": //yay options + case "aururl": case "save": case "afterclean": case "noafterclean": @@ -493,6 +494,8 @@ func isArg(arg string) bool { func handleConfig(option, value string) bool { switch option { + case "aururl": + config.AURURL = value case "save": shouldSaveConfig = true case "afterclean": @@ -702,6 +705,7 @@ func hasParam(arg string) bool { case "gpgdir": case "color": //yay params + case "aururl": case "mflags": case "gpgflags": case "gitflags": diff --git a/print.go b/print.go index 40284a8b..cb477932 100644 --- a/print.go +++ b/print.go @@ -285,7 +285,7 @@ func PrintInfo(a *rpc.Pkg) { printInfoValue("Version", a.Version) printInfoValue("Description", a.Description) printInfoValue("URL", a.URL) - printInfoValue("AUR URL", baseURL+"/packages/"+a.Name) + printInfoValue("AUR URL", config.AURURL+"/packages/"+a.Name) printInfoValue("Groups", strings.Join(a.Groups, " ")) printInfoValue("Licenses", strings.Join(a.License, " ")) printInfoValue("Provides", strings.Join(a.Provides, " ")) @@ -310,7 +310,7 @@ func PrintInfo(a *rpc.Pkg) { printInfoValue("ID", fmt.Sprintf("%d", a.ID)) printInfoValue("Package Base ID", fmt.Sprintf("%d", a.PackageBaseID)) printInfoValue("Package Base", a.PackageBase) - printInfoValue("Snapshot URL", baseURL+a.URLPath) + printInfoValue("Snapshot URL", config.AURURL+a.URLPath) } fmt.Println() From 2f545c7fdc00c501fc2ae2f870ca016748e56000 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 19 Aug 2018 05:53:32 +0100 Subject: [PATCH 127/155] Correctly set config.AURURL after parsing flags And also honour aururl during -Pc --- completions.go | 2 +- main.go | 10 ---------- parser.go | 5 +++++ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/completions.go b/completions.go index 2a83f2ff..96d9a2da 100644 --- a/completions.go +++ b/completions.go @@ -13,7 +13,7 @@ import ( //CreateAURList creates a new completion file func createAURList(out *os.File) (err error) { - resp, err := http.Get("https://aur.archlinux.org/packages.gz") + resp, err := http.Get(config.AURURL + "/packages.gz") if err != nil { return err } diff --git a/main.go b/main.go index 5198abf8..53a6db58 100644 --- a/main.go +++ b/main.go @@ -4,13 +4,10 @@ import ( "encoding/json" "fmt" "os" - "path" "path/filepath" "strings" - "net/url" alpm "github.com/jguer/go-alpm" - rpc "github.com/mikkeloscar/aur" ) func setPaths() error { @@ -50,13 +47,6 @@ func initConfig() error { } } - url, err := url.Parse(config.AURURL) - if err != nil { - return err - } - url.Path = path.Join(url.Path, "") - rpc.AURURL = url.String() + "/rpc.php?" - return nil } diff --git a/parser.go b/parser.go index bc25a387..6cbdcf00 100644 --- a/parser.go +++ b/parser.go @@ -9,6 +9,8 @@ import ( "strconv" "strings" "unicode" + + rpc "github.com/mikkeloscar/aur" ) // A basic set implementation for strings. @@ -873,6 +875,9 @@ func (parser *arguments) extractYayOptions() { parser.delArg(option) } } + + rpc.AURURL = strings.TrimRight(config.AURURL, "/") + "/rpc.php?" + config.AURURL = strings.TrimRight(config.AURURL, "/") } //parses input for number menus splitted by spaces or commas From b39f7494dfc82d71d97c14c05e66e85068a19dbc Mon Sep 17 00:00:00 2001 From: Kenny Jackson Date: Mon, 20 Aug 2018 12:05:56 -0400 Subject: [PATCH 128/155] Fixed spelling errors --- doc/yay.8 | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/yay.8 b/doc/yay.8 index 7d558c76..5195fecc 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -230,7 +230,7 @@ the same when parsed. .TP .B \-\-answerupgrade Set a predetermined answer for the upgrade menu question. Selects which package -ranges or repos to omit for updades. This answer will be used instead of +ranges or repos to omit for updates. This answer will be used instead of reading from standard input but will be treated exactly the same. .TP @@ -252,7 +252,7 @@ Unset the answer for the upgrade menu. .TP .B \-\-cleanmenu 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. +downloaded build files from Yay's cache before redownloading a fresh copy. .TP .B \-\-diffmenu @@ -275,7 +275,7 @@ recommended to edit pkgbuild variables unless you know what you are doing. .B \-\-upgrademenu 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. +Additionally ^ can be used to invert the selection. \fBWarning\fR: It is not recommended to skip updates from the repositories as this can lead to partial upgrades. This feature is intended to easily skip AUR @@ -388,21 +388,21 @@ PKGBUILD. .TP .B \-\-nopgpfetch -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 +Do not prompt to import unknown PGP keys. This is likely to cause a build +failure unless using options such as \fB\-\-skippgpcheck\fR or a customized gpg config\%. .TP .B \-\-useask Use pacman's --ask flag to automatically confirm package conflicts. Yay lists -conflicts ahead of time. It is possible thay Yay does not detect -a conflict. Causing a package to be removed without the user's confimation. -Although this is very unlikley. +conflicts ahead of time. It is possible that Yay does not detect +a conflict, causing a package to be removed without the user's confirmation. +However, this is very unlikely. .TP .B \-\-nouseask Manually resolve package conflicts during the install. Packages which do not -conflict will not need to be confimed manually. +conflict will not need to be confined manually. .TP .B \-\-combinedupgrade @@ -433,7 +433,7 @@ in cache. .TP .B \-\-rebuildtree When installing an AUR package rebuild and reinstall all of its AUR -dependencies recursivley, even the ones already installed. This flag allows +dependencies recursively, even the ones already installed. This flag allows you to easily rebuild packages against your current system's libraries if they have become incompatible. From d34ce70455535510564b9f4c44702762d42eecaf Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 28 Aug 2018 04:33:51 +0100 Subject: [PATCH 129/155] Expand documentation for --devel Correclty say Git instead of GitHub Brielfly explain how --devel checks for updates Give an example of pacaur-like devel --- doc/yay.8 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/yay.8 b/doc/yay.8 index 5195fecc..66c310e5 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -321,7 +321,14 @@ Show AUR packages first and then repository packages. .TP .B \-\-devel During sysupgrade also check AUR development packages for updates. Currently -only GitHub packages are supported. +only Git packages are supported. + +Devel checking is done using \fBgit ls-remote\fR. The newest commit hash is +compared against the hash at install time. This allows devel updates to be +checked almost instantly and not require the original pkgbuild to be downloaded. + +The slower pacaur-like devel checks can be implemented manually by piping +a list of packages into yay (see \fBexamples\fR). .TP .B \-\-nodevel @@ -502,6 +509,10 @@ Sets devel to true in the config. yay \-P \-\-stats Shows statistics for installed packages and system health. +.TP +pacman -Qmq | grep -Ee '-(cvs|svn|git|hg|bzr|darcs)$' | yay -S --needed - +pacaur-like devel check. + .SH FILES .TP .B CONFIG DIRECTORY From 6894ddfd5cd46056e42d9cd0368e7cdbe37f9ec3 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 28 Aug 2018 04:04:18 +0100 Subject: [PATCH 130/155] Remove the timeout warning for vcs checks This message is proving to be more misleading than helpful. For git+https sources, many hosts seem to always timeout when trying ls-remote over git:// but then succeed on https://. This leads to a time out message being displayed even though the URL was queried successfully on the second try. --- vcs.go | 1 - 1 file changed, 1 deletion(-) diff --git a/vcs.go b/vcs.go index 584ed899..aba8c0cf 100644 --- a/vcs.go +++ b/vcs.go @@ -160,7 +160,6 @@ func getCommit(url string, branch string, protocols []string) string { //Introduce a time out so this can not hang timer := time.AfterFunc(5*time.Second, func() { cmd.Process.Kill() - fmt.Println(bold(yellow(arrow)), "Timeout:", cyan(url)) }) err = cmd.Wait() From d0cb79de6b4374a9913f9505c9188442b1958128 Mon Sep 17 00:00:00 2001 From: Jguer Date: Wed, 29 Aug 2018 18:30:16 +0100 Subject: [PATCH 131/155] Make hash an unsigned integer --- print.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print.go b/print.go index cb477932..8e4e2f5c 100644 --- a/print.go +++ b/print.go @@ -587,9 +587,9 @@ func colourHash(name string) (output string) { if !useColor { return name } - var hash = 5381 + var hash uint = 5381 for i := 0; i < len(name); i++ { - hash = int(name[i]) + ((hash << 5) + (hash)) + hash = uint(name[i]) + ((hash << 5) + (hash)) } return fmt.Sprintf("\x1b[%dm%s\x1b[0m", hash%6+31, name) } From c93b3fca9e7c4768df90b2555c66308228d24644 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 29 Aug 2018 20:19:31 +0100 Subject: [PATCH 132/155] Fix tests --- download.go | 2 +- keys_test.go | 26 +++++++++----------------- print_test.go | 2 +- upgrade_test.go | 4 ++-- vcs_test.go | 4 ++-- 5 files changed, 15 insertions(+), 23 deletions(-) diff --git a/download.go b/download.go index e1bcefad..c93fbf9b 100644 --- a/download.go +++ b/download.go @@ -67,7 +67,7 @@ func gitDownload(url string, path string, name string) (bool, error) { cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0") _, stderr, err := capture(cmd) if err != nil { - return false, fmt.Errorf("error cloning %s: stderr", name, stderr) + return false, fmt.Errorf("error cloning %s: %s", name, stderr) } return true, nil diff --git a/keys_test.go b/keys_test.go index d8717519..1b563682 100644 --- a/keys_test.go +++ b/keys_test.go @@ -146,34 +146,30 @@ func TestCheckPgpKeys(t *testing.T) { defer server.Shutdown(context.TODO()) casetests := []struct { - pkgs []*rpc.Pkg + pkgs Base srcinfos map[string]*gosrc.Srcinfo - bases map[string][]*rpc.Pkg wantError bool }{ // cower: single package, one valid key not yet in the keyring. // 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner. { - pkgs: []*rpc.Pkg{newPkg("cower")}, + pkgs: Base{newPkg("cower")}, srcinfos: map[string]*gosrc.Srcinfo{"cower": makeSrcinfo("cower", "487EACC08557AD082088DABA1EB2638FF56C0C53")}, - bases: map[string][]*rpc.Pkg{"cower": {newPkg("cower")}}, wantError: false, }, // libc++: single package, two valid keys not yet in the keyring. // 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard. // B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg. { - pkgs: []*rpc.Pkg{newPkg("libc++")}, + pkgs: Base{newPkg("libc++")}, srcinfos: map[string]*gosrc.Srcinfo{"libc++": makeSrcinfo("libc++", "11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D")}, - bases: map[string][]*rpc.Pkg{"libc++": {newPkg("libc++")}}, wantError: false, }, // Two dummy packages requiring the same key. // ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds. { - pkgs: []*rpc.Pkg{newPkg("dummy-1"), newPkg("dummy-2")}, + pkgs: Base{newPkg("dummy-1"), newPkg("dummy-2")}, srcinfos: map[string]*gosrc.Srcinfo{"dummy-1": makeSrcinfo("dummy-1", "ABAF11C65A2970B130ABE3C479BE3E4300411886"), "dummy-2": makeSrcinfo("dummy-2", "ABAF11C65A2970B130ABE3C479BE3E4300411886")}, - bases: map[string][]*rpc.Pkg{"dummy-1": {newPkg("dummy-1")}, "dummy-2": {newPkg("dummy-2")}}, wantError: false, }, // dummy package: single package, two valid keys, one of them already @@ -181,37 +177,33 @@ func TestCheckPgpKeys(t *testing.T) { // 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard. // C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey. { - pkgs: []*rpc.Pkg{newPkg("dummy-3")}, + pkgs: Base{newPkg("dummy-3")}, srcinfos: map[string]*gosrc.Srcinfo{"dummy-3": makeSrcinfo("dummy-3", "11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB")}, - bases: map[string][]*rpc.Pkg{"dummy-3": {newPkg("dummy-3")}}, wantError: false, }, // Two dummy packages with existing keys. { - pkgs: []*rpc.Pkg{newPkg("dummy-4"), newPkg("dummy-5")}, + pkgs: Base{newPkg("dummy-4"), newPkg("dummy-5")}, srcinfos: map[string]*gosrc.Srcinfo{"dummy-4": makeSrcinfo("dummy-4", "11E521D646982372EB577A1F8F0871F202119294"), "dummy-5": makeSrcinfo("dummy-5", "C52048C0C0748FEE227D47A2702353E0F7E48EDB")}, - bases: map[string][]*rpc.Pkg{"dummy-4": {newPkg("dummy-4")}, "dummy-5": {newPkg("dummy-5")}}, wantError: false, }, // Dummy package with invalid key, should fail. { - pkgs: []*rpc.Pkg{newPkg("dummy-7")}, + pkgs: Base{newPkg("dummy-7")}, srcinfos: map[string]*gosrc.Srcinfo{"dummy-7": makeSrcinfo("dummy-7", "THIS-SHOULD-FAIL")}, - bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}}, wantError: true, }, // Dummy package with both an invalid an another valid key, should fail. // A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler. { - pkgs: []*rpc.Pkg{newPkg("dummy-8")}, + pkgs: Base{newPkg("dummy-8")}, srcinfos: map[string]*gosrc.Srcinfo{"dummy-8": makeSrcinfo("dummy-8", "A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL")}, - bases: map[string][]*rpc.Pkg{"dummy-8": {newPkg("dummy-8")}}, wantError: true, }, } for _, tt := range casetests { - err := checkPgpKeys(tt.pkgs, tt.bases, tt.srcinfos) + err := checkPgpKeys([]Base{tt.pkgs}, tt.srcinfos) if !tt.wantError { if err != nil { t.Fatalf("Got error %q, want no error", err) diff --git a/print_test.go b/print_test.go index fec362d8..d05e58d7 100644 --- a/print_test.go +++ b/print_test.go @@ -11,7 +11,7 @@ func benchmarkPrintSearch(search string, b *testing.B) { os.Stdout = w for n := 0; n < b.N; n++ { - res, _, _ := queryRepo(append([]string{}, search)) + res, _ := queryRepo(append([]string{}, search)) res.printSearch() } os.Stdout = old diff --git a/upgrade_test.go b/upgrade_test.go index 47f301ea..3fab5139 100644 --- a/upgrade_test.go +++ b/upgrade_test.go @@ -32,7 +32,7 @@ func TestGetVersionDiff(t *testing.T) { } out := []versionPair{ - {"1-1", "1-1"}, + {"1-1" + red(""), "1-1" + green("")}, {red("1-1"), green("2-1")}, {red("2-1"), green("1-1")}, {"1-" + red("1"), "1-" + green("2")}, @@ -56,7 +56,7 @@ func TestGetVersionDiff(t *testing.T) { o, n := getVersionDiff(pair.Old, pair.New) if o != out[i].Old || n != out[i].New { - t.Errorf("Test %d failed for update: (%s => %s) expected (%s => %s) got (%s => %s)", i+1, in[i].Old, in[i].New, out[i].Old, out[i].New, o, n) + t.Errorf("Test %d failed for update: expected (%s => %s) got (%s => %s) %d %d %d %d", i+1, in[i].Old, in[i].New, o, n, len(in[i].Old), len(in[i].New), len(o), len(n)) } } } diff --git a/vcs_test.go b/vcs_test.go index 5354b40b..6fdee82a 100644 --- a/vcs_test.go +++ b/vcs_test.go @@ -49,7 +49,7 @@ func TestParsing(t *testing.T) { {"github.com/davidgiven/ack", "HEAD", []string{"git"}}, {"", "", nil}, {"", "", nil}, - {"github.com/jguer/yay.git", "foo", []string{"a", "b", "c", "d", "e", "f"}}, + {"", "", nil}, } for n, url := range urls { @@ -60,7 +60,7 @@ func TestParsing(t *testing.T) { branch != compare.Branch || !isEqual(protocols, compare.Protocols) { - t.Fatalf("Test %d failed: Expected: url=%+v branch=%+v protocols=%+v\ngot url=%+v branch=%+v protocols=%+v", n+1, url, branch, protocols, compare.URL, compare.Branch, compare.Protocols) + t.Fatalf("Test %d failed: Expected: url=%+v branch=%+v protocols=%+v\ngot url=%+v branch=%+v protocols=%+v", n+1, compare.URL, compare.Branch, compare.Protocols, url, branch, protocols) } } From 92ff640a6535d05b74c41b5ac03f4e5de6ed40d5 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 29 Aug 2018 20:37:25 +0100 Subject: [PATCH 133/155] Document --aururl --- cmd.go | 1 + doc/yay.8 | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/cmd.go b/cmd.go index 738d1ea9..c7bd5901 100644 --- a/cmd.go +++ b/cmd.go @@ -39,6 +39,7 @@ Permanent configuration options: --save Causes the following options to be saved back to the config file when used + --aururl Set an alternative AUR URL --builddir Directory used to download and run PKBUILDS --editor Editor to use when editing PKGBUILDs --editorflags Pass arguments to editor diff --git a/doc/yay.8 b/doc/yay.8 index 66c310e5..6f389d85 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -136,6 +136,11 @@ Causes the following options to be saved back to the config file. This provides an easy way to change config options without directly editing the file. +.TP +.B \-\-aururl +Set an alternative AUR URL. This is mostly useful for users in china who wish +to use https://aur.tuna.tsinghua.edu.cn/. + .TP .B \-\-builddir Directory to use for Building AUR Packages. This directory is also used as From 0a120132ec6f309a5fcf4b9e68c31fcc0aa6b1c9 Mon Sep 17 00:00:00 2001 From: digimokan Date: Thu, 30 Aug 2018 04:54:16 -0500 Subject: [PATCH 134/155] README grammar, spelling, rewording, organizing (#661) * README grammar, spelling, rewording, organizing - Add "Objectives" section to group objectives. - Transform Objective/Feature section bullets into action phrases. - Fix yay/yaourt/etc capitalization. Italicize and follow ArchWiki style. - Clearly identify the two Install section options with similar wording. - Reorganize and reword Contributing section. - Fix wording in last Code Style section sentence. - Fix misc FAQ wording. - Use same style for all FAQ issue links. - Change link in "skipping packages" FAQ item to ArchWiki partial upgrade. - Fix FAQ aur-only/repo-only cmd example line-spacing. - Remove yay -Pu example since it is a deprecated (and wrapped) option. * Fixup remove trailing newline in README file * Add warning about editing files in vendor/ * Fixup revert italicized project/program names * Change obj to Yaourt-style interactive srch/inst * Change obj to Minimal dependencies * Remove the limit-to-pacman deps feature * Revert init-install sentence, but add "alternatively" * Add provide-handling bullet to features * Revert aur/repo-only FAQ item to one line * Format cmd line examples similar to man page format * Revert interface-for-pacman objective * Mention dep instead of just saying don't touch * Merge gopath into the build stage Setting the gopath is more of a note than a step. It is not required and I would expect most people can simply ignore it. * Reword dependencies section. The contributing section should be information and say what dependencies are needed. There's no need to tell the user how to install them, they can figure that out themselves. Also mention git as a dependency. * Tweak headings and drop numbers Similar to the last commit. The headings should be informative "Code Style", not commanding "Check code". * yay -> Yay Be more consistent when writing Yay as a name. * Use ### instead of #### in Contributing These are real subheadings, #### looks too small. * Add support section --- README.md | 170 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index c227244f..ea47f6d3 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,59 @@ -# yay +# Yay -Yet another Yogurt - An AUR Helper written in Go +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) + +## Objectives + 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), [apacman](https://github.com/oshazard/apacman) and [pacaur](https://github.com/rmarquis/pacaur): +Yay is based on the design of [yaourt](https://github.com/archlinuxfr/yaourt), [apacman](https://github.com/oshazard/apacman) and [pacaur](https://github.com/rmarquis/pacaur). It is developed with these objectives in mind: -* Have almost no dependencies * Provide an interface for pacman -* Have yaourt-like search +* Yaourt-style interactive search/install +* Minimal dependencies * Minimize user input -* Know when git packages are due for an upgrade +* Know when git packages are due for upgrades ## Features -* AUR Tab completion -* Download PKGBUILD from ABS or AUR -* Ask all questions first and then start building -* 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 -* Advanced dependency solving +* Perform advanced dependency solving +* Download PKGBUILDs from ABS or AUR +* Tab-complete the AUR +* Query user up-front for all input (prior to starting builds) +* Narrow search terms (`yay linux header` will first search `linux` and then narrow on `header`) +* Find matching package providers during search and allow selection * Remove make dependencies at the end of the build process +* Run without sourcing PKGBUILD ## Installation -If you are migrating from another AUR helper you can simply install Yay from -the AUR like any other package. +If you are migrating from another AUR helper, you can simply install Yay with that helper. -The initial installation of Yay can be done by cloning the PKGBUILD and -building with makepkg. +Alternatively, 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 ``` +## Support + +All support related to Yay should be requested via GitHub issues. Since Yay is not +officially supported by Arch Linux, support should not be sought out on the +forums, AUR comments or other official channels. + +A broken AUR package should be reported as a comment on the package's AUR page. +A package may only be considered broken if it fails to build with makepkg. +Reports should be made using makepkg and include the full output as well as any +other relevant information. Never make reports using Yay or any other external +tools. + ## Contributing Contributors are always welcome! @@ -49,83 +63,105 @@ 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 +### Dependencies -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. +Yay depends on: -### Building +* go (make only) +* git +* base-devel -Yay is easy to build with its only build dependency being `go` and the -assumption of `base-devel` being installed. +Note: Yay also depends on a few other projects (as vendored dependencies). These +projects are stored in `vendor/`, are built into yay at build time, and do not +need to be installed separately. These files are managed by +[dep](https://github.com/golang/dep) and should not be modified manually. -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 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`. - -### 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 separately. - -Currently yay Depends on: +Following are the dependencies managed under dep: * https://github.com/Jguer/go-alpm * https://github.com/Morganamilo/go-srcinfo * https://github.com/mikkeloscar/aur +### Building + +Run `make` to build Yay. This command will generate a binary called `yay` in +the same directory as the Makefile. + +Note: Yay's Makefile automatically sets the `GOPATH` to `$PWD/.go`. This path will +ensure dependencies in `vendor/` are built. Running manual go commands such as +`go build` will require that you either set the `GOPATH` manually or `go get` +the vendored dependencies into your own `GOPATH`. + +### Code Style + +All code should be formatted through `go fmt`. This tool will automatically +format code for you. We recommend, however, that you write code in the proper +style and use `go fmt` only to catch mistakes. + +### Testing + +Run `make test` to test Yay. This command will verify that the code is +formatted correctly, run the code through `go vet`, and run unit tests. + ## 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) + Make sure you have the `Color` option in your `/etc/pacman.conf` + (see issue [#123](https://github.com/Jguer/yay/issues/123)). -#### Yay is not prompting to skip packages during sysupgrade (issue [#554](https://github.com/Jguer/yay/issues/554)) - The default behavior was changed after [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) - (see: [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc)). - To restore such behavior use `--combinedupgrade`. This can also be - permanently enabled by appending `--save`. - Note: this causes [native pacman](https://wiki.archlinux.org/index.php/AUR_helpers) to become partial. +#### Yay is not prompting to skip packages during system upgrade. + The default behavior was changed after + [v8.918](https://github.com/Jguer/yay/releases/tag/v8.918) + (see [3bdb534](https://github.com/Jguer/yay/commit/3bdb5343218d99d40f8a449b887348611f6bdbfc) + and issue [#554](https://github.com/Jguer/yay/issues/554)). + To restore the package-skip behavior use `--combinedupgrade` (make + it permanent by appending `--save`). Note: skipping packages will leave your + system in a + [partially-upgraded state](https://wiki.archlinux.org/index.php/System_maintenance#Partial_upgrades_are_unsupported). -#### Sometimes diffs are printed to the terminal and other times they are paged 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`. +#### Sometimes diffs are printed to the terminal, and other times they are paged via less. How do I fix this? + Yay uses `git diff` to display diffs, which by default tells less not to + page if the output can fit into one terminal length. This behavior 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 is not asking me to edit PKGBUILDS, and I don't like the diff menu! What can I do? `yay --editmenu --nodiffmenu --save` -#### Only act on AUR packages or only on repo packages? +#### How can I tell Yay to act only on AUR packages, or only on repo packages? `yay -{OPERATION} --aur` `yay -{OPERATION} --repo` -#### `Out Of Date AUR Packages` message is displayed, why doesn't `yay` update them? - This means the package has been flagged out of date on the AUR, but its - maintainer has not yet updated the `PKGBUILD`. +#### An `Out Of Date AUR Packages` message is displayed. Why doesn't Yay update them? + This message does not mean that updated AUR packages are available. It means + means the packages have been flagged out of date on the AUR, but + their maintainers have not yet updated the `PKGBUILD`s + (see [outdated AUR packages](https://wiki.archlinux.org/index.php/Arch_User_Repository#Foo_in_the_AUR_is_outdated.3B_what_should_I_do.3F)). -#### Yay doesn't install dependencies added to PKGBUILD during installation. +#### Yay doesn't install dependencies added to a PKGBUILD during installation. Yay resolves all dependencies ahead of time. You are free to edit the PKGBUILD in any way, but any problems you cause are your own and should not be reported unless they can be reproduced with the original PKGBUILD. ## Examples of Custom Operations -* `yay ` presents package selection menu -* `yay -Ps` prints system statistics -* `yay -Pu` prints update list -* `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 +`yay ` +        Present package-installation selection menu. + +`yay -Ps` +        Print system statistics. + +`yay -Yc` +        Clean unneeded dependencies. + +`yay -G ` +        Download PKGBUILD from ABS or AUR. + +`yay -Y --gendb` +        Generate development package database used for devel update. + +`yay -Syu --devel --timeupdate` +        Perform system upgrade, but also check for development package updates and use +        PKGBUILD modification time (not version number) to determine update. ## Images From 127c5e7cb9549e10e11a46cf04000393f08c7491 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 30 Aug 2018 11:06:03 +0100 Subject: [PATCH 135/155] Update shell completion for --aururl --- completions/bash | 2 +- completions/fish | 1 + completions/zsh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/completions/bash b/completions/bash index 39551ca1..bc700a77 100644 --- a/completions/bash +++ b/completions/bash @@ -69,7 +69,7 @@ _yay() { noansweredit noanswerupgrade cleanmenu diffmenu editmenu upgrademenu nocleanmenu nodiffmenu noupgrademenu provides noprovides pgpfetch nopgpfetch useask nouseask combinedupgrade nocombinedupgrade aur repo makepkgconf - nomakepkgconf askremovemake removemake noremovemake completioninterval' + nomakepkgconf askremovemake removemake noremovemake completioninterval aururl' 'b d h q r v') core=('database files help query remove sync upgrade version' 'D F Q R S U V h') diff --git a/completions/fish b/completions/fish index e9a84928..94ab4bba 100644 --- a/completions/fish +++ b/completions/fish @@ -46,6 +46,7 @@ complete -c $progname -s h -f -l help -n $noopt -d 'Display help' 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 aururl -d 'Set an alternative AUR URL' -f 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' diff --git a/completions/zsh b/completions/zsh index 8d005f44..ed1dd572 100644 --- a/completions/zsh +++ b/completions/zsh @@ -24,7 +24,7 @@ _pacman_opts_commands=( _pacman_opts_common=( '--repo[Assume targets are from the repositories]' {-a,--aur}'[Assume targets are from the AUR]' - + '--aururl[Set an alternative AUR URL]:url' '--arch[Set an alternate architecture]' {-b,--dbpath}'[Alternate database location]:database_location:_files -/' '--color[colorize the output]:color options:(always never auto)' From 5996e28e322584a18b72831582cdd4a533568ef2 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 30 Aug 2018 11:32:14 +0100 Subject: [PATCH 136/155] Use tabs and use pacman-conf over config parsing This makes our zsh completion more similar to pacmans. Making it easier to view diffs between the two. --- completions/zsh | 928 ++++++++++++++++++++++++------------------------ 1 file changed, 464 insertions(+), 464 deletions(-) diff --git a/completions/zsh b/completions/zsh index ed1dd572..71417205 100644 --- a/completions/zsh +++ b/completions/zsh @@ -6,598 +6,598 @@ setopt extendedglob # options for passing to _arguments: main pacman commands _pacman_opts_commands=( - {-D,--database}'[Modify database]' - {-F,--files}'[Query the files database]' - {-G,--getpkgbuild}'[Get PKGBUILD from ABS or AUR]' - {-Q,--query}'[Query the package database]' - {-R,--remove}'[Remove a package from the system]' - {-P,--print}'[Print yay information]' - {-S,--sync}'[Synchronize packages]' - {-T,--deptest}'[Check if dependencies are installed]' - {-U,--upgrade}'[Upgrade a package]' - {-Y,--yay}'[Yay specific options]' - {-V,--version}'[Display version and exit]' - '(-h --help)'{-h,--help}'[Display usage]' + {-D,--database}'[Modify database]' + {-F,--files}'[Query the files database]' + {-G,--getpkgbuild}'[Get PKGBUILD from ABS or AUR]' + {-Q,--query}'[Query the package database]' + {-R,--remove}'[Remove a package from the system]' + {-P,--print}'[Print yay information]' + {-S,--sync}'[Synchronize packages]' + {-T,--deptest}'[Check if dependencies are installed]' + {-U,--upgrade}'[Upgrade a package]' + {-Y,--yay}'[Yay specific options]' + {-V,--version}'[Display version and exit]' + '(-h --help)'{-h,--help}'[Display usage]' ) # 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]' - '--aururl[Set an alternative AUR URL]:url' - '--arch[Set an alternate architecture]' - {-b,--dbpath}'[Alternate database location]:database_location:_files -/' - '--color[colorize the output]:color options:(always never auto)' - {-h,--help}'[Display syntax for the given operation]' - {-r,--root}'[Set alternate installation root]:installation root:_files -/' - {-v,--verbose}'[Be more verbose]' - '--cachedir[Alternate package cache location]:cache_location:_files -/' - '--config[An alternate configuration file]:config file:_files' - '--makepkgconf[makepkg.conf file to use]:config file:_files' - '--nomakepkgconf[Use the default makepkg.conf]' - '--requestsplitn[Max amount of packages to query per AUR request]:number' - '--completioninterval[Time in days to to refresh completion cache]:number' - '--confirm[Always ask for confirmation]' - '--debug[Display debug messages]' - '--gpgdir[Set an alternate directory for GnuPG (instead of /etc/pacman.d/gnupg)]: :_files -/' - '--hookdir[Set an alternate hook location]: :_files -/' - '--logfile[An alternate log file]:config file:_files' - '--noconfirm[Do not ask for confirmation]' - '--noprogressbar[Do not show a progress bar when downloading files]' - '--noscriptlet[Do not execute the install scriptlet if one exists]' + '--repo[Assume targets are from the repositories]' + {-a,--aur}'[Assume targets are from the AUR]' + '--aururl[Set an alternative AUR URL]:url' + '--arch[Set an alternate architecture]' + {-b,--dbpath}'[Alternate database location]:database_location:_files -/' + '--color[colorize the output]:color options:(always never auto)' + {-h,--help}'[Display syntax for the given operation]' + {-r,--root}'[Set alternate installation root]:installation root:_files -/' + {-v,--verbose}'[Be more verbose]' + '--cachedir[Alternate package cache location]:cache_location:_files -/' + '--config[An alternate configuration file]:config file:_files' + '--makepkgconf[makepkg.conf file to use]:config file:_files' + '--nomakepkgconf[Use the default makepkg.conf]' + '--requestsplitn[Max amount of packages to query per AUR request]:number' + '--completioninterval[Time in days to to refresh completion cache]:number' + '--confirm[Always ask for confirmation]' + '--debug[Display debug messages]' + '--gpgdir[Set an alternate directory for GnuPG (instead of /etc/pacman.d/gnupg)]: :_files -/' + '--hookdir[Set an alternate hook location]: :_files -/' + '--logfile[An alternate log file]:config file:_files' + '--noconfirm[Do not ask for confirmation]' + '--noprogressbar[Do not show a progress bar when downloading files]' + '--noscriptlet[Do not execute the install scriptlet if one exists]' - '--save[Causes config options to be saved back to the config file]' + '--save[Causes config options to be saved back to the config file]' - '--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' - '--git[git command to use]:git:_files' - '--gpg[gpg command to use]:gpg:_files' + '--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' + '--git[git command to use]:git:_files' + '--gpg[gpg command to use]:gpg:_files' - '--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]: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]" - "--askremovemake[Ask to remove makedepends after install]" - "--removemake[Remove makedepends after install]" - "--noremovemake[Don't remove makedepends after install]" + '--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]: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]" + "--askremovemake[Ask to remove makedepends after install]" + "--removemake[Remove makedepends after install]" + "--noremovemake[Don't remove makedepends after install]" - '--bottomup[Show AUR packages first]' - '--topdown[Show repository packages first]' - '--devel[Check -git/-svn/-hg development version]' - '--nodevel[Disable development version checking]' - '--afterclean[Clean package sources after successful build]' - '--noafterclean[Disable package sources cleaning after successful build]' - '--timeupdate[Check packages modification date and version]' - '--notimeupdate[Check only package version change]' - '--redownload[Always download pkgbuilds of targets]' - '--redownloadall[Always download pkgbuilds of all AUR packages]' - '--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]" - "--useask[Automatically resolve conflicts using pacman's ask flag]" - '--nouseask[Confirm conflicts manually during the install]' - '--combinedupgrade[Refresh then perform the repo and AUR upgrade together]' - '--nocombinedupgrade[Perform the repo upgrade and AUR upgrade separately]' - '--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' - '--gpgflags[Pass arguments to gpg]:gpgflags' - '--sudoloop[Loop sudo calls in the background to avoid timeout]' - '--nosudoloop[Do not loop sudo calls in the backgrount]' + '--bottomup[Show AUR packages first]' + '--topdown[Show repository packages first]' + '--devel[Check -git/-svn/-hg development version]' + '--nodevel[Disable development version checking]' + '--afterclean[Clean package sources after successful build]' + '--noafterclean[Disable package sources cleaning after successful build]' + '--timeupdate[Check packages modification date and version]' + '--notimeupdate[Check only package version change]' + '--redownload[Always download pkgbuilds of targets]' + '--redownloadall[Always download pkgbuilds of all AUR packages]' + '--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]" + "--useask[Automatically resolve conflicts using pacman's ask flag]" + '--nouseask[Confirm conflicts manually during the install]' + '--combinedupgrade[Refresh then perform the repo and AUR upgrade together]' + '--nocombinedupgrade[Perform the repo upgrade and AUR upgrade separately]' + '--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' + '--gpgflags[Pass arguments to gpg]:gpgflags' + '--sudoloop[Loop sudo calls in the background to avoid timeout]' + '--nosudoloop[Do not loop sudo calls in the backgrount]' ) # options for passing to _arguments: options for --upgrade commands _pacman_opts_pkgfile=( - '*-d[Skip dependency checks]' - '*--nodeps[Skip dependency checks]' - '*--assume-installed[Add virtual package to satisfy dependencies]' - '--dbonly[Only remove database entry, do not remove files]' - '--force[Overwrite conflicting files]' - '--needed[Do not reinstall up to date packages]' - '--asdeps[mark packages as non-explicitly installed]' - '--asexplicit[mark packages as explicitly installed]' - {-p,--print}'[Only print the targets instead of performing the operation]' - '*--ignore[Ignore a package upgrade]:package: _pacman_completions_all_packages' - '*--ignoregroup[Ignore a group upgrade]:package group:_pacman_completions_all_groups' - '--print-format[Specify how the targets should be printed]' - '*:package file:_files -g "*.pkg.tar*~*.sig(.,@)"' + '*-d[Skip dependency checks]' + '*--nodeps[Skip dependency checks]' + '*--assume-installed[Add virtual package to satisfy dependencies]' + '--dbonly[Only remove database entry, do not remove files]' + '--force[Overwrite conflicting files]' + '--needed[Do not reinstall up to date packages]' + '--asdeps[mark packages as non-explicitly installed]' + '--asexplicit[mark packages as explicitly installed]' + {-p,--print}'[Only print the targets instead of performing the operation]' + '*--ignore[Ignore a package upgrade]:package: _pacman_completions_all_packages' + '*--ignoregroup[Ignore a group upgrade]:package group:_pacman_completions_all_groups' + '--print-format[Specify how the targets should be printed]' + '*:package file:_files -g "*.pkg.tar*~*.sig(.,@)"' ) # options for passing to _arguments: subactions for --query command _pacman_opts_query_actions=( - '(-Q --query)'{-Q,--query} - {-g,--groups}'[View all members of a package group]:*:package groups:->query_group' - {-o,--owns}'[Query the package that owns a file]:file:_files' - {-p,--file}'[Package file to query]:*:package file:->query_file' - {-s,--search}'[Search package names and descriptions]:*:search text:->query_search' + '(-Q --query)'{-Q,--query} + {-g,--groups}'[View all members of a package group]:*:package groups:->query_group' + {-o,--owns}'[Query the package that owns a file]:file:_files' + {-p,--file}'[Package file to query]:*:package file:->query_file' + {-s,--search}'[Search package names and descriptions]:*:search text:->query_search' ) # options for passing to _arguments: options for --query and subcommands _pacman_opts_query_modifiers=( - {-c,--changelog}'[List package changelog]' - {-d,--deps}'[List packages installed as dependencies]' - {-e,--explicit}'[List packages explicitly installed]' - {\*-i,\*--info}'[View package information]' - {\*-k,\*--check}'[Check package files]' - {-l,--list}'[List package contents]' - {-m,--foreign}'[List installed packages not found in sync db(s)]' - {-n,--native}'[List installed packages found in sync db(s)]' - {-q,--quiet}'[Show less information for query and search]' - {-t,--unrequired}'[List packages not required by any package]' - {-u,--upgrades}'[List packages that can be upgraded]' + {-c,--changelog}'[List package changelog]' + {-d,--deps}'[List packages installed as dependencies]' + {-e,--explicit}'[List packages explicitly installed]' + {\*-i,\*--info}'[View package information]' + {\*-k,\*--check}'[Check package files]' + {-l,--list}'[List package contents]' + {-m,--foreign}'[List installed packages not found in sync db(s)]' + {-n,--native}'[List installed packages found in sync db(s)]' + {-q,--quiet}'[Show less information for query and search]' + {-t,--unrequired}'[List packages not required by any package]' + {-u,--upgrades}'[List packages that can be upgraded]' ) # -Y _pacman_opts_yay_modifiers=( - {-c,--clean}'[Remove unneeded dependencies]' - '--gendb[Generates development package DB used for updating]' + {-c,--clean}'[Remove unneeded dependencies]' + '--gendb[Generates development package DB used for updating]' ) # -P _pacman_opts_print_modifiers=( - {-c,--complete}'[Used for completions]' - {-d,--defaultconfig}'[Print default yay configuration]' - {-g,--config}'[Print current yay configuration]' - {-n,--numberupgrades}'[Print number of updates]' - {-s,--stats}'[Display system package statistics]' - {-u,--upgrades}'[Print update list]' - {-w,--news}'[Print arch news]' + {-c,--complete}'[Used for completions]' + {-d,--defaultconfig}'[Print default yay configuration]' + {-g,--config}'[Print current yay configuration]' + {-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=( - {-c,--cascade}'[Remove all dependent packages]' - {-d,--nodeps}'[Skip dependency checks]' - '*--assume-installed[Add virtual package to satisfy dependencies]' - {-n,--nosave}'[Remove protected configuration files]' - {-p,--print}'[Only print the targets instead of performing the operation]' - {\*-s,\*--recursive}'[Remove dependencies not required by other packages]' - {-u,--unneeded}'[Remove unneeded packages]' - '--dbonly[Only remove database entry, do not remove files]' - '--print-format[Specify how the targets should be printed]' - '*:installed package:_pacman_completions_installed_packages' + {-c,--cascade}'[Remove all dependent packages]' + {-d,--nodeps}'[Skip dependency checks]' + '*--assume-installed[Add virtual package to satisfy dependencies]' + {-n,--nosave}'[Remove protected configuration files]' + {-p,--print}'[Only print the targets instead of performing the operation]' + {\*-s,\*--recursive}'[Remove dependencies not required by other packages]' + {-u,--unneeded}'[Remove unneeded packages]' + '--dbonly[Only remove database entry, do not remove files]' + '--print-format[Specify how the targets should be printed]' + '*:installed package:_pacman_completions_installed_packages' ) _pacman_opts_database=( - '--asdeps[mark packages as non-explicitly installed]' - '--asexplicit[mark packages as explicitly installed]' - '*:installed package:_pacman_completions_installed_packages' + '--asdeps[mark packages as non-explicitly installed]' + '--asexplicit[mark packages as explicitly installed]' + '*:installed package:_pacman_completions_installed_packages' ) _pacman_opts_files=( - {-l,--list}'[List the files owned by the queried package]:package:_pacman_completions_all_packages' - {-o,--owns}'[Query the package that owns]:files:_files' - {-s,--search}'[Search package file names for matching strings]:files:_files' - {-x,--regex}'[Enable searching using regular expressions]:regex:' - {-y,--refresh}'[Download fresh files databases from the server]' - '--machinereadable[Produce machine-readable output]' - {-q,--quiet}'[Show less information for query and search]' + {-l,--list}'[List the files owned by the queried package]:package:_pacman_completions_all_packages' + {-o,--owns}'[Query the package that owns]:files:_files' + {-s,--search}'[Search package file names for matching strings]:files:_files' + {-x,--regex}'[Enable searching using regular expressions]:regex:' + {-y,--refresh}'[Download fresh files databases from the server]' + '--machinereadable[Produce machine-readable output]' + {-q,--quiet}'[Show less information for query and search]' ) # options for passing to _arguments: options for --sync command _pacman_opts_sync_actions=( - '(-S --sync)'{-S,--sync} - {\*-c,\*--clean}'[Remove old packages from cache]:\*:clean:->sync_clean' - {-g,--groups}'[View all members of a package group]:*:package groups:->sync_group' - {-s,--search}'[Search package names and descriptions]:*:search text:->sync_search' - '--dbonly[Only remove database entry, do not remove files]' - '--needed[Do not reinstall up to date packages]' - '--recursive[Reinstall all dependencies of target packages]' + '(-S --sync)'{-S,--sync} + {\*-c,\*--clean}'[Remove old packages from cache]:\*:clean:->sync_clean' + {-g,--groups}'[View all members of a package group]:*:package groups:->sync_group' + {-s,--search}'[Search package names and descriptions]:*:search text:->sync_search' + '--dbonly[Only remove database entry, do not remove files]' + '--needed[Do not reinstall up to date packages]' + '--recursive[Reinstall all dependencies of target packages]' ) # options for passing to _arguments: options for --sync command _pacman_opts_sync_modifiers=( - {\*-d,\*--nodeps}'[Skip dependency checks]' - '*--assume-installed[Add virtual package to satisfy dependencies]' - {\*-i,\*--info}'[View package information]' - {-l,--list}'[List all packages in a repository]' - {-p,--print}'[Print download URIs for each package to be installed]' - {-q,--quiet}'[Show less information for query and search]' - {\*-u,\*--sysupgrade}'[Upgrade all out-of-date packages]' - {-w,--downloadonly}'[Download packages only]' - {\*-y,\*--refresh}'[Download fresh package databases]' - '*--ignore[Ignore a package upgrade]:package: _pacman_completions_all_packages' - '*--ignoregroup[Ignore a group upgrade]:package group:_pacman_completions_all_groups' - '--asdeps[Install packages as non-explicitly installed]' - '--asexplicit[Install packages as explicitly installed]' - '--force[Overwrite conflicting files]' - '--print-format[Specify how the targets should be printed]' + {\*-d,\*--nodeps}'[Skip dependency checks]' + '*--assume-installed[Add virtual package to satisfy dependencies]' + {\*-i,\*--info}'[View package information]' + {-l,--list}'[List all packages in a repository]' + {-p,--print}'[Print download URIs for each package to be installed]' + {-q,--quiet}'[Show less information for query and search]' + {\*-u,\*--sysupgrade}'[Upgrade all out-of-date packages]' + {-w,--downloadonly}'[Download packages only]' + {\*-y,\*--refresh}'[Download fresh package databases]' + '*--ignore[Ignore a package upgrade]:package: _pacman_completions_all_packages' + '*--ignoregroup[Ignore a group upgrade]:package group:_pacman_completions_all_groups' + '--asdeps[Install packages as non-explicitly installed]' + '--asexplicit[Install packages as explicitly installed]' + '--force[Overwrite conflicting files]' + '--print-format[Specify how the targets should be printed]' ) # handles --help subcommand _pacman_action_help() { - _arguments -s : \ - "$_pacman_opts_commands[@]" + _arguments -s : \ + "$_pacman_opts_commands[@]" } # handles cases where no subcommand has yet been given _pacman_action_none() { - _arguments -s : \ - "$_pacman_opts_commands[@]" + _arguments -s : \ + "$_pacman_opts_commands[@]" } # handles --query subcommand _pacman_action_query() { - local context state line - typeset -A opt_args + local context state line + typeset -A opt_args - case $state in - query_file) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:package file:_files -g "*.pkg.tar*~*.sig(.,@)"' - ;; - query_group) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:groups:_pacman_completions_installed_groups' - ;; - query_owner) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:file:_files' - ;; - query_search) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:search text: ' - ;; - *) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_actions[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:package:_pacman_completions_installed_packages' - ;; - esac + case $state in + query_file) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:package file:_files -g "*.pkg.tar*~*.sig(.,@)"' + ;; + query_group) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:groups:_pacman_completions_installed_groups' + ;; + query_owner) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:file:_files' + ;; + query_search) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:search text: ' + ;; + *) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_actions[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:package:_pacman_completions_installed_packages' + ;; + esac } # handles --remove subcommand _pacman_action_remove() { - _arguments -s : \ - '(--remove -R)'{-R,--remove} \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_remove[@]" + _arguments -s : \ + '(--remove -R)'{-R,--remove} \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_remove[@]" } # handles --database subcommand _pacman_action_database() { - _arguments -s : \ - '(--database -D)'{-D,--database} \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_database[@]" + _arguments -s : \ + '(--database -D)'{-D,--database} \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_database[@]" } # handles --files subcommand _pacman_action_files() { - _arguments -s : \ - '(--files -F)'{-F,--files} \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_files[@]" + _arguments -s : \ + '(--files -F)'{-F,--files} \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_files[@]" } _pacman_action_deptest () { - _arguments -s : \ - '(--deptest)-T' \ - "$_pacman_opts_common[@]" \ - ":packages:_pacman_all_packages" + _arguments -s : \ + '(--deptest)-T' \ + "$_pacman_opts_common[@]" \ + ":packages:_pacman_all_packages" } # handles --sync subcommand _pacman_action_sync() { - local context state line - typeset -A opt_args - if (( $+words[(r)--clean] )); then - state=sync_clean - elif (( $+words[(r)--groups] )); then - state=sync_group - elif (( $+words[(r)--search] )); then - state=sync_search - fi + local context state line + typeset -A opt_args + if (( $+words[(r)--clean] )); then + state=sync_clean + elif (( $+words[(r)--groups] )); then + state=sync_group + elif (( $+words[(r)--search] )); then + state=sync_search + fi - case $state in - sync_clean) - _arguments -s : \ - {\*-c,\*--clean}'[Remove old packages from cache]' \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_modifiers[@]" - ;; - sync_group) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_modifiers[@]" \ - '(-g --group)'{-g,--groups} \ - '*:package group:_pacman_completions_all_groups' - ;; - sync_search) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_modifiers[@]" \ - '*:search text: ' - ;; - *) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_actions[@]" \ - "$_pacman_opts_sync_modifiers[@]" \ - '*:package:_pacman_completions_all_packages' - ;; - esac + case $state in + sync_clean) + _arguments -s : \ + {\*-c,\*--clean}'[Remove old packages from cache]' \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_modifiers[@]" + ;; + sync_group) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_modifiers[@]" \ + '(-g --group)'{-g,--groups} \ + '*:package group:_pacman_completions_all_groups' + ;; + sync_search) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_modifiers[@]" \ + '*:search text: ' + ;; + *) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_actions[@]" \ + "$_pacman_opts_sync_modifiers[@]" \ + '*:package:_pacman_completions_all_packages' + ;; + esac } # handles --upgrade subcommand _pacman_action_upgrade() { - _arguments -s : \ - '(-U --upgrade)'{-U,--upgrade} \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_pkgfile[@]" + _arguments -s : \ + '(-U --upgrade)'{-U,--upgrade} \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_pkgfile[@]" } # handles --version subcommand _pacman_action_version() { - # no further arguments - return 0 + # no further arguments + return 0 } # provides completions for package groups _pacman_completions_all_groups() { - local -a cmd groups - _pacman_get_command - groups=( $(_call_program groups $cmd[@] -Sg) ) - typeset -U groups + local -a cmd groups + _pacman_get_command + groups=( $(_call_program groups $cmd[@] -Sg) ) + typeset -U groups - if [[ ${words[CURRENT-1]} == '--ignoregroup' ]]; then - _sequence compadd -S ',' "$@" -a groups - else - compadd "$@" -a groups - fi + if [[ ${words[CURRENT-1]} == '--ignoregroup' ]]; then + _sequence compadd -S ',' "$@" -a groups + else + compadd "$@" -a groups + fi } # provides completions for packages available from repositories # these can be specified as either 'package' or 'repository/package' _pacman_completions_all_packages() { - local -a seq sep cmd packages repositories packages_long + local -a seq sep cmd packages repositories packages_long - if [[ ${words[CURRENT-1]} == '--ignore' ]]; then - seq='_sequence' - sep=(-S ',') - else - seq= - sep=() - fi + if [[ ${words[CURRENT-1]} == '--ignore' ]]; then + seq='_sequence' + sep=(-S ',') + else + seq= + sep=() + fi - if compset -P1 '*/*'; then - packages=( $(_call_program packages yay -Pc ${words[CURRENT]%/*}) ) - typeset -U packages - ${seq} _wanted repo_packages expl "repository/package" compadd ${sep[@]} ${(@)packages} - else - packages=( $(_call_program packages yay -Pc ) ) - typeset -U packages - ${seq} _wanted packages expl "packages" compadd ${sep[@]} - "${(@)packages}" + if compset -P1 '*/*'; then + packages=( $(_call_program packages yay -Pc ${words[CURRENT]%/*}) ) + typeset -U packages + ${seq} _wanted repo_packages expl "repository/package" compadd ${sep[@]} ${(@)packages} + else + packages=( $(_call_program packages yay -Pc ) ) + typeset -U packages + ${seq} _wanted packages expl "packages" compadd ${sep[@]} - "${(@)packages}" - repositories=(${(o)${${${(M)${(f)"$(/dev/null") - integer i - for (( i = 2; i < CURRENT - 1; i++ )); do - if [[ ${words[i]} = "--config" || ${words[i]} = "--root" ]]; then - cmd+=( ${words[i,i+1]} ) - fi - done + # this is mostly nicked from _perforce + cmd=( "pacman" "2>/dev/null") + integer i + for (( i = 2; i < CURRENT - 1; i++ )); do + if [[ ${words[i]} = "--config" || ${words[i]} = "--root" ]]; then + cmd+=( ${words[i,i+1]} ) + fi + done } # main dispatcher _pacman_zsh_comp() { - local -a args cmds; - local tmp - args=( ${${${(M)words:#-*}#-}:#-*} ) - for tmp in $words; do - cmds+=("${${_pacman_opts_commands[(r)*$tmp\[*]%%\[*}#*\)}") - done - case $args in #$words[2] in - h*) - if (( ${(c)#args} <= 1 && ${(w)#cmds} <= 1 )); then - _pacman_action_help - else - _message "no more arguments" - fi - ;; - *h*) - _message "no more arguments" - ;; - D*) - _pacman_action_database - ;; - F*) - _pacman_action_files - ;; - Q*g*) # ipkg groups - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:groups:_pacman_completions_installed_groups' - ;; - Q*o*) # file - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:package file:_files' - ;; - Q*p*) # file *.pkg.tar* - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_query_modifiers[@]" \ - '*:package file:_files -g "*.pkg.tar*~*.sig(.,@)"' - ;; - T*) - _pacman_action_deptest - ;; - Q*) - _pacman_action_query - ;; - P*) - _arguments -s : \ - "$_pacman_opts_print_modifiers[@]" - ;; - R*) - _pacman_action_remove - ;; - S*c*) # no completion - _arguments -s : \ - '(-c --clean)'{\*-c,\*--clean}'[Remove all files from the cache]' \ - "$_pacman_opts_common[@]" - ;; - S*l*) # repos - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_modifiers[@]" \ - '*:package repo:_pacman_completions_repositories' \ - ;; - S*g*) # pkg groups - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_modifiers[@]" \ - '*:package group:_pacman_completions_all_groups' - ;; - S*s*) - _arguments -s : \ - "$_pacman_opts_common[@]" \ - "$_pacman_opts_sync_modifiers[@]" \ - '*:search text: ' - ;; - S*) - _pacman_action_sync - ;; - T*) - _arguments -s : \ - '-T' \ - "$_pacman_opts_common[@]" \ - ":packages:_pacman_all_packages" - ;; - U*) - _pacman_action_upgrade - ;; - V*) - _pacman_action_version - ;; - Y*) - _arguments -s : \ - "$_pacman_opts_yay_modifiers[@]" - ;; - *) + local -a args cmds; + local tmp + args=( ${${${(M)words:#-*}#-}:#-*} ) + for tmp in $words; do + cmds+=("${${_pacman_opts_commands[(r)*$tmp\[*]%%\[*}#*\)}") + done + case $args in #$words[2] in + h*) + if (( ${(c)#args} <= 1 && ${(w)#cmds} <= 1 )); then + _pacman_action_help + else + _message "no more arguments" + fi + ;; + *h*) + _message "no more arguments" + ;; + D*) + _pacman_action_database + ;; + F*) + _pacman_action_files + ;; + Q*g*) # ipkg groups + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:groups:_pacman_completions_installed_groups' + ;; + Q*o*) # file + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:package file:_files' + ;; + Q*p*) # file *.pkg.tar* + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_query_modifiers[@]" \ + '*:package file:_files -g "*.pkg.tar*~*.sig(.,@)"' + ;; + T*) + _pacman_action_deptest + ;; + Q*) + _pacman_action_query + ;; + P*) + _arguments -s : \ + "$_pacman_opts_print_modifiers[@]" + ;; + R*) + _pacman_action_remove + ;; + S*c*) # no completion + _arguments -s : \ + '(-c --clean)'{\*-c,\*--clean}'[Remove all files from the cache]' \ + "$_pacman_opts_common[@]" + ;; + S*l*) # repos + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_modifiers[@]" \ + '*:package repo:_pacman_completions_repositories' \ + ;; + S*g*) # pkg groups + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_modifiers[@]" \ + '*:package group:_pacman_completions_all_groups' + ;; + S*s*) + _arguments -s : \ + "$_pacman_opts_common[@]" \ + "$_pacman_opts_sync_modifiers[@]" \ + '*:search text: ' + ;; + S*) + _pacman_action_sync + ;; + T*) + _arguments -s : \ + '-T' \ + "$_pacman_opts_common[@]" \ + ":packages:_pacman_all_packages" + ;; + U*) + _pacman_action_upgrade + ;; + V*) + _pacman_action_version + ;; + Y*) + _arguments -s : \ + "$_pacman_opts_yay_modifiers[@]" + ;; + *) - case ${(M)words:#--*} in - *--help*) - if (( ${(w)#cmds} == 1 )); then - _pacman_action_help - else - return 0; - fi - ;; - *--sync*) - _pacman_action_sync - ;; - *--query*) - _pacman_action_query - ;; - *--remove*) - _pacman_action_remove - ;; - *--deptest*) - _pacman_action_deptest - ;; - *--database*) - _pacman_action_database - ;; - *--files*) - _pacman_action_files - ;; - *--version*) - _pacman_action_version - ;; - *--upgrade*) - _pacman_action_upgrade - ;; - *) - _pacman_action_none - ;; - esac - ;; - esac + case ${(M)words:#--*} in + *--help*) + if (( ${(w)#cmds} == 1 )); then + _pacman_action_help + else + return 0; + fi + ;; + *--sync*) + _pacman_action_sync + ;; + *--query*) + _pacman_action_query + ;; + *--remove*) + _pacman_action_remove + ;; + *--deptest*) + _pacman_action_deptest + ;; + *--database*) + _pacman_action_database + ;; + *--files*) + _pacman_action_files + ;; + *--version*) + _pacman_action_version + ;; + *--upgrade*) + _pacman_action_upgrade + ;; + *) + _pacman_action_none + ;; + esac + ;; + esac } _pacman_comp() { - case "$service" in - yay) - _pacman_zsh_comp "$@" - ;; - *) - _message "Error" - ;; - esac + case "$service" in + yay) + _pacman_zsh_comp "$@" + ;; + *) + _message "Error" + ;; + esac } _pacman_comp "$@" From 004595a396438867bdc3f7bba0dc72eca43aa951 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 30 Aug 2018 15:30:52 +0100 Subject: [PATCH 137/155] Dont rm directories with -G unless using -f --- download.go | 37 +++++++++++++++++++++++++++++++++---- parser.go | 2 +- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/download.go b/download.go index c93fbf9b..37747c9b 100644 --- a/download.go +++ b/download.go @@ -158,9 +158,29 @@ func getPkgbuilds(pkgs []string) error { } if len(aur) > 0 { - bases := getBases(info) - toSkip := pkgbuildsToSkip(bases, nil) - if _, err = downloadPkgbuilds(bases, toSkip, wd); err != nil { + allBases := getBases(info) + bases := make([]Base, 0) + + for _, base := range allBases { + name := base.Pkgbase() + _, err = os.Stat(filepath.Join(wd, name)) + if err != nil && !os.IsNotExist(err) { + fmt.Println(bold(red(smallArrow)), err) + continue + } else if os.IsNotExist(err) || cmdArgs.existsArg("f", "force") || shouldUseGit(filepath.Join(wd, name)) { + if err = os.RemoveAll(filepath.Join(wd, name)); err != nil { + fmt.Println(bold(red(smallArrow)), err) + continue + } + } else { + fmt.Printf("%s %s %s\n", yellow(smallArrow), cyan(name), "already downloaded -- use -f to overwrite") + continue + } + + bases = append(bases, base) + } + + if _, err = downloadPkgbuilds(bases, nil, wd); err != nil { return err } @@ -227,9 +247,18 @@ func getPkgbuildsfromABS(pkgs []string, path string) (bool, error) { continue } - if err = os.RemoveAll(filepath.Join(path, name)); err != nil { + _, err = os.Stat(filepath.Join(path, name)) + if err != nil && !os.IsNotExist(err) { fmt.Println(bold(red(smallArrow)), err) continue + } else if os.IsNotExist(err) || cmdArgs.existsArg("f", "force") { + if err = os.RemoveAll(filepath.Join(path, name)); err != nil { + fmt.Println(bold(red(smallArrow)), err) + continue + } + } else { + fmt.Printf("%s %s %s\n", yellow(smallArrow), cyan(name), "already downloaded -- use -f to overwrite") + continue } names[name] = url diff --git a/parser.go b/parser.go index 6cbdcf00..1c1ccd86 100644 --- a/parser.go +++ b/parser.go @@ -389,7 +389,7 @@ func isArg(arg string) bool { case "ignoregroup": case "needed": case "overwrite": - case "force": + case "f", "force": case "c", "changelog": case "deps": case "e", "explicit": From ae06ca23804574b2a1c2a3ec7c868f9d35da2c00 Mon Sep 17 00:00:00 2001 From: Cirelli Date: Thu, 30 Aug 2018 17:02:20 +0200 Subject: [PATCH 138/155] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea47f6d3..333d0258 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ formatted correctly, run the code through `go vet`, and run unit tests. #### An `Out Of Date AUR Packages` message is displayed. Why doesn't Yay update them? This message does not mean that updated AUR packages are available. It means - means the packages have been flagged out of date on the AUR, but + the packages have been flagged out of date on the AUR, but their maintainers have not yet updated the `PKGBUILD`s (see [outdated AUR packages](https://wiki.archlinux.org/index.php/Arch_User_Repository#Foo_in_the_AUR_is_outdated.3B_what_should_I_do.3F)). From 29642d181fefc52f65126ba8af365f7a57acc0be Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 30 Aug 2018 15:48:13 +0100 Subject: [PATCH 139/155] Document -f for -G and --print -> --show --- cmd.go | 7 +++++-- doc/yay.8 | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cmd.go b/cmd.go index c7bd5901..2da1f9b5 100644 --- a/cmd.go +++ b/cmd.go @@ -109,17 +109,20 @@ Permanent configuration options: --timeupdate Check packages' AUR page for changes during sysupgrade --notimeupdate Do not check packages' AUR page for changes -Print specific options: +show specific options: -c --complete Used for completions -d --defaultconfig Print default yay configuration -g --currentconfig Print current yay configuration -s --stats Display system package statistics -w --news Print arch news -Yay specific options: +yay specific options: -c --clean Remove unneeded dependencies --gendb Generates development package DB used for updating +getpkgbuild specific options: + -f --force Force download for existing tar packages + If no arguments are provided 'yay -Syu' will be performed If no operation is provided -Y will be assumed`) } diff --git a/doc/yay.8 b/doc/yay.8 index 6f389d85..03af0dfc 100644 --- a/doc/yay.8 +++ b/doc/yay.8 @@ -87,7 +87,7 @@ used when migrating to Yay from another AUR helper. .B \-c, \-\-clean Remove unneeded dependencies. -.SH PRINT OPTIONS (APPLY TO \-P AND \-\-PRINT) +.SH SHOW OPTIONS (APPLY TO \-P AND \-\-SHOW) .TP .B \-c, \-\-complete Print a list of all AUR and repo packages. This is to allow shell completion @@ -129,6 +129,13 @@ available news. .B \-q, \-\-quiet Only show titles when printing news. +.SH GETPKGBUILD OPTIONS (APPLY TO \-G AND \-\-GETPKGBUILD) +.TP +.B \-f, \-\-force +Force download for packages that already exist in the current directory. This +is to ensure directories are not accidentally overwritten. This option is not +needed for git based downloads as \fBgit pull\fR already has saftey mechanisms. + .SH PERMANENT CONFIGURATION SETTINGS .TP .B \-\-save From 0657f7e23f92a0d6be83ed99986526c7fa7e8e66 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 30 Aug 2018 16:07:45 +0100 Subject: [PATCH 140/155] Complete -f for -G and --print -> --show --- completions/bash | 7 ++++--- completions/fish | 21 ++++++++++++--------- completions/zsh | 12 +++++++++++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/completions/bash b/completions/bash index bc700a77..83ef41b7 100644 --- a/completions/bash +++ b/completions/bash @@ -48,7 +48,7 @@ _pacman_repo_list() { _yay() { local common core cur database files prev query remove sync upgrade o - local yays show + local yays show getpkgbuild COMPREPLY=() _get_comp_words_by_ref cur prev database=('asdeps asexplicit') @@ -75,9 +75,10 @@ _yay() { ##yay stuff yays=('clean gendb' 'c') - print=('complete defaultconfig currentconfig stats news' 'c d g s w') + show=('complete defaultconfig currentconfig stats news' 'c d g s w') + getpkgbuild=('force' 'f') - for o in 'D database' 'F files' 'Q query' 'R remove' 'S sync' 'U upgrade' 'Y yays' 'P show'; do + for o in 'D database' 'F files' 'Q query' 'R remove' 'S sync' 'U upgrade' 'Y yays' 'P show' 'G getpkgbuild'; do _arch_incomp "$o" && break done diff --git a/completions/fish b/completions/fish index 94ab4bba..552983d3 100644 --- a/completions/fish +++ b/completions/fish @@ -15,7 +15,7 @@ set -l listpacman "(__fish_print_packages)" set -l noopt 'not __fish_contains_opt -s Y -s G -s V -s P -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' +set -l show '__fish_contains_opt -s P show' set -l query '__fish_contains_opt -s Q query' set -l remove '__fish_contains_opt -s R remove' set -l sync '__fish_contains_opt -s S sync' @@ -31,7 +31,7 @@ set -l yayspecific '__fish_contains_opt -s Y yay' complete -c $progname -s D -f -l database -n $noopt -d 'Modify 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 P -f -l show -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' @@ -134,13 +134,16 @@ complete -c $progname -n "not $noopt" -l completioninterval -d 'Refresh interval complete -c $progname -n $yayspecific -s c -l clean -d 'Remove unneeded dependencies' -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 -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' -complete -c $progname -n $print -s q -l quiet -d 'Do not print news description' +# Show options +complete -c $progname -n $show -s d -l defaultconfig -d 'Print current yay configuration' -f +complete -c $progname -n $show -s n -l numberupgrades -d 'Print number of updates' -f +complete -c $progname -n $show -s s -l stats -d 'Display system package statistics' -f +complete -c $progname -n $show -s u -l upgrades -d 'Print update list' -f +complete -c $progname -n $show -s w -l news -d 'Print arch news' +complete -c $progname -n $show -s q -l quiet -d 'Do not print news description' + +# Getpkgbuild options +complete -c $progname -n $getpkgbuild -s f -l force -d 'Force download for existing tar packages' -f # Transaction options (sync, remove, upgrade) for condition in sync remove upgrade diff --git a/completions/zsh b/completions/zsh index 71417205..cb76a2f8 100644 --- a/completions/zsh +++ b/completions/zsh @@ -11,7 +11,7 @@ _pacman_opts_commands=( {-G,--getpkgbuild}'[Get PKGBUILD from ABS or AUR]' {-Q,--query}'[Query the package database]' {-R,--remove}'[Remove a package from the system]' - {-P,--print}'[Print yay information]' + {-P,--show}'[Print yay information]' {-S,--sync}'[Synchronize packages]' {-T,--deptest}'[Check if dependencies are installed]' {-U,--upgrade}'[Upgrade a package]' @@ -152,6 +152,11 @@ _pacman_opts_yay_modifiers=( '--gendb[Generates development package DB used for updating]' ) +# -G +_pacman_opts_getpkgbuild_modifiers=( + {-f,--force}'[Force download for existing tar packages]' +) + # -P _pacman_opts_print_modifiers=( {-c,--complete}'[Used for completions]' @@ -548,6 +553,11 @@ _pacman_zsh_comp() { _arguments -s : \ "$_pacman_opts_yay_modifiers[@]" ;; + G*) + _arguments -s : \ + "$_pacman_opts_getpkgbuild_modifiers[@]" + ;; + *) case ${(M)words:#--*} in From b757d0abd399adaaf7139eb59d0ccd4c4c81ed04 Mon Sep 17 00:00:00 2001 From: Jguer Date: Fri, 31 Aug 2018 13:33:01 +0100 Subject: [PATCH 141/155] Set correct version for manual builds Signed-off-by: Jguer --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 0148c8c8..e4c2ecaa 100644 --- a/config.go +++ b/config.go @@ -77,7 +77,7 @@ type Configuration struct { UseAsk bool `json:"useask"` } -var version = "7.885" +var version = "8.1101" // configFileName holds the name of the config file. const configFileName string = "config.json" From 8c1658df0bd836e4df0d422545e902f9a08949c4 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 31 Aug 2018 21:19:40 +0100 Subject: [PATCH 142/155] Expand environment variables in config --- cmd.go | 5 ++++- config.go | 35 +++++++++++++++++++++++++++++++++-- main.go | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cmd.go b/cmd.go index 2da1f9b5..1e9e0b58 100644 --- a/cmd.go +++ b/cmd.go @@ -132,6 +132,8 @@ func handleCmd() (err error) { config.saveConfig() } + config.expandEnv() + if cmdArgs.existsArg("h", "help") { err = handleHelp() return @@ -196,7 +198,8 @@ func handlePrint() (err error) { switch { case cmdArgs.existsArg("d", "defaultconfig"): var tmpConfig Configuration - defaultSettings(&tmpConfig) + tmpConfig.defaultSettings() + tmpConfig.expandEnv() fmt.Printf("%v", tmpConfig) case cmdArgs.existsArg("g", "currentconfig"): fmt.Printf("%v", config) diff --git a/config.go b/config.go index e4c2ecaa..e2dc47dc 100644 --- a/config.go +++ b/config.go @@ -146,9 +146,14 @@ func (config *Configuration) saveConfig() error { return err } -func defaultSettings(config *Configuration) { +func (config *Configuration) defaultSettings() { + buildDir := "$HOME/.config/yay" + if os.Getenv("XDG_CONFIG_HOME") != "" { + buildDir = "$XDG_CONFIG_HOME/yay" + } + config.AURURL = "https://aur.archlinux.org" - config.BuildDir = cacheHome + config.BuildDir = buildDir config.CleanAfter = false config.Editor = "" config.EditorFlags = "" @@ -188,6 +193,32 @@ func defaultSettings(config *Configuration) { config.CombinedUpgrade = false } + +func (config *Configuration) expandEnv() { + config.AURURL = os.ExpandEnv(config.AURURL) + config.BuildDir = os.ExpandEnv(config.BuildDir) + config.Editor = os.ExpandEnv(config.Editor) + config.EditorFlags = os.ExpandEnv(config.EditorFlags) + config.MakepkgBin = os.ExpandEnv(config.MakepkgBin) + config.MakepkgConf = os.ExpandEnv(config.MakepkgConf) + config.PacmanBin = os.ExpandEnv(config.PacmanBin) + config.PacmanConf = os.ExpandEnv(config.PacmanConf) + config.GpgFlags = os.ExpandEnv(config.GpgFlags) + config.MFlags = os.ExpandEnv(config.MFlags) + config.GitFlags = os.ExpandEnv(config.GitFlags) + config.SortBy = os.ExpandEnv(config.SortBy) + config.TarBin = os.ExpandEnv(config.TarBin) + config.GitBin = os.ExpandEnv(config.GitBin) + config.GpgBin = os.ExpandEnv(config.GpgBin) + config.ReDownload = os.ExpandEnv(config.ReDownload) + config.ReBuild = os.ExpandEnv(config.ReBuild) + config.AnswerClean = os.ExpandEnv(config.AnswerClean) + config.AnswerDiff = os.ExpandEnv(config.AnswerDiff) + config.AnswerEdit = os.ExpandEnv(config.AnswerEdit) + config.AnswerUpgrade = os.ExpandEnv(config.AnswerUpgrade) + config.RemoveMake = os.ExpandEnv(config.RemoveMake) +} + // Editor returns the preferred system editor. func editor() (string, []string) { switch { diff --git a/main.go b/main.go index 53a6db58..b108bf9b 100644 --- a/main.go +++ b/main.go @@ -198,7 +198,7 @@ func main() { } exitOnError(setPaths()) - defaultSettings(&config) + config.defaultSettings() exitOnError(initHomeDirs()) exitOnError(initConfig()) exitOnError(cmdArgs.parseCommandLine()) From 00b880baf92483a479e6b56aa50b814e28cfbd28 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 17:43:32 +0100 Subject: [PATCH 143/155] Fix depends sometimes being ordered incorrectly --- config.go | 1 - depOrder.go | 22 ++++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/config.go b/config.go index e2dc47dc..2c285395 100644 --- a/config.go +++ b/config.go @@ -193,7 +193,6 @@ func (config *Configuration) defaultSettings() { config.CombinedUpgrade = false } - func (config *Configuration) expandEnv() { config.AURURL = os.ExpandEnv(config.AURURL) config.BuildDir = os.ExpandEnv(config.BuildDir) diff --git a/depOrder.go b/depOrder.go index f1d0e4cb..e2d3f9a1 100644 --- a/depOrder.go +++ b/depOrder.go @@ -35,18 +35,17 @@ func makeDepOrder() *depOrder { func getDepOrder(dp *depPool) *depOrder { do := makeDepOrder() - basesMap := make(map[string]Base) for _, target := range dp.Targets { dep := target.DepString() aurPkg := dp.Aur[dep] if aurPkg != nil && pkgSatisfies(aurPkg.Name, aurPkg.Version, dep) { - do.orderPkgAur(aurPkg, dp, basesMap, true) + do.orderPkgAur(aurPkg, dp, true) } aurPkg = dp.findSatisfierAur(dep) if aurPkg != nil { - do.orderPkgAur(aurPkg, dp, basesMap, true) + do.orderPkgAur(aurPkg, dp, true) } repoPkg := dp.findSatisfierRepo(dep) @@ -55,14 +54,10 @@ func getDepOrder(dp *depPool) *depOrder { } } - for _, base := range basesMap { - do.Aur = append(do.Aur, base) - } - return do } -func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, basesMap map[string]Base, runtime bool) { +func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) { if runtime { do.Runtime.set(pkg.Name) } @@ -72,7 +67,7 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, basesMap map[string]B for _, dep := range deps { aurPkg := dp.findSatisfierAur(dep) if aurPkg != nil { - do.orderPkgAur(aurPkg, dp, basesMap, runtime && i == 0) + do.orderPkgAur(aurPkg, dp, runtime && i == 0) } repoPkg := dp.findSatisfierRepo(dep) @@ -82,7 +77,14 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, basesMap map[string]B } } - basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg) + for i, base := range do.Aur { + if base.Pkgbase() == pkg.PackageBase { + do.Aur[i] = append(base, pkg) + return + } + } + + do.Aur = append(do.Aur, Base{pkg}) } func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { From 2b6a73041f7a4e486b3b1d7bf6f928b0d8a02eae Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 18:23:05 +0100 Subject: [PATCH 144/155] Fix redownload logic --redownload was reversed and redownloaded the deps instead of the targets. --- install.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/install.go b/install.go index ecceb784..0f4d3d42 100644 --- a/install.go +++ b/install.go @@ -796,14 +796,16 @@ func pkgbuildsToSkip(bases []Base, targets stringSet) stringSet { isTarget = isTarget || targets.get(pkg.Name) } - if config.ReDownload == "no" || (config.ReDownload == "yes" && isTarget) { - dir := filepath.Join(config.BuildDir, base.Pkgbase(), ".SRCINFO") - pkgbuild, err := gosrc.ParseFile(dir) + if (config.ReDownload == "yes" && isTarget) || config.ReDownload == "all" { + continue + } - if err == nil { - if alpm.VerCmp(pkgbuild.Version(), base.Version()) >= 0 { - toSkip.set(base.Pkgbase()) - } + dir := filepath.Join(config.BuildDir, base.Pkgbase(), ".SRCINFO") + pkgbuild, err := gosrc.ParseFile(dir) + + if err == nil { + if alpm.VerCmp(pkgbuild.Version(), base.Version()) >= 0 { + toSkip.set(base.Pkgbase()) } } } From 1beeaaf299500a095404c79e1df4020a6d18afd8 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 18:28:36 +0100 Subject: [PATCH 145/155] Limit download concurrency to 25 threads --- download.go | 5 +++++ install.go | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/download.go b/download.go index 37747c9b..32e6516f 100644 --- a/download.go +++ b/download.go @@ -286,9 +286,14 @@ func getPkgbuildsfromABS(pkgs []string, path string) (bool, error) { mux.Unlock() } + count := 0 for name, url := range names { wg.Add(1) go download(name, url) + count++ + if count%25 == 0 { + wg.Wait() + } } wg.Wait() diff --git a/install.go b/install.go index 0f4d3d42..229662e0 100644 --- a/install.go +++ b/install.go @@ -872,9 +872,14 @@ func downloadPkgbuilds(bases []Base, toSkip stringSet, buildDir string) (stringS mux.Unlock() } + count := 0 for k, base := range bases { wg.Add(1) go download(k, base) + count++ + if count%25 == 0 { + wg.Wait() + } } wg.Wait() From 5c7d6fa3bed5a330a72ca25a751aa69fe41ddaf8 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 20:01:49 +0100 Subject: [PATCH 146/155] Fix --rebuild logic --- depPool.go | 9 +++------ install.go | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/depPool.go b/depPool.go index ef6ee0a1..a598e56b 100644 --- a/depPool.go +++ b/depPool.go @@ -301,14 +301,12 @@ func (dp *depPool) resolveAURPackages(pkgs stringSet, explicit bool) error { continue } - //has satisfier installed: skip - _, isInstalled := dp.LocalDb.PkgCache().FindSatisfier(dep) - if isInstalled == nil { + _, isInstalled := dp.LocalDb.PkgCache().FindSatisfier(dep) //has satisfier installed: skip + repoPkg, inRepos := dp.SyncDb.FindSatisfier(dep) //has satisfier in repo: fetch it + if isInstalled == nil && (config.ReBuild != "tree" || inRepos == nil) { continue } - //has satisfier in repo: fetch it - repoPkg, inRepos := dp.SyncDb.FindSatisfier(dep) if inRepos == nil { dp.ResolveRepoDependency(repoPkg) continue @@ -321,7 +319,6 @@ func (dp *depPool) resolveAURPackages(pkgs stringSet, explicit bool) error { } err = dp.resolveAURPackages(newAURPackages, false) - return err } diff --git a/install.go b/install.go index 229662e0..623b0ecb 100644 --- a/install.go +++ b/install.go @@ -935,7 +935,7 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc for _, b := range base { isExplicit = isExplicit || dp.Explicit.get(b.Name) } - if config.ReBuild == "no" || (config.ReBuild == "yes" && isExplicit) { + if config.ReBuild == "no" || (config.ReBuild == "yes" && !isExplicit) { for _, split := range base { pkgdest, ok := pkgdests[split.Name] if !ok { From a109ea480c19882e4bcc8ef8d75d5030dd474890 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 4 Sep 2018 20:18:33 +0100 Subject: [PATCH 147/155] Set version manually for gcc-go Signed-off-by: Jguer --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 2c285395..b8a73d62 100644 --- a/config.go +++ b/config.go @@ -77,7 +77,7 @@ type Configuration struct { UseAsk bool `json:"useask"` } -var version = "8.1101" +var version = "8.1110" // configFileName holds the name of the config file. const configFileName string = "config.json" From 0e695468b80da3ed9d7b2fe479f49b46267e2390 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 23:05:35 +0100 Subject: [PATCH 148/155] Expand env before making builddir --- cmd.go | 6 ------ main.go | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cmd.go b/cmd.go index 1e9e0b58..8819e739 100644 --- a/cmd.go +++ b/cmd.go @@ -128,12 +128,6 @@ If no operation is provided -Y will be assumed`) } func handleCmd() (err error) { - if shouldSaveConfig { - config.saveConfig() - } - - config.expandEnv() - if cmdArgs.existsArg("h", "help") { err = handleHelp() return diff --git a/main.go b/main.go index b108bf9b..304c03a4 100644 --- a/main.go +++ b/main.go @@ -202,6 +202,10 @@ func main() { exitOnError(initHomeDirs()) exitOnError(initConfig()) exitOnError(cmdArgs.parseCommandLine()) + if shouldSaveConfig { + config.saveConfig() + } + config.expandEnv() exitOnError(initBuildDir()) exitOnError(initVCS()) exitOnError(initAlpm()) From c00436486427b2233678a00828a08a006e254f14 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 23:19:31 +0100 Subject: [PATCH 149/155] Fix builddir defaulting to config instead of cache --- config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index b8a73d62..74755f5f 100644 --- a/config.go +++ b/config.go @@ -147,9 +147,9 @@ func (config *Configuration) saveConfig() error { } func (config *Configuration) defaultSettings() { - buildDir := "$HOME/.config/yay" - if os.Getenv("XDG_CONFIG_HOME") != "" { - buildDir = "$XDG_CONFIG_HOME/yay" + buildDir := "$HOME/.cache/yay" + if os.Getenv("XDG_CACHE_HOME") != "" { + buildDir = "$XDG_CACHE_HOME/yay" } config.AURURL = "https://aur.archlinux.org" From 6e0797a8c7729ed4d028f3cb3f5ccca3b7944c89 Mon Sep 17 00:00:00 2001 From: Jguer Date: Wed, 5 Sep 2018 09:21:11 +0100 Subject: [PATCH 150/155] Set version manually for gcc-go Signed-off-by: Jguer --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 74755f5f..e199bcbc 100644 --- a/config.go +++ b/config.go @@ -77,7 +77,7 @@ type Configuration struct { UseAsk bool `json:"useask"` } -var version = "8.1110" +var version = "8.1115" // configFileName holds the name of the config file. const configFileName string = "config.json" From 81bccfd34e4d40c242b6eecfb2bb0243f8215344 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 7 Sep 2018 18:55:24 +0100 Subject: [PATCH 151/155] Don't assume the go root The go root might be in different places if the user is using a different go binary that is not managed by the system (eg /usr/local/bin/go). In this case the go binary should be smart enough to default to it's own go root. Or if there are still problems, it is on the user to configure it themselves. --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 39bb7fb3..2c23b15d 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,6 @@ BINNAME := yay PACKAGE := ${PKGNAME}_${VERSION}_${ARCH} export GOPATH=$(shell pwd)/.go -export GOROOT=/usr/lib/go default: build From 83d3411549b907ba90ddb92ccd006a2485186686 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 10 Sep 2018 23:07:19 +0100 Subject: [PATCH 152/155] Add go-pacmanconf --- Gopkg.lock | 12 + Gopkg.toml | 4 + .../Morganamilo/go-pacmanconf/LICENSE | 674 ++++++++++++++++++ .../Morganamilo/go-pacmanconf/cmd.go | 20 + .../Morganamilo/go-pacmanconf/ini/ini.go | 65 ++ .../Morganamilo/go-pacmanconf/pacmanconf.go | 46 ++ .../Morganamilo/go-pacmanconf/parser.go | 137 ++++ 7 files changed, 958 insertions(+) create mode 100644 vendor/github.com/Morganamilo/go-pacmanconf/LICENSE create mode 100644 vendor/github.com/Morganamilo/go-pacmanconf/cmd.go create mode 100644 vendor/github.com/Morganamilo/go-pacmanconf/ini/ini.go create mode 100644 vendor/github.com/Morganamilo/go-pacmanconf/pacmanconf.go create mode 100644 vendor/github.com/Morganamilo/go-pacmanconf/parser.go diff --git a/Gopkg.lock b/Gopkg.lock index 97953b93..4709b2ef 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,17 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + digest = "1:4e8f84eb856dd3ed05982f065caf7866a4995be9cc3718614dcecbd57e26c260" + name = "github.com/Morganamilo/go-pacmanconf" + packages = [ + ".", + "ini", + ] + pruneopts = "NUT" + revision = "9c5265e1b14f7e21dafabbad9ccf801d3815d707" + [[projects]] branch = "master" digest = "1:5f709618dc8a0ff9221d3685c95d69ed7d80ca94e58f3483f5d9bdefb4e6bb25" @@ -29,6 +40,7 @@ analyzer-name = "dep" analyzer-version = 1 input-imports = [ + "github.com/Morganamilo/go-pacmanconf", "github.com/Morganamilo/go-srcinfo", "github.com/jguer/go-alpm", "github.com/mikkeloscar/aur", diff --git a/Gopkg.toml b/Gopkg.toml index 82d4ef9c..d7fdafcf 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -14,3 +14,7 @@ [[constraint]] branch = "master" name = "github.com/Morganamilo/go-srcinfo" + +[[constraint]] + branch = "master" + name = "github.com/Morganamilo/go-pacmanconf" diff --git a/vendor/github.com/Morganamilo/go-pacmanconf/LICENSE b/vendor/github.com/Morganamilo/go-pacmanconf/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/vendor/github.com/Morganamilo/go-pacmanconf/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/vendor/github.com/Morganamilo/go-pacmanconf/cmd.go b/vendor/github.com/Morganamilo/go-pacmanconf/cmd.go new file mode 100644 index 00000000..f23510da --- /dev/null +++ b/vendor/github.com/Morganamilo/go-pacmanconf/cmd.go @@ -0,0 +1,20 @@ +package pacmanconf + +import ( + "bytes" + "os/exec" +) + +func pacmanconf(args []string) (string, string, error) { + var outbuf, errbuf bytes.Buffer + cmd := exec.Command("pacman-conf", args...) + + cmd.Stdout = &outbuf + cmd.Stderr = &errbuf + + err := cmd.Run() + stdout := outbuf.String() + stderr := errbuf.String() + + return stdout, stderr, err +} diff --git a/vendor/github.com/Morganamilo/go-pacmanconf/ini/ini.go b/vendor/github.com/Morganamilo/go-pacmanconf/ini/ini.go new file mode 100644 index 00000000..9a2993b8 --- /dev/null +++ b/vendor/github.com/Morganamilo/go-pacmanconf/ini/ini.go @@ -0,0 +1,65 @@ +package ini + +import ( + "strings" + "io/ioutil" +) + +type Callback func(fileName string, line int, section string, + key string, value string, data interface{}) error + +func Parse(ini string, cb Callback, data interface{}) error { + return parse("", ini, cb, data) +} + +func ParseFile(fileName string, cb Callback, data interface{}) error { + file, err := ioutil.ReadFile(fileName) + if err != nil { + return cb(fileName, -1, err.Error(), "", "", data) + } + + return parse(fileName, string(file), cb, data) +} + +func parse(fileName string, ini string, cb Callback, data interface{}) error { + lines := strings.Split(ini, "\n") + header := "" + + for n, line := range lines { + line = strings.TrimSpace(line) + + if len(line) == 0 || strings.HasPrefix(line, "#") { + continue + } + + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + runes := []rune(line) + header = string(runes[1 : len(runes)-1]) + + if err := cb(fileName, n, header, "", "", data); err != nil { + return err + } + continue + } + + key, value := splitPair(line) + if err := cb(fileName, n, header, key, value, data); err != nil { + return err + } + } + + return nil +} + +func splitPair(line string) (string, string) { + split := strings.SplitN(line, "=", 2) + + key := strings.TrimSpace(split[0]) + + if len(split) == 1 { + return key, "" + } + + value := strings.TrimSpace(split[1]) + return key, value +} diff --git a/vendor/github.com/Morganamilo/go-pacmanconf/pacmanconf.go b/vendor/github.com/Morganamilo/go-pacmanconf/pacmanconf.go new file mode 100644 index 00000000..357c4040 --- /dev/null +++ b/vendor/github.com/Morganamilo/go-pacmanconf/pacmanconf.go @@ -0,0 +1,46 @@ +package pacmanconf + +type Repository struct { + Name string + Servers []string + SigLevel []string + Usage []string +} + +type Config struct { + RootDir string + DBPath string + CacheDir []string + HookDir []string + GPGDir string + LogFile string + HoldPkg []string + IgnorePkg []string + IgnoreGroup []string + Architecture string + XferCommand string + NoUpgrade []string + NoExtract []string + CleanMethod []string + SigLevel []string + LocalFileSigLevel []string + RemoteFileSigLevel []string + UseSyslog bool + Color bool + UseDelta float64 + TotalDownload bool + CheckSpace bool + VerbosePkgLists bool + DisableDownloadTimeout bool + Repos []Repository +} + +func (conf *Config) Repository(name string) *Repository { + for _, repo := range conf.Repos { + if repo.Name == name { + return &repo + } + } + + return nil +} diff --git a/vendor/github.com/Morganamilo/go-pacmanconf/parser.go b/vendor/github.com/Morganamilo/go-pacmanconf/parser.go new file mode 100644 index 00000000..18623fde --- /dev/null +++ b/vendor/github.com/Morganamilo/go-pacmanconf/parser.go @@ -0,0 +1,137 @@ +package pacmanconf + +import ( + "fmt" + "github.com/Morganamilo/go-pacmanconf/ini" + "strconv" +) + +type callbackData struct { + conf *Config + repo *Repository +} + +func parseCallback(fileName string, line int, section string, + key string, value string, data interface{}) error { + if line < 0 { + return fmt.Errorf("unable to read file: %s: %s", fileName, section) + } + + d, ok := data.(*callbackData) + if !ok { + return fmt.Errorf("type assert failed when parsing: %s", fileName) + } + + if key == "" && value == "" { + if section == "options" { + d.repo = nil + } else { + d.conf.Repos = append(d.conf.Repos, Repository{}) + d.repo = &d.conf.Repos[len(d.conf.Repos)-1] + d.repo.Name = section + } + + return nil + } + + if section == "" { + return fmt.Errorf("line %d is not in a section: %s", line, fileName) + } + + if d.repo == nil { + setOption(d.conf, key, value) + } else { + setRepo(d.repo, key, value) + } + + return nil +} + +func setRepo(repo *Repository, key string, value string) { + switch key { + case "Server": + repo.Servers = append(repo.Servers, value) + case "SigLevel": + repo.SigLevel = append(repo.SigLevel, value) + case "Usage": + repo.Usage = append(repo.Usage, value) + } +} + +func setOption(conf *Config, key string, value string) { + switch key { + case "RootDir": + conf.RootDir = value + case "DBPath": + conf.DBPath = value + case "CacheDir": + conf.CacheDir = append(conf.CacheDir, value) + case "HookDir": + conf.HookDir = append(conf.HookDir, value) + case "GPGDir": + conf.GPGDir = value + case "LogFile": + conf.LogFile = value + case "HoldPkg": + conf.HoldPkg = append(conf.HoldPkg, value) + case "IgnorePkg": + conf.IgnorePkg = append(conf.IgnorePkg, value) + case "IgnoreGroup": + conf.IgnoreGroup = append(conf.IgnoreGroup, value) + case "Architecture": + conf.Architecture = value + case "XferCommand": + conf.XferCommand = value + case "NoUpgrade": + conf.NoUpgrade = append(conf.NoUpgrade, value) + case "NoExtract": + conf.NoExtract = append(conf.NoExtract, value) + case "CleanMethod": + conf.CleanMethod = append(conf.CleanMethod, value) + case "SigLevel": + conf.SigLevel = append(conf.SigLevel, value) + case "LocalFileSigLevel": + conf.LocalFileSigLevel = append(conf.LocalFileSigLevel, value) + case "RemoteFileSigLevel": + conf.RemoteFileSigLevel = append(conf.RemoteFileSigLevel, value) + case "UseSyslog": + conf.UseSyslog = true + case "Color": + conf.Color = true + case "UseDelta": + f, err := strconv.ParseFloat(value, 64) + if err == nil { + conf.UseDelta = f + } + case "TotalDownload": + conf.TotalDownload = true + case "CheckSpace": + conf.CheckSpace = true + case "VerbosePkgLists": + conf.VerbosePkgLists = true + case "DisableDownloadTimeout": + conf.DisableDownloadTimeout = true + } +} + +func Parse(iniData string) (*Config, error) { + data := callbackData{&Config{}, nil} + err := ini.Parse(iniData, parseCallback, &data) + return data.conf, err +} + +func PacmanConf(args ...string) (*Config, string, error) { + stdout, stderr, err := pacmanconf(args) + + if err != nil { + return nil, stderr, err + } + + conf, err := Parse(stdout) + + return conf, "", err +} + +func ParseFile(path string) (*Config, string, error) { + return PacmanConf("--config", path) +} From b2f636d93b9768344823f2e9b225c645c2e7be58 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Tue, 4 Sep 2018 15:47:22 +0100 Subject: [PATCH 153/155] Use go-pacmanconf for config parsing This moves the config parsing from out of alpm and into the go-pacmanconf libary plus some boilerplate code to get it into our alpm config. This makes sense as many config options such as UseColor and CleanMethod have nothing to do with alpm and only relate to pacman. pacman-conf is used instead of direct config parsing. This tool resolves defaults and includes for us, so we don't need to handle it. It is now safe to drop all the config parsing from go-alpm. --- clean.go | 2 +- config.go | 124 ++++++++++++++++++++++++++++++++++++++++++++++++------ exec.go | 4 +- main.go | 36 ++++++++++------ 4 files changed, 136 insertions(+), 30 deletions(-) diff --git a/clean.go b/clean.go index f8e743b2..eb3faa74 100644 --- a/clean.go +++ b/clean.go @@ -59,7 +59,7 @@ func syncClean(parser *arguments) error { _, removeAll, _ := parser.getArg("c", "clean") - for _, v := range alpmConf.CleanMethod { + for _, v := range pacmanConf.CleanMethod { if v == "KeepInstalled" { keepInstalled = true } else if v == "KeepCurrent" { diff --git a/config.go b/config.go index e199bcbc..f725b4cb 100644 --- a/config.go +++ b/config.go @@ -9,6 +9,7 @@ import ( "os/exec" "strings" + pacmanconf "github.com/Morganamilo/go-pacmanconf" alpm "github.com/jguer/go-alpm" ) @@ -110,7 +111,7 @@ var shouldSaveConfig bool var config Configuration // AlpmConf holds the current config values for pacman. -var alpmConf alpm.PacmanConfig +var pacmanConf *pacmanconf.Config // AlpmHandle is the alpm handle used by yay. var alpmHandle *alpm.Handle @@ -118,18 +119,6 @@ var alpmHandle *alpm.Handle // Mode is used to restrict yay to AUR or repo only modes var mode = ModeAny -func readAlpmConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { - file, err := os.Open(pacmanconf) - if err != nil { - return - } - conf, err = alpm.ParseConfig(file) - if err != nil { - return - } - return -} - // SaveConfig writes yay config to file. func (config *Configuration) saveConfig() error { marshalledinfo, _ := json.MarshalIndent(config, "", "\t") @@ -332,3 +321,112 @@ func (config Configuration) String() string { } return buf.String() } + +func toUsage(usages []string) alpm.Usage { + if len(usages) == 0 { + return alpm.UsageAll + } + + var ret alpm.Usage = 0 + for _, usage := range usages { + switch usage { + case "Sync": + ret |= alpm.UsageSync + case "Search": + ret |= alpm.UsageSearch + case "Install": + ret |= alpm.UsageInstall + case "Upgrade": + ret |= alpm.UsageUpgrade + case "All": + ret |= alpm.UsageAll + } + } + + return ret +} + +func configureAlpm(conf *pacmanconf.Config) error { + var err error + + // TODO: set SigLevel + sigLevel := alpm.SigPackage | alpm.SigPackageOptional | alpm.SigDatabase | alpm.SigDatabaseOptional + localFileSigLevel := alpm.SigUseDefault + remoteFileSigLevel := alpm.SigUseDefault + + for _, repo := range pacmanConf.Repos { + // TODO: set SigLevel + db, err := alpmHandle.RegisterSyncDb(repo.Name, sigLevel) + if err != nil { + return err + } + + db.SetServers(repo.Servers) + db.SetUsage(toUsage(repo.Usage)) + } + + if err = alpmHandle.SetCacheDirs(pacmanConf.CacheDir...); err != nil { + return err + } + + // add hook directories 1-by-1 to avoid overwriting the system directory + for _, dir := range pacmanConf.HookDir { + if err = alpmHandle.AddHookDir(dir); err != nil { + return err + } + } + + if err = alpmHandle.SetGPGDir(pacmanConf.GPGDir); err != nil { + return err + } + + if err = alpmHandle.SetLogFile(pacmanConf.LogFile); err != nil { + return err + } + + if err = alpmHandle.SetIgnorePkgs(pacmanConf.IgnorePkg...); err != nil { + return err + } + + if err = alpmHandle.SetIgnoreGroups(pacmanConf.IgnoreGroup...); err != nil { + return err + } + + if err = alpmHandle.SetArch(pacmanConf.Architecture); err != nil { + return err + } + + if err = alpmHandle.SetNoUpgrades(pacmanConf.NoUpgrade...); err != nil { + return err + } + + if alpmHandle.SetNoExtracts(pacmanConf.NoExtract...); err != nil { + return err + } + + if err = alpmHandle.SetDefaultSigLevel(sigLevel); err != nil { + return err + } + + if err = alpmHandle.SetLocalFileSigLevel(localFileSigLevel); err != nil { + return err + } + + if err = alpmHandle.SetRemoteFileSigLevel(remoteFileSigLevel); err != nil { + return err + } + + if err = alpmHandle.SetDeltaRatio(pacmanConf.UseDelta); err != nil { + return err + } + + if err = alpmHandle.SetUseSyslog(pacmanConf.UseSyslog); err != nil { + return err + } + + if err = alpmHandle.SetCheckSpace(pacmanConf.CheckSpace); err != nil { + return err + } + + return nil +} diff --git a/exec.go b/exec.go index 0049af48..4f1b0f24 100644 --- a/exec.go +++ b/exec.go @@ -56,7 +56,7 @@ func updateSudo() { // waitLock will lock yay checking the status of db.lck until it does not exist func waitLock() { - if _, err := os.Stat(filepath.Join(alpmConf.DBPath, "db.lck")); err != nil { + if _, err := os.Stat(filepath.Join(pacmanConf.DBPath, "db.lck")); err != nil { return } @@ -64,7 +64,7 @@ func waitLock() { for { time.Sleep(3 * time.Second) - if _, err := os.Stat(filepath.Join(alpmConf.DBPath, "db.lck")); err != nil { + if _, err := os.Stat(filepath.Join(pacmanConf.DBPath, "db.lck")); err != nil { fmt.Println() return } diff --git a/main.go b/main.go index 304c03a4..1e1734bd 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" + pacmanconf "github.com/Morganamilo/go-pacmanconf" alpm "github.com/jguer/go-alpm" ) @@ -101,29 +102,32 @@ func initBuildDir() error { func initAlpm() error { var err error + var stderr string - if alpmConf, err = readAlpmConfig(config.PacmanConf); err != nil { - return fmt.Errorf("Unable to read Pacman conf: %s", err) + root := "/" + if value, _, exists := cmdArgs.getArg("root", "r"); exists { + root = value + } + + pacmanConf, stderr, err = pacmanconf.PacmanConf("--config", config.PacmanConf, "--root", root) + if err != nil { + return fmt.Errorf("%s", stderr) } if value, _, exists := cmdArgs.getArg("dbpath", "b"); exists { - alpmConf.DBPath = value - } - - if value, _, exists := cmdArgs.getArg("root", "r"); exists { - alpmConf.RootDir = value + pacmanConf.DBPath = value } if value, _, exists := cmdArgs.getArg("arch"); exists { - alpmConf.Architecture = value + pacmanConf.Architecture = value } if value, _, exists := cmdArgs.getArg("ignore"); exists { - alpmConf.IgnorePkg = append(alpmConf.IgnorePkg, strings.Split(value, ",")...) + pacmanConf.IgnorePkg = append(pacmanConf.IgnorePkg, strings.Split(value, ",")...) } if value, _, exists := cmdArgs.getArg("ignoregroup"); exists { - alpmConf.IgnoreGroup = append(alpmConf.IgnoreGroup, strings.Split(value, ",")...) + pacmanConf.IgnoreGroup = append(pacmanConf.IgnoreGroup, strings.Split(value, ",")...) } //TODO @@ -131,11 +135,11 @@ func initAlpm() error { //but pacman allows multiple cachdirs to be passed //for now only handle one cache dir if value, _, exists := cmdArgs.getArg("cachdir"); exists { - alpmConf.CacheDir = []string{value} + pacmanConf.CacheDir = []string{value} } if value, _, exists := cmdArgs.getArg("gpgdir"); exists { - alpmConf.GPGDir = value + pacmanConf.GPGDir = value } if err = initAlpmHandle(); err != nil { @@ -147,7 +151,7 @@ func initAlpm() error { } else if value == "never" { useColor = false } else { - useColor = alpmConf.Options&alpm.ConfColor > 0 + useColor = pacmanConf.Color } return nil @@ -162,10 +166,14 @@ func initAlpmHandle() error { } } - if alpmHandle, err = alpmConf.CreateHandle(); err != nil { + if alpmHandle, err = alpm.Init(pacmanConf.RootDir, pacmanConf.DBPath); err != nil { return fmt.Errorf("Unable to CreateHandle: %s", err) } + if err = configureAlpm(pacmanConf); err != nil { + return err + } + alpmHandle.SetQuestionCallback(questionCallback) alpmHandle.SetLogCallback(logCallback) return nil From 7251ffac8ac74f909b01f3b0861a8f3fa8889718 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 10 Sep 2018 21:25:38 +0100 Subject: [PATCH 154/155] Add test for reading pacman config --- config_test.go | 61 ++++++++++++++++++++++++++++++++++++++++++++ testdata/pacman.conf | 27 ++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 config_test.go create mode 100644 testdata/pacman.conf diff --git a/config_test.go b/config_test.go new file mode 100644 index 00000000..f549885c --- /dev/null +++ b/config_test.go @@ -0,0 +1,61 @@ +package main + +import ( + "reflect" + "testing" +) + +func expect(t *testing.T, field string, a interface{}, b interface{}, err error) { + if err != nil { + t.Error(err) + } else if !reflect.DeepEqual(a, b) { + t.Errorf("%s expected: %s got %s", field, a, b) + } +} + +func TestConfig(t *testing.T) { + config.PacmanConf = "/home/morganamilo/git/yay/testdata/pacman.conf" + + err := initAlpm() + if err != nil { + t.Fatal(err) + } + + h := alpmHandle + + root, err := h.Root() + expect(t, "RootDir", "/", root, err) + + cache, err := h.CacheDirs() + expect(t, "CacheDir", []string{"/cachedir/", "/another/"}, cache.Slice(), err) + + log, err := h.LogFile() + expect(t, "LogFile", "/logfile", log, err) + + gpg, err := h.GPGDir() + expect(t, "GPGDir", "/gpgdir/", gpg, err) + + hook, err := h.HookDirs() + expect(t, "HookDir", []string{"/usr/share/libalpm/hooks/", "/hookdir/"}, hook.Slice(), err) + + delta, err := h.DeltaRatio() + expect(t, "UseDelta", 0.5, delta, err) + + arch, err := h.Arch() + expect(t, "Architecture", "8086", arch, err) + + ignorePkg, err := h.IgnorePkgs() + expect(t, "IgnorePkg", []string{"ignore", "this", "package"}, ignorePkg.Slice(), err) + + ignoreGroup, err := h.IgnoreGroups() + expect(t, "IgnoreGroup", []string{"ignore", "this", "group"}, ignoreGroup.Slice(), err) + + noUp, err := h.NoUpgrades() + expect(t, "NoUpgrade", []string{"noupgrade"}, noUp.Slice(), err) + + noEx, err := h.NoExtracts() + expect(t, "NoExtract", []string{"noextract"}, noEx.Slice(), err) + + check, err := h.CheckSpace() + expect(t, "CheckSpace", true, check, err) +} diff --git a/testdata/pacman.conf b/testdata/pacman.conf new file mode 100644 index 00000000..3c7606b3 --- /dev/null +++ b/testdata/pacman.conf @@ -0,0 +1,27 @@ +[options] +RootDir = / +CacheDir = /cachedir/ /another/ +LogFile = /logfile +GPGDir = /gpgdir/ +HookDir = /hookdir/ +UseDelta = 0.5 +Architecture = 8086 +IgnorePkg = ignore +IgnorePkg = this +IgnorePkg = package +IgnoreGroup = ignore +IgnoreGroup = this +IgnoreGroup = group +NoUpgrade = noupgrade +NoExtract = noextract + +CheckSpace +TotalDownload +ILoveCandy +VerbosePkgLists + +[repo1] +Server = repo1 + +[repo2] +Server = repo2 From b10b88faf6680f55b5fd770afc819b6dbd8da726 Mon Sep 17 00:00:00 2001 From: Jguer Date: Fri, 14 Sep 2018 01:29:33 +0100 Subject: [PATCH 155/155] Update vendored dependencies Signed-off-by: Jguer --- Gopkg.lock | 4 +- vendor/github.com/jguer/go-alpm/callbacks.go | 12 +- vendor/github.com/jguer/go-alpm/conf.go | 428 ------------------- vendor/github.com/jguer/go-alpm/handle.go | 104 ++--- vendor/github.com/jguer/go-alpm/package.go | 8 +- vendor/github.com/jguer/go-alpm/types.go | 30 +- 6 files changed, 80 insertions(+), 506 deletions(-) delete mode 100644 vendor/github.com/jguer/go-alpm/conf.go diff --git a/Gopkg.lock b/Gopkg.lock index 4709b2ef..f59b46ad 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -22,11 +22,11 @@ [[projects]] branch = "master" - digest = "1:7681cb2a269451c1a0f781e1241ce0bd8e515d5e9a3b12f67fd768bafe08e682" + digest = "1:6eef31522b3a2349e9399c903ffa76c084c7fb9ef9d17a4e3da420649b0f5d17" name = "github.com/jguer/go-alpm" packages = ["."] pruneopts = "NUT" - revision = "39edc7671fa431a0d14ba6e023f5f2290a86333b" + revision = "643c287316a5456348cc689e1f2c980410e17d47" [[projects]] branch = "master" diff --git a/vendor/github.com/jguer/go-alpm/callbacks.go b/vendor/github.com/jguer/go-alpm/callbacks.go index 66467930..ac4ed989 100644 --- a/vendor/github.com/jguer/go-alpm/callbacks.go +++ b/vendor/github.com/jguer/go-alpm/callbacks.go @@ -31,26 +31,26 @@ func DefaultLogCallback(lvl LogLevel, s string) { } } -var log_callback logCallbackSig -var question_callback questionCallbackSig +var globalLogCallback logCallbackSig +var globalQuestionCallback questionCallbackSig //export logCallback func logCallback(level C.alpm_loglevel_t, cstring *C.char) { - log_callback(LogLevel(level), C.GoString(cstring)) + globalLogCallback(LogLevel(level), C.GoString(cstring)) } //export questionCallback func questionCallback(question *C.alpm_question_t) { q := (*C.alpm_question_any_t)(unsafe.Pointer(question)) - question_callback(QuestionAny{q}) + globalQuestionCallback(QuestionAny{q}) } func (h *Handle) SetLogCallback(cb logCallbackSig) { - log_callback = cb + globalLogCallback = cb C.go_alpm_set_logging(h.ptr) } func (h *Handle) SetQuestionCallback(cb questionCallbackSig) { - question_callback = cb + globalQuestionCallback = cb C.go_alpm_set_question(h.ptr) } diff --git a/vendor/github.com/jguer/go-alpm/conf.go b/vendor/github.com/jguer/go-alpm/conf.go deleted file mode 100644 index 62284726..00000000 --- a/vendor/github.com/jguer/go-alpm/conf.go +++ /dev/null @@ -1,428 +0,0 @@ -// conf.go - Functions for pacman.conf parsing. -// -// Copyright (c) 2013 The go-alpm Authors -// -// MIT Licensed. See LICENSE for details. - -package alpm - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "reflect" - "strconv" - "strings" - "syscall" -) - -type PacmanOption uint - -const ( - ConfUseSyslog PacmanOption = 1 << iota - ConfColor - ConfTotalDownload - ConfCheckSpace - ConfVerbosePkgLists - ConfILoveCandy -) - -var optionsMap = map[string]PacmanOption{ - "UseSyslog": ConfUseSyslog, - "Color": ConfColor, - "TotalDownload": ConfTotalDownload, - "CheckSpace": ConfCheckSpace, - "VerbosePkgLists": ConfVerbosePkgLists, - "ILoveCandy": ConfILoveCandy, -} - -// PacmanConfig is a type for holding pacman options parsed from pacman -// configuration data passed to ParseConfig. -type PacmanConfig struct { - RootDir string - DBPath string - CacheDir []string - HookDir []string - GPGDir string - LogFile string - HoldPkg []string - IgnorePkg []string - IgnoreGroup []string - Include []string - Architecture string - XferCommand string - NoUpgrade []string - NoExtract []string - CleanMethod []string - SigLevel SigLevel - LocalFileSigLevel SigLevel - RemoteFileSigLevel SigLevel - UseDelta float64 - Options PacmanOption - Repos []RepoConfig -} - -// RepoConfig is a type that stores the signature level of a repository -// specified in the pacman config file. -type RepoConfig struct { - Name string - SigLevel SigLevel - Usage Usage - Servers []string -} - -// Constants for pacman configuration parsing -const ( - tokenSection = iota - tokenKey - tokenComment -) - -type iniToken struct { - Type uint - Name string - Values []string -} - -type confReader struct { - *bufio.Reader - Lineno uint -} - -// newConfReader reads from the io.Reader if it is buffered and returns a -// confReader containing the number of bytes read and 0 for the first line. If -// r is not a buffered reader, a new buffered reader is created using r as its -// input and returned. -func newConfReader(r io.Reader) confReader { - if buf, ok := r.(*bufio.Reader); ok { - return confReader{buf, 0} - } - buf := bufio.NewReader(r) - return confReader{buf, 0} -} - -func (rdr *confReader) ParseLine() (tok iniToken, err error) { - line, overflow, err := rdr.ReadLine() - switch { - case err != nil: - return - case overflow: - err = fmt.Errorf("line %d too long", rdr.Lineno) - return - } - rdr.Lineno++ - - line = bytes.TrimSpace(line) - if len(line) == 0 { - tok.Type = tokenComment - return - } - switch line[0] { - case '#': - tok.Type = tokenComment - return - case '[': - closing := bytes.IndexByte(line, ']') - if closing < 0 { - err = fmt.Errorf("missing ']' is section name at line %d", rdr.Lineno) - return - } - tok.Name = string(line[1:closing]) - if closing+1 < len(line) { - err = fmt.Errorf("trailing characters %q after section name %s", - line[closing+1:], tok.Name) - return - } - return - default: - tok.Type = tokenKey - if idx := bytes.IndexByte(line, '='); idx >= 0 { - optname := bytes.TrimSpace(line[:idx]) - values := bytes.Split(line[idx+1:], []byte{' '}) - tok.Name = string(optname) - tok.Values = make([]string, 0, len(values)) - for _, word := range values { - word = bytes.TrimSpace(word) - if len(word) > 0 { - tok.Values = append(tok.Values, string(word)) - } - } - } else { - // boolean option - tok.Name = string(line) - tok.Values = nil - } - return - } -} - -func ParseConfig(r io.Reader) (conf PacmanConfig, err error) { - rdr := newConfReader(r) - rdrStack := []confReader{rdr} - conf.SetDefaults() - confReflect := reflect.ValueOf(&conf).Elem() - var currentSection string - var curRepo *RepoConfig -lineloop: - for { - line, err := rdr.ParseLine() - // fmt.Printf("%+v\n", line) - switch err { - case io.EOF: - // pop reader stack. - l := len(rdrStack) - if l == 1 { - break lineloop - } - rdr = rdrStack[l-2] - rdrStack = rdrStack[:l-1] - default: - break lineloop - case nil: - // Ok. - } - - switch line.Type { - case tokenComment: - case tokenSection: - currentSection = line.Name - if currentSection != "options" { - conf.Repos = append(conf.Repos, RepoConfig{}) - curRepo = &conf.Repos[len(conf.Repos)-1] - curRepo.Name = line.Name - } - case tokenKey: - switch line.Name { - case "SigLevel": - // TODO: implement SigLevel parsing. - continue lineloop - case "Usage": - for _, usage := range line.Values { - switch usage { - case "Sync": - curRepo.Usage |= UsageSync - case "Search": - curRepo.Usage |= UsageSearch - case "Install": - curRepo.Usage |= UsageInstall - case "Upgrade": - curRepo.Usage |= UsageUpgrade - case "All": - curRepo.Usage |= UsageAll - default: - err = fmt.Errorf("unknown option at line %d: %s", rdr.Lineno, line.Name) - break lineloop - } - } - case "Server": - 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", - rdr.Lineno, err) - break lineloop - } - rdr = newConfReader(f) - rdrStack = append(rdrStack, rdr) - continue lineloop - case "UseDelta": - if len(line.Values) > 0 { - deltaRatio, err := strconv.ParseFloat(line.Values[0], 64) - - if err != nil { - break lineloop - } - - conf.UseDelta = deltaRatio - } - continue lineloop - } - - if currentSection != "options" { - err = fmt.Errorf("option %s outside of [options] section, at line %d", - line.Name, rdr.Lineno) - break lineloop - } - // main options. - if opt, ok := optionsMap[line.Name]; ok { - // boolean option. - conf.Options |= opt - } else { - // key-value option. - fld := confReflect.FieldByName(line.Name) - if !fld.IsValid() || !fld.CanAddr() { - _ = fmt.Errorf("unknown option at line %d: %s", rdr.Lineno, line.Name) - continue - } - - switch fieldP := fld.Addr().Interface().(type) { - case *string: - // single valued option. - *fieldP = strings.Join(line.Values, " ") - case *[]string: - //many valued option. - *fieldP = append(*fieldP, line.Values...) - } - } - } - } - - if len(conf.CleanMethod) == 0 { - conf.CleanMethod = []string{"KeepInstalled"} - } - - if len(conf.CacheDir) == 0 { - conf.CacheDir = []string{"/var/cache/pacman/pkg/"} //should only be set if the config does not specify this - } - - for n, _ := range conf.Repos { - repo := &conf.Repos[n] - if repo.Usage == 0 { - repo.Usage = UsageAll - } - } - - return conf, err -} - -func (conf *PacmanConfig) SetDefaults() { - conf.RootDir = "/" - conf.DBPath = "/var/lib/pacman" - conf.DBPath = "/var/lib/pacman/" - conf.HookDir = []string{"/etc/pacman.d/hooks/"} //should be added to whatever the config states - conf.GPGDir = "/etc/pacman.d/gnupg/" - conf.LogFile = "/var/log/pacman.log" - conf.UseDelta = 0.7 - - conf.SigLevel = SigPackage | SigPackageOptional | SigDatabase | SigDatabaseOptional - conf.LocalFileSigLevel = SigUseDefault - conf.RemoteFileSigLevel = SigUseDefault -} - -func getArch() (string, error) { - var uname syscall.Utsname - err := syscall.Uname(&uname) - if err != nil { - return "", err - } - var arch [65]byte - for i, c := range uname.Machine { - if c == 0 { - return string(arch[:i]), nil - } - arch[i] = byte(c) - } - return string(arch[:]), nil -} - -func (conf *PacmanConfig) CreateHandle() (*Handle, error) { - h, err := Init(conf.RootDir, conf.DBPath) - if err != nil { - return nil, err - } - if conf.Architecture == "auto" { - conf.Architecture, err = getArch() - if err != nil { - return nil, fmt.Errorf("architecture is 'auto' but couldn't uname()") - } - } - - for _, repoconf := range conf.Repos { - // TODO: set SigLevel - db, err := h.RegisterSyncDb(repoconf.Name, 0) - if err == nil { - for i, addr := range repoconf.Servers { - addr = strings.Replace(addr, "$repo", repoconf.Name, -1) - addr = strings.Replace(addr, "$arch", conf.Architecture, -1) - repoconf.Servers[i] = addr - } - db.SetServers(repoconf.Servers) - db.SetUsage(repoconf.Usage) - } - } - - err = h.SetCacheDirs(conf.CacheDir...) - if err != nil { - return nil, err - } - - // add hook directories 1-by-1 to avoid overwriting the system directory - for _, dir := range conf.HookDir { - err = h.AddHookDir(dir) - if err != nil { - return nil, err - } - } - - err = h.SetGPGDir(conf.GPGDir) - if err != nil { - return nil, err - } - - err = h.SetLogFile(conf.LogFile) - if err != nil { - return nil, err - } - - err = h.SetIgnorePkgs(conf.IgnorePkg...) - if err != nil { - return nil, err - } - - err = h.SetIgnoreGroups(conf.IgnoreGroup...) - if err != nil { - return nil, err - } - - err = h.SetArch(conf.Architecture) - if err != nil { - return nil, err - } - - h.SetNoUpgrades(conf.NoUpgrade...) - if err != nil { - return nil, err - } - - h.SetNoExtracts(conf.NoExtract...) - if err != nil { - return nil, err - } - - err = h.SetDefaultSigLevel(conf.SigLevel) - if err != nil { - return nil, err - } - - err = h.SetLocalFileSigLevel(conf.LocalFileSigLevel) - if err != nil { - return nil, err - } - - err = h.SetRemoteFileSigLevel(conf.RemoteFileSigLevel) - if err != nil { - return nil, err - } - - err = h.SetDeltaRatio(conf.UseDelta) - if err != nil { - return nil, err - } - - err = h.SetUseSyslog(conf.Options&ConfUseSyslog > 0) - if err != nil { - return nil, err - } - - err = h.SetCheckSpace(conf.Options&ConfCheckSpace > 0) - if err != nil { - return nil, err - } - - return h, nil -} diff --git a/vendor/github.com/jguer/go-alpm/handle.go b/vendor/github.com/jguer/go-alpm/handle.go index d2c8ee82..613156a7 100644 --- a/vendor/github.com/jguer/go-alpm/handle.go +++ b/vendor/github.com/jguer/go-alpm/handle.go @@ -20,27 +20,29 @@ import ( "unsafe" ) +// Handle contains the pointer to the alpm handle type Handle struct { ptr *C.alpm_handle_t } -// Initialize +// Init initializes alpm handle func Init(root, dbpath string) (*Handle, error) { - c_root := C.CString(root) - c_dbpath := C.CString(dbpath) - var c_err C.alpm_errno_t - h := C.alpm_initialize(c_root, c_dbpath, &c_err) + cRoot := C.CString(root) + cDBPath := C.CString(dbpath) + var cErr C.alpm_errno_t + h := C.alpm_initialize(cRoot, cDBPath, &cErr) - defer C.free(unsafe.Pointer(c_root)) - defer C.free(unsafe.Pointer(c_dbpath)) + defer C.free(unsafe.Pointer(cRoot)) + defer C.free(unsafe.Pointer(cDBPath)) - if c_err != 0 { - return nil, Error(c_err) + if cErr != 0 { + return nil, Error(cErr) } return &Handle{h}, nil } +// Release releases the alpm handle func (h *Handle) Release() error { if er := C.alpm_release(h.ptr); er != 0 { return Error(er) @@ -52,9 +54,9 @@ func (h *Handle) Release() error { // LastError gets the last pm_error func (h Handle) LastError() error { if h.ptr != nil { - c_err := C.alpm_errno(h.ptr) - if c_err != 0 { - return Error(c_err) + cErr := C.alpm_errno(h.ptr) + if cErr != 0 { + return Error(cErr) } } return nil @@ -76,12 +78,12 @@ func (h Handle) optionGetList(f func(*C.alpm_handle_t) *C.alpm_list_t) (StringLi } func (h Handle) optionSetList(hookDirs []string, f func(*C.alpm_handle_t, *C.alpm_list_t) C.int) error { - var list *C.alpm_list_t = nil + var list *C.alpm_list_t for _, dir := range hookDirs { - c_dir := C.CString(dir) - list = C.alpm_list_add(list, unsafe.Pointer(c_dir)) - defer C.free(unsafe.Pointer(c_dir)) + cDir := C.CString(dir) + list = C.alpm_list_add(list, unsafe.Pointer(cDir)) + defer C.free(unsafe.Pointer(cDir)) } ok := f(h.ptr, list) @@ -92,9 +94,9 @@ func (h Handle) optionSetList(hookDirs []string, f func(*C.alpm_handle_t, *C.alp } func (h Handle) optionAddList(hookDir string, f func(*C.alpm_handle_t, *C.char) C.int) error { - c_hookdir := C.CString(hookDir) - defer C.free(unsafe.Pointer(c_hookdir)) - ok := f(h.ptr, c_hookdir) + cHookDir := C.CString(hookDir) + defer C.free(unsafe.Pointer(cHookDir)) + ok := f(h.ptr, cHookDir) if ok < 0 { return h.LastError() } @@ -102,9 +104,9 @@ func (h Handle) optionAddList(hookDir string, f func(*C.alpm_handle_t, *C.char) } func (h Handle) optionRemoveList(dir string, f func(*C.alpm_handle_t, *C.char) C.int) (bool, error) { - c_dir := C.CString(dir) - ok := f(h.ptr, c_dir) - defer C.free(unsafe.Pointer(c_dir)) + cDir := C.CString(dir) + ok := f(h.ptr, cDir) + defer C.free(unsafe.Pointer(cDir)) if ok < 0 { return ok == 1, h.LastError() } @@ -112,9 +114,9 @@ func (h Handle) optionRemoveList(dir string, f func(*C.alpm_handle_t, *C.char) C } func (h Handle) optionMatchList(dir string, f func(*C.alpm_handle_t, *C.char) C.int) (bool, error) { - c_dir := C.CString(dir) - ok := f(h.ptr, c_dir) - defer C.free(unsafe.Pointer(c_dir)) + cDir := C.CString(dir) + ok := f(h.ptr, cDir) + defer C.free(unsafe.Pointer(cDir)) if ok == 0 { return true, nil } else if ok == C.FNM_NOMATCH { @@ -125,9 +127,9 @@ func (h Handle) optionMatchList(dir string, f func(*C.alpm_handle_t, *C.char) C. //helper functions for *char based getters and setters func (h Handle) optionGetStr(f func(*C.alpm_handle_t) *C.char) (string, error) { - c_str := f(h.ptr) - str := C.GoString(c_str) - if c_str == nil { + cStr := f(h.ptr) + str := C.GoString(cStr) + if cStr == nil { return str, h.LastError() } @@ -135,9 +137,9 @@ func (h Handle) optionGetStr(f func(*C.alpm_handle_t) *C.char) (string, error) { } func (h Handle) optionSetStr(str string, f func(*C.alpm_handle_t, *C.char) C.int) error { - c_str := C.CString(str) - defer C.free(unsafe.Pointer(c_str)) - ok := f(h.ptr, c_str) + cStr := C.CString(str) + defer C.free(unsafe.Pointer(cStr)) + ok := f(h.ptr, cStr) if ok < 0 { h.LastError() @@ -253,12 +255,12 @@ func (h Handle) UseSyslog() (bool, error) { } func (h Handle) SetUseSyslog(value bool) error { - var int_value C.int = 0 + var intValue C.int if value { - int_value = 1 + intValue = 1 } - ok := C.alpm_option_set_usesyslog(h.ptr, int_value) + ok := C.alpm_option_set_usesyslog(h.ptr, intValue) if ok < 0 { return h.LastError() } @@ -395,10 +397,10 @@ func (h Handle) AssumeInstalled() (DependList, error) { } func (h Handle) AddAssumeInstalled(dep Depend) error { - c_dep := convertCDepend(dep) - defer freeCDepend(c_dep) + cDep := convertCDepend(dep) + defer freeCDepend(cDep) - ok := C.alpm_option_add_assumeinstalled(h.ptr, c_dep) + ok := C.alpm_option_add_assumeinstalled(h.ptr, cDep) if ok < 0 { return h.LastError() } @@ -417,12 +419,12 @@ func (h Handle) SetAssumeInstalled(deps ...Depend) error { //although for the sake of completeness it would be nice to have this //working panic("This function (SetAssumeInstalled) does not work properly, please do not use. See source code for more details") - var list *C.alpm_list_t = nil + var list *C.alpm_list_t for _, dep := range deps { - c_dep := convertCDepend(dep) - defer freeCDepend(c_dep) - list = C.alpm_list_add(list, unsafe.Pointer(c_dep)) + cDep := convertCDepend(dep) + defer freeCDepend(cDep) + list = C.alpm_list_add(list, unsafe.Pointer(cDep)) } ok := C.alpm_option_set_assumeinstalled(h.ptr, list) @@ -448,10 +450,10 @@ func (h Handle) RemoveAssumeInstalled(dep Depend) (bool, error) { //although for the sake of completeness it would be nice to have this //working panic("This function (RemoveAssumeInstalled) does not work properly, please do not use. See source code for more details") - c_dep := convertCDepend(dep) - defer freeCDepend(c_dep) + cDep := convertCDepend(dep) + defer freeCDepend(cDep) - ok := C.alpm_option_remove_assumeinstalled(h.ptr, c_dep) + ok := C.alpm_option_remove_assumeinstalled(h.ptr, cDep) if ok < 0 { return ok == 1, h.LastError() } @@ -465,8 +467,8 @@ func (h Handle) Arch() (string, error) { } func (h Handle) SetArch(str string) error { - return h.optionSetStr(str, func(handle *C.alpm_handle_t, c_str *C.char) C.int { - return C.alpm_option_set_arch(handle, c_str) + return h.optionSetStr(str, func(handle *C.alpm_handle_t, cStr *C.char) C.int { + return C.alpm_option_set_arch(handle, cStr) }) } @@ -500,12 +502,12 @@ func (h Handle) CheckSpace() (bool, error) { } func (h Handle) SetCheckSpace(value bool) error { - var int_value C.int = 0 + var cValue C.int if value { - int_value = 1 + cValue = 1 } - ok := C.alpm_option_set_checkspace(h.ptr, int_value) + ok := C.alpm_option_set_checkspace(h.ptr, cValue) if ok < 0 { return h.LastError() } @@ -519,8 +521,8 @@ func (h Handle) DBExt() (string, error) { } func (h Handle) SetDBExt(str string) error { - return h.optionSetStr(str, func(handle *C.alpm_handle_t, c_str *C.char) C.int { - return C.alpm_option_set_dbext(handle, c_str) + return h.optionSetStr(str, func(handle *C.alpm_handle_t, cStr *C.char) C.int { + return C.alpm_option_set_dbext(handle, cStr) }) } diff --git a/vendor/github.com/jguer/go-alpm/package.go b/vendor/github.com/jguer/go-alpm/package.go index 8873eb5b..76acd0a0 100644 --- a/vendor/github.com/jguer/go-alpm/package.go +++ b/vendor/github.com/jguer/go-alpm/package.go @@ -272,8 +272,8 @@ func (pkg Package) ComputeRequiredBy() []string { for i := (*list)(unsafe.Pointer(result)); i != nil; i = i.Next { defer C.free(unsafe.Pointer(i)) if i.Data != nil { - defer C.free(unsafe.Pointer(i.Data)) - name := C.GoString((*C.char)(unsafe.Pointer(i.Data))) + defer C.free(i.Data) + name := C.GoString((*C.char)(i.Data)) requiredby = append(requiredby, name) } } @@ -287,8 +287,8 @@ func (pkg Package) ComputeOptionalFor() []string { for i := (*list)(unsafe.Pointer(result)); i != nil; i = i.Next { defer C.free(unsafe.Pointer(i)) if i.Data != nil { - defer C.free(unsafe.Pointer(i.Data)) - name := C.GoString((*C.char)(unsafe.Pointer(i.Data))) + defer C.free(i.Data) + name := C.GoString((*C.char)(i.Data)) optionalfor = append(optionalfor, name) } } diff --git a/vendor/github.com/jguer/go-alpm/types.go b/vendor/github.com/jguer/go-alpm/types.go index 351a21ee..0ff31de0 100644 --- a/vendor/github.com/jguer/go-alpm/types.go +++ b/vendor/github.com/jguer/go-alpm/types.go @@ -16,7 +16,7 @@ import ( "unsafe" ) -// Description of a dependency. +// Depend provides a description of a dependency. type Depend struct { Name string Version string @@ -36,19 +36,19 @@ func convertDepend(dep *C.alpm_depend_t) Depend { } func convertCDepend(dep Depend) *C.alpm_depend_t { - c_name := C.CString(dep.Name) - c_version := C.CString(dep.Version) - c_desc := C.CString(dep.Description) + cName := C.CString(dep.Name) + cVersion := C.CString(dep.Version) + cDesc := C.CString(dep.Description) - c_dep := C.alpm_depend_t{ - name: c_name, - version: c_version, - desc: c_desc, + cDep := C.alpm_depend_t{ + name: cName, + version: cVersion, + desc: cDesc, name_hash: C.ulong(dep.NameHash), mod: C.alpm_depmod_t(dep.Mod), } - return &c_dep + return &cDep } func freeCDepend(dep *C.alpm_depend_t) { @@ -61,7 +61,7 @@ func (dep Depend) String() string { return dep.Name + dep.Mod.String() + dep.Version } -// Description of package files. +// File provides a description of package files. type File struct { Name string Size int64 @@ -72,18 +72,18 @@ func convertFilelist(files *C.alpm_filelist_t) []File { size := int(files.count) items := make([]File, size) - raw_items := reflect.SliceHeader{ + rawItems := reflect.SliceHeader{ Len: size, Cap: size, Data: uintptr(unsafe.Pointer(files.files))} - c_files := *(*[]C.alpm_file_t)(unsafe.Pointer(&raw_items)) + cFiles := *(*[]C.alpm_file_t)(unsafe.Pointer(&rawItems)) for i := 0; i < size; i++ { items[i] = File{ - Name: C.GoString(c_files[i].name), - Size: int64(c_files[i].size), - Mode: uint32(c_files[i].mode)} + Name: C.GoString(cFiles[i].name), + Size: int64(cFiles[i].size), + Mode: uint32(cFiles[i].mode)} } return items }