yay/keys.go
morganamilo 4bcd3a6297
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.
2018-03-19 19:24:51 +00:00

122 lines
3.2 KiB
Go

package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
rpc "github.com/mikkeloscar/aur"
gopkg "github.com/mikkeloscar/gopkgbuild"
)
// 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
func (set pgpKeySet) toSlice() []string {
slice := make([]string, 0, len(set))
for v := range set {
slice = append(slice, v)
}
return slice
}
func (set pgpKeySet) set(key string, p *rpc.Pkg) {
// 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)
}
func (set pgpKeySet) get(key string) bool {
upperKey := strings.ToUpper(key)
_, exists := set[upperKey]
return exists
}
// 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]*gopkg.PKGBUILD) 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 _, key := range srcinfo.Validpgpkeys {
// If key already marked as problematic, indicate the current
// PKGBUILD requires it.
if problematic.get(key) {
problematic.set(key, pkg)
continue
}
cmd := exec.Command(config.GpgBin, append(args, key)...)
err := cmd.Run()
if err != nil {
problematic.set(key, pkg)
}
}
}
// No key issues!
if len(problematic) == 0 {
return nil
}
fmt.Println()
question, err := formatKeysToImport(problematic, bases)
if err != nil {
return err
}
if continueTask(question, "nN") {
return importKeys(problematic.toSlice())
}
return nil
}
// importKeys tries to import the list of keys specified in its argument.
func importKeys(keys []string) error {
args := append(strings.Fields(config.GpgFlags), "--recv-keys")
cmd := exec.Command(config.GpgBin, append(args, keys...)...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
fmt.Printf("%s Importing keys with gpg...\n", bold(cyan("::")))
err := cmd.Run()
if err != nil {
return fmt.Errorf("%s Problem importing keys", bold(red(arrow+" Error:")))
}
return nil
}
// 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) {
if len(keys) == 0 {
return "", fmt.Errorf("%s No keys to import", bold(red(arrow+" Error:")))
}
var buffer bytes.Buffer
buffer.WriteString(bold(green(("GPG keys need importing:\n"))))
for key, pkgs := range keys {
pkglist := ""
for _, pkg := range pkgs {
pkglist += formatPkgbase(pkg, bases) + " "
}
pkglist = strings.TrimRight(pkglist, " ")
buffer.WriteString(fmt.Sprintf("\t%s, required by: %s\n", green(key), cyan(pkglist)))
}
buffer.WriteString(bold(green(fmt.Sprintf("%s Import?", arrow))))
return buffer.String(), nil
}