Merge pull request #637 from Morganamilo/refactorinstall2

Refactor install
This commit is contained in:
Anna 2018-08-18 17:08:34 +01:00 committed by GitHub
commit a37bbd851e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 230 additions and 214 deletions

16
dep.go
View File

@ -149,15 +149,15 @@ func splitDbFromName(pkg string) (string, string) {
return "", split[0] return "", split[0]
} }
func getBases(pkgs map[string]*rpc.Pkg) map[string][]*rpc.Pkg { func getBases(pkgs []*rpc.Pkg) []Base {
bases := make(map[string][]*rpc.Pkg) basesMap := make(map[string]Base)
for _, pkg := range pkgs { for _, pkg := range pkgs {
_, ok := bases[pkg.PackageBase] basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg)
if !ok { }
bases[pkg.PackageBase] = make([]*rpc.Pkg, 0)
} bases := make([]Base, 0, len(basesMap))
bases[pkg.PackageBase] = append(bases[pkg.PackageBase], pkg) for _, base := range basesMap {
bases = append(bases, base)
} }
return bases return bases

View File

@ -5,35 +5,48 @@ import (
rpc "github.com/mikkeloscar/aur" 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 { type depOrder struct {
Aur []*rpc.Pkg Aur []Base
Repo []*alpm.Package Repo []*alpm.Package
Runtime stringSet Runtime stringSet
Bases map[string][]*rpc.Pkg
} }
func makeDepOrder() *depOrder { func makeDepOrder() *depOrder {
return &depOrder{ return &depOrder{
make([]*rpc.Pkg, 0), make([]Base, 0),
make([]*alpm.Package, 0), make([]*alpm.Package, 0),
make(stringSet), make(stringSet),
make(map[string][]*rpc.Pkg),
} }
} }
func getDepOrder(dp *depPool) *depOrder { func getDepOrder(dp *depPool) *depOrder {
do := makeDepOrder() do := makeDepOrder()
basesMap := make(map[string]Base)
for _, target := range dp.Targets { for _, target := range dp.Targets {
dep := target.DepString() dep := target.DepString()
aurPkg := dp.Aur[dep] aurPkg := dp.Aur[dep]
if aurPkg != nil && pkgSatisfies(aurPkg.Name, aurPkg.Version, 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) aurPkg = dp.findSatisfierAur(dep)
if aurPkg != nil { if aurPkg != nil {
do.orderPkgAur(aurPkg, dp, true) do.orderPkgAur(aurPkg, dp, basesMap, true)
} }
repoPkg := dp.findSatisfierRepo(dep) 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 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 { if runtime {
do.Runtime.set(pkg.Name) do.Runtime.set(pkg.Name)
} }
@ -55,7 +72,7 @@ func (do *depOrder) orderPkgAur(pkg *rpc.Pkg, dp *depPool, runtime bool) {
for _, dep := range deps { for _, dep := range deps {
aurPkg := dp.findSatisfierAur(dep) aurPkg := dp.findSatisfierAur(dep)
if aurPkg != nil { if aurPkg != nil {
do.orderPkgAur(aurPkg, dp, runtime && i == 0) do.orderPkgAur(aurPkg, dp, basesMap, runtime && i == 0)
} }
repoPkg := dp.findSatisfierRepo(dep) 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 { basesMap[pkg.PackageBase] = append(basesMap[pkg.PackageBase], pkg)
do.Aur = append(do.Aur, pkg)
do.Bases[pkg.PackageBase] = make([]*rpc.Pkg, 0)
}
do.Bases[pkg.PackageBase] = append(do.Bases[pkg.PackageBase], pkg)
} }
func (do *depOrder) orderPkgRepo(pkg *alpm.Package, dp *depPool, runtime bool) { 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 { func (do *depOrder) HasMake() bool {
lenAur := 0 lenAur := 0
for _, base := range do.Bases { for _, base := range do.Aur {
lenAur += len(base) lenAur += len(base)
} }
@ -102,7 +115,7 @@ func (do *depOrder) HasMake() bool {
func (do *depOrder) getMake() []string { func (do *depOrder) getMake() []string {
makeOnly := make([]string, 0, len(do.Aur)+len(do.Repo)-len(do.Runtime)) 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 { for _, pkg := range base {
if !do.Runtime.get(pkg.Name) { if !do.Runtime.get(pkg.Name) {
makeOnly = append(makeOnly, pkg.Name) makeOnly = append(makeOnly, pkg.Name)

View File

@ -11,7 +11,6 @@ import (
gosrc "github.com/Morganamilo/go-srcinfo" gosrc "github.com/Morganamilo/go-srcinfo"
alpm "github.com/jguer/go-alpm" alpm "github.com/jguer/go-alpm"
rpc "github.com/mikkeloscar/aur"
) )
// Install handles package installs // Install handles package installs
@ -23,10 +22,10 @@ func install(parser *arguments) error {
var aurUp upSlice var aurUp upSlice
var repoUp upSlice var repoUp upSlice
warnings := &aurWarnings{} var srcinfos map[string]*gosrc.Srcinfo
warnings := &aurWarnings{}
removeMake := false removeMake := false
srcinfosStale := make(map[string]*gosrc.Srcinfo)
if mode == ModeAny || mode == ModeRepo { if mode == ModeAny || mode == ModeRepo {
if config.CombinedUpgrade { if config.CombinedUpgrade {
@ -94,7 +93,7 @@ func install(parser *arguments) error {
} }
for up := range aurUp { for up := range aurUp {
requestTargets = append(requestTargets, "aur/" + up) requestTargets = append(requestTargets, "aur/"+up)
parser.addTarget("aur/" + up) parser.addTarget("aur/" + up)
} }
@ -176,7 +175,7 @@ func install(parser *arguments) error {
} }
if config.CleanMenu { if config.CleanMenu {
askClean := pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) askClean := pkgbuildNumberMenu(do.Aur, remoteNamesCache)
toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean) toClean, err := cleanNumberMenu(do.Aur, remoteNamesCache, askClean)
if err != nil { if err != nil {
return err return err
@ -185,24 +184,24 @@ func install(parser *arguments) error {
cleanBuilds(toClean) cleanBuilds(toClean)
} }
toSkip := pkgBuildsToSkip(do.Aur, targets) toSkip := pkgbuildsToSkip(do.Aur, targets)
cloned, err := downloadPkgBuilds(do.Aur, do.Bases, toSkip) cloned, err := downloadPkgbuilds(do.Aur, toSkip)
if err != nil { if err != nil {
return err return err
} }
var toDiff []*rpc.Pkg var toDiff []Base
var toEdit []*rpc.Pkg var toEdit []Base
if config.DiffMenu { if config.DiffMenu {
pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) pkgbuildNumberMenu(do.Aur, remoteNamesCache)
toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache) toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache)
if err != nil { if err != nil {
return err return err
} }
if len(toDiff) > 0 { if len(toDiff) > 0 {
err = showPkgBuildDiffs(toDiff, do.Bases, cloned) err = showPkgbuildDiffs(toDiff, cloned)
if err != nil { if err != nil {
return err return err
} }
@ -219,26 +218,25 @@ func install(parser *arguments) error {
config.NoConfirm = oldValue config.NoConfirm = oldValue
} }
err = mergePkgBuilds(do.Aur) err = mergePkgbuilds(do.Aur)
if err != nil { if err != nil {
return err return err
} }
//initial srcinfo parse before pkgver() bump srcinfos, err = parseSrcinfoFiles(do.Aur, true)
err = parseSRCINFOFiles(do.Aur, srcinfosStale, do.Bases)
if err != nil { if err != nil {
return err return err
} }
if config.EditMenu { if config.EditMenu {
pkgbuildNumberMenu(do.Aur, do.Bases, remoteNamesCache) pkgbuildNumberMenu(do.Aur, remoteNamesCache)
toEdit, err = editNumberMenu(do.Aur, remoteNamesCache) toEdit, err = editNumberMenu(do.Aur, remoteNamesCache)
if err != nil { if err != nil {
return err return err
} }
if len(toEdit) > 0 { if len(toEdit) > 0 {
err = editPkgBuilds(toEdit, srcinfosStale) err = editPkgbuilds(toEdit, srcinfos)
if err != nil { if err != nil {
return err return err
} }
@ -255,13 +253,13 @@ func install(parser *arguments) error {
config.NoConfirm = oldValue config.NoConfirm = oldValue
} }
incompatible, err = getIncompatible(do.Aur, srcinfosStale) incompatible, err = getIncompatible(do.Aur, srcinfos)
if err != nil { if err != nil {
return err return err
} }
if config.PGPFetch { if config.PGPFetch {
err = checkPgpKeys(do.Aur, do.Bases, srcinfosStale) err = checkPgpKeys(do.Aur, srcinfos)
if err != nil { if err != nil {
return err return err
} }
@ -312,12 +310,12 @@ func install(parser *arguments) error {
go updateCompletion(false) go updateCompletion(false)
err = downloadPkgBuildsSources(do.Aur, do.Bases, incompatible) err = downloadPkgbuildsSources(do.Aur, incompatible)
if err != nil { if err != nil {
return err return err
} }
err = buildInstallPkgBuilds(dp, do, srcinfosStale, parser, incompatible, conflicts) err = buildInstallPkgbuilds(dp, do, srcinfos, parser, incompatible, conflicts)
if err != nil { if err != nil {
return err return err
} }
@ -341,7 +339,7 @@ func install(parser *arguments) error {
} }
if config.CleanAfter { if config.CleanAfter {
clean(do.Aur) cleanBuilds(do.Aur)
} }
return nil return nil
@ -416,29 +414,31 @@ func earlyRefresh(parser *arguments) error {
return show(passToPacman(arguments)) 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) incompatible := make(stringSet)
basesMap := make(map[string]Base)
alpmArch, err := alpmHandle.Arch() alpmArch, err := alpmHandle.Arch()
if err != nil { if err != nil {
return nil, err return nil, err
} }
nextpkg: nextpkg:
for _, pkg := range pkgs { for _, base := range bases {
for _, arch := range srcinfos[pkg.PackageBase].Arch { for _, arch := range srcinfos[base.Pkgbase()].Arch {
if arch == "any" || arch == alpmArch { if arch == "any" || arch == alpmArch {
continue nextpkg continue nextpkg
} }
} }
incompatible.set(pkg.PackageBase) incompatible.set(base.Pkgbase())
basesMap[base.Pkgbase()] = base
} }
if len(incompatible) > 0 { if len(incompatible) > 0 {
fmt.Println() fmt.Println()
fmt.Print(bold(yellow(arrow)) + " The following packages are not compatible with your architecture:") fmt.Print(bold(yellow(arrow)) + " The following packages are not compatible with your architecture:")
for pkg := range incompatible { for pkg := range incompatible {
fmt.Print(" " + cyan(pkg)) fmt.Print(" " + cyan((basesMap[pkg].String())))
} }
fmt.Println() fmt.Println()
@ -485,16 +485,23 @@ func parsePackageList(dir string) (map[string]string, string, error) {
return pkgdests, version, nil 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 := "" toPrint := ""
askClean := false askClean := false
for n, pkg := range pkgs { for n, base := range bases {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(pkgs)-n, toPrint += fmt.Sprintf(magenta("%3d")+" %-40s", len(bases)-n,
bold(formatPkgbase(pkg, bases))) bold(base.String()))
if installed.get(pkg.Name) {
anyInstalled := false
for _, b := range base {
anyInstalled = anyInstalled || installed.get(b.Name)
}
if anyInstalled {
toPrint += bold(green(" (Installed)")) toPrint += bold(green(" (Installed)"))
} }
@ -511,8 +518,8 @@ func pkgbuildNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed
return askClean return askClean
} }
func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rpc.Pkg, error) { func cleanNumberMenu(bases []Base, installed stringSet, hasClean bool) ([]Base, error) {
toClean := make([]*rpc.Pkg, 0) toClean := make([]Base, 0)
if !hasClean { if !hasClean {
return toClean, nil return toClean, nil
@ -534,38 +541,44 @@ func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rp
} }
if !cOtherInclude.get("n") && !cOtherInclude.get("none") { if !cOtherInclude.get("n") && !cOtherInclude.get("none") {
for i, pkg := range pkgs { for i, base := range bases {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) 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) { if _, err := os.Stat(dir); os.IsNotExist(err) {
continue continue
} }
if !cIsInclude && cExclude.get(len(pkgs)-i) { if !cIsInclude && cExclude.get(len(bases)-i) {
continue continue
} }
if installed.get(pkg.Name) && (cOtherInclude.get("i") || cOtherInclude.get("installed")) { if anyInstalled && (cOtherInclude.get("i") || cOtherInclude.get("installed")) {
toClean = append(toClean, pkg) toClean = append(toClean, base)
continue continue
} }
if !installed.get(pkg.Name) && (cOtherInclude.get("no") || cOtherInclude.get("notinstalled")) { if !anyInstalled && (cOtherInclude.get("no") || cOtherInclude.get("notinstalled")) {
toClean = append(toClean, pkg) toClean = append(toClean, base)
continue continue
} }
if cOtherInclude.get("a") || cOtherInclude.get("all") { if cOtherInclude.get("a") || cOtherInclude.get("all") {
toClean = append(toClean, pkg) toClean = append(toClean, base)
continue continue
} }
if cIsInclude && (cInclude.get(len(pkgs)-i) || cOtherInclude.get(pkg.PackageBase)) { if cIsInclude && (cInclude.get(len(bases)-i) || cOtherInclude.get(pkg)) {
toClean = append(toClean, pkg) toClean = append(toClean, base)
continue continue
} }
if !cIsInclude && (!cExclude.get(len(pkgs)-i) && !cOtherExclude.get(pkg.PackageBase)) { if !cIsInclude && (!cExclude.get(len(bases)-i) && !cOtherExclude.get(pkg)) {
toClean = append(toClean, pkg) toClean = append(toClean, base)
continue continue
} }
} }
@ -574,16 +587,16 @@ func cleanNumberMenu(pkgs []*rpc.Pkg, installed stringSet, hasClean bool) ([]*rp
return toClean, nil return toClean, nil
} }
func editNumberMenu(pkgs []*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { func editNumberMenu(bases []Base, installed stringSet) ([]Base, error) {
return editDiffNumberMenu(pkgs, installed, false) return editDiffNumberMenu(bases, installed, false)
} }
func diffNumberMenu(pkgs []*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, error) { func diffNumberMenu(bases []Base, installed stringSet) ([]Base, error) {
return editDiffNumberMenu(pkgs, installed, true) return editDiffNumberMenu(bases, installed, true)
} }
func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc.Pkg, error) { func editDiffNumberMenu(bases []Base, installed stringSet, diff bool) ([]Base, error) {
toEdit := make([]*rpc.Pkg, 0) toEdit := make([]Base, 0)
var editInput string var editInput string
var err error var err error
@ -613,32 +626,38 @@ func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc
} }
if !eOtherInclude.get("n") && !eOtherInclude.get("none") { if !eOtherInclude.get("n") && !eOtherInclude.get("none") {
for i, pkg := range pkgs { for i, base := range bases {
if !eIsInclude && eExclude.get(len(pkgs)-i) { pkg := base.Pkgbase()
anyInstalled := false
for _, b := range base {
anyInstalled = anyInstalled || installed.get(b.Name)
}
if !eIsInclude && eExclude.get(len(bases)-i) {
continue continue
} }
if installed.get(pkg.Name) && (eOtherInclude.get("i") || eOtherInclude.get("installed")) { if anyInstalled && (eOtherInclude.get("i") || eOtherInclude.get("installed")) {
toEdit = append(toEdit, pkg) toEdit = append(toEdit, base)
continue continue
} }
if !installed.get(pkg.Name) && (eOtherInclude.get("no") || eOtherInclude.get("notinstalled")) { if !anyInstalled && (eOtherInclude.get("no") || eOtherInclude.get("notinstalled")) {
toEdit = append(toEdit, pkg) toEdit = append(toEdit, base)
continue continue
} }
if eOtherInclude.get("a") || eOtherInclude.get("all") { if eOtherInclude.get("a") || eOtherInclude.get("all") {
toEdit = append(toEdit, pkg) toEdit = append(toEdit, base)
continue continue
} }
if eIsInclude && (eInclude.get(len(pkgs)-i) || eOtherInclude.get(pkg.PackageBase)) { if eIsInclude && (eInclude.get(len(bases)-i) || eOtherInclude.get(pkg)) {
toEdit = append(toEdit, pkg) toEdit = append(toEdit, base)
} }
if !eIsInclude && (!eExclude.get(len(pkgs)-i) && !eOtherExclude.get(pkg.PackageBase)) { if !eIsInclude && (!eExclude.get(len(bases)-i) && !eOtherExclude.get(pkg)) {
toEdit = append(toEdit, pkg) toEdit = append(toEdit, base)
} }
} }
} }
@ -646,30 +665,31 @@ func editDiffNumberMenu(pkgs []*rpc.Pkg, installed stringSet, diff bool) ([]*rpc
return toEdit, nil return toEdit, nil
} }
func cleanBuilds(pkgs []*rpc.Pkg) { func cleanBuilds(bases []Base) {
for i, pkg := range pkgs { for i, base := range bases {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) dir := filepath.Join(config.BuildDir, base.Pkgbase())
fmt.Printf(bold(cyan("::")+" Deleting (%d/%d): %s\n"), i+1, len(pkgs), cyan(dir)) fmt.Printf(bold(cyan("::")+" Deleting (%d/%d): %s\n"), i+1, len(bases), cyan(dir))
os.RemoveAll(dir) os.RemoveAll(dir)
} }
} }
func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stringSet) error { func showPkgbuildDiffs(bases []Base, cloned stringSet) error {
for _, pkg := range pkgs { for _, base := range bases {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
if shouldUseGit(dir) { if shouldUseGit(dir) {
start := "HEAD" start := "HEAD"
if cloned.get(pkg.PackageBase) { if cloned.get(pkg) {
start = gitEmptyTree start = gitEmptyTree
} else { } else {
hasDiff, err := gitHasDiff(config.BuildDir, pkg.PackageBase) hasDiff, err := gitHasDiff(config.BuildDir, pkg)
if err != nil { if err != nil {
return err return err
} }
if !hasDiff { 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 continue
} }
} }
@ -700,13 +720,14 @@ func showPkgBuildDiffs(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, cloned stri
return nil return nil
} }
func editPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo) error { func editPkgbuilds(bases []Base, srcinfos map[string]*gosrc.Srcinfo) error {
pkgbuilds := make([]string, 0, len(pkgs)) pkgbuilds := make([]string, 0, len(bases))
for _, pkg := range pkgs { for _, base := range bases {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD")) pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD"))
for _, splitPkg := range srcinfos[pkg.PackageBase].SplitPackages() { for _, splitPkg := range srcinfos[pkg].SplitPackages() {
if splitPkg.Install != "" { if splitPkg.Install != "" {
pkgbuilds = append(pkgbuilds, filepath.Join(dir, 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 return nil
} }
func parseSRCINFOFiles(pkgs []*rpc.Pkg, srcinfos map[string]*gosrc.Srcinfo, bases map[string][]*rpc.Pkg) error { func parseSrcinfoFiles(bases []Base, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) {
for k, pkg := range pkgs { srcinfos := make(map[string]*gosrc.Srcinfo)
dir := filepath.Join(config.BuildDir, pkg.PackageBase) for k, base := range bases {
pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n") 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")) pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO"))
if err != nil { 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) { func pkgbuildsToSkip(bases []Base, targets stringSet) stringSet {
for k, pkg := range pkgs {
dir := filepath.Join(config.BuildDir, pkg.PackageBase)
str := bold(cyan("::") + " Parsing SRCINFO (%d/%d): %s\n")
fmt.Printf(str, k+1, len(pkgs), cyan(formatPkgbase(pkg, bases)))
pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO"))
if err != nil {
fmt.Printf("cannot parse %s skipping: %s\n", pkg.Name, err)
continue
}
srcinfos[pkg.PackageBase] = pkgbuild
}
}
func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet {
toSkip := make(stringSet) toSkip := make(stringSet)
for _, pkg := range pkgs { for _, base := range bases {
if config.ReDownload == "no" || (config.ReDownload == "yes" && !targets.get(pkg.Name)) { isTarget := false
dir := filepath.Join(config.BuildDir, pkg.PackageBase, ".SRCINFO") for _, pkg := range base {
isTarget = isTarget || targets.get(pkg.Name)
}
if config.ReDownload == "no" || (config.ReDownload == "yes" && isTarget) {
dir := filepath.Join(config.BuildDir, base.Pkgbase(), ".SRCINFO")
pkgbuild, err := gosrc.ParseFile(dir) pkgbuild, err := gosrc.ParseFile(dir)
if err == nil { if err == nil {
if alpm.VerCmp(pkgbuild.Version(), pkg.Version) >= 0 { if alpm.VerCmp(pkgbuild.Version(), base.Version()) >= 0 {
toSkip.set(pkg.PackageBase) toSkip.set(base.Pkgbase())
} }
} }
} }
@ -781,10 +796,10 @@ func pkgBuildsToSkip(pkgs []*rpc.Pkg, targets stringSet) stringSet {
return toSkip return toSkip
} }
func mergePkgBuilds(pkgs []*rpc.Pkg) error { func mergePkgbuilds(bases []Base) error {
for _, pkg := range pkgs { for _, base := range bases {
if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { if shouldUseGit(filepath.Join(config.BuildDir, base.Pkgbase())) {
err := gitMerge(config.BuildDir, pkg.PackageBase) err := gitMerge(config.BuildDir, base.Pkgbase())
if err != nil { if err != nil {
return err return err
} }
@ -794,38 +809,39 @@ func mergePkgBuilds(pkgs []*rpc.Pkg) error {
return nil 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) cloned := make(stringSet)
downloaded := 0 downloaded := 0
var wg sync.WaitGroup var wg sync.WaitGroup
var mux sync.Mutex var mux sync.Mutex
var errs MultiError var errs MultiError
download := func(k int, pkg *rpc.Pkg) { download := func(k int, base Base) {
defer wg.Done() defer wg.Done()
pkg := base.Pkgbase()
if toSkip.get(pkg.PackageBase) { if toSkip.get(pkg) {
mux.Lock() mux.Lock()
downloaded++ downloaded++
str := bold(cyan("::") + " PKGBUILD up to date, Skipping (%d/%d): %s\n") 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() mux.Unlock()
return return
} }
if shouldUseGit(filepath.Join(config.BuildDir, pkg.PackageBase)) { if shouldUseGit(filepath.Join(config.BuildDir, pkg)) {
clone, err := gitDownload(baseURL+"/"+pkg.PackageBase+".git", config.BuildDir, pkg.PackageBase) clone, err := gitDownload(baseURL+"/"+pkg+".git", config.BuildDir, pkg)
if err != nil { if err != nil {
errs.Add(err) errs.Add(err)
return return
} }
if clone { if clone {
mux.Lock() mux.Lock()
cloned.set(pkg.PackageBase) cloned.set(pkg)
mux.Unlock() mux.Unlock()
} }
} else { } else {
err := downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir) err := downloadAndUnpack(baseURL+base.URLPath(), config.BuildDir)
if err != nil { if err != nil {
errs.Add(err) errs.Add(err)
return return
@ -835,13 +851,13 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri
mux.Lock() mux.Lock()
downloaded++ downloaded++
str := bold(cyan("::") + " Downloaded PKGBUILD (%d/%d): %s\n") 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() mux.Unlock()
} }
for k, pkg := range pkgs { for k, base := range bases {
wg.Add(1) wg.Add(1)
go download(k, pkg) go download(k, base)
} }
wg.Wait() wg.Wait()
@ -849,41 +865,43 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, toSkip stri
return cloned, errs.Return() return cloned, errs.Return()
} }
func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatible stringSet) (err error) { func downloadPkgbuildsSources(bases []Base, incompatible stringSet) (err error) {
for _, pkg := range pkgs { for _, base := range bases {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
args := []string{"--verifysource", "-Ccf"} args := []string{"--verifysource", "-Ccf"}
if incompatible.get(pkg.PackageBase) { if incompatible.get(pkg) {
args = append(args, "--ignorearch") args = append(args, "--ignorearch")
} }
err = show(passToMakepkg(dir, args...)) err = show(passToMakepkg(dir, args...))
if err != nil { 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 return
} }
func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error { func buildInstallPkgbuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc.Srcinfo, parser *arguments, incompatible stringSet, conflicts mapStringSet) error {
for _, pkg := range do.Aur { for _, base := range do.Aur {
dir := filepath.Join(config.BuildDir, pkg.PackageBase) pkg := base.Pkgbase()
dir := filepath.Join(config.BuildDir, pkg)
built := true built := true
srcinfo := srcinfos[pkg.PackageBase] srcinfo := srcinfos[pkg]
args := []string{"--nobuild", "-fC"} args := []string{"--nobuild", "-fC"}
if incompatible.get(pkg.PackageBase) { if incompatible.get(pkg) {
args = append(args, "--ignorearch") args = append(args, "--ignorearch")
} }
//pkgver bump //pkgver bump
err := show(passToMakepkg(dir, args...)) err := show(passToMakepkg(dir, args...))
if err != nil { if err != nil {
return fmt.Errorf("Error making: %s", pkg.Name) return fmt.Errorf("Error making: %s", base.String())
} }
pkgdests, version, err := parsePackageList(dir) pkgdests, version, err := parsePackageList(dir)
@ -891,8 +909,12 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
return err return err
} }
if config.ReBuild == "no" || (config.ReBuild == "yes" && !dp.Explicit.get(pkg.Name)) { isExplicit := false
for _, split := range do.Bases[pkg.PackageBase] { 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] pkgdest, ok := pkgdests[split.Name]
if !ok { if !ok {
return fmt.Errorf("Could not find PKGDEST for: %s", split.Name) 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 { if built {
fmt.Println(bold(yellow(arrow)), fmt.Println(bold(yellow(arrow)),
cyan(pkg.Name+"-"+version)+bold(" Already made -- skipping build")) cyan(pkg+"-"+version)+bold(" Already made -- skipping build"))
} else { } else {
args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
if incompatible.get(pkg.PackageBase) { if incompatible.get(pkg) {
args = append(args, "--ignorearch") args = append(args, "--ignorearch")
} }
err := show(passToMakepkg(dir, args...)) err := show(passToMakepkg(dir, args...))
if err != nil { 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) cmdArgs.globals["ask"] = fmt.Sprint(uask)
} else { } else {
conflict := false conflict := false
for _, split := range do.Bases[pkg.PackageBase] { for _, split := range base {
if _, ok := conflicts[split.Name]; ok { if _, ok := conflicts[split.Name]; ok {
conflict = true conflict = true
} }
@ -973,7 +995,7 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
remoteNamesCache := sliceToStringSet(remoteNames) remoteNamesCache := sliceToStringSet(remoteNames)
localNamesCache := sliceToStringSet(localNames) localNamesCache := sliceToStringSet(localNames)
for _, split := range do.Bases[pkg.PackageBase] { for _, split := range base {
pkgdest, ok := pkgdests[split.Name] pkgdest, ok := pkgdests[split.Name]
if !ok { if !ok {
return fmt.Errorf("Could not find PKGDEST for: %s", split.Name) 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 mux sync.Mutex
var wg sync.WaitGroup var wg sync.WaitGroup
for _, pkg := range do.Bases[pkg.PackageBase] { for _, pkg := range base {
wg.Add(1) wg.Add(1)
go updateVCSData(pkg.Name, srcinfo.Source, &mux, &wg) go updateVCSData(pkg.Name, srcinfo.Source, &mux, &wg)
} }
@ -1023,13 +1045,3 @@ func buildInstallPkgBuilds(dp *depPool, do *depOrder, srcinfos map[string]*gosrc
return nil 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)
}
}

33
keys.go
View File

@ -8,12 +8,11 @@ import (
"strings" "strings"
gosrc "github.com/Morganamilo/go-srcinfo" gosrc "github.com/Morganamilo/go-srcinfo"
rpc "github.com/mikkeloscar/aur"
) )
// pgpKeySet maps a PGP key with a list of PKGBUILDs that require it. // pgpKeySet maps a PGP key with a list of PKGBUILDs that require it.
// This is similar to stringSet, used throughout the code. // 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 { func (set pgpKeySet) toSlice() []string {
slice := make([]string, 0, len(set)) slice := make([]string, 0, len(set))
@ -23,14 +22,11 @@ func (set pgpKeySet) toSlice() []string {
return slice 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 // Using ToUpper to make sure keys with a different case will be
// considered the same. // considered the same.
upperKey := strings.ToUpper(key) upperKey := strings.ToUpper(key)
if _, exists := set[upperKey]; !exists { set[key] = append(set[upperKey], p)
set[upperKey] = []*rpc.Pkg{}
}
set[key] = append(set[key], p)
} }
func (set pgpKeySet) get(key string) bool { 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, // checkPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,
// asks the user whether yay should try to import them. // 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 // Let's check the keys individually, and then we can offer to import
// the problematic ones. // the problematic ones.
problematic := make(pgpKeySet) problematic := make(pgpKeySet)
args := append(strings.Fields(config.GpgFlags), "--list-keys") args := append(strings.Fields(config.GpgFlags), "--list-keys")
// Mapping all the keys. // Mapping all the keys.
for _, pkg := range pkgs { for _, base := range bases {
srcinfo := srcinfos[pkg.PackageBase] pkg := base.Pkgbase()
srcinfo := srcinfos[pkg]
for _, key := range srcinfo.ValidPGPKeys { for _, key := range srcinfo.ValidPGPKeys {
// If key already marked as problematic, indicate the current // If key already marked as problematic, indicate the current
// PKGBUILD requires it. // PKGBUILD requires it.
if problematic.get(key) { if problematic.get(key) {
problematic.set(key, pkg) problematic.set(key, base)
continue continue
} }
cmd := exec.Command(config.GpgBin, append(args, key)...) cmd := exec.Command(config.GpgBin, append(args, key)...)
err := cmd.Run() err := cmd.Run()
if err != nil { 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 return nil
} }
str, err := formatKeysToImport(problematic, bases) str, err := formatKeysToImport(problematic)
if err != nil { if err != nil {
return err return err
} }
@ -104,7 +101,7 @@ func importKeys(keys []string) error {
// formatKeysToImport receives a set of keys and returns a string containing the // formatKeysToImport receives a set of keys and returns a string containing the
// question asking the user wants to import the problematic keys. // 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 { if len(keys) == 0 {
return "", fmt.Errorf("%s No keys to import", bold(red(arrow+" Error:"))) 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 var buffer bytes.Buffer
buffer.WriteString(bold(green(arrow))) buffer.WriteString(bold(green(arrow)))
buffer.WriteString(bold(green(" PGP keys need importing:"))) buffer.WriteString(bold(green(" PGP keys need importing:")))
for key, pkgs := range keys { for key, bases := range keys {
pkglist := "" pkglist := ""
for _, pkg := range pkgs { for _, base := range bases {
pkglist += formatPkgbase(pkg, 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))) buffer.WriteString(fmt.Sprintf("\n%s %s, required by: %s", yellow(bold(smallArrow)), cyan(key), cyan(pkglist)))
} }
return buffer.String(), nil return buffer.String(), nil

View File

@ -143,11 +143,12 @@ func (s repoQuery) printSearch() {
// Pretty print a set of packages from the same package base. // Pretty print a set of packages from the same package base.
// Packages foo and bar from a pkgbase named base would print like so: // Packages foo and bar from a pkgbase named base would print like so:
// base (foo bar) // 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 str := pkg.PackageBase
if len(bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name { if len(base) > 1 || pkg.PackageBase != pkg.Name {
str2 := " (" str2 := " ("
for _, split := range bases[pkg.PackageBase] { for _, split := range base {
str2 += split.Name + " " str2 += split.Name + " "
} }
str2 = str2[:len(str2)-1] + ")" str2 = str2[:len(str2)-1] + ")"
@ -210,18 +211,19 @@ func (do *depOrder) Print() {
} }
} }
for _, pkg := range do.Aur { for _, base := range do.Aur {
pkgStr := " " + pkg.PackageBase + "-" + pkg.Version pkg := base.Pkgbase()
pkgStr := " " + pkg + "-" + base[0].Version
pkgStrMake := pkgStr pkgStrMake := pkgStr
push := false push := false
pushMake := false pushMake := false
if len(do.Bases[pkg.PackageBase]) > 1 || pkg.PackageBase != pkg.Name { if len(base) > 1 || pkg != base[0].Name {
pkgStr += " (" pkgStr += " ("
pkgStrMake += " (" pkgStrMake += " ("
for _, split := range do.Bases[pkg.PackageBase] { for _, split := range base {
if do.Runtime.get(split.Name) { if do.Runtime.get(split.Name) {
pkgStr += split.Name + " " pkgStr += split.Name + " "
aurLen++ aurLen++
@ -235,7 +237,7 @@ func (do *depOrder) Print() {
pkgStr = pkgStr[:len(pkgStr)-1] + ")" pkgStr = pkgStr[:len(pkgStr)-1] + ")"
pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")" pkgStrMake = pkgStrMake[:len(pkgStrMake)-1] + ")"
} else if do.Runtime.get(pkg.Name) { } else if do.Runtime.get(base[0].Name) {
aurLen++ aurLen++
push = true push = true
} else { } else {

18
vcs.go
View File

@ -10,7 +10,6 @@ import (
"time" "time"
gosrc "github.com/Morganamilo/go-srcinfo" gosrc "github.com/Morganamilo/go-srcinfo"
rpc "github.com/mikkeloscar/aur"
) )
// Info contains the last commit sha of a repo // Info contains the last commit sha of a repo
@ -26,8 +25,6 @@ type shaInfo struct {
func createDevelDB() error { func createDevelDB() error {
var mux sync.Mutex var mux sync.Mutex
var wg sync.WaitGroup var wg sync.WaitGroup
infoMap := make(map[string]*rpc.Pkg)
srcinfosStale := make(map[string]*gosrc.Srcinfo)
_, _, _, remoteNames, err := filterPackages() _, _, _, remoteNames, err := filterPackages()
if err != nil { if err != nil {
@ -39,17 +36,12 @@ func createDevelDB() error {
return err return err
} }
for _, pkg := range info { bases := getBases(info)
infoMap[pkg.Name] = pkg toSkip := pkgbuildsToSkip(bases, sliceToStringSet(remoteNames))
} downloadPkgbuilds(bases, toSkip)
srcinfos, _ := parseSrcinfoFiles(bases, false)
bases := getBases(infoMap) for _, pkgbuild := range srcinfos {
toSkip := pkgBuildsToSkip(info, sliceToStringSet(remoteNames))
downloadPkgBuilds(info, bases, toSkip)
tryParsesrcinfosFile(info, srcinfosStale, bases)
for _, pkgbuild := range srcinfosStale {
for _, pkg := range pkgbuild.Packages { for _, pkg := range pkgbuild.Packages {
wg.Add(1) wg.Add(1)
go updateVCSData(pkg.Pkgname, pkgbuild.Source, &mux, &wg) go updateVCSData(pkg.Pkgname, pkgbuild.Source, &mux, &wg)