Browse Source

Merge pull request #637 from Morganamilo/refactorinstall2

Refactor install
Anna 6 years ago
parent
commit
a37bbd851e
6 changed files with 229 additions and 213 deletions
  1. 8 8
      dep.go
  2. 28 15
      depOrder.go
  3. 163 151
      install.go
  4. 15 18
      keys.go
  5. 10 8
      print.go
  6. 5 13
      vcs.go

+ 8 - 8
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 []*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

+ 28 - 15
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)

+ 163 - 151
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
@@ -23,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 {
@@ -94,7 +93,7 @@ func install(parser *arguments) error {
 		}
 
 		for up := range aurUp {
-			requestTargets = append(requestTargets, "aur/" + up)
+			requestTargets = append(requestTargets, "aur/"+up)
 			parser.addTarget("aur/" + up)
 		}
 
@@ -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
@@ -185,24 +184,24 @@ func install(parser *arguments) error {
 		cleanBuilds(toClean)
 	}
 
-	toSkip := pkgBuildsToSkip(do.Aur, targets)
-	cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip)
+	toSkip := pkgbuildsToSkip(do.Aur, targets)
+	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
 			}
@@ -219,26 +218,25 @@ 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, do.Bases)
+	srcinfos, err = parseSrcinfoFiles(do.Aur, true)
 	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
 		}
 
 		if len(toEdit) > 0 {
-			err = editPkgBuilds(toEdit, srcinfosStale)
+			err = editPkgbuilds(toEdit, srcinfos)
 			if err != nil {
 				return err
 			}
@@ -255,13 +253,13 @@ func install(parser *arguments) error {
 		config.NoConfirm = oldValue
 	}
 
-	incompatible, err = getIncompatible(do.Aur, srcinfosStale)
+	incompatible, err = getIncompatible(do.Aur, srcinfos)
 	if err != nil {
 		return err
 	}
 
 	if config.PGPFetch {
-		err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale)
+		err = checkPgpKeys(do.Aur, srcinfos)
 		if err != nil {
 			return err
 		}
@@ -312,12 +310,12 @@ 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
 	}
 
-	err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible, conflicts)
+	err = buildInstallPkgbuilds(dp, do, srcinfos, parser, incompatible, conflicts)
 	if err != nil {
 		return err
 	}
@@ -341,7 +339,7 @@ func install(parser *arguments) error {
 	}
 
 	if config.CleanAfter {
-		clean(do.Aur)
+		cleanBuilds(do.Aur)
 	}
 
 	return nil
@@ -416,29 +414,31 @@ 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)
+	basesMap := make(map[string]Base)
 	alpmArch, err := alpmHandle.Arch()
 	if err != nil {
 		return nil, err
 	}
 
 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())
+		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((basesMap[pkg].String())))
 		}
 
 		fmt.Println()
@@ -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(bases)-n,
+			bold(base.String()))
+
+		anyInstalled := false
+		for _, b := range base {
+			anyInstalled = anyInstalled || installed.get(b.Name)
+		}
 
-		toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(pkgs)-n,
-			bold(formatPkgbase(pkg, bases)))
-		if installed.get(pkg.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(pkg, bases)), bold("No changes -- skipping"))
+					fmt.Printf("%s %s: %s\n", bold(yellow(arrow)), cyan(base.String()), 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,46 @@ 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, 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)
 
 		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(bases), cyan(base.String()))
 
 		pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO"))
 		if err != nil {
-			return fmt.Errorf("%s: %s", pkg.Name, err)
+			if !errIsFatal {
+				fmt.Printf("failed to parse %s -- skipping: %s\n", base.String(), err)
+				continue
+			}
+			return nil, fmt.Errorf("failed to parse %s: %s", base.String(), err)
 		}
 
-		srcinfos[pkg.PackageBase] = pkgbuild
+		srcinfos[pkg] = pkgbuild
 	}
 
-	return nil
+	return srcinfos, 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)
-
-		str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n")
-		fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases)))
+func pkgbuildsToSkip(bases []Base, targets stringSet) stringSet {
+	toSkip := make(stringSet)
 
-		pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO"))
-		if err != nil {
-			fmt.Printf("cannot parse %s skipping: %s\n", pkg.Name, err)
-			continue
+	for _, base := range bases {
+		isTarget := false
+		for _, pkg := range base {
+			isTarget = isTarget || targets.get(pkg.Name)
 		}
 
-		srcinfos[pkg.PackageBase] = pkgbuild
-	}
-}
-
-func pkgBuildsToSkip(pkgs []*rpc.Pkg, 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")
+		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 +796,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 +809,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(pkg, bases)))
+			fmt.Printf(str, downloaded, len(bases), cyan(base.String()))
 			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 +851,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(pkg, bases)))
+		fmt.Printf(str, downloaded, len(bases), cyan(base.String()))
 		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,41 +865,43 @@ 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(pkg, bases)))
+			return fmt.Errorf("Error downloading sources: %s", cyan(base.String()))
 		}
 	}
 
 	return
 }
 
-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)
+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)
 		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", base.String())
 		}
 
 		pkgdests, version, err := parsePackageList(dir)
@@ -891,8 +909,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 +933,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", base.String())
 			}
 		}
 
@@ -946,7 +968,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 +995,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 +1022,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)
 		}
@@ -1023,13 +1045,3 @@ 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)
-
-		fmt.Println(bold(green(arrow +
-			" CleanAfter enabled. Deleting " + pkg.Name + " source folder.")))
-		os.RemoveAll(dir)
-	}
-}

+ 15 - 18
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(pkg, bases) + " "
+		for _, base := range bases {
+			pkglist += base.String() + "  "
 		}
-		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

+ 10 - 8
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 (base Base) String() 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] + ")"
@@ -210,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++
@@ -235,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 {

+ 5 - 13
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,8 +25,6 @@ type shaInfo struct {
 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 {
@@ -39,17 +36,12 @@ func createDevelDB() error {
 		return err
 	}
 
-	for _, pkg := range info {
-		infoMap[pkg.Name] = pkg
-	}
-
-	bases := getBases(infoMap)
-
-	toSkip := pkgBuildsToSkip(info, sliceToStringSet(remoteNames))
-	downloadPkgBuilds(info, bases, toSkip)
-	tryParsesrcinfosFile(info, srcinfosStale, bases)
+	bases := getBases(info)
+	toSkip := pkgbuildsToSkip(bases, sliceToStringSet(remoteNames))
+	downloadPkgbuilds(bases, toSkip)
+	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)