浏览代码

Allow many aur packages to be installed at once.

After building an AUR package don't install it right away. Instead queue
it for install.

Then when a package comes along that does not have all of its
dependencies satisfied, install the queued packages before builting.

This allows a standard AUR update to be done with one transaction, while
building AUR packages with long dependency chains will work as normal.

This feature is behind the `--batchinstall` flag.
morganamilo 6 年之前
父节点
当前提交
80e66ce479
共有 4 个文件被更改,包括 86 次插入46 次删除
  1. 3 1
      config.go
  2. 76 44
      install.go
  3. 1 1
      main.go
  4. 6 0
      parser.go

+ 3 - 1
config.go

@@ -9,8 +9,8 @@ import (
 	"os/exec"
 	"strings"
 
-	pacmanconf "github.com/Morganamilo/go-pacmanconf"
 	alpm "github.com/Jguer/go-alpm"
+	pacmanconf "github.com/Morganamilo/go-pacmanconf"
 )
 
 // Verbosity settings for search
@@ -47,6 +47,7 @@ type Configuration struct {
 	TarBin             string `json:"tarbin"`
 	ReDownload         string `json:"redownload"`
 	ReBuild            string `json:"rebuild"`
+	BatchInstall       bool   `json:"batchinstall"`
 	AnswerClean        string `json:"answerclean"`
 	AnswerDiff         string `json:"answerdiff"`
 	AnswerEdit         string `json:"answeredit"`
@@ -165,6 +166,7 @@ func defaultSettings() *Configuration {
 		RequestSplitN:      150,
 		ReDownload:         "no",
 		ReBuild:            "no",
+		BatchInstall:       false,
 		AnswerClean:        "",
 		AnswerDiff:         "",
 		AnswerEdit:         "",

+ 76 - 44
install.go

@@ -916,11 +916,81 @@ func downloadPkgbuildsSources(bases []Base, incompatible stringSet) (err error)
 }
 
 func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error {
+	arguments := parser.copy()
+	arguments.clearTargets()
+	arguments.op = "U"
+	arguments.delArg("confirm")
+	arguments.delArg("noconfirm")
+	arguments.delArg("c", "clean")
+	arguments.delArg("q", "quiet")
+	arguments.delArg("q", "quiet")
+	arguments.delArg("y", "refresh")
+	arguments.delArg("u", "sysupgrade")
+	arguments.delArg("w", "downloadonly")
+
+	deps := make([]string, 0)
+	exp := make([]string, 0)
+	oldConfirm := config.NoConfirm
+	config.NoConfirm = true
+
+	doInstall := func() error {
+		if len(arguments.targets) == 0 {
+			return nil
+		}
+
+		err := show(passToPacman(arguments))
+		if err != nil {
+			return err
+		}
+
+		err = saveVCSInfo()
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+		}
+
+		if err = asdeps(parser, deps); err != nil {
+			return err
+		}
+		if err = asexp(parser, exp); err != nil {
+			return err
+		}
+
+		config.NoConfirm = oldConfirm
+
+		arguments.clearTargets()
+		deps = make([]string, 0)
+		exp = make([]string, 0)
+		config.NoConfirm = true
+		return nil
+	}
+
 	for _, base := range do.Aur {
+		var err error
 		pkg := base.Pkgbase()
 		dir := filepath.Join(config.BuildDir, pkg)
 		built := true
 
+		satisfied := true
+	all:
+		for _, pkg := range base {
+			for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
+				for _, dep := range deps {
+					if _, err := dp.LocalDB.PkgCache().FindSatisfier(dep); err != nil {
+						satisfied = false
+						fmt.Printf("%s not satisfied, flushing install queue", dep)
+						break all
+					}
+				}
+			}
+		}
+
+		if !satisfied || !config.BatchInstall {
+			err = doInstall()
+			if err != nil {
+				return err
+			}
+		}
+
 		srcinfo := srcinfos[pkg]
 
 		args := []string{"--nobuild", "-fC"}
@@ -930,7 +1000,7 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
 		}
 
 		//pkgver bump
-		err := show(passToMakepkg(dir, args...))
+		err = show(passToMakepkg(dir, args...))
 		if err != nil {
 			return fmt.Errorf("Error making: %s", base.String())
 		}
@@ -994,41 +1064,20 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
 			}
 		}
 
-		arguments := parser.copy()
-		arguments.clearTargets()
-		arguments.op = "U"
-		arguments.delArg("confirm")
-		arguments.delArg("noconfirm")
-		arguments.delArg("c", "clean")
-		arguments.delArg("q", "quiet")
-		arguments.delArg("q", "quiet")
-		arguments.delArg("y", "refresh")
-		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 base {
 				if _, ok := conflicts[split.Name]; ok {
-					conflict = true
+					config.NoConfirm = false
+					break
 				}
 			}
-
-			if !conflict {
-				config.NoConfirm = true
-			}
 		}
 
-		deps := make([]string, 0)
-		exp := make([]string, 0)
-
 		//remotenames: names of all non repo packages on the system
 		_, _, localNames, remoteNames, err := filterPackages()
 		if err != nil {
@@ -1056,11 +1105,6 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
 			}
 		}
 
-		err = show(passToPacman(arguments))
-		if err != nil {
-			return err
-		}
-
 		var mux sync.Mutex
 		var wg sync.WaitGroup
 		for _, pkg := range base {
@@ -1069,21 +1113,9 @@ func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
 		}
 
 		wg.Wait()
-
-		err = saveVCSInfo()
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err)
-		}
-
-		if err = asdeps(parser, deps); err != nil {
-			return err
-		}
-		if err = asexp(parser, exp); err != nil {
-			return err
-		}
-
-		config.NoConfirm = oldConfirm
 	}
 
-	return nil
+	err := doInstall()
+	config.NoConfirm = oldConfirm
+	return err
 }

+ 1 - 1
main.go

@@ -7,8 +7,8 @@ import (
 	"path/filepath"
 	"strings"
 
-	pacmanconf "github.com/Morganamilo/go-pacmanconf"
 	alpm "github.com/Jguer/go-alpm"
+	pacmanconf "github.com/Morganamilo/go-pacmanconf"
 )
 
 func setPaths() error {

+ 6 - 0
parser.go

@@ -449,6 +449,8 @@ func isArg(arg string) bool {
 	case "rebuildall":
 	case "rebuildtree":
 	case "norebuild":
+	case "batchinstall":
+	case "nobatchinstall":
 	case "answerclean":
 	case "noanswerclean":
 	case "answerdiff":
@@ -555,6 +557,10 @@ func handleConfig(option, value string) bool {
 		config.ReBuild = "tree"
 	case "norebuild":
 		config.ReBuild = "no"
+	case "batchinstall":
+		config.BatchInstall = true
+	case "nobatchinstall":
+		config.BatchInstall = false
 	case "answerclean":
 		config.AnswerClean = value
 	case "noanswerclean":