mirror of
https://github.com/Jguer/yay.git
synced 2025-12-27 10:01:53 -05:00
feat(new engine): local install feature testing (#1867)
* make config into parameter * test(new engine): local install test * test(keys): fix test keys * complete integration test for local install * add simple mising mechanism
This commit is contained in:
28
cmd.go
28
cmd.go
@@ -149,13 +149,13 @@ getpkgbuild specific options:
|
||||
-p --print Print pkgbuild of packages`)
|
||||
}
|
||||
|
||||
func handleCmd(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
||||
func handleCmd(ctx context.Context, cfg *settings.Configuration, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
|
||||
if cmdArgs.ExistsArg("h", "help") {
|
||||
return handleHelp(ctx, cmdArgs)
|
||||
}
|
||||
|
||||
if config.SudoLoop && cmdArgs.NeedRoot(config.Runtime.Mode) {
|
||||
config.Runtime.CmdBuilder.SudoLoop()
|
||||
if cfg.SudoLoop && cmdArgs.NeedRoot(cfg.Runtime.Mode) {
|
||||
cfg.Runtime.CmdBuilder.SudoLoop()
|
||||
}
|
||||
|
||||
switch cmdArgs.Op {
|
||||
@@ -164,30 +164,30 @@ func handleCmd(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Exe
|
||||
|
||||
return nil
|
||||
case "D", "database":
|
||||
return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, config.Runtime.Mode, settings.NoConfirm))
|
||||
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, cfg.Runtime.Mode, settings.NoConfirm))
|
||||
case "F", "files":
|
||||
return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, config.Runtime.Mode, settings.NoConfirm))
|
||||
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, cfg.Runtime.Mode, settings.NoConfirm))
|
||||
case "Q", "query":
|
||||
return handleQuery(ctx, cmdArgs, dbExecutor)
|
||||
case "R", "remove":
|
||||
return handleRemove(ctx, cmdArgs, config.Runtime.VCSStore)
|
||||
return handleRemove(ctx, cmdArgs, cfg.Runtime.VCSStore)
|
||||
case "S", "sync":
|
||||
return handleSync(ctx, cmdArgs, dbExecutor)
|
||||
case "T", "deptest":
|
||||
return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, config.Runtime.Mode, settings.NoConfirm))
|
||||
return cfg.Runtime.CmdBuilder.Show(cfg.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, cfg.Runtime.Mode, settings.NoConfirm))
|
||||
case "U", "upgrade":
|
||||
return handleUpgrade(ctx, config, cmdArgs)
|
||||
return handleUpgrade(ctx, cfg, cmdArgs)
|
||||
case "B", "build":
|
||||
return handleBuild(ctx, config, dbExecutor, cmdArgs)
|
||||
return handleBuild(ctx, cfg, dbExecutor, cmdArgs)
|
||||
case "G", "getpkgbuild":
|
||||
return handleGetpkgbuild(ctx, cmdArgs, dbExecutor)
|
||||
case "P", "show":
|
||||
return handlePrint(ctx, cmdArgs, dbExecutor)
|
||||
case "Y", "yay":
|
||||
return handleYay(ctx, cmdArgs, dbExecutor, config.Runtime.QueryBuilder)
|
||||
return handleYay(ctx, cmdArgs, dbExecutor, cfg.Runtime.QueryBuilder)
|
||||
case "W", "web":
|
||||
return handleWeb(ctx, cmdArgs)
|
||||
}
|
||||
@@ -379,7 +379,7 @@ func handleSync(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Ex
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRemove(ctx context.Context, cmdArgs *parser.Arguments, localCache *vcs.InfoStore) error {
|
||||
func handleRemove(ctx context.Context, cmdArgs *parser.Arguments, localCache vcs.Store) error {
|
||||
err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
|
||||
cmdArgs, config.Runtime.Mode, settings.NoConfirm))
|
||||
if err == nil {
|
||||
|
||||
22
install.go
22
install.go
@@ -278,7 +278,7 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu
|
||||
text.Errorln(errDiffMenu)
|
||||
}
|
||||
|
||||
if errM := mergePkgbuilds(ctx, pkgbuildDirs); errM != nil {
|
||||
if errM := mergePkgbuilds(ctx, config.Runtime.CmdBuilder, pkgbuildDirs); errM != nil {
|
||||
return errM
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu
|
||||
}
|
||||
|
||||
if config.PGPFetch {
|
||||
if _, errCPK := pgp.CheckPgpKeys(pkgbuildDirs, srcinfos, config.GpgBin, config.GpgFlags, settings.NoConfirm); errCPK != nil {
|
||||
if _, errCPK := pgp.CheckPgpKeys(ctx, pkgbuildDirs, srcinfos, config.Runtime.CmdBuilder, settings.NoConfirm); errCPK != nil {
|
||||
return errCPK
|
||||
}
|
||||
}
|
||||
@@ -587,16 +587,16 @@ func pkgbuildsToSkip(bases []dep.Base, targets stringset.StringSet) stringset.St
|
||||
return toSkip
|
||||
}
|
||||
|
||||
func gitMerge(ctx context.Context, dir string) error {
|
||||
_, stderr, err := config.Runtime.CmdBuilder.Capture(
|
||||
config.Runtime.CmdBuilder.BuildGitCmd(ctx,
|
||||
func gitMerge(ctx context.Context, cmdBuilder exe.ICmdBuilder, dir string) error {
|
||||
_, stderr, err := cmdBuilder.Capture(
|
||||
cmdBuilder.BuildGitCmd(ctx,
|
||||
dir, "reset", "--hard", "HEAD"))
|
||||
if err != nil {
|
||||
return errors.New(gotext.Get("error resetting %s: %s", dir, stderr))
|
||||
}
|
||||
|
||||
_, stderr, err = config.Runtime.CmdBuilder.Capture(
|
||||
config.Runtime.CmdBuilder.BuildGitCmd(ctx,
|
||||
_, stderr, err = cmdBuilder.Capture(
|
||||
cmdBuilder.BuildGitCmd(ctx,
|
||||
dir, "merge", "--no-edit", "--ff"))
|
||||
if err != nil {
|
||||
return errors.New(gotext.Get("error merging %s: %s", dir, stderr))
|
||||
@@ -605,9 +605,9 @@ func gitMerge(ctx context.Context, dir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergePkgbuilds(ctx context.Context, pkgbuildDirs map[string]string) error {
|
||||
func mergePkgbuilds(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgbuildDirs map[string]string) error {
|
||||
for _, dir := range pkgbuildDirs {
|
||||
err := gitMerge(ctx, dir)
|
||||
err := gitMerge(ctx, cmdBuilder, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -710,7 +710,7 @@ func buildInstallPkgbuilds(
|
||||
for _, split := range base {
|
||||
pkgdest, ok := pkgdests[split.Name]
|
||||
if !ok {
|
||||
return errors.New(gotext.Get("could not find PKGDEST for: %s", split.Name))
|
||||
return &PkgDestNotInListError{split.Name}
|
||||
}
|
||||
|
||||
if _, errStat := os.Stat(pkgdest); os.IsNotExist(errStat) {
|
||||
@@ -894,7 +894,7 @@ func doAddTarget(dp *dep.Pool, localNamesCache, remoteNamesCache stringset.Strin
|
||||
return deps, exp, pkgArchives, nil
|
||||
}
|
||||
|
||||
return deps, exp, pkgArchives, errors.New(gotext.Get("could not find PKGDEST for: %s", name))
|
||||
return deps, exp, pkgArchives, &PkgDestNotInListError{name}
|
||||
}
|
||||
|
||||
if _, errStat := os.Stat(pkgdest); os.IsNotExist(errStat) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
"github.com/Jguer/yay/v11/pkg/dep"
|
||||
"github.com/Jguer/yay/v11/pkg/multierror"
|
||||
"github.com/Jguer/yay/v11/pkg/settings"
|
||||
"github.com/Jguer/yay/v11/pkg/settings/parser"
|
||||
"github.com/Jguer/yay/v11/pkg/topo"
|
||||
@@ -51,5 +52,16 @@ func installLocalPKGBUILD(
|
||||
}
|
||||
|
||||
opService := NewOperationService(ctx, config, dbExecutor)
|
||||
return opService.Run(ctx, cmdArgs, graph.TopoSortedLayerMap())
|
||||
multiErr := &multierror.MultiError{}
|
||||
targets := graph.TopoSortedLayerMap(func(name string, ii *dep.InstallInfo) error {
|
||||
if ii.Source == dep.Missing {
|
||||
multiErr.Add(errors.New(gotext.Get("could not find %s%s", name, ii.Version)))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := multiErr.Return(); err != nil {
|
||||
return err
|
||||
}
|
||||
return opService.Run(ctx, cmdArgs, targets)
|
||||
}
|
||||
|
||||
281
local_install_test.go
Normal file
281
local_install_test.go
Normal file
@@ -0,0 +1,281 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
aur "github.com/Jguer/aur"
|
||||
"github.com/Jguer/aur/metadata"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/db/mock"
|
||||
mockaur "github.com/Jguer/yay/v11/pkg/dep/mock"
|
||||
"github.com/Jguer/yay/v11/pkg/settings"
|
||||
"github.com/Jguer/yay/v11/pkg/settings/exe"
|
||||
"github.com/Jguer/yay/v11/pkg/settings/parser"
|
||||
"github.com/Jguer/yay/v11/pkg/vcs"
|
||||
)
|
||||
|
||||
func TestIntegrationLocalInstall(t *testing.T) {
|
||||
makepkgBin := t.TempDir() + "/makepkg"
|
||||
pacmanBin := t.TempDir() + "/pacman"
|
||||
gitBin := t.TempDir() + "/git"
|
||||
tmpDir := t.TempDir()
|
||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
tars := []string{
|
||||
tmpDir + "/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
tmpDir + "/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
tmpDir + "/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
}
|
||||
|
||||
wantShow := []string{
|
||||
"makepkg --verifysource -Ccf",
|
||||
"pacman -S --config /etc/pacman.conf -- community/dotnet-sdk-6.0 community/dotnet-runtime-6.0",
|
||||
"pacman -D -q --asdeps --config /etc/pacman.conf -- dotnet-runtime-6.0 dotnet-sdk-6.0",
|
||||
"makepkg --nobuild -fC --ignorearch",
|
||||
"makepkg -c --nobuild --noextract --ignorearch",
|
||||
"makepkg --nobuild -fC --ignorearch",
|
||||
"makepkg -c --nobuild --noextract --ignorearch",
|
||||
"makepkg --nobuild -fC --ignorearch",
|
||||
"makepkg -c --nobuild --noextract --ignorearch",
|
||||
"pacman -U --config /etc/pacman.conf -- /testdir/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-10.8.4-1-x86_64.pkg.tar.zst /testdir/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
"pacman -D -q --asexplicit --config /etc/pacman.conf -- jellyfin-server jellyfin jellyfin-web",
|
||||
}
|
||||
|
||||
wantCapture := []string{
|
||||
"makepkg --packagelist",
|
||||
"git -C testdata/jfin git reset --hard HEAD",
|
||||
"git -C testdata/jfin git merge --no-edit --ff",
|
||||
"makepkg --packagelist",
|
||||
"makepkg --packagelist",
|
||||
}
|
||||
|
||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||
return strings.Join(tars, "\n"), "", nil
|
||||
}
|
||||
|
||||
once := sync.Once{}
|
||||
|
||||
showOverride := func(cmd *exec.Cmd) error {
|
||||
once.Do(func() {
|
||||
for _, tar := range tars {
|
||||
f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
||||
cmdBuilder := &exe.CmdBuilder{
|
||||
MakepkgBin: makepkgBin,
|
||||
SudoBin: "su",
|
||||
PacmanBin: pacmanBin,
|
||||
PacmanConfigPath: "/etc/pacman.conf",
|
||||
GitBin: "git",
|
||||
Runner: mockRunner,
|
||||
SudoLoopEnabled: false,
|
||||
}
|
||||
|
||||
cmdArgs := parser.MakeArguments()
|
||||
cmdArgs.AddArg("B")
|
||||
cmdArgs.AddArg("i")
|
||||
cmdArgs.AddTarget("testdata/jfin")
|
||||
db := &mock.DBExecutor{
|
||||
AlpmArchitecturesFn: func() ([]string, error) {
|
||||
return []string{"x86_64"}, nil
|
||||
},
|
||||
LocalSatisfierExistsFn: func(s string) bool {
|
||||
switch s {
|
||||
case "dotnet-sdk>=6", "dotnet-sdk<7", "dotnet-runtime>=6", "dotnet-runtime<7", "jellyfin-server=10.8.4", "jellyfin-web=10.8.4":
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
||||
switch s {
|
||||
case "dotnet-runtime>=6", "dotnet-runtime<7":
|
||||
return &mock.Package{
|
||||
PName: "dotnet-runtime-6.0",
|
||||
PBase: "dotnet-runtime-6.0",
|
||||
PVersion: "6.0.100-1",
|
||||
PDB: mock.NewDB("community"),
|
||||
}
|
||||
case "dotnet-sdk>=6", "dotnet-sdk<7":
|
||||
return &mock.Package{
|
||||
PName: "dotnet-sdk-6.0",
|
||||
PBase: "dotnet-sdk-6.0",
|
||||
PVersion: "6.0.100-1",
|
||||
PDB: mock.NewDB("community"),
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
config := &settings.Configuration{
|
||||
Runtime: &settings.Runtime{
|
||||
CmdBuilder: cmdBuilder,
|
||||
VCSStore: &vcs.Mock{},
|
||||
AURCache: &mockaur.MockAUR{
|
||||
GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) {
|
||||
return []*aur.Pkg{}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err = handleCmd(context.Background(), config, cmdArgs, db)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
||||
require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
|
||||
|
||||
for i, call := range mockRunner.ShowCalls {
|
||||
show := call.Args[0].(*exec.Cmd).String()
|
||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
||||
show = strings.ReplaceAll(show, gitBin, "pacman")
|
||||
|
||||
// options are in a different order on different systems and on CI root user is used
|
||||
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationLocalInstallMissingDep(t *testing.T) {
|
||||
wantErr := "could not find dotnet-sdk>=6"
|
||||
makepkgBin := t.TempDir() + "/makepkg"
|
||||
pacmanBin := t.TempDir() + "/pacman"
|
||||
gitBin := t.TempDir() + "/git"
|
||||
tmpDir := t.TempDir()
|
||||
f, err := os.OpenFile(makepkgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
f, err = os.OpenFile(pacmanBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
f, err = os.OpenFile(gitBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
tars := []string{
|
||||
tmpDir + "/jellyfin-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
tmpDir + "/jellyfin-web-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
tmpDir + "/jellyfin-server-10.8.4-1-x86_64.pkg.tar.zst",
|
||||
}
|
||||
|
||||
wantShow := []string{}
|
||||
wantCapture := []string{}
|
||||
|
||||
captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||
return strings.Join(tars, "\n"), "", nil
|
||||
}
|
||||
|
||||
once := sync.Once{}
|
||||
|
||||
showOverride := func(cmd *exec.Cmd) error {
|
||||
once.Do(func() {
|
||||
for _, tar := range tars {
|
||||
f, err := os.OpenFile(tar, os.O_RDONLY|os.O_CREATE, 0o666)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride}
|
||||
cmdBuilder := &exe.CmdBuilder{
|
||||
MakepkgBin: makepkgBin,
|
||||
SudoBin: "su",
|
||||
PacmanBin: pacmanBin,
|
||||
PacmanConfigPath: "/etc/pacman.conf",
|
||||
GitBin: "git",
|
||||
Runner: mockRunner,
|
||||
SudoLoopEnabled: false,
|
||||
}
|
||||
|
||||
cmdArgs := parser.MakeArguments()
|
||||
cmdArgs.AddArg("B")
|
||||
cmdArgs.AddArg("i")
|
||||
cmdArgs.AddTarget("testdata/jfin")
|
||||
db := &mock.DBExecutor{
|
||||
AlpmArchitecturesFn: func() ([]string, error) {
|
||||
return []string{"x86_64"}, nil
|
||||
},
|
||||
LocalSatisfierExistsFn: func(s string) bool {
|
||||
switch s {
|
||||
case "dotnet-sdk>=6", "dotnet-sdk<7", "dotnet-runtime>=6", "dotnet-runtime<7", "jellyfin-server=10.8.4", "jellyfin-web=10.8.4":
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
SyncSatisfierFn: func(s string) mock.IPackage {
|
||||
switch s {
|
||||
case "dotnet-runtime>=6", "dotnet-runtime<7":
|
||||
return &mock.Package{
|
||||
PName: "dotnet-runtime-6.0",
|
||||
PBase: "dotnet-runtime-6.0",
|
||||
PVersion: "6.0.100-1",
|
||||
PDB: mock.NewDB("community"),
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
config := &settings.Configuration{
|
||||
Runtime: &settings.Runtime{
|
||||
CmdBuilder: cmdBuilder,
|
||||
VCSStore: &vcs.Mock{},
|
||||
AURCache: &mockaur.MockAUR{
|
||||
GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) {
|
||||
return []*aur.Pkg{}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err = handleCmd(context.Background(), config, cmdArgs, db)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, wantErr)
|
||||
|
||||
require.Len(t, mockRunner.ShowCalls, len(wantShow))
|
||||
require.Len(t, mockRunner.CaptureCalls, len(wantCapture))
|
||||
|
||||
for i, call := range mockRunner.ShowCalls {
|
||||
show := call.Args[0].(*exec.Cmd).String()
|
||||
show = strings.ReplaceAll(show, tmpDir, "/testdir") // replace the temp dir with a static path
|
||||
show = strings.ReplaceAll(show, makepkgBin, "makepkg")
|
||||
show = strings.ReplaceAll(show, pacmanBin, "pacman")
|
||||
show = strings.ReplaceAll(show, gitBin, "pacman")
|
||||
|
||||
// options are in a different order on different systems and on CI root user is used
|
||||
assert.Subset(t, strings.Split(show, " "), strings.Split(wantShow[i], " "), fmt.Sprintf("%d - %s", i, show))
|
||||
}
|
||||
}
|
||||
2
main.go
2
main.go
@@ -141,7 +141,7 @@ func main() {
|
||||
dbExecutor.Cleanup()
|
||||
}()
|
||||
|
||||
if err = handleCmd(ctx, cmdArgs, db.Executor(dbExecutor)); err != nil {
|
||||
if err = handleCmd(ctx, config, cmdArgs, db.Executor(dbExecutor)); err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
text.Errorln(str)
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func graphPackage(
|
||||
fmt.Fprintln(os.Stdout, graph.String())
|
||||
fmt.Fprintln(os.Stdout, "\nlayers\n", graph.TopoSortedLayers())
|
||||
fmt.Fprintln(os.Stdout, "\ninverted order\n", graph.TopoSorted())
|
||||
fmt.Fprintln(os.Stdout, "\nlayers map\n", graph.TopoSortedLayerMap())
|
||||
fmt.Fprintln(os.Stdout, "\nlayers map\n", graph.TopoSortedLayerMap(nil))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,9 +21,13 @@ type DBExecutor struct {
|
||||
PackagesFromGroupFn func(string) []IPackage
|
||||
LocalSatisfierExistsFn func(string) bool
|
||||
SyncSatisfierFn func(string) IPackage
|
||||
AlpmArchitecturesFn func() ([]string, error)
|
||||
}
|
||||
|
||||
func (t *DBExecutor) AlpmArchitectures() ([]string, error) {
|
||||
if t.AlpmArchitecturesFn != nil {
|
||||
return t.AlpmArchitecturesFn()
|
||||
}
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ func (g *Grapher) addNodes(
|
||||
depType Reason,
|
||||
) {
|
||||
for _, depString := range deps {
|
||||
depName, _, _ := splitDep(depString)
|
||||
depName, mod, ver := splitDep(depString)
|
||||
|
||||
if g.dbExecutor.LocalSatisfierExists(depString) {
|
||||
if g.fullGraph {
|
||||
@@ -403,7 +403,16 @@ func (g *Grapher) addNodes(
|
||||
}
|
||||
|
||||
// no dep found. add as missing
|
||||
graph.SetNodeInfo(depString, &topo.NodeInfo[*InstallInfo]{Color: colorMap[depType], Background: bgColorMap[Missing]})
|
||||
graph.AddNode(depName)
|
||||
graph.SetNodeInfo(depName, &topo.NodeInfo[*InstallInfo]{
|
||||
Color: colorMap[depType],
|
||||
Background: bgColorMap[Missing],
|
||||
Value: &InstallInfo{
|
||||
Source: Missing,
|
||||
Reason: depType,
|
||||
Version: fmt.Sprintf("%s%s", mod, ver),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
"github.com/Jguer/yay/v11/pkg/db/mock"
|
||||
mockaur "github.com/Jguer/yay/v11/pkg/dep/mock"
|
||||
aur "github.com/Jguer/yay/v11/pkg/query"
|
||||
|
||||
"github.com/Jguer/aur/metadata"
|
||||
@@ -19,21 +20,7 @@ func ptrString(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
type getFunc func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error)
|
||||
|
||||
type MockAUR struct {
|
||||
GetFn getFunc
|
||||
}
|
||||
|
||||
func (m *MockAUR) Get(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) {
|
||||
if m.GetFn != nil {
|
||||
return m.GetFn(ctx, query)
|
||||
}
|
||||
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func getFromFile(t *testing.T, filePath string) getFunc {
|
||||
func getFromFile(t *testing.T, filePath string) mockaur.GetFunc {
|
||||
f, err := os.Open(filePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -85,7 +72,7 @@ func TestGrapher_GraphFromTargets_jellyfin(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
mockAUR := &MockAUR{GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) {
|
||||
mockAUR := &mockaur.MockAUR{GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) {
|
||||
if query.Needles[0] == "jellyfin" {
|
||||
jfinFn := getFromFile(t, "testdata/jellyfin.json")
|
||||
return jfinFn(ctx, query)
|
||||
@@ -210,7 +197,7 @@ func TestGrapher_GraphFromTargets_jellyfin(t *testing.T) {
|
||||
tt.fields.noDeps, tt.fields.noCheckDeps)
|
||||
got, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets)
|
||||
require.NoError(t, err)
|
||||
layers := got.TopoSortedLayerMap()
|
||||
layers := got.TopoSortedLayerMap(nil)
|
||||
require.EqualValues(t, tt.want, layers, layers)
|
||||
})
|
||||
}
|
||||
|
||||
22
pkg/dep/mock/aur.go
Normal file
22
pkg/dep/mock/aur.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Jguer/aur"
|
||||
"github.com/Jguer/aur/metadata"
|
||||
)
|
||||
|
||||
type GetFunc func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error)
|
||||
|
||||
type MockAUR struct {
|
||||
GetFn GetFunc
|
||||
}
|
||||
|
||||
func (m *MockAUR) Get(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) {
|
||||
if m.GetFn != nil {
|
||||
return m.GetFn(ctx, query)
|
||||
}
|
||||
|
||||
panic("implement me")
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package pgp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/settings/exe"
|
||||
"github.com/Jguer/yay/v11/pkg/text"
|
||||
)
|
||||
|
||||
@@ -41,17 +43,20 @@ func (set pgpKeySet) get(key string) bool {
|
||||
return exists
|
||||
}
|
||||
|
||||
type GPGCmdBuilder interface {
|
||||
exe.Runner
|
||||
BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd
|
||||
}
|
||||
|
||||
// CheckPgpKeys iterates through the keys listed in the PKGBUILDs and if needed,
|
||||
// asks the user whether yay should try to import them.
|
||||
func CheckPgpKeys(pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
|
||||
gpgBin, gpgFlags string, noConfirm bool,
|
||||
func CheckPgpKeys(ctx context.Context, pkgbuildDirsByBase map[string]string, srcinfos map[string]*gosrc.Srcinfo,
|
||||
cmdBuilder GPGCmdBuilder, noConfirm bool,
|
||||
) ([]string, error) {
|
||||
// Let's check the keys individually, and then we can offer to import
|
||||
// the problematic ones.
|
||||
problematic := make(pgpKeySet)
|
||||
|
||||
args := append(strings.Fields(gpgFlags), "--list-keys")
|
||||
|
||||
// Mapping all the keys.
|
||||
for pkg := range pkgbuildDirsByBase {
|
||||
srcinfo := srcinfos[pkg]
|
||||
@@ -64,8 +69,7 @@ func CheckPgpKeys(pkgbuildDirsByBase map[string]string, srcinfos map[string]*gos
|
||||
continue
|
||||
}
|
||||
|
||||
cmd := exec.Command(gpgBin, append(args, key)...)
|
||||
if err := cmd.Run(); err != nil {
|
||||
if err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, "--list-keys", key)); err != nil {
|
||||
problematic.set(key, pkg)
|
||||
}
|
||||
}
|
||||
@@ -85,21 +89,17 @@ func CheckPgpKeys(pkgbuildDirsByBase map[string]string, srcinfos map[string]*gos
|
||||
fmt.Println(str)
|
||||
|
||||
if text.ContinueTask(os.Stdin, gotext.Get("Import?"), true, noConfirm) {
|
||||
return problematic.toSlice(), importKeys(problematic.toSlice(), gpgBin, gpgFlags)
|
||||
return problematic.toSlice(), importKeys(ctx, cmdBuilder, problematic.toSlice())
|
||||
}
|
||||
|
||||
return problematic.toSlice(), nil
|
||||
}
|
||||
|
||||
// importKeys tries to import the list of keys specified in its argument.
|
||||
func importKeys(keys []string, gpgBin, gpgFlags string) error {
|
||||
args := append(strings.Fields(gpgFlags), "--recv-keys")
|
||||
cmd := exec.Command(gpgBin, append(args, keys...)...)
|
||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||
|
||||
func importKeys(ctx context.Context, cmdBuilder GPGCmdBuilder, keys []string) error {
|
||||
text.OperationInfoln(gotext.Get("Importing keys with gpg..."))
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
if err := cmdBuilder.Show(cmdBuilder.BuildGPGCmd(ctx, append([]string{"--recv-keys"}, keys...)...)); err != nil {
|
||||
return errors.New(gotext.Get("problem importing keys"))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,134 +1,21 @@
|
||||
package pgp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/settings/exe"
|
||||
)
|
||||
|
||||
const (
|
||||
// The default port used by the PGP key server.
|
||||
gpgServerPort = 11371
|
||||
)
|
||||
|
||||
func init() {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
regex := regexp.MustCompile(`search=0[xX]([a-fA-F0-9]+)`)
|
||||
matches := regex.FindStringSubmatch(r.RequestURI)
|
||||
data := ""
|
||||
if matches != nil {
|
||||
data = getPgpKey(matches[1])
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/pgp-keys")
|
||||
_, err := w.Write([]byte(data))
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getPgpKey(key string) string {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
if contents, err := os.ReadFile(path.Join("testdata", key)); err == nil {
|
||||
buffer.WriteString("-----BEGIN PGP PUBLIC KEY BLOCK-----\n")
|
||||
buffer.WriteString("Version: SKS 1.1.6\n")
|
||||
buffer.WriteString("Comment: Hostname: yay\n\n")
|
||||
buffer.Write(contents)
|
||||
buffer.WriteString("\n-----END PGP PUBLIC KEY BLOCK-----\n")
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func startPgpKeyServer() *http.Server {
|
||||
srv := &http.Server{Addr: fmt.Sprintf("127.0.0.1:%d", gpgServerPort), ReadHeaderTimeout: 1 * time.Second}
|
||||
|
||||
go func() {
|
||||
err := srv.ListenAndServe()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}()
|
||||
return srv
|
||||
}
|
||||
|
||||
func TestImportKeys(t *testing.T) {
|
||||
keyringDir := t.TempDir()
|
||||
|
||||
server := startPgpKeyServer()
|
||||
defer func() {
|
||||
err := server.Shutdown(context.TODO())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}()
|
||||
|
||||
casetests := []struct {
|
||||
keys []string
|
||||
wantError bool
|
||||
}{
|
||||
// Single key, should succeed.
|
||||
// C52048C0C0748FEE227D47A2702353E0F7E48EDB: Thomas Dickey.
|
||||
{
|
||||
keys: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"},
|
||||
wantError: false,
|
||||
},
|
||||
// Two keys, should succeed as well.
|
||||
// 11E521D646982372EB577A1F8F0871F202119294: Tom Stellard.
|
||||
// B6C8F98282B944E3B0D5C2530FC3042E345AD05D: Hans Wennborg.
|
||||
{
|
||||
keys: []string{
|
||||
"11E521D646982372EB577A1F8F0871F202119294",
|
||||
"B6C8F98282B944E3B0D5C2530FC3042E345AD05D",
|
||||
},
|
||||
wantError: false,
|
||||
},
|
||||
// Single invalid key, should fail.
|
||||
{
|
||||
keys: []string{"THIS-SHOULD-FAIL"},
|
||||
wantError: true,
|
||||
},
|
||||
// Two invalid keys, should fail.
|
||||
{
|
||||
keys: []string{"THIS-SHOULD-FAIL", "THIS-ONE-SHOULD-FAIL-TOO"},
|
||||
wantError: true,
|
||||
},
|
||||
// Invalid + valid key. Should fail as well.
|
||||
// 647F28654894E3BD457199BE38DBBDC86092693E: Greg Kroah-Hartman.
|
||||
{
|
||||
keys: []string{
|
||||
"THIS-SHOULD-FAIL",
|
||||
"647F28654894E3BD457199BE38DBBDC86092693E",
|
||||
},
|
||||
wantError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range casetests {
|
||||
err := importKeys(tt.keys, "gpg", fmt.Sprintf("--homedir %s --keyserver 127.0.0.1", keyringDir))
|
||||
if !tt.wantError {
|
||||
if err != nil {
|
||||
t.Fatalf("Got error %q, want no error", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Here, we want to see the error.
|
||||
if err == nil {
|
||||
t.Fatalf("Got no error; want error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeSrcinfo(pkgbase string, pgpkeys ...string) *gosrc.Srcinfo {
|
||||
srcinfo := gosrc.Srcinfo{}
|
||||
srcinfo.Pkgbase = pkgbase
|
||||
@@ -138,22 +25,21 @@ func makeSrcinfo(pkgbase string, pgpkeys ...string) *gosrc.Srcinfo {
|
||||
}
|
||||
|
||||
func TestCheckPgpKeys(t *testing.T) {
|
||||
keyringDir := t.TempDir()
|
||||
gpgBin := t.TempDir() + "/gpg"
|
||||
|
||||
server := startPgpKeyServer()
|
||||
defer func() {
|
||||
err := server.Shutdown(context.TODO())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}()
|
||||
f, err := os.OpenFile(gpgBin, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
casetests := []struct {
|
||||
name string
|
||||
pkgs map[string]string
|
||||
srcinfos map[string]*gosrc.Srcinfo
|
||||
wantError bool
|
||||
expected []string
|
||||
testcases := []struct {
|
||||
name string
|
||||
pkgs map[string]string
|
||||
srcinfos map[string]*gosrc.Srcinfo
|
||||
wantError bool
|
||||
wantShow []string
|
||||
wantCapture []string
|
||||
showFn func(cmd *exec.Cmd) error
|
||||
expected []string
|
||||
}{
|
||||
// cower: single package, one valid key not yet in the keyring.
|
||||
// 487EACC08557AD082088DABA1EB2638FF56C0C53: Dave Reisner.
|
||||
@@ -162,22 +48,44 @@ func TestCheckPgpKeys(t *testing.T) {
|
||||
pkgs: map[string]string{"cower": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"cower": makeSrcinfo("cower", "487EACC08557AD082088DABA1EB2638FF56C0C53")},
|
||||
wantError: false,
|
||||
expected: []string{"487EACC08557AD082088DABA1EB2638FF56C0C53"},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys 487EACC08557AD082088DABA1EB2638FF56C0C53",
|
||||
"gpg --homedir /tmp --recv-keys 487EACC08557AD082088DABA1EB2638FF56C0C53",
|
||||
},
|
||||
wantCapture: []string{},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
s := cmd.String()
|
||||
if strings.Contains(s, "--list-keys") {
|
||||
return fmt.Errorf("key not found")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
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: map[string]string{"libc++": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{
|
||||
"libc++": makeSrcinfo("libc++", "11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"),
|
||||
},
|
||||
name: "two valid keys not yet in the keyring",
|
||||
pkgs: map[string]string{"libc++": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"libc++": makeSrcinfo("libc++", "11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D")},
|
||||
wantError: false,
|
||||
expected: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys 11E521D646982372EB577A1F8F0871F202119294",
|
||||
"gpg --homedir /tmp --list-keys B6C8F98282B944E3B0D5C2530FC3042E345AD05D",
|
||||
"gpg --homedir /tmp --recv-keys 11E521D646982372EB577A1F8F0871F202119294 B6C8F98282B944E3B0D5C2530FC3042E345AD05D",
|
||||
},
|
||||
wantCapture: []string{},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
s := cmd.String()
|
||||
if strings.Contains(s, "--list-keys") {
|
||||
return fmt.Errorf("key not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
expected: []string{"11E521D646982372EB577A1F8F0871F202119294", "B6C8F98282B944E3B0D5C2530FC3042E345AD05D"},
|
||||
},
|
||||
// Two dummy packages requiring the same key.
|
||||
// ABAF11C65A2970B130ABE3C479BE3E4300411886: Linus Torvalds.
|
||||
{
|
||||
name: "Two dummy packages requiring the same key",
|
||||
pkgs: map[string]string{"dummy-1": "", "dummy-2": ""},
|
||||
@@ -186,8 +94,21 @@ func TestCheckPgpKeys(t *testing.T) {
|
||||
"ABAF11C65A2970B130ABE3C479BE3E4300411886"),
|
||||
"dummy-2": makeSrcinfo("dummy-2", "ABAF11C65A2970B130ABE3C479BE3E4300411886"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"},
|
||||
wantError: false,
|
||||
expected: []string{"ABAF11C65A2970B130ABE3C479BE3E4300411886"},
|
||||
wantCapture: []string{},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys ABAF11C65A2970B130ABE3C479BE3E4300411886",
|
||||
"gpg --homedir /tmp --recv-keys ABAF11C65A2970B130ABE3C479BE3E4300411886",
|
||||
},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
s := cmd.String()
|
||||
if strings.Contains(s, "--list-keys") {
|
||||
return fmt.Errorf("key not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
// dummy package: single package, two valid keys, one of them already
|
||||
// in the keyring.
|
||||
@@ -199,8 +120,23 @@ func TestCheckPgpKeys(t *testing.T) {
|
||||
srcinfos: map[string]*gosrc.Srcinfo{
|
||||
"dummy-3": makeSrcinfo("dummy-3", "11E521D646982372EB577A1F8F0871F202119294", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"},
|
||||
wantError: false,
|
||||
expected: []string{"C52048C0C0748FEE227D47A2702353E0F7E48EDB"},
|
||||
wantCapture: []string{},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
s := cmd.String()
|
||||
if strings.Contains(s, "--list-keys") &&
|
||||
!strings.Contains(s, "11E521D646982372EB577A1F8F0871F202119294") {
|
||||
return fmt.Errorf("key not found")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys 11E521D646982372EB577A1F8F0871F202119294",
|
||||
"gpg --homedir /tmp --list-keys C52048C0C0748FEE227D47A2702353E0F7E48EDB",
|
||||
"gpg --homedir /tmp --recv-keys C52048C0C0748FEE227D47A2702353E0F7E48EDB",
|
||||
},
|
||||
},
|
||||
// Two dummy packages with existing keys.
|
||||
{
|
||||
@@ -210,32 +146,106 @@ func TestCheckPgpKeys(t *testing.T) {
|
||||
"dummy-4": makeSrcinfo("dummy-4", "11E521D646982372EB577A1F8F0871F202119294"),
|
||||
"dummy-5": makeSrcinfo("dummy-5", "C52048C0C0748FEE227D47A2702353E0F7E48EDB"),
|
||||
},
|
||||
wantError: false,
|
||||
expected: []string{},
|
||||
wantError: false,
|
||||
expected: []string{},
|
||||
wantCapture: []string{},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
return nil
|
||||
},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys 11E521D646982372EB577A1F8F0871F202119294",
|
||||
"gpg --homedir /tmp --list-keys C52048C0C0748FEE227D47A2702353E0F7E48EDB",
|
||||
},
|
||||
},
|
||||
// Dummy package with invalid key, should fail.
|
||||
{
|
||||
name: "one invalid",
|
||||
pkgs: map[string]string{"dummy-7": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"dummy-7": makeSrcinfo("dummy-7", "THIS-SHOULD-FAIL")},
|
||||
wantError: true,
|
||||
name: "one invalid",
|
||||
pkgs: map[string]string{"dummy-7": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"dummy-7": makeSrcinfo("dummy-7", "THIS-SHOULD-FAIL")},
|
||||
wantError: true,
|
||||
wantCapture: []string{},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys THIS-SHOULD-FAIL",
|
||||
"gpg --homedir /tmp --recv-keys THIS-SHOULD-FAIL",
|
||||
},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
s := cmd.String()
|
||||
if strings.Contains(s, "--list-keys") {
|
||||
return fmt.Errorf("key not found")
|
||||
}
|
||||
|
||||
if strings.Contains(s, "--recv-keys") {
|
||||
return fmt.Errorf("invalid key")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
// Dummy package with both an invalid an another valid key, should fail.
|
||||
// A314827C4E4250A204CE6E13284FC34C8E4B1A25: Thomas Bächler.
|
||||
{
|
||||
name: "one invalid, one valid",
|
||||
pkgs: map[string]string{"dummy-8": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"dummy-8": makeSrcinfo("dummy-8", "A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL")},
|
||||
wantError: true,
|
||||
expected: []string{},
|
||||
name: "one invalid, one valid",
|
||||
pkgs: map[string]string{"dummy-8": ""},
|
||||
srcinfos: map[string]*gosrc.Srcinfo{"dummy-8": makeSrcinfo("dummy-8", "A314827C4E4250A204CE6E13284FC34C8E4B1A25", "THIS-SHOULD-FAIL")},
|
||||
wantError: true,
|
||||
expected: []string{},
|
||||
wantCapture: []string{},
|
||||
showFn: func(cmd *exec.Cmd) error {
|
||||
s := cmd.String()
|
||||
if strings.Contains(s, "--list-keys") {
|
||||
return fmt.Errorf("key not found")
|
||||
}
|
||||
|
||||
if strings.Contains(s, "--recv-keys") {
|
||||
return fmt.Errorf("invalid key")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
wantShow: []string{
|
||||
"gpg --homedir /tmp --list-keys A314827C4E4250A204CE6E13284FC34C8E4B1A25",
|
||||
"gpg --homedir /tmp --list-keys THIS-SHOULD-FAIL",
|
||||
"gpg --homedir /tmp --recv-keys A314827C4E4250A204CE6E13284FC34C8E4B1A25 THIS-SHOULD-FAIL",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range casetests {
|
||||
for _, tt := range testcases {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
problematic, err := CheckPgpKeys(tt.pkgs, tt.srcinfos, "gpg",
|
||||
fmt.Sprintf("--homedir %s --keyserver 127.0.0.1", keyringDir), true)
|
||||
mockRunner := &exe.MockRunner{
|
||||
ShowFn: tt.showFn,
|
||||
CaptureFn: func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
|
||||
return "", "", nil
|
||||
},
|
||||
}
|
||||
|
||||
cmdBuilder := exe.CmdBuilder{
|
||||
GPGBin: gpgBin,
|
||||
GPGFlags: []string{"--homedir /tmp"},
|
||||
Runner: mockRunner,
|
||||
}
|
||||
problematic, err := CheckPgpKeys(context.Background(), tt.pkgs, tt.srcinfos, &cmdBuilder, true)
|
||||
|
||||
require.Len(t, mockRunner.ShowCalls, len(tt.wantShow))
|
||||
require.Len(t, mockRunner.CaptureCalls, len(tt.wantCapture))
|
||||
|
||||
sort.SliceStable(mockRunner.ShowCalls, func(i, j int) bool {
|
||||
return mockRunner.ShowCalls[i].Args[0].(*exec.Cmd).String() < mockRunner.ShowCalls[j].Args[0].(*exec.Cmd).String()
|
||||
})
|
||||
for i, call := range mockRunner.ShowCalls {
|
||||
show := call.Args[0].(*exec.Cmd).String()
|
||||
show = strings.ReplaceAll(show, gpgBin, "gpg")
|
||||
|
||||
// options are in a different order on different systems and on CI root user is used
|
||||
assert.Subset(t, strings.Split(show, " "), strings.Split(tt.wantShow[i], " "), show)
|
||||
}
|
||||
|
||||
for i, call := range mockRunner.CaptureCalls {
|
||||
capture := call.Args[0].(*exec.Cmd).String()
|
||||
capture = strings.ReplaceAll(capture, gpgBin, "gpg")
|
||||
assert.Subset(t, strings.Split(capture, " "), strings.Split(tt.wantCapture[i], " "), capture)
|
||||
}
|
||||
|
||||
if tt.wantError {
|
||||
require.Error(t, err)
|
||||
|
||||
@@ -28,6 +28,10 @@ const (
|
||||
Minimal
|
||||
)
|
||||
|
||||
type AURCache interface {
|
||||
Get(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error)
|
||||
}
|
||||
|
||||
type SourceQueryBuilder struct {
|
||||
repoQuery
|
||||
aurQuery
|
||||
@@ -40,12 +44,12 @@ type SourceQueryBuilder struct {
|
||||
singleLineResults bool
|
||||
|
||||
aurClient aur.ClientInterface
|
||||
aurCache *metadata.Client
|
||||
aurCache AURCache
|
||||
}
|
||||
|
||||
func NewSourceQueryBuilder(
|
||||
aurClient aur.ClientInterface,
|
||||
aurCache *metadata.Client,
|
||||
aurCache AURCache,
|
||||
sortBy string,
|
||||
targetMode parser.TargetMode,
|
||||
searchBy string,
|
||||
@@ -193,7 +197,7 @@ func filterAURResults(pkgS []string, results []aur.Pkg) []aur.Pkg {
|
||||
|
||||
// queryAUR searches AUR and narrows based on subarguments.
|
||||
func queryAUR(ctx context.Context,
|
||||
aurClient aur.ClientInterface, aurMetadata *metadata.Client,
|
||||
aurClient aur.ClientInterface, aurMetadata AURCache,
|
||||
pkgS []string, searchBy string, newEngine bool,
|
||||
) ([]aur.Pkg, error) {
|
||||
var (
|
||||
|
||||
@@ -28,6 +28,7 @@ type GitCmdBuilder interface {
|
||||
type ICmdBuilder interface {
|
||||
Runner
|
||||
BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
|
||||
BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd
|
||||
BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd
|
||||
BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd
|
||||
AddMakepkgFlag(string)
|
||||
@@ -38,6 +39,8 @@ type ICmdBuilder interface {
|
||||
type CmdBuilder struct {
|
||||
GitBin string
|
||||
GitFlags []string
|
||||
GPGBin string
|
||||
GPGFlags []string
|
||||
MakepkgFlags []string
|
||||
MakepkgConfPath string
|
||||
MakepkgBin string
|
||||
@@ -50,6 +53,21 @@ type CmdBuilder struct {
|
||||
Runner Runner
|
||||
}
|
||||
|
||||
func (c *CmdBuilder) BuildGPGCmd(ctx context.Context, extraArgs ...string) *exec.Cmd {
|
||||
args := make([]string, len(c.GPGFlags), len(c.GPGFlags)+len(extraArgs))
|
||||
copy(args, c.GPGFlags)
|
||||
|
||||
if len(extraArgs) > 0 {
|
||||
args = append(args, extraArgs...)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, c.GPGBin, args...)
|
||||
|
||||
cmd = c.deElevateCommand(ctx, cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c *CmdBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd {
|
||||
args := make([]string, len(c.GitFlags), len(c.GitFlags)+len(extraArgs))
|
||||
copy(args, c.GitFlags)
|
||||
|
||||
@@ -2,6 +2,7 @@ package exe
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/settings/parser"
|
||||
@@ -10,6 +11,11 @@ import (
|
||||
type Call struct {
|
||||
Res []interface{}
|
||||
Args []interface{}
|
||||
Dir string
|
||||
}
|
||||
|
||||
func (c *Call) String() string {
|
||||
return fmt.Sprintf("%+v", c.Args)
|
||||
}
|
||||
|
||||
type MockBuilder struct {
|
||||
@@ -84,6 +90,7 @@ func (m *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) {
|
||||
Args: []interface{}{
|
||||
cmd,
|
||||
},
|
||||
Dir: cmd.Dir,
|
||||
})
|
||||
|
||||
if m.CaptureFn != nil {
|
||||
@@ -103,6 +110,7 @@ func (m *MockRunner) Show(cmd *exec.Cmd) error {
|
||||
Args: []interface{}{
|
||||
cmd,
|
||||
},
|
||||
Dir: cmd.Dir,
|
||||
})
|
||||
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
@@ -15,6 +16,10 @@ import (
|
||||
"github.com/Morganamilo/go-pacmanconf"
|
||||
)
|
||||
|
||||
type AURCache interface {
|
||||
Get(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error)
|
||||
}
|
||||
|
||||
type Runtime struct {
|
||||
Mode parser.TargetMode
|
||||
QueryBuilder query.Builder
|
||||
@@ -23,11 +28,11 @@ type Runtime struct {
|
||||
CompletionPath string
|
||||
ConfigPath string
|
||||
PacmanConf *pacmanconf.Config
|
||||
VCSStore *vcs.InfoStore
|
||||
VCSStore vcs.Store
|
||||
CmdBuilder exe.ICmdBuilder
|
||||
HTTPClient *http.Client
|
||||
AURClient *aur.Client
|
||||
VoteClient *vote.Client
|
||||
AURCache *metadata.Client
|
||||
AURCache AURCache
|
||||
DBExecutor db.Executor
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ type NodeInfo[V any] struct {
|
||||
Value V
|
||||
}
|
||||
|
||||
type CheckFn[T comparable, V any] func(T, V) error
|
||||
|
||||
type Graph[T comparable, V any] struct {
|
||||
alias AliasMap[T] // alias -> aliased
|
||||
aliases DepMap[T] // aliased -> alias
|
||||
@@ -234,7 +236,7 @@ func (g *Graph[T, V]) TopoSortedLayers() [][]T {
|
||||
}
|
||||
|
||||
// TopoSortedLayerMap returns a slice of all of the graph nodes in topological sort order with their node info.
|
||||
func (g *Graph[T, V]) TopoSortedLayerMap() []map[T]V {
|
||||
func (g *Graph[T, V]) TopoSortedLayerMap(checkFn CheckFn[T, V]) []map[T]V {
|
||||
layers := []map[T]V{}
|
||||
|
||||
// Copy the graph
|
||||
@@ -249,6 +251,11 @@ func (g *Graph[T, V]) TopoSortedLayerMap() []map[T]V {
|
||||
layers = append(layers, leaves)
|
||||
|
||||
for leafNode := range leaves {
|
||||
if checkFn != nil {
|
||||
if err := checkFn(leafNode, leaves[leafNode]); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
shrinkingGraph.remove(leafNode)
|
||||
}
|
||||
}
|
||||
|
||||
36
preparer.go
36
preparer.go
@@ -26,31 +26,31 @@ type PreparerHookFunc func(ctx context.Context, config *settings.Configuration,
|
||||
type Preparer struct {
|
||||
dbExecutor db.Executor
|
||||
cmdBuilder exe.ICmdBuilder
|
||||
config *settings.Configuration
|
||||
cfg *settings.Configuration
|
||||
postDownloadHooks []PreparerHookFunc
|
||||
postMergeHooks []PreparerHookFunc
|
||||
|
||||
makeDeps []string
|
||||
}
|
||||
|
||||
func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder, config *settings.Configuration) *Preparer {
|
||||
func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder, cfg *settings.Configuration) *Preparer {
|
||||
preper := &Preparer{
|
||||
dbExecutor: dbExecutor,
|
||||
cmdBuilder: cmdBuilder,
|
||||
config: config,
|
||||
cfg: cfg,
|
||||
postDownloadHooks: []PreparerHookFunc{},
|
||||
postMergeHooks: []PreparerHookFunc{},
|
||||
}
|
||||
|
||||
if config.CleanMenu {
|
||||
if cfg.CleanMenu {
|
||||
preper.postDownloadHooks = append(preper.postDownloadHooks, menus.CleanFn)
|
||||
}
|
||||
|
||||
if config.DiffMenu {
|
||||
if cfg.DiffMenu {
|
||||
preper.postMergeHooks = append(preper.postMergeHooks, menus.DiffFn)
|
||||
}
|
||||
|
||||
if config.EditMenu {
|
||||
if cfg.EditMenu {
|
||||
preper.postMergeHooks = append(preper.postMergeHooks, menus.EditFn)
|
||||
}
|
||||
|
||||
@@ -58,14 +58,14 @@ func NewPreparer(dbExecutor db.Executor, cmdBuilder exe.ICmdBuilder, config *set
|
||||
}
|
||||
|
||||
func (preper *Preparer) ShouldCleanAURDirs(pkgBuildDirs map[string]string) PostInstallHookFunc {
|
||||
if !preper.config.CleanAfter || len(pkgBuildDirs) == 0 {
|
||||
if !preper.cfg.CleanAfter || len(pkgBuildDirs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
text.Debugln("added post install hook to clean up AUR dirs", pkgBuildDirs)
|
||||
|
||||
return func(ctx context.Context) error {
|
||||
cleanAfter(ctx, preper.config.Runtime.CmdBuilder, pkgBuildDirs)
|
||||
cleanAfter(ctx, preper.cfg.Runtime.CmdBuilder, pkgBuildDirs)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func (preper *Preparer) ShouldCleanMakeDeps() PostInstallHookFunc {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch preper.config.RemoveMake {
|
||||
switch preper.cfg.RemoveMake {
|
||||
case "yes":
|
||||
break
|
||||
case "no":
|
||||
@@ -89,7 +89,7 @@ func (preper *Preparer) ShouldCleanMakeDeps() PostInstallHookFunc {
|
||||
text.Debugln("added post install hook to clean up AUR makedeps", preper.makeDeps)
|
||||
|
||||
return func(ctx context.Context) error {
|
||||
return removeMake(ctx, preper.config.Runtime.CmdBuilder, preper.makeDeps)
|
||||
return removeMake(ctx, preper.cfg.Runtime.CmdBuilder, preper.makeDeps)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
|
||||
for _, info := range layer {
|
||||
if info.Source == dep.AUR {
|
||||
pkgBase := *info.AURBase
|
||||
pkgBuildDir := filepath.Join(preper.config.BuildDir, pkgBase)
|
||||
pkgBuildDir := filepath.Join(preper.cfg.BuildDir, pkgBase)
|
||||
if preper.needToCloneAURBase(info, pkgBuildDir) {
|
||||
aurBasesToClone.Add(pkgBase)
|
||||
}
|
||||
@@ -166,27 +166,27 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
|
||||
|
||||
if _, errA := download.AURPKGBUILDRepos(ctx,
|
||||
preper.cmdBuilder, aurBasesToClone.ToSlice(),
|
||||
config.AURURL, config.BuildDir, false); errA != nil {
|
||||
preper.cfg.AURURL, preper.cfg.BuildDir, false); errA != nil {
|
||||
return nil, errA
|
||||
}
|
||||
|
||||
if errP := downloadPKGBUILDSourceFanout(ctx, config.Runtime.CmdBuilder,
|
||||
pkgBuildDirsByBase, false, config.MaxConcurrentDownloads); errP != nil {
|
||||
if errP := downloadPKGBUILDSourceFanout(ctx, preper.cmdBuilder,
|
||||
pkgBuildDirsByBase, false, preper.cfg.MaxConcurrentDownloads); errP != nil {
|
||||
text.Errorln(errP)
|
||||
}
|
||||
|
||||
for _, hookFn := range preper.postDownloadHooks {
|
||||
if err := hookFn(ctx, preper.config, os.Stdout, pkgBuildDirsByBase); err != nil {
|
||||
if err := hookFn(ctx, preper.cfg, os.Stdout, pkgBuildDirsByBase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := mergePkgbuilds(ctx, pkgBuildDirsByBase); err != nil {
|
||||
if err := mergePkgbuilds(ctx, preper.cmdBuilder, pkgBuildDirsByBase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, hookFn := range preper.postMergeHooks {
|
||||
if err := hookFn(ctx, preper.config, os.Stdout, pkgBuildDirsByBase); err != nil {
|
||||
if err := hookFn(ctx, preper.cfg, os.Stdout, pkgBuildDirsByBase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ func (preper *Preparer) PrepareWorkspace(ctx context.Context, targets []map[stri
|
||||
}
|
||||
|
||||
func (preper *Preparer) needToCloneAURBase(installInfo *dep.InstallInfo, pkgbuildDir string) bool {
|
||||
if preper.config.ReDownload == "all" {
|
||||
if preper.cfg.ReDownload == "all" {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
11
srcinfo.go
11
srcinfo.go
@@ -1,18 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Jguer/yay/v11/pkg/db"
|
||||
"github.com/Jguer/yay/v11/pkg/pgp"
|
||||
"github.com/Jguer/yay/v11/pkg/settings"
|
||||
"github.com/Jguer/yay/v11/pkg/settings/exe"
|
||||
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
)
|
||||
|
||||
type srcinfoOperator struct {
|
||||
dbExecutor db.Executor
|
||||
cfg *settings.Configuration
|
||||
cmdBuilder exe.ICmdBuilder
|
||||
}
|
||||
|
||||
func (s *srcinfoOperator) Run(pkgbuildDirs map[string]string) (map[string]*gosrc.Srcinfo, error) {
|
||||
func (s *srcinfoOperator) Run(ctx context.Context, pkgbuildDirs map[string]string) (map[string]*gosrc.Srcinfo, error) {
|
||||
srcinfos, err := parseSrcinfoFiles(pkgbuildDirs, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -22,8 +27,8 @@ func (s *srcinfoOperator) Run(pkgbuildDirs map[string]string) (map[string]*gosrc
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if config.PGPFetch {
|
||||
if _, errCPK := pgp.CheckPgpKeys(pkgbuildDirs, srcinfos, config.GpgBin, config.GpgFlags, settings.NoConfirm); errCPK != nil {
|
||||
if s.cfg.PGPFetch {
|
||||
if _, errCPK := pgp.CheckPgpKeys(ctx, pkgbuildDirs, srcinfos, s.cmdBuilder, settings.NoConfirm); errCPK != nil {
|
||||
return nil, errCPK
|
||||
}
|
||||
}
|
||||
|
||||
28
sync.go
28
sync.go
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -59,7 +60,18 @@ func syncInstall(ctx context.Context,
|
||||
}
|
||||
|
||||
opService := NewOperationService(ctx, config, dbExecutor)
|
||||
return opService.Run(ctx, cmdArgs, graph.TopoSortedLayerMap())
|
||||
multiErr := &multierror.MultiError{}
|
||||
targets := graph.TopoSortedLayerMap(func(s string, ii *dep.InstallInfo) error {
|
||||
if ii.Source == dep.Missing {
|
||||
multiErr.Add(errors.New(gotext.Get("could not find %s%s", s, ii.Version)))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := multiErr.Return(); err != nil {
|
||||
return err
|
||||
}
|
||||
return opService.Run(ctx, cmdArgs, targets)
|
||||
}
|
||||
|
||||
type OperationService struct {
|
||||
@@ -84,7 +96,7 @@ func (o *OperationService) Run(ctx context.Context,
|
||||
fmt.Fprintln(os.Stdout, "", gotext.Get("there is nothing to do"))
|
||||
return nil
|
||||
}
|
||||
preparer := NewPreparer(o.dbExecutor, config.Runtime.CmdBuilder, config)
|
||||
preparer := NewPreparer(o.dbExecutor, o.cfg.Runtime.CmdBuilder, o.cfg)
|
||||
installer := NewInstaller(o.dbExecutor, o.cfg.Runtime.CmdBuilder, o.cfg.Runtime.VCSStore, o.cfg.Runtime.Mode)
|
||||
|
||||
pkgBuildDirs, err := preparer.Run(ctx, os.Stdout, targets)
|
||||
@@ -101,15 +113,19 @@ func (o *OperationService) Run(ctx context.Context,
|
||||
installer.AddPostInstallHook(cleanAURDirsFunc)
|
||||
}
|
||||
|
||||
srcinfoOp := srcinfoOperator{dbExecutor: o.dbExecutor}
|
||||
srcinfos, err := srcinfoOp.Run(pkgBuildDirs)
|
||||
srcinfoOp := srcinfoOperator{
|
||||
dbExecutor: o.dbExecutor,
|
||||
cfg: o.cfg,
|
||||
cmdBuilder: installer.exeCmd,
|
||||
}
|
||||
srcinfos, err := srcinfoOp.Run(ctx, pkgBuildDirs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
_ = completion.Update(ctx, config.Runtime.HTTPClient, o.dbExecutor,
|
||||
config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, false)
|
||||
_ = completion.Update(ctx, o.cfg.Runtime.HTTPClient, o.dbExecutor,
|
||||
o.cfg.AURURL, o.cfg.Runtime.CompletionPath, o.cfg.CompletionInterval, false)
|
||||
}()
|
||||
|
||||
err = installer.Install(ctx, cmdArgs, targets, pkgBuildDirs, srcinfos)
|
||||
|
||||
43
testdata/jfin/.SRCINFO
vendored
Normal file
43
testdata/jfin/.SRCINFO
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
pkgbase = jellyfin
|
||||
pkgdesc = The Free Software Media System
|
||||
pkgver = 10.8.4
|
||||
pkgrel = 1
|
||||
url = https://github.com/jellyfin/jellyfin
|
||||
arch = i686
|
||||
arch = x86_64
|
||||
arch = armv6h
|
||||
license = GPL2
|
||||
makedepends = dotnet-sdk>=6
|
||||
makedepends = dotnet-sdk<7
|
||||
makedepends = nodejs
|
||||
makedepends = npm
|
||||
makedepends = git
|
||||
source = jellyfin-10.8.4.tar.gz::https://github.com/jellyfin/jellyfin/archive/v10.8.4.tar.gz
|
||||
source = jellyfin-web-10.8.4.tar.gz::https://github.com/jellyfin/jellyfin-web/archive/v10.8.4.tar.gz
|
||||
source = jellyfin.conf
|
||||
source = jellyfin.service
|
||||
source = jellyfin.sysusers
|
||||
source = jellyfin.tmpfiles
|
||||
sha512sums = cf472f36a759a7eb3724dac79d3bd2d6c9c58fc375293ad6eb8b5ce1ea1a8f6dd296cc36113b80b1c705a99eafb2bd9ffd9381fd52fa19aa12018d50656c9bde
|
||||
sha512sums = 21983940689475de7f9d37a1016fb2dd740986ac27ffa2e0eac0bc9c84d68ac557fdc8afb64ca70b867af2d1e438293b98d5c155da402d3e985ab831042ba176
|
||||
sha512sums = 2aa97a1a7a8a447171b59be3e93183e09cbbc32c816843cc47c6777b9aec48bd9c1d9d354f166e0b000ad8d2e94e6e4b0559aa52e5c159abbc103ed2c5afa3f0
|
||||
sha512sums = 99d02080b1b92e731250f39ddd13ceca7129d69d0c05e0939620cbc3f499a9574668c63fa889704a4905560888131e980d7ab1fbcc5837b04d33ce26daa9d42b
|
||||
sha512sums = 6fc2638e6ec4b1ee0240e17815c91107b694e5fde72c1bc7956c83067bbeacb632de899b86837e47a0ec04288131b15c20746373b45e0669c8976069a55d627a
|
||||
sha512sums = 45a62b62d97b9a83289d4dfde684163b1bcf340c1921fb958e5a701812c61b392901841940c67e5fa5148783277d5b4dc65ba01d3a22e8f855ea62154ad9be33
|
||||
|
||||
pkgname = jellyfin
|
||||
depends = jellyfin-web=10.8.4
|
||||
depends = jellyfin-server=10.8.4
|
||||
|
||||
pkgname = jellyfin-web
|
||||
pkgdesc = Jellyfin web client
|
||||
|
||||
pkgname = jellyfin-server
|
||||
pkgdesc = Jellyfin server component
|
||||
depends = dotnet-runtime>=6
|
||||
depends = dotnet-runtime<7
|
||||
depends = aspnet-runtime>=6
|
||||
depends = aspnet-runtime<7
|
||||
depends = ffmpeg
|
||||
depends = sqlite
|
||||
backup = etc/conf.d/jellyfin
|
||||
@@ -37,7 +37,7 @@ func filterUpdateList(list []db.Upgrade, filter upgrade.Filter) []db.Upgrade {
|
||||
}
|
||||
|
||||
// upList returns lists of packages to upgrade from each source.
|
||||
func upList(ctx context.Context, aurCache *metadata.Client,
|
||||
func upList(ctx context.Context, aurCache settings.AURCache,
|
||||
warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade bool,
|
||||
filter upgrade.Filter,
|
||||
) (aurUp, repoUp upgrade.UpSlice, err error) {
|
||||
@@ -262,7 +262,7 @@ func sysupgradeTargets(ctx context.Context, dbExecutor db.Executor,
|
||||
|
||||
// Targets for sys upgrade.
|
||||
func sysupgradeTargetsV2(ctx context.Context,
|
||||
aurCache *metadata.Client,
|
||||
aurCache settings.AURCache,
|
||||
dbExecutor db.Executor,
|
||||
graph *topo.Graph[string, *dep.InstallInfo],
|
||||
enableDowngrade bool,
|
||||
|
||||
Reference in New Issue
Block a user