mirror of
https://github.com/Jguer/yay
synced 2024-10-01 13:53:32 +00:00
parent
6ad63cae10
commit
9f67d10d5c
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
"github.com/Jguer/yay/v11/pkg/dep"
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"github.com/Jguer/yay/v11/pkg/settings/parser"
|
||||
"github.com/Jguer/yay/v11/pkg/text"
|
||||
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
mapset "github.com/deckarep/golang-set/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
@ -48,10 +50,11 @@ func (installer *Installer) Install(ctx context.Context,
|
|||
cmdArgs *parser.Arguments,
|
||||
targets []map[string]*dep.InstallInfo,
|
||||
pkgBuildDirs map[string]string,
|
||||
srcinfos map[string]*gosrc.Srcinfo,
|
||||
) error {
|
||||
// Reorganize targets into layers of dependencies
|
||||
for i := len(targets) - 1; i >= 0; i-- {
|
||||
err := installer.handleLayer(ctx, cmdArgs, targets[i], pkgBuildDirs)
|
||||
err := installer.handleLayer(ctx, cmdArgs, targets[i], pkgBuildDirs, srcinfos)
|
||||
if err != nil {
|
||||
// rollback
|
||||
return err
|
||||
|
@ -62,7 +65,10 @@ func (installer *Installer) Install(ctx context.Context,
|
|||
}
|
||||
|
||||
func (installer *Installer) handleLayer(ctx context.Context,
|
||||
cmdArgs *parser.Arguments, layer map[string]*dep.InstallInfo, pkgBuildDirs map[string]string,
|
||||
cmdArgs *parser.Arguments,
|
||||
layer map[string]*dep.InstallInfo,
|
||||
pkgBuildDirs map[string]string,
|
||||
srcinfos map[string]*gosrc.Srcinfo,
|
||||
) error {
|
||||
// Install layer
|
||||
nameToBaseMap := make(map[string]string, 0)
|
||||
|
@ -107,7 +113,8 @@ func (installer *Installer) handleLayer(ctx context.Context,
|
|||
return ErrInstallRepoPkgs
|
||||
}
|
||||
|
||||
errAur := installer.installAURPackages(ctx, cmdArgs, aurDeps, aurExp, nameToBaseMap, pkgBuildDirs, false)
|
||||
errAur := installer.installAURPackages(ctx, cmdArgs, aurDeps, aurExp,
|
||||
nameToBaseMap, pkgBuildDirs, true, srcinfos)
|
||||
|
||||
return errAur
|
||||
}
|
||||
|
@ -117,11 +124,22 @@ func (installer *Installer) installAURPackages(ctx context.Context,
|
|||
aurDepNames, aurExpNames mapset.Set[string],
|
||||
nameToBase, pkgBuildDirsByBase map[string]string,
|
||||
installIncompatible bool,
|
||||
srcinfos map[string]*gosrc.Srcinfo,
|
||||
) error {
|
||||
all := aurDepNames.Union(aurExpNames).ToSlice()
|
||||
if len(all) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
deps, exps := make([]string, 0, aurDepNames.Cardinality()), make([]string, 0, aurExpNames.Cardinality())
|
||||
pkgArchives := make([]string, 0, len(exps)+len(deps))
|
||||
|
||||
for _, name := range aurDepNames.Union(aurExpNames).ToSlice() {
|
||||
var (
|
||||
mux sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
|
||||
for _, name := range all {
|
||||
base := nameToBase[name]
|
||||
dir := pkgBuildDirsByBase[base]
|
||||
args := []string{"--nobuild", "-fC"}
|
||||
|
@ -169,8 +187,14 @@ func (installer *Installer) installAURPackages(ctx context.Context,
|
|||
if hasDebug {
|
||||
deps = append(deps, name+"-debug")
|
||||
}
|
||||
|
||||
srcinfo := srcinfos[base]
|
||||
wg.Add(1)
|
||||
go config.Runtime.VCSStore.Update(ctx, name, srcinfo.Source, &mux, &wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if err := installPkgArchive(ctx, cmdArgs, pkgArchives); err != nil {
|
||||
return fmt.Errorf("%s - %w", fmt.Sprintf(gotext.Get("error installing:")+" %v", pkgArchives), err)
|
||||
}
|
||||
|
|
85
install.go
85
install.go
|
@ -75,7 +75,6 @@ func asexp(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string) error
|
|||
// Install handles package installs.
|
||||
func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor, ignoreProviders bool) error {
|
||||
var (
|
||||
incompatible stringset.StringSet
|
||||
do *dep.Order
|
||||
srcinfos map[string]*gosrc.Srcinfo
|
||||
noDeps = cmdArgs.ExistsDouble("d", "nodeps")
|
||||
|
@ -270,11 +269,11 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu
|
|||
text.Errorln(errDiffMenu)
|
||||
}
|
||||
|
||||
if errM := mergePkgbuilds(ctx, do.Aur); errM != nil {
|
||||
if errM := mergePkgbuilds(ctx, pkgbuildDirs); errM != nil {
|
||||
return errM
|
||||
}
|
||||
|
||||
srcinfos, err = parseSrcinfoFiles(do.Aur, true)
|
||||
srcinfos, err = parseSrcinfoFiles(pkgbuildDirs, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -289,13 +288,12 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu
|
|||
text.Errorln(errEditMenu)
|
||||
}
|
||||
|
||||
incompatible, err = getIncompatible(do.Aur, srcinfos, dbExecutor)
|
||||
if err != nil {
|
||||
return err
|
||||
if errI := confirmIncompatibleInstall(srcinfos, dbExecutor); errI != nil {
|
||||
return errI
|
||||
}
|
||||
|
||||
if config.PGPFetch {
|
||||
if errCPK := pgp.CheckPgpKeys(do.Aur, srcinfos, config.GpgBin, config.GpgFlags, settings.NoConfirm); errCPK != nil {
|
||||
if _, errCPK := pgp.CheckPgpKeys(pkgbuildDirs, srcinfos, config.GpgBin, config.GpgFlags, settings.NoConfirm); errCPK != nil {
|
||||
return errCPK
|
||||
}
|
||||
}
|
||||
|
@ -341,19 +339,14 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu
|
|||
config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, false)
|
||||
}()
|
||||
|
||||
pkgBuildDirs := make(map[string]string, len(do.Aur))
|
||||
for _, base := range do.Aur {
|
||||
pkgBuildDirs[base.Pkgbase()] = filepath.Join(config.BuildDir, base.Pkgbase())
|
||||
}
|
||||
|
||||
if errP := downloadPKGBUILDSourceFanout(ctx,
|
||||
config.Runtime.CmdBuilder,
|
||||
pkgBuildDirs,
|
||||
len(incompatible) > 0, config.MaxConcurrentDownloads); errP != nil {
|
||||
pkgbuildDirs,
|
||||
true, config.MaxConcurrentDownloads); errP != nil {
|
||||
text.Errorln(errP)
|
||||
}
|
||||
|
||||
if errB := buildInstallPkgbuilds(ctx, cmdArgs, dbExecutor, dp, do, srcinfos, incompatible, conflicts, noDeps, noCheck); errB != nil {
|
||||
if errB := buildInstallPkgbuilds(ctx, cmdArgs, dbExecutor, dp, do, srcinfos, true, conflicts, noDeps, noCheck); errB != nil {
|
||||
return errB
|
||||
}
|
||||
|
||||
|
@ -461,42 +454,39 @@ func earlyRefresh(ctx context.Context, cmdArgs *parser.Arguments) error {
|
|||
arguments, config.Runtime.Mode, settings.NoConfirm))
|
||||
}
|
||||
|
||||
func getIncompatible(bases []dep.Base, srcinfos map[string]*gosrc.Srcinfo, dbExecutor db.Executor) (stringset.StringSet, error) {
|
||||
incompatible := make(stringset.StringSet)
|
||||
basesMap := make(map[string]dep.Base)
|
||||
func confirmIncompatibleInstall(srcinfos map[string]*gosrc.Srcinfo, dbExecutor db.Executor) error {
|
||||
incompatible := []string{}
|
||||
|
||||
alpmArch, err := dbExecutor.AlpmArchitectures()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
nextpkg:
|
||||
for _, base := range bases {
|
||||
for _, arch := range srcinfos[base.Pkgbase()].Arch {
|
||||
for base, srcinfo := range srcinfos {
|
||||
for _, arch := range srcinfo.Arch {
|
||||
if db.ArchIsSupported(alpmArch, arch) {
|
||||
continue nextpkg
|
||||
}
|
||||
}
|
||||
|
||||
incompatible.Set(base.Pkgbase())
|
||||
basesMap[base.Pkgbase()] = base
|
||||
incompatible = append(incompatible, base)
|
||||
}
|
||||
|
||||
if len(incompatible) > 0 {
|
||||
text.Warnln(gotext.Get("The following packages are not compatible with your architecture:"))
|
||||
|
||||
for pkg := range incompatible {
|
||||
fmt.Print(" " + text.Cyan(basesMap[pkg].String()))
|
||||
for _, pkg := range incompatible {
|
||||
fmt.Print(" " + text.Cyan(pkg))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
if !text.ContinueTask(os.Stdin, gotext.Get("Try to build them anyway?"), true, settings.NoConfirm) {
|
||||
return nil, &settings.ErrUserAbort{}
|
||||
return &settings.ErrUserAbort{}
|
||||
}
|
||||
}
|
||||
|
||||
return incompatible, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func parsePackageList(ctx context.Context, dir string) (pkgdests map[string]string, pkgVersion string, err error) {
|
||||
|
@ -532,26 +522,25 @@ func parsePackageList(ctx context.Context, dir string) (pkgdests map[string]stri
|
|||
return pkgdests, pkgVersion, nil
|
||||
}
|
||||
|
||||
func parseSrcinfoFiles(bases []dep.Base, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) {
|
||||
func parseSrcinfoFiles(pkgBuildDirs map[string]string, 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)
|
||||
|
||||
text.OperationInfoln(gotext.Get("(%d/%d) Parsing SRCINFO: %s", k+1, len(bases), text.Cyan(base.String())))
|
||||
k := 0
|
||||
for base, dir := range pkgBuildDirs {
|
||||
text.OperationInfoln(gotext.Get("(%d/%d) Parsing SRCINFO: %s", k+1, len(pkgBuildDirs), text.Cyan(base)))
|
||||
|
||||
pkgbuild, err := gosrc.ParseFile(filepath.Join(dir, ".SRCINFO"))
|
||||
if err != nil {
|
||||
if !errIsFatal {
|
||||
text.Warnln(gotext.Get("failed to parse %s -- skipping: %s", base.String(), err))
|
||||
text.Warnln(gotext.Get("failed to parse %s -- skipping: %s", base, err))
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, errors.New(gotext.Get("failed to parse %s: %s", base.String(), err))
|
||||
return nil, errors.New(gotext.Get("failed to parse %s: %s", base, err))
|
||||
}
|
||||
|
||||
srcinfos[pkg] = pkgbuild
|
||||
srcinfos[base] = pkgbuild
|
||||
k++
|
||||
}
|
||||
|
||||
return srcinfos, nil
|
||||
|
@ -583,27 +572,27 @@ func pkgbuildsToSkip(bases []dep.Base, targets stringset.StringSet) stringset.St
|
|||
return toSkip
|
||||
}
|
||||
|
||||
func gitMerge(ctx context.Context, path, name string) error {
|
||||
func gitMerge(ctx context.Context, dir string) error {
|
||||
_, stderr, err := config.Runtime.CmdBuilder.Capture(
|
||||
config.Runtime.CmdBuilder.BuildGitCmd(ctx,
|
||||
filepath.Join(path, name), "reset", "--hard", "HEAD"))
|
||||
dir, "reset", "--hard", "HEAD"))
|
||||
if err != nil {
|
||||
return errors.New(gotext.Get("error resetting %s: %s", name, stderr))
|
||||
return errors.New(gotext.Get("error resetting %s: %s", dir, stderr))
|
||||
}
|
||||
|
||||
_, stderr, err = config.Runtime.CmdBuilder.Capture(
|
||||
config.Runtime.CmdBuilder.BuildGitCmd(ctx,
|
||||
filepath.Join(path, name), "merge", "--no-edit", "--ff"))
|
||||
dir, "merge", "--no-edit", "--ff"))
|
||||
if err != nil {
|
||||
return errors.New(gotext.Get("error merging %s: %s", name, stderr))
|
||||
return errors.New(gotext.Get("error merging %s: %s", dir, stderr))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergePkgbuilds(ctx context.Context, bases []dep.Base) error {
|
||||
for _, base := range bases {
|
||||
err := gitMerge(ctx, config.BuildDir, base.Pkgbase())
|
||||
func mergePkgbuilds(ctx context.Context, pkgbuildDirs map[string]string) error {
|
||||
for _, dir := range pkgbuildDirs {
|
||||
err := gitMerge(ctx, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -619,7 +608,7 @@ func buildInstallPkgbuilds(
|
|||
dp *dep.Pool,
|
||||
do *dep.Order,
|
||||
srcinfos map[string]*gosrc.Srcinfo,
|
||||
incompatible stringset.StringSet,
|
||||
incompatible bool,
|
||||
conflicts stringset.MapStringSet, noDeps, noCheck bool,
|
||||
) error {
|
||||
deps := make([]string, 0)
|
||||
|
@ -680,7 +669,7 @@ func buildInstallPkgbuilds(
|
|||
|
||||
args := []string{"--nobuild", "-fC"}
|
||||
|
||||
if incompatible.Get(pkg) {
|
||||
if incompatible {
|
||||
args = append(args, "--ignorearch")
|
||||
}
|
||||
|
||||
|
@ -749,7 +738,7 @@ func buildInstallPkgbuilds(
|
|||
} else {
|
||||
args := []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"}
|
||||
|
||||
if incompatible.Get(pkg) {
|
||||
if incompatible {
|
||||
args = append(args, "--ignorearch")
|
||||
}
|
||||
|
||||
|
|
|
@ -58,24 +58,27 @@ func installLocalPKGBUILD(
|
|||
}
|
||||
installer := &Installer{dbExecutor: dbExecutor}
|
||||
|
||||
if errP := preparer.Present(os.Stdout, topoSorted); errP != nil {
|
||||
return errP
|
||||
pkgBuildDirs, err := preparer.Run(ctx, os.Stdout, topoSorted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cleanFunc := preparer.ShouldCleanMakeDeps(); cleanFunc != nil {
|
||||
installer.AddPostInstallHook(cleanFunc)
|
||||
}
|
||||
|
||||
pkgBuildDirs, err := preparer.PrepareWorkspace(ctx, topoSorted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cleanAURDirsFunc := preparer.ShouldCleanAURDirs(pkgBuildDirs); cleanAURDirsFunc != nil {
|
||||
installer.AddPostInstallHook(cleanAURDirsFunc)
|
||||
}
|
||||
|
||||
if err = installer.Install(ctx, cmdArgs, topoSorted, pkgBuildDirs); err != nil {
|
||||
srcinfoOp := srcinfoOperator{dbExecutor: dbExecutor}
|
||||
|
||||
srcinfos, err := srcinfoOp.Run(pkgBuildDirs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = installer.Install(ctx, cmdArgs, topoSorted, pkgBuildDirs, srcinfos); err != nil {
|
||||
if errHook := installer.RunPostInstallHooks(ctx); errHook != nil {
|
||||
text.Errorln(errHook)
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
|
|||
if pkg := g.dbExecutor.SyncPackage(target.Name); pkg != nil {
|
||||
dbName := pkg.DB().Name()
|
||||
graph.AddNode(pkg.Name())
|
||||
g.ValidateAndSetNodeInfo(graph, target.Name, &topo.NodeInfo[*InstallInfo]{
|
||||
g.ValidateAndSetNodeInfo(graph, pkg.Name(), &topo.NodeInfo[*InstallInfo]{
|
||||
Color: colorMap[Explicit],
|
||||
Background: bgColorMap[Sync],
|
||||
Value: &InstallInfo{
|
||||
|
@ -144,6 +144,24 @@ func (g *Grapher) GraphFromTargets(ctx context.Context,
|
|||
continue
|
||||
}
|
||||
|
||||
groupPackages := g.dbExecutor.PackagesFromGroup(target.Name)
|
||||
if len(groupPackages) > 0 {
|
||||
dbName := groupPackages[0].DB().Name()
|
||||
graph.AddNode(target.Name)
|
||||
g.ValidateAndSetNodeInfo(graph, target.Name, &topo.NodeInfo[*InstallInfo]{
|
||||
Color: colorMap[Explicit],
|
||||
Background: bgColorMap[Sync],
|
||||
Value: &InstallInfo{
|
||||
Source: Sync,
|
||||
Reason: Explicit,
|
||||
Version: "",
|
||||
SyncDBName: &dbName,
|
||||
},
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case "aur":
|
||||
graph, err = g.GraphFromAURCache(ctx, graph, []string{target.Name})
|
||||
|
|
|
@ -25,6 +25,10 @@ func anyExistInCache(pkgbuildDirs map[string]string) bool {
|
|||
}
|
||||
|
||||
func CleanFn(ctx context.Context, config *settings.Configuration, w io.Writer, pkgbuildDirsByBase map[string]string) error {
|
||||
if len(pkgbuildDirsByBase) == 0 {
|
||||
return nil // no work to do
|
||||
}
|
||||
|
||||
if !anyExistInCache(pkgbuildDirsByBase) {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -182,6 +182,10 @@ func Diff(ctx context.Context, cmdBuilder exe.ICmdBuilder, w io.Writer,
|
|||
}
|
||||
|
||||
func DiffFn(ctx context.Context, config *settings.Configuration, w io.Writer, pkgbuildDirsByBase map[string]string) error {
|
||||
if len(pkgbuildDirsByBase) == 0 {
|
||||
return nil // no work to do
|
||||
}
|
||||
|
||||
bases := make([]string, 0, len(pkgbuildDirsByBase))
|
||||
for base := range pkgbuildDirsByBase {
|
||||
bases = append(bases, base)
|
||||
|
|
|
@ -150,6 +150,10 @@ func Edit(w io.Writer, editMenuOption bool, pkgbuildDirs map[string]string, edit
|
|||
func EditFn(ctx context.Context, config *settings.Configuration, w io.Writer,
|
||||
pkgbuildDirsByBase map[string]string,
|
||||
) error {
|
||||
if len(pkgbuildDirsByBase) == 0 {
|
||||
return nil // no work to do
|
||||
}
|
||||
|
||||
bases := make([]string, 0, len(pkgbuildDirsByBase))
|
||||
for pkg := range pkgbuildDirsByBase {
|
||||
bases = append(bases, pkg)
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
|
||||
[1m[33m -> [0m[0m[36mABAF11C65A2970B130ABE3C479BE3E4300411886[0m, required by: [36mdummy-1 (dummy-1 dummy-2)[0m
|
||||
[1m[36m:: [0m[0m[1mImporting keys with gpg...[0m
|
||||
[1m[36m:: [0m[0m[1mPGP keys need importing:[0m
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
|
||||
[1m[33m -> [0m[0m[36m487EACC08557AD082088DABA1EB2638FF56C0C53[0m, required by: [36mcower[0m
|
||||
[1m[36m:: [0m[0m[1mImporting keys with gpg...[0m
|
||||
[1m[36m:: [0m[0m[1mPGP keys need importing:[0m
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
|
||||
[1m[33m -> [0m[0m[36mC52048C0C0748FEE227D47A2702353E0F7E48EDB[0m, required by: [36mdummy-3[0m
|
||||
[1m[36m:: [0m[0m[1mImporting keys with gpg...[0m
|
||||
[1m[36m:: [0m[0m[1mPGP keys need importing:[0m
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
|
||||
[1m[33m -> [0m[0m[36m11E521D646982372EB577A1F8F0871F202119294[0m, required by: [36mlibc++[0m
|
||||
[1m[33m -> [0m[0m[36mB6C8F98282B944E3B0D5C2530FC3042E345AD05D[0m, required by: [36mlibc++[0m
|
||||
[1m[36m:: [0m[0m[1mImporting keys with gpg...[0m
|
||||
[1m[36m:: [0m[0m[1mPGP keys need importing:[0m
|
|
@ -11,13 +11,12 @@ import (
|
|||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/dep"
|
||||
"github.com/Jguer/yay/v11/pkg/text"
|
||||
)
|
||||
|
||||
// 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][]dep.Base
|
||||
type pgpKeySet map[string][]string
|
||||
|
||||
func (set pgpKeySet) toSlice() []string {
|
||||
slice := make([]string, 0, len(set))
|
||||
|
@ -28,7 +27,7 @@ func (set pgpKeySet) toSlice() []string {
|
|||
return slice
|
||||
}
|
||||
|
||||
func (set pgpKeySet) set(key string, p dep.Base) {
|
||||
func (set pgpKeySet) set(key, p string) {
|
||||
// Using ToUpper to make sure keys with a different case will be
|
||||
// considered the same.
|
||||
upperKey := strings.ToUpper(key)
|
||||
|
@ -44,9 +43,9 @@ 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(bases []dep.Base, srcinfos map[string]*gosrc.Srcinfo,
|
||||
func CheckPgpKeys(pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
|
||||
gpgBin, gpgFlags string, noConfirm bool,
|
||||
) error {
|
||||
) ([]string, error) {
|
||||
// Let's check the keys individually, and then we can offer to import
|
||||
// the problematic ones.
|
||||
problematic := make(pgpKeySet)
|
||||
|
@ -54,43 +53,42 @@ func CheckPgpKeys(bases []dep.Base, srcinfos map[string]*gosrc.Srcinfo,
|
|||
args := append(strings.Fields(gpgFlags), "--list-keys")
|
||||
|
||||
// Mapping all the keys.
|
||||
for _, base := range bases {
|
||||
pkg := base.Pkgbase()
|
||||
for pkg := range pkgbuildDirsByBase {
|
||||
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, base)
|
||||
problematic.set(key, pkg)
|
||||
continue
|
||||
}
|
||||
|
||||
cmd := exec.Command(gpgBin, append(args, key)...)
|
||||
if err := cmd.Run(); err != nil {
|
||||
problematic.set(key, base)
|
||||
problematic.set(key, pkg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No key issues!
|
||||
if len(problematic) == 0 {
|
||||
return nil
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
str, err := formatKeysToImport(problematic)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println(str)
|
||||
|
||||
if text.ContinueTask(os.Stdin, gotext.Get("Import?"), true, noConfirm) {
|
||||
return importKeys(problematic.toSlice(), gpgBin, gpgFlags)
|
||||
return problematic.toSlice(), importKeys(problematic.toSlice(), gpgBin, gpgFlags)
|
||||
}
|
||||
|
||||
return nil
|
||||
return problematic.toSlice(), nil
|
||||
}
|
||||
|
||||
// importKeys tries to import the list of keys specified in its argument.
|
||||
|
@ -122,7 +120,7 @@ func formatKeysToImport(keys pgpKeySet) (string, error) {
|
|||
for key, bases := range keys {
|
||||
pkglist := ""
|
||||
for _, base := range bases {
|
||||
pkglist += base.String() + " "
|
||||
pkglist += base + " "
|
||||
}
|
||||
|
||||
pkglist = strings.TrimRight(pkglist, " ")
|
||||
|
|
|
@ -4,21 +4,16 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
aur "github.com/Jguer/aur"
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
"github.com/bradleyjkemp/cupaloy"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/dep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -42,10 +37,6 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
func newPkg(basename string) *aur.Pkg {
|
||||
return &aur.Pkg{Name: basename, PackageBase: basename}
|
||||
}
|
||||
|
||||
func getPgpKey(key string) string {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
|
@ -159,40 +150,44 @@ func TestCheckPgpKeys(t *testing.T) {
|
|||
|
||||
casetests := []struct {
|
||||
name string
|
||||
pkgs dep.Base
|
||||
pkgs map[string]string
|
||||
srcinfos map[string]*gosrc.Srcinfo
|
||||
wantError bool
|
||||
expected []string
|
||||
}{
|
||||
// cower: single package, one valid key not yet in the keyring.
|
||||
// 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner.
|
||||
{
|
||||
name: " one valid key not yet in the keyring",
|
||||
pkgs: dep.Base{newPkg("cower")},
|
||||
pkgs: map[string]string{"cower": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"cower": makeSrcinfo("cower", "487EACC08557AD082088DABA1EB2638FF56C0C53")},
|
||||
wantError: false,
|
||||
expected: []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"},
|
||||
},
|
||||
// libc++: single package, two valid keys not yet in the keyring.
|
||||
// 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.
|
||||
// B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg.
|
||||
{
|
||||
name: "two valid keys not yet in the keyring",
|
||||
pkgs: dep.Base{newPkg("libc++")},
|
||||
pkgs: map[string]string{"libc++": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{
|
||||
"libc++": makeSrcinfo("libc++", "11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"},
|
||||
},
|
||||
// Two dummy packages requiring the same key.
|
||||
// ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds.
|
||||
{
|
||||
name: "Two dummy packages requiring the same key",
|
||||
pkgs: dep.Base{newPkg("dummy-1"), newPkg("dummy-2")},
|
||||
pkgs: map[string]string{"dummy-1": "", "dummy-2": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{
|
||||
"dummy-1": makeSrcinfo("dummy-1",
|
||||
"ABAF11C65A2970B130ABE3C479BE3E4300411886"),
|
||||
"dummy-2": makeSrcinfo("dummy-2", "ABAF11C65A2970B130ABE3C479BE3E4300411886"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"},
|
||||
},
|
||||
// dummy package: single package, two valid keys, one of them already
|
||||
// in the keyring.
|
||||
|
@ -200,26 +195,28 @@ func TestCheckPgpKeys(t *testing.T) {
|
|||
// C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey.
|
||||
{
|
||||
name: "one already in keyring",
|
||||
pkgs: dep.Base{newPkg("dummy-3")},
|
||||
pkgs: map[string]string{"dummy-3": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{
|
||||
"dummy-3": makeSrcinfo("dummy-3", "11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"},
|
||||
},
|
||||
// Two dummy packages with existing keys.
|
||||
{
|
||||
name: "two existing",
|
||||
pkgs: dep.Base{newPkg("dummy-4"), newPkg("dummy-5")},
|
||||
pkgs: map[string]string{"dummy-4": "", "dummy-5": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{
|
||||
"dummy-4": makeSrcinfo("dummy-4", "11E521D646982372EB577A1F8F0871F202119294"),
|
||||
"dummy-5": makeSrcinfo("dummy-5", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{},
|
||||
},
|
||||
// Dummy package with invalid key, should fail.
|
||||
{
|
||||
name: "one invalid",
|
||||
pkgs: dep.Base{newPkg("dummy-7")},
|
||||
pkgs: map[string]string{"dummy-7": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"dummy-7": makeSrcinfo("dummy-7", "THIS-SHOULD-FAIL")},
|
||||
wantError: true,
|
||||
},
|
||||
|
@ -227,40 +224,27 @@ func TestCheckPgpKeys(t *testing.T) {
|
|||
// A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler.
|
||||
{
|
||||
name: "one invalid, one valid",
|
||||
pkgs: dep.Base{newPkg("dummy-8")},
|
||||
pkgs: map[string]string{"dummy-8": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"dummy-8": makeSrcinfo("dummy-8", "A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL")},
|
||||
wantError: true,
|
||||
expected: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range casetests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rescueStdout := os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
err := CheckPgpKeys([]dep.Base{tt.pkgs}, tt.srcinfos, "gpg",
|
||||
problematic, err := CheckPgpKeys(tt.pkgs, tt.srcinfos, "gpg",
|
||||
fmt.Sprintf("--homedir %s --keyserver 127.0.0.1", keyringDir), true)
|
||||
if !tt.wantError {
|
||||
if err != nil {
|
||||
t.Fatalf("Got error %q, want no error", err)
|
||||
}
|
||||
|
||||
w.Close()
|
||||
out, _ := io.ReadAll(r)
|
||||
os.Stdout = rescueStdout
|
||||
|
||||
splitLines := strings.Split(string(out), "\n")
|
||||
sort.Strings(splitLines)
|
||||
|
||||
cupaloy.SnapshotT(t, strings.Join(splitLines, "\n"))
|
||||
if tt.wantError {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
// Here, we want to see the error.
|
||||
if err == nil {
|
||||
t.Fatalf("Got no error; want error")
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.ElementsMatch(t, tt.expected, problematic, fmt.Sprintf("%#v", problematic))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
42
preparer.go
42
preparer.go
|
@ -21,13 +21,14 @@ import (
|
|||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
type PostDownloadHookFunc func(ctx context.Context, config *settings.Configuration, w io.Writer, pkgbuildDirsByBase map[string]string) error
|
||||
type PreparerHookFunc func(ctx context.Context, config *settings.Configuration, w io.Writer, pkgbuildDirsByBase map[string]string) error
|
||||
|
||||
type Preparer struct {
|
||||
dbExecutor db.Executor
|
||||
cmdBuilder exe.ICmdBuilder
|
||||
config *settings.Configuration
|
||||
postDownloadHooks []PostDownloadHookFunc
|
||||
postDownloadHooks []PreparerHookFunc
|
||||
postMergeHooks []PreparerHookFunc
|
||||
|
||||
makeDeps []string
|
||||
}
|
||||
|
@ -37,7 +38,8 @@ func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder, config *set
|
|||
dbExecutor: dbExecutor,
|
||||
cmdBuilder: cmdBuilder,
|
||||
config: config,
|
||||
postDownloadHooks: []PostDownloadHookFunc{},
|
||||
postDownloadHooks: []PreparerHookFunc{},
|
||||
postMergeHooks: []PreparerHookFunc{},
|
||||
}
|
||||
|
||||
if config.CleanMenu {
|
||||
|
@ -45,11 +47,11 @@ func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder, config *set
|
|||
}
|
||||
|
||||
if config.DiffMenu {
|
||||
preper.postDownloadHooks = append(preper.postDownloadHooks, menus.DiffFn)
|
||||
preper.postMergeHooks = append(preper.postMergeHooks, menus.DiffFn)
|
||||
}
|
||||
|
||||
if config.EditMenu {
|
||||
preper.postDownloadHooks = append(preper.postDownloadHooks, menus.EditFn)
|
||||
preper.postMergeHooks = append(preper.postMergeHooks, menus.EditFn)
|
||||
}
|
||||
|
||||
return preper
|
||||
|
@ -91,7 +93,20 @@ func (preper *Preparer) ShouldCleanMakeDeps() PostInstallHookFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (preper *Preparer) Present(w io.Writer, targets []map[string]*dep.InstallInfo) error {
|
||||
func (preper *Preparer) Run(ctx context.Context,
|
||||
w io.Writer, targets []map[string]*dep.InstallInfo,
|
||||
) (pkgbuildDirsByBase map[string]string, err error) {
|
||||
preper.Present(w, targets)
|
||||
|
||||
pkgBuildDirs, err := preper.PrepareWorkspace(ctx, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pkgBuildDirs, nil
|
||||
}
|
||||
|
||||
func (preper *Preparer) Present(w io.Writer, targets []map[string]*dep.InstallInfo) {
|
||||
pkgsBySourceAndReason := map[string]map[string][]string{}
|
||||
|
||||
for _, layer := range targets {
|
||||
|
@ -127,8 +142,6 @@ func (preper *Preparer) Present(w io.Writer, targets []map[string]*dep.InstallIn
|
|||
strings.Join(pkgs, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[string]*dep.InstallInfo) (map[string]string, error) {
|
||||
|
@ -168,6 +181,16 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
|
|||
}
|
||||
}
|
||||
|
||||
if err := mergePkgbuilds(ctx, pkgBuildDirsByBase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, hookFn := range preper.postMergeHooks {
|
||||
if err := hookFn(ctx, preper.config, os.Stdout, pkgBuildDirsByBase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return pkgBuildDirsByBase, nil
|
||||
}
|
||||
|
||||
|
@ -179,6 +202,9 @@ func (preper *Preparer) needToCloneAURBase(installInfo *dep.InstallInfo, pkgbuil
|
|||
srcinfoFile := filepath.Join(pkgbuildDir, ".SRCINFO")
|
||||
if pkgbuild, err := gosrc.ParseFile(srcinfoFile); err == nil {
|
||||
if db.VerCmp(pkgbuild.Version(), installInfo.Version) >= 0 {
|
||||
text.OperationInfoln(
|
||||
gotext.Get("PKGBUILD up to date, skipping download: %s",
|
||||
text.Cyan(*installInfo.AURBase)))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
32
srcinfo.go
Normal file
32
srcinfo.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
"github.com/Jguer/yay/v11/pkg/pgp"
|
||||
"github.com/Jguer/yay/v11/pkg/settings"
|
||||
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
)
|
||||
|
||||
type srcinfoOperator struct {
|
||||
dbExecutor db.Executor
|
||||
}
|
||||
|
||||
func (s *srcinfoOperator) Run(pkgbuildDirs map[string]string) (map[string]*gosrc.Srcinfo, error) {
|
||||
srcinfos, err := parseSrcinfoFiles(pkgbuildDirs, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := confirmIncompatibleInstall(srcinfos, s.dbExecutor); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if config.PGPFetch {
|
||||
if _, errCPK := pgp.CheckPgpKeys(pkgbuildDirs, srcinfos, config.GpgBin, config.GpgFlags, settings.NoConfirm); errCPK != nil {
|
||||
return nil, errCPK
|
||||
}
|
||||
}
|
||||
|
||||
return srcinfos, nil
|
||||
}
|
25
sync.go
25
sync.go
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/completion"
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
"github.com/Jguer/yay/v11/pkg/dep"
|
||||
"github.com/Jguer/yay/v11/pkg/settings"
|
||||
|
@ -55,8 +56,9 @@ func syncInstall(ctx context.Context,
|
|||
preparer := NewPreparer(dbExecutor, config.Runtime.CmdBuilder, config)
|
||||
installer := &Installer{dbExecutor: dbExecutor}
|
||||
|
||||
if errP := preparer.Present(os.Stdout, topoSorted); errP != nil {
|
||||
return errP
|
||||
pkgBuildDirs, err := preparer.Run(ctx, os.Stdout, topoSorted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cleanFunc := preparer.ShouldCleanMakeDeps()
|
||||
|
@ -64,16 +66,23 @@ func syncInstall(ctx context.Context,
|
|||
installer.AddPostInstallHook(cleanFunc)
|
||||
}
|
||||
|
||||
pkgBuildDirs, err := preparer.PrepareWorkspace(ctx, topoSorted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cleanAURDirsFunc := preparer.ShouldCleanAURDirs(pkgBuildDirs); cleanAURDirsFunc != nil {
|
||||
installer.AddPostInstallHook(cleanAURDirsFunc)
|
||||
}
|
||||
|
||||
err = installer.Install(ctx, cmdArgs, topoSorted, pkgBuildDirs)
|
||||
srcinfoOp := srcinfoOperator{dbExecutor: dbExecutor}
|
||||
|
||||
srcinfos, err := srcinfoOp.Run(pkgBuildDirs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
_ = completion.Update(ctx, config.Runtime.HTTPClient, dbExecutor,
|
||||
config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, false)
|
||||
}()
|
||||
|
||||
err = installer.Install(ctx, cmdArgs, topoSorted, pkgBuildDirs, srcinfos)
|
||||
if err != nil {
|
||||
if errHook := installer.RunPostInstallHooks(ctx); errHook != nil {
|
||||
text.Errorln(errHook)
|
||||
|
|
6
vcs.go
6
vcs.go
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
@ -33,11 +34,14 @@ func createDevelDB(ctx context.Context, config *settings.Configuration, dbExecut
|
|||
toSkip := pkgbuildsToSkip(bases, stringset.FromSlice(remoteNames))
|
||||
|
||||
targets := make([]string, 0, len(bases))
|
||||
pkgBuildDirsByBase := make(map[string]string, len(bases))
|
||||
|
||||
for _, base := range bases {
|
||||
if !toSkip.Get(base.Pkgbase()) {
|
||||
targets = append(targets, base.Pkgbase())
|
||||
}
|
||||
|
||||
pkgBuildDirsByBase[base.Pkgbase()] = filepath.Join(config.BuildDir, base.Pkgbase())
|
||||
}
|
||||
|
||||
toSkipSlice := toSkip.ToSlice()
|
||||
|
@ -52,7 +56,7 @@ func createDevelDB(ctx context.Context, config *settings.Configuration, dbExecut
|
|||
return err
|
||||
}
|
||||
|
||||
srcinfos, err := parseSrcinfoFiles(bases, false)
|
||||
srcinfos, err := parseSrcinfoFiles(pkgBuildDirsByBase, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue