浏览代码

chore(yay): modernize exec commands

jguer 3 年之前
父节点
当前提交
e231b2b02d

+ 20 - 15
clean.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -18,17 +19,17 @@ import (
 )
 
 // CleanDependencies removes all dangling dependencies in system.
-func cleanDependencies(cmdArgs *parser.Arguments, dbExecutor db.Executor, removeOptional bool) error {
+func cleanDependencies(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor, removeOptional bool) error {
 	hanging := hangingPackages(removeOptional, dbExecutor)
 	if len(hanging) != 0 {
-		return cleanRemove(cmdArgs, hanging)
+		return cleanRemove(ctx, cmdArgs, hanging)
 	}
 
 	return nil
 }
 
 // CleanRemove sends a full removal command to pacman with the pkgName slice.
-func cleanRemove(cmdArgs *parser.Arguments, pkgNames []string) error {
+func cleanRemove(ctx context.Context, cmdArgs *parser.Arguments, pkgNames []string) error {
 	if len(pkgNames) == 0 {
 		return nil
 	}
@@ -38,11 +39,11 @@ func cleanRemove(cmdArgs *parser.Arguments, pkgNames []string) error {
 	arguments.AddTarget(pkgNames...)
 
 	return config.Runtime.CmdBuilder.Show(
-		config.Runtime.CmdBuilder.BuildPacmanCmd(
+		config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			arguments, config.Runtime.Mode, settings.NoConfirm))
 }
 
-func syncClean(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func syncClean(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	keepInstalled := false
 	keepCurrent := false
 
@@ -57,7 +58,7 @@ func syncClean(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	}
 
 	if config.Runtime.Mode.AtLeastRepo() {
-		if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm)); err != nil {
 			return err
 		}
@@ -77,7 +78,7 @@ func syncClean(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	fmt.Println(gotext.Get("\nBuild directory:"), config.BuildDir)
 
 	if text.ContinueTask(question, true, settings.NoConfirm) {
-		if err := cleanAUR(keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {
+		if err := cleanAUR(ctx, keepInstalled, keepCurrent, removeAll, dbExecutor); err != nil {
 			return err
 		}
 	}
@@ -87,13 +88,13 @@ func syncClean(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	}
 
 	if text.ContinueTask(gotext.Get("Do you want to remove ALL untracked AUR files?"), true, settings.NoConfirm) {
-		return cleanUntracked()
+		return cleanUntracked(ctx)
 	}
 
 	return nil
 }
 
-func cleanAUR(keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor) error {
+func cleanAUR(ctx context.Context, keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor) error {
 	fmt.Println(gotext.Get("removing AUR packages from cache..."))
 
 	installedBases := make(stringset.StringSet)
@@ -121,7 +122,7 @@ func cleanAUR(keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor
 	// Querying the AUR is slow and needs internet so don't do it if we
 	// don't need to.
 	if keepCurrent {
-		info, errInfo := query.AURInfo(config.Runtime.AURClient, cachedPackages, &query.AURWarnings{}, config.RequestSplitN)
+		info, errInfo := query.AURInfo(ctx, config.Runtime.AURClient, cachedPackages, &query.AURWarnings{}, config.RequestSplitN)
 		if errInfo != nil {
 			return errInfo
 		}
@@ -163,7 +164,7 @@ func cleanAUR(keepInstalled, keepCurrent, removeAll bool, dbExecutor db.Executor
 	return nil
 }
 
-func cleanUntracked() error {
+func cleanUntracked(ctx context.Context) error {
 	fmt.Println(gotext.Get("removing untracked AUR files from cache..."))
 
 	files, err := ioutil.ReadDir(config.BuildDir)
@@ -178,7 +179,7 @@ func cleanUntracked() error {
 
 		dir := filepath.Join(config.BuildDir, file.Name())
 		if isGitRepository(dir) {
-			if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(dir, "clean", "-fx")); err != nil {
+			if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, "clean", "-fx")); err != nil {
 				text.Warnln(gotext.Get("Unable to clean:"), dir)
 
 				return err
@@ -194,7 +195,7 @@ func isGitRepository(dir string) bool {
 	return !os.IsNotExist(err)
 }
 
-func cleanAfter(bases []dep.Base) {
+func cleanAfter(ctx context.Context, bases []dep.Base) {
 	fmt.Println(gotext.Get("removing untracked AUR files from cache..."))
 
 	for i, base := range bases {
@@ -205,12 +206,16 @@ func cleanAfter(bases []dep.Base) {
 
 		text.OperationInfoln(gotext.Get("Cleaning (%d/%d): %s", i+1, len(bases), text.Cyan(dir)))
 
-		_, stderr, err := config.Runtime.CmdBuilder.Capture(config.Runtime.CmdBuilder.BuildGitCmd(dir, "reset", "--hard", "HEAD"), 0)
+		_, stderr, err := config.Runtime.CmdBuilder.Capture(
+			config.Runtime.CmdBuilder.BuildGitCmd(
+				ctx, dir, "reset", "--hard", "HEAD"))
 		if err != nil {
 			text.Errorln(gotext.Get("error resetting %s: %s", base.String(), stderr))
 		}
 
-		if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(dir, "clean", "-fx", "--exclude='*.pkg.*'")); err != nil {
+		if err := config.Runtime.CmdBuilder.Show(
+			config.Runtime.CmdBuilder.BuildGitCmd(
+				ctx, "clean", "-fx", "--exclude='*.pkg.*'")); err != nil {
 			fmt.Fprintln(os.Stderr, err)
 		}
 	}

+ 50 - 50
cmd.go

@@ -145,9 +145,9 @@ getpkgbuild specific options:
     -p --print            Print pkgbuild of packages`)
 }
 
-func handleCmd(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func handleCmd(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	if cmdArgs.ExistsArg("h", "help") {
-		return handleHelp(cmdArgs)
+		return handleHelp(ctx, cmdArgs)
 	}
 
 	if config.SudoLoop && cmdArgs.NeedRoot(config.Runtime.Mode) {
@@ -160,29 +160,29 @@ func handleCmd(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 
 		return nil
 	case "D", "database":
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	case "F", "files":
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	case "Q", "query":
-		return handleQuery(cmdArgs, dbExecutor)
+		return handleQuery(ctx, cmdArgs, dbExecutor)
 	case "R", "remove":
-		return handleRemove(cmdArgs, config.Runtime.VCSStore)
+		return handleRemove(ctx, cmdArgs, config.Runtime.VCSStore)
 	case "S", "sync":
-		return handleSync(cmdArgs, dbExecutor)
+		return handleSync(ctx, cmdArgs, dbExecutor)
 	case "T", "deptest":
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	case "U", "upgrade":
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	case "G", "getpkgbuild":
-		return handleGetpkgbuild(cmdArgs, dbExecutor)
+		return handleGetpkgbuild(ctx, cmdArgs, dbExecutor)
 	case "P", "show":
-		return handlePrint(cmdArgs, dbExecutor)
+		return handlePrint(ctx, cmdArgs, dbExecutor)
 	case "Y", "--yay":
-		return handleYay(cmdArgs, dbExecutor)
+		return handleYay(ctx, cmdArgs, dbExecutor)
 	}
 
 	return fmt.Errorf(gotext.Get("unhandled operation"))
@@ -212,27 +212,27 @@ func getFilter(cmdArgs *parser.Arguments) (upgrade.Filter, error) {
 	}, nil
 }
 
-func handleQuery(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func handleQuery(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	if cmdArgs.ExistsArg("u", "upgrades") {
 		filter, err := getFilter(cmdArgs)
 		if err != nil {
 			return err
 		}
 
-		return printUpdateList(cmdArgs, dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
+		return printUpdateList(ctx, cmdArgs, dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
 	}
 
-	return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 }
 
-func handleHelp(cmdArgs *parser.Arguments) error {
+func handleHelp(ctx context.Context, cmdArgs *parser.Arguments) error {
 	if cmdArgs.Op == "Y" || cmdArgs.Op == "yay" {
 		usage()
 		return nil
 	}
 
-	return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 }
 
@@ -240,7 +240,7 @@ func handleVersion() {
 	fmt.Printf("yay v%s - libalpm v%s\n", yayVersion, alpm.Version())
 }
 
-func handlePrint(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func handlePrint(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	switch {
 	case cmdArgs.ExistsArg("d", "defaultconfig"):
 		tmpConfig := settings.DefaultConfig()
@@ -257,54 +257,54 @@ func handlePrint(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 			return err
 		}
 
-		return printNumberOfUpdates(dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
+		return printNumberOfUpdates(ctx, dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"), filter)
 	case cmdArgs.ExistsArg("w", "news"):
 		double := cmdArgs.ExistsDouble("w", "news")
 		quiet := cmdArgs.ExistsArg("q", "quiet")
 
-		return news.PrintNewsFeed(config.Runtime.HTTPClient, dbExecutor.LastBuildTime(), config.SortMode, double, quiet)
+		return news.PrintNewsFeed(ctx, config.Runtime.HTTPClient, dbExecutor.LastBuildTime(), config.SortMode, double, quiet)
 	case cmdArgs.ExistsDouble("c", "complete"):
-		return completion.Show(config.Runtime.HTTPClient, dbExecutor,
+		return completion.Show(ctx, config.Runtime.HTTPClient, dbExecutor,
 			config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, true)
 	case cmdArgs.ExistsArg("c", "complete"):
-		return completion.Show(config.Runtime.HTTPClient, dbExecutor,
+		return completion.Show(ctx, config.Runtime.HTTPClient, dbExecutor,
 			config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, false)
 	case cmdArgs.ExistsArg("s", "stats"):
-		return localStatistics(dbExecutor)
+		return localStatistics(ctx, dbExecutor)
 	}
 
 	return nil
 }
 
-func handleYay(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func handleYay(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	switch {
 	case cmdArgs.ExistsArg("gendb"):
-		return createDevelDB(config, dbExecutor)
+		return createDevelDB(ctx, config, dbExecutor)
 	case cmdArgs.ExistsDouble("c"):
-		return cleanDependencies(cmdArgs, dbExecutor, true)
+		return cleanDependencies(ctx, cmdArgs, dbExecutor, true)
 	case cmdArgs.ExistsArg("c", "clean"):
-		return cleanDependencies(cmdArgs, dbExecutor, false)
+		return cleanDependencies(ctx, cmdArgs, dbExecutor, false)
 	case len(cmdArgs.Targets) > 0:
-		return handleYogurt(cmdArgs, dbExecutor)
+		return handleYogurt(ctx, cmdArgs, dbExecutor)
 	}
 
 	return nil
 }
 
-func handleGetpkgbuild(cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {
+func handleGetpkgbuild(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor download.DBSearcher) error {
 	if cmdArgs.ExistsArg("p", "print") {
 		return printPkgbuilds(dbExecutor, config.Runtime.HTTPClient, cmdArgs.Targets, config.Runtime.Mode, config.AURURL)
 	}
 
-	return getPkgbuilds(dbExecutor, config, cmdArgs.Targets, cmdArgs.ExistsArg("f", "force"))
+	return getPkgbuilds(ctx, dbExecutor, config, cmdArgs.Targets, cmdArgs.ExistsArg("f", "force"))
 }
 
-func handleYogurt(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func handleYogurt(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	config.SearchMode = numberMenu
-	return displayNumberMenu(cmdArgs.Targets, dbExecutor, cmdArgs)
+	return displayNumberMenu(ctx, cmdArgs.Targets, dbExecutor, cmdArgs)
 }
 
-func handleSync(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func handleSync(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	targets := cmdArgs.Targets
 
 	switch {
@@ -315,33 +315,33 @@ func handleSync(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 			config.SearchMode = detailed
 		}
 
-		return syncSearch(targets, config.Runtime.AURClient, dbExecutor)
+		return syncSearch(ctx, targets, config.Runtime.AURClient, dbExecutor)
 	case cmdArgs.ExistsArg("p", "print", "print-format"):
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	case cmdArgs.ExistsArg("c", "clean"):
-		return syncClean(cmdArgs, dbExecutor)
+		return syncClean(ctx, cmdArgs, dbExecutor)
 	case cmdArgs.ExistsArg("l", "list"):
-		return syncList(config.Runtime.HTTPClient, cmdArgs, dbExecutor)
+		return syncList(ctx, config.Runtime.HTTPClient, cmdArgs, dbExecutor)
 	case cmdArgs.ExistsArg("g", "groups"):
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	case cmdArgs.ExistsArg("i", "info"):
-		return syncInfo(cmdArgs, targets, dbExecutor)
+		return syncInfo(ctx, cmdArgs, targets, dbExecutor)
 	case cmdArgs.ExistsArg("u", "sysupgrade"):
-		return install(cmdArgs, dbExecutor, false)
+		return install(ctx, cmdArgs, dbExecutor, false)
 	case len(cmdArgs.Targets) > 0:
-		return install(cmdArgs, dbExecutor, false)
+		return install(ctx, cmdArgs, dbExecutor, false)
 	case cmdArgs.ExistsArg("y", "refresh"):
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	}
 
 	return nil
 }
 
-func handleRemove(cmdArgs *parser.Arguments, localCache *vcs.InfoStore) error {
-	err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+func handleRemove(ctx context.Context, cmdArgs *parser.Arguments, localCache *vcs.InfoStore) error {
+	err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	if err == nil {
 		localCache.RemovePackage(cmdArgs.Targets)
@@ -351,7 +351,7 @@ func handleRemove(cmdArgs *parser.Arguments, localCache *vcs.InfoStore) error {
 }
 
 // NumberMenu presents a CLI for selecting packages to install.
-func displayNumberMenu(pkgS []string, dbExecutor db.Executor, cmdArgs *parser.Arguments) error {
+func displayNumberMenu(ctx context.Context, pkgS []string, dbExecutor db.Executor, cmdArgs *parser.Arguments) error {
 	var (
 		aurErr, repoErr error
 		aq              aurQuery
@@ -362,7 +362,7 @@ func displayNumberMenu(pkgS []string, dbExecutor db.Executor, cmdArgs *parser.Ar
 	pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode)
 
 	if config.Runtime.Mode.AtLeastAUR() {
-		aq, aurErr = narrowSearch(config.Runtime.AURClient, pkgS, true)
+		aq, aurErr = narrowSearch(ctx, config.Runtime.AURClient, pkgS, true)
 		lenaq = len(aq)
 	}
 
@@ -463,10 +463,10 @@ func displayNumberMenu(pkgS []string, dbExecutor db.Executor, cmdArgs *parser.Ar
 		return nil
 	}
 
-	return install(arguments, dbExecutor, true)
+	return install(ctx, arguments, dbExecutor, true)
 }
 
-func syncList(httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func syncList(ctx context.Context, httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	aur := false
 
 	for i := len(cmdArgs.Targets) - 1; i >= 0; i-- {
@@ -477,7 +477,7 @@ func syncList(httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.
 	}
 
 	if config.Runtime.Mode.AtLeastAUR() && (len(cmdArgs.Targets) == 0 || aur) {
-		req, err := http.NewRequestWithContext(context.Background(), "GET", config.AURURL+"/packages.gz", nil)
+		req, err := http.NewRequestWithContext(ctx, "GET", config.AURURL+"/packages.gz", nil)
 		if err != nil {
 			return err
 		}
@@ -509,7 +509,7 @@ func syncList(httpClient *http.Client, cmdArgs *parser.Arguments, dbExecutor db.
 	}
 
 	if config.Runtime.Mode.AtLeastRepo() && (len(cmdArgs.Targets) != 0 || !aur) {
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	}
 

+ 23 - 22
diff.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"path/filepath"
 	"strings"
@@ -14,14 +15,14 @@ import (
 
 const gitDiffRefName = "AUR_SEEN"
 
-func showPkgbuildDiffs(bases []dep.Base, cloned map[string]bool) error {
+func showPkgbuildDiffs(ctx context.Context, bases []dep.Base, cloned map[string]bool) error {
 	var errMulti multierror.MultiError
 
 	for _, base := range bases {
 		pkg := base.Pkgbase()
 		dir := filepath.Join(config.BuildDir, pkg)
 
-		start, err := getLastSeenHash(config.BuildDir, pkg)
+		start, err := getLastSeenHash(ctx, config.BuildDir, pkg)
 		if err != nil {
 			errMulti.Add(err)
 
@@ -31,7 +32,7 @@ func showPkgbuildDiffs(bases []dep.Base, cloned map[string]bool) error {
 		if cloned[pkg] {
 			start = gitEmptyTree
 		} else {
-			hasDiff, err := gitHasDiff(config.BuildDir, pkg)
+			hasDiff, err := gitHasDiff(ctx, config.BuildDir, pkg)
 			if err != nil {
 				errMulti.Add(err)
 
@@ -56,7 +57,7 @@ func showPkgbuildDiffs(bases []dep.Base, cloned map[string]bool) error {
 			args = append(args, "--color=never")
 		}
 
-		_ = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(dir, args...))
+		_ = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, args...))
 	}
 
 	return errMulti.Return()
@@ -64,10 +65,10 @@ func showPkgbuildDiffs(bases []dep.Base, cloned map[string]bool) error {
 
 // Check whether or not a diff exists between the last reviewed diff and
 // HEAD@{upstream}.
-func gitHasDiff(path, name string) (bool, error) {
-	if gitHasLastSeenRef(path, name) {
+func gitHasDiff(ctx context.Context, path, name string) (bool, error) {
+	if gitHasLastSeenRef(ctx, path, name) {
 		stdout, stderr, err := config.Runtime.CmdBuilder.Capture(
-			config.Runtime.CmdBuilder.BuildGitCmd(filepath.Join(path, name), "rev-parse", gitDiffRefName, "HEAD@{upstream}"), 0)
+			config.Runtime.CmdBuilder.BuildGitCmd(ctx, filepath.Join(path, name), "rev-parse", gitDiffRefName, "HEAD@{upstream}"))
 		if err != nil {
 			return false, fmt.Errorf("%s%s", stderr, err)
 		}
@@ -85,21 +86,21 @@ func gitHasDiff(path, name string) (bool, error) {
 
 // Return wether or not we have reviewed a diff yet. It checks for the existence of
 // YAY_DIFF_REVIEW in the git ref-list.
-func gitHasLastSeenRef(path, name string) bool {
+func gitHasLastSeenRef(ctx context.Context, path, name string) bool {
 	_, _, err := config.Runtime.CmdBuilder.Capture(
-		config.Runtime.CmdBuilder.BuildGitCmd(
-			filepath.Join(path, name), "rev-parse", "--quiet", "--verify", gitDiffRefName), 0)
+		config.Runtime.CmdBuilder.BuildGitCmd(ctx,
+			filepath.Join(path, name), "rev-parse", "--quiet", "--verify", gitDiffRefName))
 
 	return err == nil
 }
 
 // Returns the last reviewed hash. If YAY_DIFF_REVIEW exists it will return this hash.
 // If it does not it will return empty tree as no diff have been reviewed yet.
-func getLastSeenHash(path, name string) (string, error) {
-	if gitHasLastSeenRef(path, name) {
+func getLastSeenHash(ctx context.Context, path, name string) (string, error) {
+	if gitHasLastSeenRef(ctx, path, name) {
 		stdout, stderr, err := config.Runtime.CmdBuilder.Capture(
-			config.Runtime.CmdBuilder.BuildGitCmd(
-				filepath.Join(path, name), "rev-parse", gitDiffRefName), 0)
+			config.Runtime.CmdBuilder.BuildGitCmd(ctx,
+				filepath.Join(path, name), "rev-parse", gitDiffRefName))
 		if err != nil {
 			return "", fmt.Errorf("%s %s", stderr, err)
 		}
@@ -114,10 +115,10 @@ func getLastSeenHash(path, name string) (string, error) {
 
 // Update the YAY_DIFF_REVIEW ref to HEAD. We use this ref to determine which diff were
 // reviewed by the user.
-func gitUpdateSeenRef(path, name string) error {
+func gitUpdateSeenRef(ctx context.Context, path, name string) error {
 	_, stderr, err := config.Runtime.CmdBuilder.Capture(
-		config.Runtime.CmdBuilder.BuildGitCmd(
-			filepath.Join(path, name), "update-ref", gitDiffRefName, "HEAD"), 0)
+		config.Runtime.CmdBuilder.BuildGitCmd(ctx,
+			filepath.Join(path, name), "update-ref", gitDiffRefName, "HEAD"))
 	if err != nil {
 		return fmt.Errorf("%s %s", stderr, err)
 	}
@@ -125,17 +126,17 @@ func gitUpdateSeenRef(path, name string) error {
 	return nil
 }
 
-func gitMerge(path, name string) error {
+func gitMerge(ctx context.Context, path, name string) error {
 	_, stderr, err := config.Runtime.CmdBuilder.Capture(
-		config.Runtime.CmdBuilder.BuildGitCmd(
-			filepath.Join(path, name), "reset", "--hard", "HEAD"), 0)
+		config.Runtime.CmdBuilder.BuildGitCmd(ctx,
+			filepath.Join(path, name), "reset", "--hard", "HEAD"))
 	if err != nil {
 		return fmt.Errorf(gotext.Get("error resetting %s: %s", name, stderr))
 	}
 
 	_, stderr, err = config.Runtime.CmdBuilder.Capture(
-		config.Runtime.CmdBuilder.BuildGitCmd(
-			filepath.Join(path, name), "merge", "--no-edit", "--ff"), 0)
+		config.Runtime.CmdBuilder.BuildGitCmd(ctx,
+			filepath.Join(path, name), "merge", "--no-edit", "--ff"))
 	if err != nil {
 		return fmt.Errorf(gotext.Get("error merging %s: %s", name, stderr))
 	}

+ 4 - 3
get.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"net/http"
 	"os"
@@ -47,14 +48,14 @@ func printPkgbuilds(dbExecutor download.DBSearcher, httpClient *http.Client, tar
 }
 
 // yay -G.
-func getPkgbuilds(dbExecutor download.DBSearcher, config *settings.Configuration, targets []string,
-	force bool) error {
+func getPkgbuilds(ctx context.Context, dbExecutor download.DBSearcher,
+	config *settings.Configuration, targets []string, force bool) error {
 	wd, err := os.Getwd()
 	if err != nil {
 		return err
 	}
 
-	cloned, errD := download.PKGBUILDRepos(dbExecutor,
+	cloned, errD := download.PKGBUILDRepos(ctx, dbExecutor,
 		config.Runtime.CmdBuilder, targets, config.Runtime.Mode, config.AURURL, wd, force)
 	if errD != nil {
 		text.Errorln(errD)

+ 51 - 49
install.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"os"
@@ -30,7 +31,7 @@ import (
 
 const gitEmptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
 
-func asdeps(cmdArgs *parser.Arguments, pkgs []string) (err error) {
+func asdeps(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string) (err error) {
 	if len(pkgs) == 0 {
 		return nil
 	}
@@ -39,7 +40,7 @@ func asdeps(cmdArgs *parser.Arguments, pkgs []string) (err error) {
 	_ = cmdArgs.AddArg("q", "D", "asdeps")
 	cmdArgs.AddTarget(pkgs...)
 
-	err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	if err != nil {
 		return fmt.Errorf(gotext.Get("error updating package install reason to dependency"))
@@ -48,7 +49,7 @@ func asdeps(cmdArgs *parser.Arguments, pkgs []string) (err error) {
 	return nil
 }
 
-func asexp(cmdArgs *parser.Arguments, pkgs []string) (err error) {
+func asexp(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string) (err error) {
 	if len(pkgs) == 0 {
 		return nil
 	}
@@ -57,7 +58,7 @@ func asexp(cmdArgs *parser.Arguments, pkgs []string) (err error) {
 	_ = cmdArgs.AddArg("q", "D", "asexplicit")
 	cmdArgs.AddTarget(pkgs...)
 
-	err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	if err != nil {
 		return fmt.Errorf(gotext.Get("error updating package install reason to explicit"))
@@ -67,7 +68,7 @@ func asexp(cmdArgs *parser.Arguments, pkgs []string) (err error) {
 }
 
 // Install handles package installs.
-func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders bool) (err error) {
+func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders bool) (err error) {
 	var (
 		incompatible    stringset.StringSet
 		do              *dep.Order
@@ -87,13 +88,13 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 	if config.Runtime.Mode.AtLeastRepo() {
 		if config.CombinedUpgrade {
 			if refreshArg {
-				err = earlyRefresh(cmdArgs)
+				err = earlyRefresh(ctx, cmdArgs)
 				if err != nil {
 					return fmt.Errorf(gotext.Get("error refreshing databases"))
 				}
 			}
 		} else if refreshArg || sysupgradeArg || len(cmdArgs.Targets) > 0 {
-			err = earlyPacmanCall(cmdArgs, dbExecutor)
+			err = earlyPacmanCall(ctx, cmdArgs, dbExecutor)
 			if err != nil {
 				return err
 			}
@@ -130,7 +131,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 
 	// if we are doing -u also request all packages needing update
 	if sysupgradeArg {
-		ignore, targets, errUp := sysupgradeTargets(dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"))
+		ignore, targets, errUp := sysupgradeTargets(ctx, dbExecutor, cmdArgs.ExistsDouble("u", "sysupgrade"))
 		if errUp != nil {
 			return errUp
 		}
@@ -147,7 +148,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 
 	targets := stringset.FromSlice(cmdArgs.Targets)
 
-	dp, err := dep.GetPool(requestTargets,
+	dp, err := dep.GetPool(ctx, requestTargets,
 		warnings, dbExecutor, config.Runtime.AURClient, config.Runtime.Mode,
 		ignoreProviders, settings.NoConfirm, config.Provides, config.ReBuild, config.RequestSplitN, noDeps, noCheck, assumeInstalled)
 	if err != nil {
@@ -175,7 +176,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 			cmdArgs.CreateOrAppendOption("ignore", arguments.GetArgs("ignore")...)
 		}
 
-		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 	}
 
@@ -208,14 +209,14 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 	fmt.Println()
 
 	if config.CleanAfter {
-		defer cleanAfter(do.Aur)
+		defer cleanAfter(ctx, do.Aur)
 	}
 
 	if do.HasMake() {
 		switch config.RemoveMake {
 		case "yes":
 			defer func() {
-				err = removeMake(do)
+				err = removeMake(ctx, do)
 			}()
 
 		case "no":
@@ -223,7 +224,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 		default:
 			if text.ContinueTask(gotext.Get("Remove make dependencies after install?"), false, settings.NoConfirm) {
 				defer func() {
-					err = removeMake(do)
+					err = removeMake(ctx, do)
 				}()
 			}
 		}
@@ -258,7 +259,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 				len(toSkipSlice), len(toClone), text.Cyan(strings.Join(toSkipSlice, ", "))))
 	}
 
-	cloned, errA := download.AURPKGBUILDRepos(
+	cloned, errA := download.AURPKGBUILDRepos(ctx,
 		config.Runtime.CmdBuilder, toClone, config.AURURL, config.BuildDir, false)
 	if errA != nil {
 		return err
@@ -278,7 +279,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 		}
 
 		if len(toDiff) > 0 {
-			err = showPkgbuildDiffs(toDiff, cloned)
+			err = showPkgbuildDiffs(ctx, toDiff, cloned)
 			if err != nil {
 				return err
 			}
@@ -295,7 +296,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 			return fmt.Errorf(gotext.Get("aborting due to user"))
 		}
 
-		err = updatePkgbuildSeenRef(toDiff)
+		err = updatePkgbuildSeenRef(ctx, toDiff)
 		if err != nil {
 			text.Errorln(err.Error())
 		}
@@ -303,7 +304,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 		settings.NoConfirm = oldValue
 	}
 
-	err = mergePkgbuilds(do.Aur)
+	err = mergePkgbuilds(ctx, do.Aur)
 	if err != nil {
 		return err
 	}
@@ -359,7 +360,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 	}
 
 	if len(arguments.Targets) > 0 || arguments.ExistsArg("u") {
-		if errShow := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		if errShow := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			arguments, config.Runtime.Mode, settings.NoConfirm)); errShow != nil {
 			return errors.New(gotext.Get("error installing repo packages"))
 		}
@@ -381,26 +382,26 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 			}
 		}
 
-		if errDeps := asdeps(cmdArgs, deps); errDeps != nil {
+		if errDeps := asdeps(ctx, cmdArgs, deps); errDeps != nil {
 			return errDeps
 		}
 
-		if errExp := asexp(cmdArgs, exp); errExp != nil {
+		if errExp := asexp(ctx, cmdArgs, exp); errExp != nil {
 			return errExp
 		}
 	}
 
 	go func() {
-		_ = completion.Update(config.Runtime.HTTPClient, dbExecutor,
+		_ = completion.Update(ctx, config.Runtime.HTTPClient, dbExecutor,
 			config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, false)
 	}()
 
-	err = downloadPkgbuildsSources(do.Aur, incompatible)
+	err = downloadPkgbuildsSources(ctx, do.Aur, incompatible)
 	if err != nil {
 		return err
 	}
 
-	err = buildInstallPkgbuilds(cmdArgs, dbExecutor, dp, do, srcinfos, incompatible, conflicts, noDeps, noCheck)
+	err = buildInstallPkgbuilds(ctx, cmdArgs, dbExecutor, dp, do, srcinfos, incompatible, conflicts, noDeps, noCheck)
 	if err != nil {
 		return err
 	}
@@ -408,7 +409,7 @@ func install(cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders
 	return nil
 }
 
-func removeMake(do *dep.Order) error {
+func removeMake(ctx context.Context, do *dep.Order) error {
 	removeArguments := parser.MakeArguments()
 
 	err := removeArguments.AddArg("R", "u")
@@ -422,7 +423,7 @@ func removeMake(do *dep.Order) error {
 
 	oldValue := settings.NoConfirm
 	settings.NoConfirm = true
-	err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		removeArguments, config.Runtime.Mode, settings.NoConfirm))
 	settings.NoConfirm = oldValue
 
@@ -446,7 +447,7 @@ func inRepos(dbExecutor db.Executor, pkg string) bool {
 	return exists || len(dbExecutor.PackagesFromGroup(target.Name)) > 0
 }
 
-func earlyPacmanCall(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
+func earlyPacmanCall(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	arguments := cmdArgs.Copy()
 	arguments.Op = "S"
 	targets := cmdArgs.Targets
@@ -467,7 +468,7 @@ func earlyPacmanCall(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	}
 
 	if cmdArgs.ExistsArg("y", "refresh") || cmdArgs.ExistsArg("u", "sysupgrade") || len(arguments.Targets) > 0 {
-		if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			arguments, config.Runtime.Mode, settings.NoConfirm)); err != nil {
 			return errors.New(gotext.Get("error installing repo packages"))
 		}
@@ -476,7 +477,7 @@ func earlyPacmanCall(cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
 	return nil
 }
 
-func earlyRefresh(cmdArgs *parser.Arguments) error {
+func earlyRefresh(ctx context.Context, cmdArgs *parser.Arguments) error {
 	arguments := cmdArgs.Copy()
 	cmdArgs.DelArg("y", "refresh")
 	arguments.DelArg("u", "sysupgrade")
@@ -485,7 +486,7 @@ func earlyRefresh(cmdArgs *parser.Arguments) error {
 	arguments.DelArg("l", "list")
 	arguments.ClearTargets()
 
-	return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		arguments, config.Runtime.Mode, settings.NoConfirm))
 }
 
@@ -541,9 +542,9 @@ nextpkg:
 	return incompatible, nil
 }
 
-func parsePackageList(dir string) (pkgdests map[string]string, pkgVersion string, err error) {
+func parsePackageList(ctx context.Context, dir string) (pkgdests map[string]string, pkgVersion string, err error) {
 	stdout, stderr, err := config.Runtime.CmdBuilder.Capture(
-		config.Runtime.CmdBuilder.BuildMakepkgCmd(dir, "--packagelist"), 0)
+		config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, dir, "--packagelist"))
 	if err != nil {
 		return nil, "", fmt.Errorf("%s %s", stderr, err)
 	}
@@ -770,13 +771,13 @@ func editDiffNumberMenu(bases []dep.Base, installed stringset.StringSet, diff bo
 	return toEdit, nil
 }
 
-func updatePkgbuildSeenRef(bases []dep.Base) error {
+func updatePkgbuildSeenRef(ctx context.Context, bases []dep.Base) error {
 	var errMulti multierror.MultiError
 
 	for _, base := range bases {
 		pkg := base.Pkgbase()
 
-		if err := gitUpdateSeenRef(config.BuildDir, pkg); err != nil {
+		if err := gitUpdateSeenRef(ctx, config.BuildDir, pkg); err != nil {
 			errMulti.Add(err)
 		}
 	}
@@ -864,9 +865,9 @@ func pkgbuildsToSkip(bases []dep.Base, targets stringset.StringSet) stringset.St
 	return toSkip
 }
 
-func mergePkgbuilds(bases []dep.Base) error {
+func mergePkgbuilds(ctx context.Context, bases []dep.Base) error {
 	for _, base := range bases {
-		err := gitMerge(config.BuildDir, base.Pkgbase())
+		err := gitMerge(ctx, config.BuildDir, base.Pkgbase())
 		if err != nil {
 			return err
 		}
@@ -875,7 +876,7 @@ func mergePkgbuilds(bases []dep.Base) error {
 	return nil
 }
 
-func downloadPkgbuildsSources(bases []dep.Base, incompatible stringset.StringSet) (err error) {
+func downloadPkgbuildsSources(ctx context.Context, bases []dep.Base, incompatible stringset.StringSet) (err error) {
 	for _, base := range bases {
 		pkg := base.Pkgbase()
 		dir := filepath.Join(config.BuildDir, pkg)
@@ -886,7 +887,7 @@ func downloadPkgbuildsSources(bases []dep.Base, incompatible stringset.StringSet
 		}
 
 		err = config.Runtime.CmdBuilder.Show(
-			config.Runtime.CmdBuilder.BuildMakepkgCmd(dir, args...))
+			config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, dir, args...))
 		if err != nil {
 			return errors.New(gotext.Get("error downloading sources: %s", text.Cyan(base.String())))
 		}
@@ -896,6 +897,7 @@ func downloadPkgbuildsSources(bases []dep.Base, incompatible stringset.StringSet
 }
 
 func buildInstallPkgbuilds(
+	ctx context.Context,
 	cmdArgs *parser.Arguments,
 	dbExecutor db.Executor,
 	dp *dep.Pool,
@@ -953,7 +955,7 @@ func buildInstallPkgbuilds(
 		}
 
 		if !satisfied || !config.BatchInstall {
-			err = doInstall(arguments, cmdArgs, deps, exp)
+			err = doInstall(ctx, arguments, cmdArgs, deps, exp)
 			arguments.ClearTargets()
 
 			deps = make([]string, 0)
@@ -974,11 +976,11 @@ func buildInstallPkgbuilds(
 
 		// pkgver bump
 		if err = config.Runtime.CmdBuilder.Show(
-			config.Runtime.CmdBuilder.BuildMakepkgCmd(dir, args...)); err != nil {
+			config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, dir, args...)); err != nil {
 			return errors.New(gotext.Get("error making: %s", base.String()))
 		}
 
-		pkgdests, pkgVersion, errList := parsePackageList(dir)
+		pkgdests, pkgVersion, errList := parsePackageList(ctx, dir)
 		if errList != nil {
 			return errList
 		}
@@ -1013,7 +1015,7 @@ func buildInstallPkgbuilds(
 
 			if installed {
 				err = config.Runtime.CmdBuilder.Show(
-					config.Runtime.CmdBuilder.BuildMakepkgCmd(
+					config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx,
 						dir, "-c", "--nobuild", "--noextract", "--ignorearch"))
 				if err != nil {
 					return errors.New(gotext.Get("error making: %s", err))
@@ -1027,7 +1029,7 @@ func buildInstallPkgbuilds(
 
 		if built {
 			err = config.Runtime.CmdBuilder.Show(
-				config.Runtime.CmdBuilder.BuildMakepkgCmd(
+				config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx,
 					dir, "-c", "--nobuild", "--noextract", "--ignorearch"))
 			if err != nil {
 				return errors.New(gotext.Get("error making: %s", err))
@@ -1042,7 +1044,7 @@ func buildInstallPkgbuilds(
 			}
 
 			if errMake := config.Runtime.CmdBuilder.Show(
-				config.Runtime.CmdBuilder.BuildMakepkgCmd(
+				config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx,
 					dir, args...)); errMake != nil {
 				return errors.New(gotext.Get("error making: %s", base.String()))
 			}
@@ -1083,24 +1085,24 @@ func buildInstallPkgbuilds(
 		for _, pkg := range base {
 			wg.Add(1)
 
-			go config.Runtime.VCSStore.Update(pkg.Name, srcinfo.Source, &mux, &wg)
+			go config.Runtime.VCSStore.Update(ctx, pkg.Name, srcinfo.Source, &mux, &wg)
 		}
 
 		wg.Wait()
 	}
 
-	err = doInstall(arguments, cmdArgs, deps, exp)
+	err = doInstall(ctx, arguments, cmdArgs, deps, exp)
 	settings.NoConfirm = oldConfirm
 
 	return err
 }
 
-func doInstall(arguments, cmdArgs *parser.Arguments, pkgDeps, pkgExp []string) error {
+func doInstall(ctx context.Context, arguments, cmdArgs *parser.Arguments, pkgDeps, pkgExp []string) error {
 	if len(arguments.Targets) == 0 {
 		return nil
 	}
 
-	if errShow := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+	if errShow := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 		arguments, config.Runtime.Mode, settings.NoConfirm)); errShow != nil {
 		return errShow
 	}
@@ -1109,11 +1111,11 @@ func doInstall(arguments, cmdArgs *parser.Arguments, pkgDeps, pkgExp []string) e
 		fmt.Fprintln(os.Stderr, errStore)
 	}
 
-	if errDeps := asdeps(cmdArgs, pkgDeps); errDeps != nil {
+	if errDeps := asdeps(ctx, cmdArgs, pkgDeps); errDeps != nil {
 		return errDeps
 	}
 
-	return asexp(cmdArgs, pkgExp)
+	return asexp(ctx, cmdArgs, pkgExp)
 }
 
 func doAddTarget(dp *dep.Pool, localNamesCache, remoteNamesCache stringset.StringSet,

+ 7 - 4
main.go

@@ -1,6 +1,7 @@
 package main // import "github.com/Jguer/yay"
 
 import (
+	"context"
 	"fmt"
 	"os"
 	"os/exec"
@@ -84,9 +85,11 @@ func initAlpm(cmdArgs *parser.Arguments, pacmanConfigPath string) (*pacmanconf.C
 }
 
 func main() {
-	var err error
-
-	ret := 0
+	var (
+		err error
+		ctx = context.Background()
+		ret = 0
+	)
 
 	defer func() { os.Exit(ret) }()
 
@@ -154,7 +157,7 @@ func main() {
 	}
 
 	defer dbExecutor.Cleanup()
-	err = handleCmd(cmdArgs, db.Executor(dbExecutor))
+	err = handleCmd(ctx, cmdArgs, db.Executor(dbExecutor))
 
 	if err != nil {
 		if str := err.Error(); str != "" && !strings.Contains(str, "exit status") {

+ 8 - 6
pkg/completion/completion.go

@@ -21,8 +21,9 @@ type PkgSynchronizer interface {
 }
 
 // Show provides completion info for shells.
-func Show(httpClient *http.Client, dbExecutor PkgSynchronizer, aurURL, completionPath string, interval int, force bool) error {
-	err := Update(httpClient, dbExecutor, aurURL, completionPath, interval, force)
+func Show(ctx context.Context, httpClient *http.Client,
+	dbExecutor PkgSynchronizer, aurURL, completionPath string, interval int, force bool) error {
+	err := Update(ctx, httpClient, dbExecutor, aurURL, completionPath, interval, force)
 	if err != nil {
 		return err
 	}
@@ -39,7 +40,8 @@ func Show(httpClient *http.Client, dbExecutor PkgSynchronizer, aurURL, completio
 }
 
 // Update updates completion cache to be used by Complete.
-func Update(httpClient *http.Client, dbExecutor PkgSynchronizer, aurURL, completionPath string, interval int, force bool) error {
+func Update(ctx context.Context, httpClient *http.Client,
+	dbExecutor PkgSynchronizer, aurURL, completionPath string, interval int, force bool) error {
 	info, err := os.Stat(completionPath)
 
 	if os.IsNotExist(err) || (interval != -1 && time.Since(info.ModTime()).Hours() >= float64(interval*24)) || force {
@@ -53,7 +55,7 @@ func Update(httpClient *http.Client, dbExecutor PkgSynchronizer, aurURL, complet
 			return errf
 		}
 
-		if createAURList(httpClient, aurURL, out) != nil {
+		if createAURList(ctx, httpClient, aurURL, out) != nil {
 			defer os.Remove(completionPath)
 		}
 
@@ -68,7 +70,7 @@ func Update(httpClient *http.Client, dbExecutor PkgSynchronizer, aurURL, complet
 }
 
 // CreateAURList creates a new completion file.
-func createAURList(client *http.Client, aurURL string, out io.Writer) error {
+func createAURList(ctx context.Context, client *http.Client, aurURL string, out io.Writer) error {
 	u, err := url.Parse(aurURL)
 	if err != nil {
 		return err
@@ -76,7 +78,7 @@ func createAURList(client *http.Client, aurURL string, out io.Writer) error {
 
 	u.Path = path.Join(u.Path, "packages.gz")
 
-	req, err := http.NewRequestWithContext(context.Background(), "GET", u.String(), nil)
+	req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
 	if err != nil {
 		return err
 	}

+ 4 - 3
pkg/completion/completion_test.go

@@ -2,6 +2,7 @@ package completion
 
 import (
 	"bytes"
+	"context"
 	"errors"
 	"net/http"
 	"testing"
@@ -41,7 +42,7 @@ func Test_createAURList(t *testing.T) {
 		BodyString(samplePackageResp)
 
 	out := &bytes.Buffer{}
-	err := createAURList(&http.Client{}, "https://aur.archlinux.org", out)
+	err := createAURList(context.TODO(), &http.Client{}, "https://aur.archlinux.org", out)
 	assert.NoError(t, err)
 	gotOut := out.String()
 	assert.Equal(t, expectPackageCompletion, gotOut)
@@ -55,7 +56,7 @@ func Test_createAURListHTTPError(t *testing.T) {
 		ReplyError(errors.New("Not available"))
 
 	out := &bytes.Buffer{}
-	err := createAURList(&http.Client{}, "https://aur.archlinux.org", out)
+	err := createAURList(context.TODO(), &http.Client{}, "https://aur.archlinux.org", out)
 	assert.EqualError(t, err, "Get \"https://aur.archlinux.org/packages.gz\": Not available")
 }
 
@@ -67,6 +68,6 @@ func Test_createAURListStatusError(t *testing.T) {
 		Reply(503).
 		BodyString(samplePackageResp)
 	out := &bytes.Buffer{}
-	err := createAURList(&http.Client{}, "https://aur.archlinux.org", out)
+	err := createAURList(context.TODO(), &http.Client{}, "https://aur.archlinux.org", out)
 	assert.EqualError(t, err, "invalid status code: 503")
 }

+ 16 - 12
pkg/dep/depPool.go

@@ -82,7 +82,7 @@ func makePool(dbExecutor db.Executor, aurClient *aur.Client) *Pool {
 }
 
 // Includes db/ prefixes and group installs.
-func (dp *Pool) ResolveTargets(pkgs []string,
+func (dp *Pool) ResolveTargets(ctx context.Context, pkgs []string,
 	mode parser.TargetMode,
 	ignoreProviders, noConfirm, provides bool, rebuild string, splitN int, noDeps, noCheckDeps bool, assumeInstalled []string) error {
 	// RPC requests are slow
@@ -154,7 +154,8 @@ func (dp *Pool) ResolveTargets(pkgs []string,
 	}
 
 	if len(aurTargets) > 0 && mode.AtLeastAUR() {
-		return dp.resolveAURPackages(aurTargets, true, ignoreProviders, noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps)
+		return dp.resolveAURPackages(ctx, aurTargets, true, ignoreProviders,
+			noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps)
 	}
 
 	return nil
@@ -172,7 +173,7 @@ func (dp *Pool) ResolveTargets(pkgs []string,
 // positives.
 //
 // This method increases dependency resolve time.
-func (dp *Pool) findProvides(pkgs stringset.StringSet) error {
+func (dp *Pool) findProvides(ctx context.Context, pkgs stringset.StringSet) error {
 	var (
 		mux sync.Mutex
 		wg  sync.WaitGroup
@@ -193,7 +194,7 @@ func (dp *Pool) findProvides(pkgs stringset.StringSet) error {
 		words := strings.Split(pkg, "-")
 
 		for i := range words {
-			results, err = dp.aurClient.Search(context.Background(), strings.Join(words[:i+1], "-"), aur.None)
+			results, err = dp.aurClient.Search(ctx, strings.Join(words[:i+1], "-"), aur.None)
 			if err == nil {
 				break
 			}
@@ -227,7 +228,7 @@ func (dp *Pool) findProvides(pkgs stringset.StringSet) error {
 	return nil
 }
 
-func (dp *Pool) cacheAURPackages(_pkgs stringset.StringSet, provides bool, splitN int) error {
+func (dp *Pool) cacheAURPackages(ctx context.Context, _pkgs stringset.StringSet, provides bool, splitN int) error {
 	pkgs := _pkgs.Copy()
 	toQuery := make([]string, 0)
 
@@ -242,7 +243,7 @@ func (dp *Pool) cacheAURPackages(_pkgs stringset.StringSet, provides bool, split
 	}
 
 	if provides {
-		err := dp.findProvides(pkgs)
+		err := dp.findProvides(ctx, pkgs)
 		if err != nil {
 			return err
 		}
@@ -259,7 +260,7 @@ func (dp *Pool) cacheAURPackages(_pkgs stringset.StringSet, provides bool, split
 		}
 	}
 
-	info, err := query.AURInfo(dp.aurClient, toQuery, dp.Warnings, splitN)
+	info, err := query.AURInfo(ctx, dp.aurClient, toQuery, dp.Warnings, splitN)
 	if err != nil {
 		return err
 	}
@@ -290,13 +291,14 @@ func ComputeCombinedDepList(pkg *aur.Pkg, noDeps, noCheckDeps bool) [][]string {
 	return combinedDepList
 }
 
-func (dp *Pool) resolveAURPackages(pkgs stringset.StringSet,
+func (dp *Pool) resolveAURPackages(ctx context.Context,
+	pkgs stringset.StringSet,
 	explicit, ignoreProviders, noConfirm, provides bool,
 	rebuild string, splitN int, noDeps, noCheckDeps bool) error {
 	newPackages := make(stringset.StringSet)
 	newAURPackages := make(stringset.StringSet)
 
-	err := dp.cacheAURPackages(pkgs, provides, splitN)
+	err := dp.cacheAURPackages(ctx, pkgs, provides, splitN)
 	if err != nil {
 		return err
 	}
@@ -355,7 +357,8 @@ func (dp *Pool) resolveAURPackages(pkgs stringset.StringSet,
 		newAURPackages.Set(dep)
 	}
 
-	err = dp.resolveAURPackages(newAURPackages, false, ignoreProviders, noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps)
+	err = dp.resolveAURPackages(ctx, newAURPackages, false, ignoreProviders,
+		noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps)
 
 	return err
 }
@@ -384,7 +387,7 @@ func (dp *Pool) ResolveRepoDependency(pkg db.IPackage, noDeps bool) {
 	}
 }
 
-func GetPool(pkgs []string,
+func GetPool(ctx context.Context, pkgs []string,
 	warnings *query.AURWarnings,
 	dbExecutor db.Executor,
 	aurClient *aur.Client,
@@ -394,7 +397,8 @@ func GetPool(pkgs []string,
 	dp := makePool(dbExecutor, aurClient)
 
 	dp.Warnings = warnings
-	err := dp.ResolveTargets(pkgs, mode, ignoreProviders, noConfirm, provides, rebuild, splitN, noDeps, noCheckDeps, assumeInstalled)
+	err := dp.ResolveTargets(ctx, pkgs, mode, ignoreProviders, noConfirm, provides,
+		rebuild, splitN, noDeps, noCheckDeps, assumeInstalled)
 
 	return dp, err
 }

+ 4 - 2
pkg/download/abs.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"io/ioutil"
@@ -83,12 +84,13 @@ func ABSPKGBUILD(httpClient httpRequestDoer, dbName, pkgName string) ([]byte, er
 }
 
 // ABSPKGBUILDRepo retrieves the PKGBUILD repository to a dest directory.
-func ABSPKGBUILDRepo(cmdBuilder exe.GitCmdBuilder, dbName, pkgName, dest string, force bool) (bool, error) {
+func ABSPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
+	dbName, pkgName, dest string, force bool) (bool, error) {
 	pkgURL, err := getPackageRepoURL(dbName)
 	if err != nil {
 		return false, err
 	}
 
-	return downloadGitRepo(cmdBuilder, pkgURL,
+	return downloadGitRepo(ctx, cmdBuilder, pkgURL,
 		pkgName, dest, force, "--single-branch", "-b", "packages/"+pkgName)
 }

+ 3 - 2
pkg/download/abs_test.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -209,7 +210,7 @@ func TestABSPKGBUILDRepo(t *testing.T) {
 			GitFlags: []string{"--no-replace-objects"},
 		},
 	}
-	newClone, err := ABSPKGBUILDRepo(cmdBuilder, "core", "linux", "/tmp/doesnt-exist", false)
+	newClone, err := ABSPKGBUILDRepo(context.TODO(), cmdBuilder, "core", "linux", "/tmp/doesnt-exist", false)
 	assert.NoError(t, err)
 	assert.Equal(t, true, newClone)
 }
@@ -235,7 +236,7 @@ func TestABSPKGBUILDRepoExistsPerms(t *testing.T) {
 			GitFlags: []string{"--no-replace-objects"},
 		},
 	}
-	newClone, err := ABSPKGBUILDRepo(cmdBuilder, "core", "linux", dir, false)
+	newClone, err := ABSPKGBUILDRepo(context.TODO(), cmdBuilder, "core", "linux", dir, false)
 	assert.NoError(t, err)
 	assert.Equal(t, false, newClone)
 }

+ 5 - 3
pkg/download/aur.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"fmt"
 	"io/ioutil"
 	"net/http"
@@ -39,13 +40,14 @@ func AURPKGBUILD(httpClient httpRequestDoer, pkgName, aurURL string) ([]byte, er
 }
 
 // AURPkgbuildRepo retrieves the PKGBUILD repository to a dest directory.
-func AURPKGBUILDRepo(cmdBuilder exe.GitCmdBuilder, aurURL, pkgName, dest string, force bool) (bool, error) {
+func AURPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder, aurURL, pkgName, dest string, force bool) (bool, error) {
 	pkgURL := fmt.Sprintf("%s/%s.git", aurURL, pkgName)
 
-	return downloadGitRepo(cmdBuilder, pkgURL, pkgName, dest, force)
+	return downloadGitRepo(ctx, cmdBuilder, pkgURL, pkgName, dest, force)
 }
 
 func AURPKGBUILDRepos(
+	ctx context.Context,
 	cmdBuilder exe.GitCmdBuilder,
 	targets []string, aurURL, dest string, force bool) (map[string]bool, error) {
 	cloned := make(map[string]bool, len(targets))
@@ -64,7 +66,7 @@ func AURPKGBUILDRepos(
 		wg.Add(1)
 
 		go func(target string) {
-			newClone, err := AURPKGBUILDRepo(cmdBuilder, aurURL, target, dest, force)
+			newClone, err := AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, target, dest, force)
 
 			progress := 0
 

+ 4 - 3
pkg/download/aur_test.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -88,7 +89,7 @@ func TestAURPKGBUILDRepo(t *testing.T) {
 			GitFlags: []string{"--no-replace-objects"},
 		},
 	}
-	newCloned, err := AURPKGBUILDRepo(cmdBuilder, "https://aur.archlinux.org", "yay-bin", "/tmp/doesnt-exist", false)
+	newCloned, err := AURPKGBUILDRepo(context.TODO(), cmdBuilder, "https://aur.archlinux.org", "yay-bin", "/tmp/doesnt-exist", false)
 	assert.NoError(t, err)
 	assert.Equal(t, true, newCloned)
 }
@@ -114,7 +115,7 @@ func TestAURPKGBUILDRepoExistsPerms(t *testing.T) {
 			GitFlags: []string{"--no-replace-objects"},
 		},
 	}
-	cloned, err := AURPKGBUILDRepo(cmdBuilder, "https://aur.archlinux.org", "yay-bin", dir, false)
+	cloned, err := AURPKGBUILDRepo(context.TODO(), cmdBuilder, "https://aur.archlinux.org", "yay-bin", dir, false)
 	assert.NoError(t, err)
 	assert.Equal(t, false, cloned)
 }
@@ -138,7 +139,7 @@ func TestAURPKGBUILDRepos(t *testing.T) {
 			GitFlags: []string{},
 		},
 	}
-	cloned, err := AURPKGBUILDRepos(cmdBuilder, targets, "https://aur.archlinux.org", dir, false)
+	cloned, err := AURPKGBUILDRepos(context.TODO(), cmdBuilder, targets, "https://aur.archlinux.org", dir, false)
 
 	assert.NoError(t, err)
 	assert.EqualValues(t, map[string]bool{"yay": true, "yay-bin": false, "yay-git": true}, cloned)

+ 9 - 8
pkg/download/unified.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"net/http"
 	"os"
 	"path/filepath"
@@ -24,7 +25,7 @@ type DBSearcher interface {
 	SatisfierFromDB(string, string) db.IPackage
 }
 
-func downloadGitRepo(cmdBuilder exe.GitCmdBuilder,
+func downloadGitRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
 	pkgURL, pkgName, dest string, force bool, gitArgs ...string) (bool, error) {
 	finalDir := filepath.Join(dest, pkgName)
 	newClone := true
@@ -42,9 +43,9 @@ func downloadGitRepo(cmdBuilder exe.GitCmdBuilder,
 		cloneArgs := make([]string, 0, len(gitArgs)+4)
 		cloneArgs = append(cloneArgs, "clone", "--no-progress")
 		cloneArgs = append(cloneArgs, gitArgs...)
-		cmd := cmdBuilder.BuildGitCmd(dest, cloneArgs...)
+		cmd := cmdBuilder.BuildGitCmd(ctx, dest, cloneArgs...)
 
-		_, stderr, errCapture := cmdBuilder.Capture(cmd, 0)
+		_, stderr, errCapture := cmdBuilder.Capture(cmd)
 		if errCapture != nil {
 			return false, ErrGetPKGBUILDRepo{inner: errCapture, pkgName: pkgName, errOut: stderr}
 		}
@@ -55,9 +56,9 @@ func downloadGitRepo(cmdBuilder exe.GitCmdBuilder,
 			errOut:  gotext.Get("error reading %s", filepath.Join(dest, pkgName, ".git")),
 		}
 	default:
-		cmd := cmdBuilder.BuildGitCmd(filepath.Join(dest, pkgName), "pull", "--ff-only")
+		cmd := cmdBuilder.BuildGitCmd(ctx, filepath.Join(dest, pkgName), "pull", "--ff-only")
 
-		_, stderr, errCmd := cmdBuilder.Capture(cmd, 0)
+		_, stderr, errCmd := cmdBuilder.Capture(cmd)
 		if errCmd != nil {
 			return false, ErrGetPKGBUILDRepo{inner: errCmd, pkgName: pkgName, errOut: stderr}
 		}
@@ -130,7 +131,7 @@ func PKGBUILDs(dbExecutor DBSearcher, httpClient *http.Client, targets []string,
 	return pkgbuilds, errs.Return()
 }
 
-func PKGBUILDRepos(dbExecutor DBSearcher,
+func PKGBUILDRepos(ctx context.Context, dbExecutor DBSearcher,
 	cmdBuilder exe.GitCmdBuilder,
 	targets []string, mode parser.TargetMode, aurURL, dest string, force bool) (map[string]bool, error) {
 	cloned := make(map[string]bool, len(targets))
@@ -161,9 +162,9 @@ func PKGBUILDRepos(dbExecutor DBSearcher,
 			)
 
 			if aur {
-				newClone, err = AURPKGBUILDRepo(cmdBuilder, aurURL, pkgName, dest, force)
+				newClone, err = AURPKGBUILDRepo(ctx, cmdBuilder, aurURL, pkgName, dest, force)
 			} else {
-				newClone, err = ABSPKGBUILDRepo(cmdBuilder, dbName, pkgName, dest, force)
+				newClone, err = ABSPKGBUILDRepo(ctx, cmdBuilder, dbName, pkgName, dest, force)
 			}
 
 			progress := 0

+ 6 - 5
pkg/download/unified_test.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"io/ioutil"
 	"net/http"
 	"os"
@@ -39,7 +40,7 @@ func TestPKGBUILDReposDefinedDBPull(t *testing.T) {
 	searcher := &testDBSearcher{
 		absPackagesDB: map[string]string{"yay": "core"},
 	}
-	cloned, err := PKGBUILDRepos(searcher,
+	cloned, err := PKGBUILDRepos(context.TODO(), searcher,
 		cmdBuilder,
 		targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
 
@@ -69,7 +70,7 @@ func TestPKGBUILDReposDefinedDBClone(t *testing.T) {
 	searcher := &testDBSearcher{
 		absPackagesDB: map[string]string{"yay": "core"},
 	}
-	cloned, err := PKGBUILDRepos(searcher,
+	cloned, err := PKGBUILDRepos(context.TODO(), searcher,
 		cmdBuilder,
 		targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
 
@@ -99,7 +100,7 @@ func TestPKGBUILDReposClone(t *testing.T) {
 	searcher := &testDBSearcher{
 		absPackagesDB: map[string]string{"yay": "core"},
 	}
-	cloned, err := PKGBUILDRepos(searcher,
+	cloned, err := PKGBUILDRepos(context.TODO(), searcher,
 		cmdBuilder,
 		targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
 
@@ -129,7 +130,7 @@ func TestPKGBUILDReposNotFound(t *testing.T) {
 	searcher := &testDBSearcher{
 		absPackagesDB: map[string]string{"yay": "core"},
 	}
-	cloned, err := PKGBUILDRepos(searcher,
+	cloned, err := PKGBUILDRepos(context.TODO(), searcher,
 		cmdBuilder,
 		targets, parser.ModeAny, "https://aur.archlinux.org", dir, false)
 
@@ -159,7 +160,7 @@ func TestPKGBUILDReposRepoMode(t *testing.T) {
 	searcher := &testDBSearcher{
 		absPackagesDB: map[string]string{"yay": "core"},
 	}
-	cloned, err := PKGBUILDRepos(searcher,
+	cloned, err := PKGBUILDRepos(context.TODO(), searcher,
 		cmdBuilder,
 		targets, parser.ModeRepo, "https://aur.archlinux.org", dir, false)
 

+ 6 - 5
pkg/download/utils_test.go

@@ -1,6 +1,7 @@
 package download
 
 import (
+	"context"
 	"io"
 	"net/http"
 	"os/exec"
@@ -17,7 +18,7 @@ import (
 
 type testRunner struct{}
 
-func (t *testRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout string, stderr string, err error) {
+func (t *testRunner) Capture(cmd *exec.Cmd) (stdout string, stderr string, err error) {
 	return "", "", nil
 }
 
@@ -32,8 +33,8 @@ type testGitBuilder struct {
 	parentBuilder *exe.CmdBuilder
 }
 
-func (t *testGitBuilder) BuildGitCmd(dir string, extraArgs ...string) *exec.Cmd {
-	cmd := t.parentBuilder.BuildGitCmd(dir, extraArgs...)
+func (t *testGitBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {
+	cmd := t.parentBuilder.BuildGitCmd(ctx, dir, extraArgs...)
 
 	if t.want != "" {
 		assert.Equal(t.test, t.want, cmd.String())
@@ -46,8 +47,8 @@ func (c *testGitBuilder) Show(cmd *exec.Cmd) error {
 	return c.parentBuilder.Show(cmd)
 }
 
-func (c *testGitBuilder) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
-	return c.parentBuilder.Capture(cmd, timeout)
+func (c *testGitBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
+	return c.parentBuilder.Capture(cmd)
 }
 
 type (

+ 2 - 2
pkg/news/news.go

@@ -61,8 +61,8 @@ type rss struct {
 	Channel channel `xml:"channel"`
 }
 
-func PrintNewsFeed(client *http.Client, cutOffDate time.Time, sortMode int, all, quiet bool) error {
-	req, err := http.NewRequestWithContext(context.Background(), "GET", "https://archlinux.org/feeds/news", nil)
+func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Time, sortMode int, all, quiet bool) error {
+	req, err := http.NewRequestWithContext(ctx, "GET", "https://archlinux.org/feeds/news", nil)
 	if err != nil {
 		return err
 	}

+ 2 - 1
pkg/news/news_test.go

@@ -1,6 +1,7 @@
 package news
 
 import (
+	"context"
 	"io/ioutil"
 	"net/http"
 	"os"
@@ -114,7 +115,7 @@ func TestPrintNewsFeed(t *testing.T) {
 			r, w, _ := os.Pipe()
 			os.Stdout = w
 
-			err := PrintNewsFeed(&http.Client{}, tt.args.cutOffDate, tt.args.sortMode, tt.args.all, tt.args.quiet)
+			err := PrintNewsFeed(context.TODO(), &http.Client{}, tt.args.cutOffDate, tt.args.sortMode, tt.args.all, tt.args.quiet)
 			assert.NoError(t, err)
 
 			w.Close()

+ 4 - 4
pkg/query/aur_info.go

@@ -19,7 +19,7 @@ type Pkg = aur.Pkg
 // of packages exceeds the number set in config.RequestSplitN.
 // If the number does exceed config.RequestSplitN multiple aur requests will be
 // performed concurrently.
-func AURInfo(aurClient *aur.Client, names []string, warnings *AURWarnings, splitN int) ([]*Pkg, error) {
+func AURInfo(ctx context.Context, aurClient *aur.Client, names []string, warnings *AURWarnings, splitN int) ([]*Pkg, error) {
 	info := make([]*Pkg, 0, len(names))
 	seen := make(map[string]int)
 
@@ -32,7 +32,7 @@ func AURInfo(aurClient *aur.Client, names []string, warnings *AURWarnings, split
 	makeRequest := func(n, max int) {
 		defer wg.Done()
 
-		tempInfo, requestErr := aurClient.Info(context.Background(), names[n:max])
+		tempInfo, requestErr := aurClient.Info(ctx, names[n:max])
 		if requestErr != nil {
 			errs.Add(requestErr)
 			return
@@ -84,12 +84,12 @@ func AURInfo(aurClient *aur.Client, names []string, warnings *AURWarnings, split
 	return info, nil
 }
 
-func AURInfoPrint(aurClient *aur.Client, names []string, splitN int) ([]*Pkg, error) {
+func AURInfoPrint(ctx context.Context, aurClient *aur.Client, names []string, splitN int) ([]*Pkg, error) {
 	text.OperationInfoln(gotext.Get("Querying AUR..."))
 
 	warnings := &AURWarnings{}
 
-	info, err := AURInfo(aurClient, names, warnings, splitN)
+	info, err := AURInfo(ctx, aurClient, names, warnings, splitN)
 	if err != nil {
 		return info, err
 	}

+ 13 - 12
pkg/settings/exe/cmd_builder.go

@@ -1,6 +1,7 @@
 package exe
 
 import (
+	"context"
 	"fmt"
 	"os"
 	"os/exec"
@@ -17,14 +18,14 @@ const SudoLoopDuration = 241
 
 type GitCmdBuilder interface {
 	Runner
-	BuildGitCmd(dir string, extraArgs ...string) *exec.Cmd
+	BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
 }
 
 type ICmdBuilder interface {
 	Runner
-	BuildGitCmd(dir string, extraArgs ...string) *exec.Cmd
-	BuildMakepkgCmd(dir string, extraArgs ...string) *exec.Cmd
-	BuildPacmanCmd(args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
+	BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
+	BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
+	BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
 	AddMakepkgFlag(string)
 	SetPacmanDBPath(string)
 	SudoLoop()
@@ -45,7 +46,7 @@ type CmdBuilder struct {
 	Runner           Runner
 }
 
-func (c *CmdBuilder) BuildGitCmd(dir string, extraArgs ...string) *exec.Cmd {
+func (c *CmdBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {
 	args := make([]string, len(c.GitFlags), len(c.GitFlags)+len(extraArgs))
 	copy(args, c.GitFlags)
 
@@ -57,7 +58,7 @@ func (c *CmdBuilder) BuildGitCmd(dir string, extraArgs ...string) *exec.Cmd {
 		args = append(args, extraArgs...)
 	}
 
-	cmd := exec.Command(c.GitBin, args...)
+	cmd := exec.CommandContext(ctx, c.GitBin, args...)
 
 	cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
 
@@ -68,7 +69,7 @@ func (c *CmdBuilder) AddMakepkgFlag(flag string) {
 	c.MakepkgFlags = append(c.MakepkgFlags, flag)
 }
 
-func (c *CmdBuilder) BuildMakepkgCmd(dir string, extraArgs ...string) *exec.Cmd {
+func (c *CmdBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {
 	args := make([]string, len(c.MakepkgFlags), len(c.MakepkgFlags)+len(extraArgs))
 	copy(args, c.MakepkgFlags)
 
@@ -80,7 +81,7 @@ func (c *CmdBuilder) BuildMakepkgCmd(dir string, extraArgs ...string) *exec.Cmd
 		args = append(args, extraArgs...)
 	}
 
-	cmd := exec.Command(c.MakepkgBin, args...)
+	cmd := exec.CommandContext(ctx, c.MakepkgBin, args...)
 	cmd.Dir = dir
 
 	return cmd
@@ -90,7 +91,7 @@ func (c *CmdBuilder) SetPacmanDBPath(dbPath string) {
 	c.PacmanDBPath = dbPath
 }
 
-func (c *CmdBuilder) BuildPacmanCmd(args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd {
+func (c *CmdBuilder) BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd {
 	argArr := make([]string, 0, 32)
 	needsRoot := args.NeedRoot(mode)
 
@@ -114,7 +115,7 @@ func (c *CmdBuilder) BuildPacmanCmd(args *parser.Arguments, mode parser.TargetMo
 		waitLock(c.PacmanDBPath)
 	}
 
-	return exec.Command(argArr[0], argArr[1:]...)
+	return exec.CommandContext(ctx, argArr[0], argArr[1:]...)
 }
 
 // waitLock will lock yay checking the status of db.lck until it does not exist.
@@ -166,6 +167,6 @@ func (c *CmdBuilder) Show(cmd *exec.Cmd) error {
 	return c.Runner.Show(cmd)
 }
 
-func (c *CmdBuilder) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
-	return c.Runner.Capture(cmd, timeout)
+func (c *CmdBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
+	return c.Runner.Capture(cmd)
 }

+ 7 - 49
pkg/settings/exe/exec.go

@@ -1,19 +1,13 @@
 package exe
 
 import (
-	"bytes"
-	"fmt"
 	"os"
 	"os/exec"
 	"strings"
-	"syscall"
-	"time"
-
-	"github.com/Jguer/yay/v10/pkg/text"
 )
 
 type Runner interface {
-	Capture(cmd *exec.Cmd, timeout int64) (stdout string, stderr string, err error)
+	Capture(cmd *exec.Cmd) (stdout string, stderr string, err error)
 	Show(cmd *exec.Cmd) error
 }
 
@@ -24,50 +18,14 @@ func (r *OSRunner) Show(cmd *exec.Cmd) error {
 	return cmd.Run()
 }
 
-func (r *OSRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
-	var (
-		outbuf, errbuf bytes.Buffer
-		timer          *time.Timer
-		timedOut       = false
-	)
-
-	cmd.Stdout = &outbuf
-	cmd.Stderr = &errbuf
-	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
-
-	err = cmd.Start()
-	if err != nil {
-		stdout = strings.TrimSpace(outbuf.String())
-		stderr = strings.TrimSpace(errbuf.String())
-
-		return stdout, stderr, err
-	}
-
-	if timeout != 0 {
-		timer = time.AfterFunc(time.Duration(timeout)*time.Second, func() {
-			err = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
-			if err != nil {
-				text.Errorln(err)
-			}
-			timedOut = true
-		})
-	}
-
-	err = cmd.Wait()
-
-	if timeout != 0 {
-		timer.Stop()
-	}
-
-	stdout = strings.TrimSpace(outbuf.String())
-	stderr = strings.TrimSpace(errbuf.String())
+func (r *OSRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
+	outbuf, err := cmd.Output()
+	stdout = strings.TrimSpace(string(outbuf))
 
 	if err != nil {
-		return stdout, stderr, err
-	}
-
-	if timedOut {
-		err = fmt.Errorf("command timed out")
+		if exitErr, isExitError := err.(*exec.ExitError); isExitError {
+			stderr = strings.TrimSpace(string(exitErr.Stderr))
+		}
 	}
 
 	return stdout, stderr, err

+ 3 - 1
pkg/upgrade/sources.go

@@ -1,6 +1,7 @@
 package upgrade
 
 import (
+	"context"
 	"sync"
 
 	"github.com/leonelquinteros/gotext"
@@ -12,6 +13,7 @@ import (
 )
 
 func UpDevel(
+	ctx context.Context,
 	remote []db.IPackage,
 	aurdata map[string]*query.Pkg,
 	localCache *vcs.InfoStore) UpSlice {
@@ -26,7 +28,7 @@ func UpDevel(
 	checkUpdate := func(pkgName string, e vcs.OriginInfoByURL) {
 		defer wg.Done()
 
-		if localCache.NeedsUpdate(e) {
+		if localCache.NeedsUpdate(ctx, e) {
 			if _, ok := aurdata[pkgName]; ok {
 				for _, pkg := range remote {
 					if pkg.Name() == pkgName {

+ 3 - 2
pkg/upgrade/sources_test.go

@@ -1,6 +1,7 @@
 package upgrade
 
 import (
+	"context"
 	"fmt"
 	"os/exec"
 	"strconv"
@@ -85,7 +86,7 @@ func (r *MockRunner) Show(cmd *exec.Cmd) error {
 	return nil
 }
 
-func (r *MockRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
+func (r *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
 	i, _ := strconv.Atoi(cmd.Args[len(cmd.Args)-1])
 	if i >= len(r.Returned) {
 		fmt.Println(r.Returned)
@@ -270,7 +271,7 @@ func Test_upDevel(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			t.Parallel()
 			tt.args.cached.CmdBuilder.(*exe.CmdBuilder).Runner.(*MockRunner).t = t
-			got := UpDevel(tt.args.remote, tt.args.aurdata, &tt.args.cached)
+			got := UpDevel(context.TODO(), tt.args.remote, tt.args.aurdata, &tt.args.cached)
 			assert.ElementsMatch(t, tt.want.Up, got.Up)
 			assert.Equal(t, tt.finalLen, len(tt.args.cached.OriginsByPackage))
 		})

+ 13 - 7
pkg/vcs/vcs.go

@@ -1,12 +1,14 @@
 package vcs
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
 	"os"
 	"os/exec"
 	"strings"
 	"sync"
+	"time"
 
 	gosrc "github.com/Morganamilo/go-srcinfo"
 	"github.com/leonelquinteros/gotext"
@@ -52,13 +54,16 @@ func NewInfoStore(filePath string, cmdBuilder exe.GitCmdBuilder) *InfoStore {
 }
 
 // GetCommit parses HEAD commit from url and branch.
-func (v *InfoStore) getCommit(url, branch string, protocols []string) string {
+func (v *InfoStore) getCommit(ctx context.Context, url, branch string, protocols []string) string {
 	if len(protocols) > 0 {
 		protocol := protocols[len(protocols)-1]
 
-		cmd := v.CmdBuilder.BuildGitCmd("", "ls-remote", protocol+"://"+url, branch)
+		ctxTimeout, cancel := context.WithTimeout(ctx, 5*time.Second)
+		defer cancel()
 
-		stdout, _, err := v.CmdBuilder.Capture(cmd, 5)
+		cmd := v.CmdBuilder.BuildGitCmd(ctxTimeout, "", "ls-remote", protocol+"://"+url, branch)
+
+		stdout, _, err := v.CmdBuilder.Capture(cmd)
 		if err != nil {
 			if exiterr, ok := err.(*exec.ExitError); ok && exiterr.ExitCode() == 128 {
 				text.Warnln(gotext.Get("devel check for package failed: '%s' encountered an error", cmd.String()))
@@ -84,7 +89,8 @@ func (v *InfoStore) getCommit(url, branch string, protocols []string) string {
 	return ""
 }
 
-func (v *InfoStore) Update(pkgName string, sources []gosrc.ArchString, mux sync.Locker, wg *sync.WaitGroup) {
+func (v *InfoStore) Update(ctx context.Context, pkgName string,
+	sources []gosrc.ArchString, mux sync.Locker, wg *sync.WaitGroup) {
 	defer wg.Done()
 
 	info := make(OriginInfoByURL)
@@ -96,7 +102,7 @@ func (v *InfoStore) Update(pkgName string, sources []gosrc.ArchString, mux sync.
 			return
 		}
 
-		commit := v.getCommit(url, branch, protocols)
+		commit := v.getCommit(ctx, url, branch, protocols)
 		if commit == "" {
 			return
 		}
@@ -176,7 +182,7 @@ func parseSource(source string) (url, branch string, protocols []string) {
 	return url, branch, protocols
 }
 
-func (v *InfoStore) NeedsUpdate(infos OriginInfoByURL) bool {
+func (v *InfoStore) NeedsUpdate(ctx context.Context, infos OriginInfoByURL) bool {
 	// used to signal we have gone through all sources and found nothing
 	finished := make(chan struct{})
 	alive := 0
@@ -188,7 +194,7 @@ func (v *InfoStore) NeedsUpdate(infos OriginInfoByURL) bool {
 	defer close(closed)
 
 	checkHash := func(url string, info OriginInfo) {
-		hash := v.getCommit(url, info.Branch, info.Protocols)
+		hash := v.getCommit(ctx, url, info.Branch, info.Protocols)
 
 		var sendTo chan<- struct{}
 		if hash != "" && hash != info.SHA {

+ 4 - 3
pkg/vcs/vcs_test.go

@@ -1,6 +1,7 @@
 package vcs
 
 import (
+	"context"
 	"encoding/json"
 	"errors"
 	"fmt"
@@ -93,7 +94,7 @@ func (r *MockRunner) Show(cmd *exec.Cmd) error {
 	return nil
 }
 
-func (r *MockRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
+func (r *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
 	stdout = r.Returned[r.Index]
 	if r.Returned[0] == "error" {
 		err = errors.New("possible error")
@@ -224,7 +225,7 @@ func TestInfoStore_NeedsUpdate(t *testing.T) {
 			v := &InfoStore{
 				CmdBuilder: tt.fields.CmdBuilder,
 			}
-			got := v.NeedsUpdate(tt.args.infos)
+			got := v.NeedsUpdate(context.TODO(), tt.args.infos)
 			assert.Equal(t, tt.want, got)
 		})
 	}
@@ -277,7 +278,7 @@ func TestInfoStore_Update(t *testing.T) {
 			var mux sync.Mutex
 			var wg sync.WaitGroup
 			wg.Add(1)
-			v.Update(tt.args.pkgName, tt.args.sources, &mux, &wg)
+			v.Update(context.TODO(), tt.args.pkgName, tt.args.sources, &mux, &wg)
 			wg.Wait()
 			assert.Len(t, tt.fields.OriginsByPackage, 1)
 

+ 8 - 6
print.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"os"
 	"strconv"
@@ -159,7 +160,7 @@ func biggestPackages(dbExecutor db.Executor) {
 }
 
 // localStatistics prints installed packages statistics.
-func localStatistics(dbExecutor db.Executor) error {
+func localStatistics(ctx context.Context, dbExecutor db.Executor) error {
 	info := statistics(dbExecutor)
 
 	_, remoteNames, err := query.GetPackageNamesBySource(dbExecutor)
@@ -178,16 +179,16 @@ func localStatistics(dbExecutor db.Executor) error {
 	biggestPackages(dbExecutor)
 	fmt.Println(text.Bold(text.Cyan("===========================================")))
 
-	query.AURInfoPrint(config.Runtime.AURClient, remoteNames, config.RequestSplitN)
+	query.AURInfoPrint(ctx, config.Runtime.AURClient, remoteNames, config.RequestSplitN)
 
 	return nil
 }
 
-func printNumberOfUpdates(dbExecutor db.Executor, enableDowngrade bool, filter upgrade.Filter) error {
+func printNumberOfUpdates(ctx context.Context, dbExecutor db.Executor, enableDowngrade bool, filter upgrade.Filter) error {
 	warnings := query.NewWarnings()
 	old := os.Stdout // keep backup of the real stdout
 	os.Stdout = nil
-	aurUp, repoUp, err := upList(warnings, dbExecutor, enableDowngrade, filter)
+	aurUp, repoUp, err := upList(ctx, warnings, dbExecutor, enableDowngrade, filter)
 	os.Stdout = old // restoring the real stdout
 
 	if err != nil {
@@ -199,7 +200,8 @@ func printNumberOfUpdates(dbExecutor db.Executor, enableDowngrade bool, filter u
 	return nil
 }
 
-func printUpdateList(cmdArgs *parser.Arguments, dbExecutor db.Executor, enableDowngrade bool, filter upgrade.Filter) error {
+func printUpdateList(ctx context.Context, cmdArgs *parser.Arguments,
+	dbExecutor db.Executor, enableDowngrade bool, filter upgrade.Filter) error {
 	targets := stringset.FromSlice(cmdArgs.Targets)
 	warnings := query.NewWarnings()
 	old := os.Stdout // keep backup of the real stdout
@@ -211,7 +213,7 @@ func printUpdateList(cmdArgs *parser.Arguments, dbExecutor db.Executor, enableDo
 		return err
 	}
 
-	aurUp, repoUp, err := upList(warnings, dbExecutor, enableDowngrade, filter)
+	aurUp, repoUp, err := upList(ctx, warnings, dbExecutor, enableDowngrade, filter)
 	os.Stdout = old // restoring the real stdout
 
 	if err != nil {

+ 7 - 7
query.go

@@ -89,7 +89,7 @@ func getSearchBy(value string) aur.By {
 }
 
 // NarrowSearch searches AUR and narrows based on subarguments.
-func narrowSearch(aurClient *aur.Client, pkgS []string, sortS bool) (aurQuery, error) {
+func narrowSearch(ctx context.Context, aurClient *aur.Client, pkgS []string, sortS bool) (aurQuery, error) {
 	var (
 		r         []aur.Pkg
 		err       error
@@ -103,7 +103,7 @@ func narrowSearch(aurClient *aur.Client, pkgS []string, sortS bool) (aurQuery, e
 	}
 
 	for i, word := range pkgS {
-		r, err = aurClient.Search(context.Background(), word, by)
+		r, err = aurClient.Search(ctx, word, by)
 		if err == nil {
 			usedIndex = i
 
@@ -158,7 +158,7 @@ func narrowSearch(aurClient *aur.Client, pkgS []string, sortS bool) (aurQuery, e
 }
 
 // SyncSearch presents a query to the local repos and to the AUR.
-func syncSearch(pkgS []string, aurClient *aur.Client, dbExecutor db.Executor) (err error) {
+func syncSearch(ctx context.Context, pkgS []string, aurClient *aur.Client, dbExecutor db.Executor) (err error) {
 	pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode)
 
 	var (
@@ -168,7 +168,7 @@ func syncSearch(pkgS []string, aurClient *aur.Client, dbExecutor db.Executor) (e
 	)
 
 	if config.Runtime.Mode.AtLeastAUR() {
-		aq, aurErr = narrowSearch(aurClient, pkgS, true)
+		aq, aurErr = narrowSearch(ctx, aurClient, pkgS, true)
 	}
 
 	if config.Runtime.Mode.AtLeastRepo() {
@@ -205,7 +205,7 @@ func syncSearch(pkgS []string, aurClient *aur.Client, dbExecutor db.Executor) (e
 }
 
 // SyncInfo serves as a pacman -Si for repo packages and AUR packages.
-func syncInfo(cmdArgs *parser.Arguments, pkgS []string, dbExecutor db.Executor) error {
+func syncInfo(ctx context.Context, cmdArgs *parser.Arguments, pkgS []string, dbExecutor db.Executor) error {
 	var (
 		info    []*aur.Pkg
 		err     error
@@ -223,7 +223,7 @@ func syncInfo(cmdArgs *parser.Arguments, pkgS []string, dbExecutor db.Executor)
 			noDB = append(noDB, name)
 		}
 
-		info, err = query.AURInfoPrint(config.Runtime.AURClient, noDB, config.RequestSplitN)
+		info, err = query.AURInfoPrint(ctx, config.Runtime.AURClient, noDB, config.RequestSplitN)
 		if err != nil {
 			missing = true
 
@@ -237,7 +237,7 @@ func syncInfo(cmdArgs *parser.Arguments, pkgS []string, dbExecutor db.Executor)
 		arguments.ClearTargets()
 		arguments.AddTarget(repoS...)
 
-		err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(
+		err = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
 			cmdArgs, config.Runtime.Mode, settings.NoConfirm))
 		if err != nil {
 			return err

+ 8 - 5
upgrade.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"sort"
 	"strings"
@@ -32,7 +33,7 @@ func filterUpdateList(list []db.Upgrade, filter upgrade.Filter) []db.Upgrade {
 }
 
 // upList returns lists of packages to upgrade from each source.
-func upList(warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade bool,
+func upList(ctx context.Context, warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade bool,
 	filter upgrade.Filter) (aurUp, repoUp upgrade.UpSlice, err error) {
 	remote, remoteNames := query.GetRemotePackages(dbExecutor)
 
@@ -66,7 +67,7 @@ func upList(warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade
 		text.OperationInfoln(gotext.Get("Searching AUR for updates..."))
 
 		var _aurdata []*aur.Pkg
-		_aurdata, err = query.AURInfo(config.Runtime.AURClient, remoteNames, warnings, config.RequestSplitN)
+		_aurdata, err = query.AURInfo(ctx, config.Runtime.AURClient, remoteNames, warnings, config.RequestSplitN)
 		errs.Add(err)
 
 		if err == nil {
@@ -87,7 +88,7 @@ func upList(warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade
 				wg.Add(1)
 
 				go func() {
-					develUp = upgrade.UpDevel(remote, aurdata, config.Runtime.VCSStore)
+					develUp = upgrade.UpDevel(ctx, remote, aurdata, config.Runtime.VCSStore)
 
 					wg.Done()
 				}()
@@ -230,10 +231,12 @@ func upgradePkgsMenu(aurUp, repoUp upgrade.UpSlice) (stringset.StringSet, []stri
 }
 
 // Targets for sys upgrade.
-func sysupgradeTargets(dbExecutor db.Executor, enableDowngrade bool) (stringset.StringSet, []string, error) {
+func sysupgradeTargets(ctx context.Context, dbExecutor db.Executor,
+	enableDowngrade bool) (stringset.StringSet, []string, error) {
 	warnings := query.NewWarnings()
 
-	aurUp, repoUp, err := upList(warnings, dbExecutor, enableDowngrade, func(upgrade.Upgrade) bool { return true })
+	aurUp, repoUp, err := upList(ctx, warnings, dbExecutor, enableDowngrade,
+		func(upgrade.Upgrade) bool { return true })
 	if err != nil {
 		return nil, nil, err
 	}

+ 5 - 4
vcs.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"strings"
 	"sync"
 
@@ -16,7 +17,7 @@ import (
 )
 
 // createDevelDB forces yay to create a DB of the existing development packages.
-func createDevelDB(config *settings.Configuration, dbExecutor db.Executor) error {
+func createDevelDB(ctx context.Context, config *settings.Configuration, dbExecutor db.Executor) error {
 	var (
 		mux sync.Mutex
 		wg  sync.WaitGroup
@@ -27,7 +28,7 @@ func createDevelDB(config *settings.Configuration, dbExecutor db.Executor) error
 		return err
 	}
 
-	info, err := query.AURInfoPrint(config.Runtime.AURClient, remoteNames, config.RequestSplitN)
+	info, err := query.AURInfoPrint(ctx, config.Runtime.AURClient, remoteNames, config.RequestSplitN)
 	if err != nil {
 		return err
 	}
@@ -50,7 +51,7 @@ func createDevelDB(config *settings.Configuration, dbExecutor db.Executor) error
 				len(toSkipSlice), len(bases), text.Cyan(strings.Join(toSkipSlice, ", "))))
 	}
 
-	if _, errA := download.AURPKGBUILDRepos(
+	if _, errA := download.AURPKGBUILDRepos(ctx,
 		config.Runtime.CmdBuilder, targets, config.AURURL, config.BuildDir, false); errA != nil {
 		return err
 	}
@@ -64,7 +65,7 @@ func createDevelDB(config *settings.Configuration, dbExecutor db.Executor) error
 		for iP := range srcinfos[i].Packages {
 			wg.Add(1)
 
-			go config.Runtime.VCSStore.Update(srcinfos[i].Packages[iP].Pkgname, srcinfos[i].Source, &mux, &wg)
+			go config.Runtime.VCSStore.Update(ctx, srcinfos[i].Packages[iP].Pkgname, srcinfos[i].Source, &mux, &wg)
 		}
 	}