mirror of
https://github.com/Jguer/yay.git
synced 2025-08-14 10:37:09 +02:00
With the addition of pgp key checking in Yay, the srcinfo parsing was moved to before the pkgver() bump, leading to outdated pkgbuild information. Srcinfo parsing must be done after the pkgver() bump The pkgver() bump must be done after downloading sources makepkg's PGP checking is done as the sources download yays PGP importing requires the srcingo to be parsed Quite the chicken and egg problem It is possible to skip the integ checks after the sources download then parse the srcinfo do the yay PGP check then run the integ checks the problem here is that to generate the srcinfo `makepkg --printsrcingo` is ran This causes the pkgbuild to be sourced which I am not comftable with doing without the integ checks. Instead we parse the on disk .SRRCINFO that downloads with the PKGBUILD just for the PGP checking. Later on we parse a fresh srcinfo straight from `makepkg --printsrcingo`. This is a little bit less efficient but more secure than the other option.
128 lines
3.5 KiB
Go
128 lines
3.5 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. gpgExtraArgs are extra
|
|
// parameters to pass to gpg, in order to facilitate testing, such as using a
|
|
// different keyring. It can be nil.
|
|
func checkPgpKeys(pkgs []*rpc.Pkg, bases map[string][]*rpc.Pkg, gpgExtraArgs []string) error {
|
|
// Let's check the keys individually, and then we can offer to import
|
|
// the problematic ones.
|
|
problematic := make(pgpKeySet)
|
|
args := append(gpgExtraArgs, "--list-keys")
|
|
|
|
// Mapping all the keys.
|
|
for _, pkg := range pkgs {
|
|
dir := config.BuildDir + pkg.PackageBase + "/"
|
|
pkgbuild, err := gopkg.ParseSRCINFO(dir + ".SRCINFO")
|
|
if err != nil {
|
|
return fmt.Errorf("%s: %s", pkg.Name, err)
|
|
}
|
|
|
|
for _, key := range pkgbuild.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
|
|
}
|
|
|
|
question, err := formatKeysToImport(problematic, bases)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if continueTask(question, "nN") {
|
|
return importKeys(gpgExtraArgs, problematic.toSlice())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// importKeys tries to import the list of keys specified in its argument. As
|
|
// in checkGpgKeys, gpgExtraArgs are extra parameters to pass to gpg.
|
|
func importKeys(gpgExtraArgs, keys []string) error {
|
|
args := append(gpgExtraArgs, "--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
|
|
}
|