From 4bcd3a6297052714e91e3f886602ce5c12d15786 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 19 Mar 2018 16:51:11 +0000 Subject: [PATCH 1/2] Handle pkgbuilds with an unsupported arch When pkgbuilds are built by makepkg, if the pkgbuild's arch=() array does not include the current carch set in makepkg.conf, makepkg will fail to build the package. Now, Yay detects if a pkgbuild does not support the arch set in pacman.conf Yay will ask the user about this and ask them if they want to build anyway, passing `--ignorearch` to makepkg.` Note that Yay will check against the arch set in pacman.conf which is what pacman uses to only allow installs of package of that arch. makepkg will still use carch set in makepkg.conf to build packages. These two values are expected to be the same otherwise Yay will fail. The on disk .srcinfo is needed for this as the user should be asked pre source download. This and pgp checking both use the on disk .srcinfo so it is no longer a one off. Store the 'stale' srcinfos so they can be accesed by both functions. --- install.go | 99 ++++++++++++++++++++++++++++++++++++++++++------------ keys.go | 12 +++---- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/install.go b/install.go index f2172351..1e36e93d 100644 --- a/install.go +++ b/install.go @@ -16,13 +16,15 @@ import ( // Install handles package installs func install(parser *arguments) error { - removeMake := false requestTargets := parser.targets.toSlice() aurTargets, repoTargets, err := packageSlices(requestTargets) if err != nil { return err } + var incompatable stringSet + removeMake := false + srcinfosStale := make(map[string]*gopkg.PKGBUILD) srcinfos := make(map[string]*gopkg.PKGBUILD) var dc *depCatagories @@ -200,26 +202,37 @@ func install(parser *arguments) error { uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg cmdArgs.globals["ask"] = fmt.Sprint(uask) - //this downloads the package build sources but also causes - //a version bumb for vsc packages - //that should not edit the sources so we should be safe to skip - //it and parse the srcinfo at the current version + //inital srcinfo parse before pkgver() bump + err = parsesrcinfosFile(dc.Aur, srcinfosStale, dc.Bases) + if err != nil { + return err + } + if arguments.existsArg("gendb") { - err = parsesrcinfosFile(dc.Aur, srcinfos, dc.Bases) - if err != nil { - return err + for _, pkg := range dc.Aur { + pkgbuild := srcinfosStale[pkg.PackageBase] + + for _, pkg := range dc.Bases[pkg.PackageBase] { + updateVCSData(pkg.Name, pkgbuild.Source) + } } fmt.Println(bold(green(arrow + " GenDB finished. No packages were installed"))) return nil } - err = checkPgpKeys(dc.Aur, dc.Bases) + incompatable, err = getIncompatable(dc.Aur, srcinfosStale, dc.Bases) if err != nil { return err } - err = downloadPkgBuildsSources(dc.Aur, dc.Bases) + + err = checkPgpKeys(dc.Aur, dc.Bases, srcinfosStale) + if err != nil { + return err + } + + err = downloadPkgBuildsSources(dc.Aur, dc.Bases, incompatable) if err != nil { return err } @@ -228,8 +241,8 @@ func install(parser *arguments) error { if err != nil { return err } - - err = buildInstallPkgBuilds(dc.Aur, srcinfos, parser.targets, parser, dc.Bases) + + err = buildInstallPkgBuilds(dc.Aur, srcinfos, parser.targets, parser, dc.Bases, incompatable) if err != nil { return err } @@ -266,6 +279,41 @@ func install(parser *arguments) error { return nil } +func getIncompatable(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bases map[string][]*rpc.Pkg) (stringSet, error) { + incompatable := make(stringSet) + alpmArch, err := alpmHandle.Arch() + if err != nil { + return nil, err + } + + nextpkg: + for _, pkg := range pkgs { + for _, arch := range srcinfos[pkg.PackageBase].Arch { + if arch == "any" || arch == alpmArch { + continue nextpkg + } + } + + incompatable.set(pkg.PackageBase) + } + + if len(incompatable) > 0 { + fmt.Print( + bold(green(("\nThe following packages are not compatable with your architecture:")))) + for pkg := range incompatable { + fmt.Print(" " + cyan(pkg)) + } + + fmt.Println() + + if !continueTask("Try to build them anyway?", "nN") { + return nil, fmt.Errorf("Aborting due to user") + } + } + + return incompatable, nil +} + func cleanEditNumberMenu(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, installed stringSet) ([]*rpc.Pkg, []*rpc.Pkg, error) { toPrint := "" askClean := false @@ -502,12 +550,7 @@ func parsesrcinfosFile(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, bas return fmt.Errorf("%s: %s", pkg.Name, err) } - srcinfos[pkg.PackageBase] = pkgbuild - - for _, pkg := range bases[pkg.PackageBase] { - updateVCSData(pkg.Name, pkgbuild.Source) - } - + srcinfos[pkg.PackageBase] = pkgbuild } return nil @@ -571,10 +614,16 @@ func downloadPkgBuilds(pkgs []*rpc.Pkg, targets stringSet, bases map[string][]*r return nil } -func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) (err error) { +func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, incompatable stringSet) (err error) { for _, pkg := range pkgs { dir := config.BuildDir + pkg.PackageBase + "/" - err = passToMakepkg(dir, "--nobuild", "--nocheck", "--noprepare", "--nodeps") + args := []string{"--nobuild", "--nocheck", "--noprepare", "--nodeps"} + + if incompatable.get(pkg.PackageBase) { + args = append(args, "--ignorearch") + } + + err = passToMakepkg(dir, args...) if err != nil { return fmt.Errorf("Error downloading sources: %s", formatPkgbase(pkg, bases)) } @@ -583,7 +632,7 @@ func downloadPkgBuildsSources(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) (err return } -func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, targets stringSet, parser *arguments, bases map[string][]*rpc.Pkg) error { +func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, targets stringSet, parser *arguments, bases map[string][]*rpc.Pkg, incompatable stringSet) error { alpmArch, err := alpmHandle.Arch() if err != nil { return err @@ -622,7 +671,13 @@ func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, fmt.Println(bold(red(arrow+" Warning:")), pkg.Name+"-"+pkg.Version+" Already made -- skipping build") } else { - err := passToMakepkg(dir, "-Ccf", "--noconfirm") + args := []string{"-Ccf", "--noconfirm"} + + if incompatable.get(pkg.PackageBase) { + args = append(args, "--ignorearch") + } + + err := passToMakepkg(dir, args...) if err != nil { return fmt.Errorf("Error making: %s", pkg.Name) } diff --git a/keys.go b/keys.go index dc600d0f..945e5e07 100644 --- a/keys.go +++ b/keys.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "os/exec" - "path" "strings" rpc "github.com/mikkeloscar/aur" @@ -42,7 +41,7 @@ func (set pgpKeySet) get(key string) bool { // checkPgpKeys iterates through the keys listed in the PKGBUILDs and if needed, // asks the user whether yay should try to import them. -func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { +func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) error { // Let's check the keys individually, and then we can offer to import // the problematic ones. problematic := make(pgpKeySet) @@ -50,13 +49,9 @@ func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { // Mapping all the keys. for _, pkg := range pkgs { - srcinfo := path.Join(config.BuildDir, pkg.PackageBase, ".SRCINFO") - pkgbuild, err := gopkg.ParseSRCINFO(srcinfo) - if err != nil { - return fmt.Errorf("%s: %s", pkg.Name, err) - } + srcinfo := srcinfos[pkg.PackageBase] - for _, key := range pkgbuild.Validpgpkeys { + for _, key := range srcinfo.Validpgpkeys { // If key already marked as problematic, indicate the current // PKGBUILD requires it. if problematic.get(key) { @@ -77,6 +72,7 @@ func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg) error { return nil } + fmt.Println() question, err := formatKeysToImport(problematic, bases) if err != nil { return err From 42fdd01d42627bb0bfaceeff6b865965efc3266c Mon Sep 17 00:00:00 2001 From: morganamilo Date: Mon, 19 Mar 2018 19:39:17 +0000 Subject: [PATCH 2/2] Update keys_tests.go --- keys_test.go | 63 ++++++++++------------------------------------------ 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/keys_test.go b/keys_test.go index 12fc6c05..078cdf29 100644 --- a/keys_test.go +++ b/keys_test.go @@ -1,11 +1,9 @@ package main import ( - "bytes" "fmt" "io/ioutil" "os" - "path" "testing" rpc "github.com/mikkeloscar/aur" @@ -20,31 +18,6 @@ func newSplitPkg(basename, name string) *rpc.Pkg { return &rpc.Pkg{Name: name, PackageBase: basename} } -func createSrcinfo(pkgbase, srcinfoData string) error { - dir := path.Join(config.BuildDir, pkgbase) - if err := os.Mkdir(dir, 0755); err != nil { - return err - } - - return ioutil.WriteFile(path.Join(dir, ".SRCINFO"), []byte(srcinfoData), 0666) -} - -func createDummyPkg(pkgbase string, keys []string, split []string) string { - var buffer bytes.Buffer - buffer.WriteString(fmt.Sprintf("pkgbase = %s\n\tpkgver = 42\n\tarch = x86_64\n", pkgbase)) - // Keys. - for _, k := range keys { - buffer.WriteString(fmt.Sprintf("validpgpkeys = %s\n", k)) - } - - buffer.WriteString(fmt.Sprintf("\npkgname = %s\n", pkgbase)) - - for _, s := range split { - buffer.WriteString(fmt.Sprintf("\npkgname = %s%s\n", pkgbase, s)) - } - return buffer.String() -} - func TestFormatKeysToImport(t *testing.T) { casetests := []struct { keySet pgpKeySet @@ -214,25 +187,6 @@ func TestCheckPgpKeys(t *testing.T) { config.GpgBin = "gpg" config.GpgFlags = fmt.Sprintf("--homedir %s", keyringDir) - // Creating the dummy package data used in the tests. - dummyData := map[string]string{ - "cower": createDummyPkg("cower", []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"}, nil), - "libc++": createDummyPkg("libc++", []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"}, []string{"abi", "experimental"}), - "dummy-1": createDummyPkg("dummy-1", []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}, nil), - "dummy-2": createDummyPkg("dummy-2", []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}, nil), - "dummy-3": createDummyPkg("dummy-3", []string{"11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"}, nil), - "dummy-4": createDummyPkg("dummy-4", []string{"11E521D646982372EB577A1F8F0871F202119294"}, nil), - "dummy-5": createDummyPkg("dummy-5", []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"}, nil), - "dummy-6": createDummyPkg("dummy-6", []string{"THIS-SHOULD-FAIL"}, nil), - "dummy-7": createDummyPkg("dummy-7", []string{"A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL"}, nil), - } - - for pkgbase, srcinfoData := range dummyData { - if err = createSrcinfo(pkgbase, srcinfoData); err != nil { - t.Fatalf("Unable to create dummy data for package %q: %v\n", pkgbase, err) - } - } - casetests := []struct { pkgs []*rpc.Pkg srcinfos map[string]*gopkg.PKGBUILD @@ -243,6 +197,7 @@ func TestCheckPgpKeys(t *testing.T) { // 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner. { pkgs: []*rpc.Pkg{newPkg("cower")}, + srcinfos: map[string]*gopkg.PKGBUILD{"cower": &gopkg.PKGBUILD{Pkgbase: "cower", Validpgpkeys: []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"}}}, bases: map[string][]*rpc.Pkg{"cower": {newPkg("cower")}}, wantError: false, }, @@ -251,6 +206,7 @@ func TestCheckPgpKeys(t *testing.T) { // B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg. { pkgs: []*rpc.Pkg{newPkg("libc++")}, + srcinfos: map[string]*gopkg.PKGBUILD{"libc++": &gopkg.PKGBUILD{Pkgbase: "libc++", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"}}}, bases: map[string][]*rpc.Pkg{"libc++": {newPkg("libc++")}}, wantError: false, }, @@ -258,6 +214,7 @@ func TestCheckPgpKeys(t *testing.T) { // ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds. { pkgs: []*rpc.Pkg{newPkg("dummy-1"), newPkg("dummy-2")}, + srcinfos: map[string]*gopkg.PKGBUILD{"dummy-1": &gopkg.PKGBUILD{Pkgbase: "dummy-1", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}, "dummy-2": &gopkg.PKGBUILD{Pkgbase: "dummy-2", Validpgpkeys: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"}}}, bases: map[string][]*rpc.Pkg{"dummy-1": {newPkg("dummy-1")}, "dummy-2": {newPkg("dummy-2")}}, wantError: false, }, @@ -267,32 +224,36 @@ func TestCheckPgpKeys(t *testing.T) { // C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey. { pkgs: []*rpc.Pkg{newPkg("dummy-3")}, + srcinfos: map[string]*gopkg.PKGBUILD{"dummy-3": &gopkg.PKGBUILD{Pkgbase: "dummy-3", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}}, bases: map[string][]*rpc.Pkg{"dummy-3": {newPkg("dummy-3")}}, wantError: false, }, // Two dummy packages with existing keys. { pkgs: []*rpc.Pkg{newPkg("dummy-4"), newPkg("dummy-5")}, + srcinfos: map[string]*gopkg.PKGBUILD{"dummy-4": &gopkg.PKGBUILD{Pkgbase: "dummy-4", Validpgpkeys: []string{"11E521D646982372EB577A1F8F0871F202119294"}}, "dummy-5": &gopkg.PKGBUILD{Pkgbase: "dummy-5", Validpgpkeys: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"}}}, bases: map[string][]*rpc.Pkg{"dummy-4": {newPkg("dummy-4")}, "dummy-5": {newPkg("dummy-5")}}, wantError: false, }, // Dummy package with invalid key, should fail. { - pkgs: []*rpc.Pkg{newPkg("dummy-6")}, - bases: map[string][]*rpc.Pkg{"dummy-6": {newPkg("dummy-6")}}, + pkgs: []*rpc.Pkg{newPkg("dummy-7")}, + srcinfos: map[string]*gopkg.PKGBUILD{"dummy-7": &gopkg.PKGBUILD{Pkgbase: "dummy-7", Validpgpkeys: []string{"THIS-SHOULD-FAIL"}}}, + bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}}, wantError: true, }, // Dummy package with both an invalid an another valid key, should fail. // A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler. { - pkgs: []*rpc.Pkg{newPkg("dummy-7")}, - bases: map[string][]*rpc.Pkg{"dummy-7": {newPkg("dummy-7")}}, + pkgs: []*rpc.Pkg{newPkg("dummy-8")}, + srcinfos: map[string]*gopkg.PKGBUILD{"dummy-8": &gopkg.PKGBUILD{Pkgbase: "dummy-8", Validpgpkeys: []string{"A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL"}}}, + bases: map[string][]*rpc.Pkg{"dummy-8": {newPkg("dummy-8")}}, wantError: true, }, } for _, tt := range casetests { - err := checkPgpKeys(tt.pkgs, tt.bases) + err := checkPgpKeys(tt.pkgs, tt.bases, tt.srcinfos) if !tt.wantError { if err != nil { t.Fatalf("Got error %q, want no error", err)