From 7da9f4869d0e8d3897a62a662e5eec542d8377b1 Mon Sep 17 00:00:00 2001 From: Jo Date: Fri, 16 Dec 2022 17:23:44 +0000 Subject: [PATCH] feat(new engine): skip built and respect --needed (#1852) * add built package check * respect --needed for new engine * add needed check and test * add test for not built --- aur_install.go | 129 +++++++++++++++++++--------- aur_install_test.go | 179 +++++++++++++++++++++++++++++++++++++++ errors.go | 8 ++ install.go | 80 +++++++++++------ pkg/db/mock/executor.go | 4 + pkg/settings/exe/mock.go | 109 ++++++++++++++++++++++++ pkg/vcs/mock.go | 25 ++++++ pkg/vcs/vcs.go | 9 ++ sync.go | 8 +- 9 files changed, 480 insertions(+), 71 deletions(-) create mode 100644 aur_install_test.go create mode 100644 pkg/settings/exe/mock.go create mode 100644 pkg/vcs/mock.go diff --git a/aur_install.go b/aur_install.go index 7015b954..37e65c3f 100644 --- a/aur_install.go +++ b/aur_install.go @@ -10,8 +10,10 @@ import ( "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/exe" "github.com/Jguer/yay/v11/pkg/settings/parser" "github.com/Jguer/yay/v11/pkg/text" + "github.com/Jguer/yay/v11/pkg/vcs" gosrc "github.com/Morganamilo/go-srcinfo" mapset "github.com/deckarep/golang-set/v2" @@ -24,14 +26,20 @@ type ( dbExecutor db.Executor postInstallHooks []PostInstallHookFunc failedAndIngnored map[string]error + exeCmd exe.ICmdBuilder + vcsStore vcs.Store + targetMode parser.TargetMode } ) -func NewInstaller(dbExecutor db.Executor) *Installer { +func NewInstaller(dbExecutor db.Executor, exeCmd exe.ICmdBuilder, vcsStore vcs.Store, targetMode parser.TargetMode) *Installer { return &Installer{ dbExecutor: dbExecutor, postInstallHooks: []PostInstallHookFunc{}, failedAndIngnored: map[string]error{}, + exeCmd: exeCmd, + vcsStore: vcsStore, + targetMode: targetMode, } } @@ -163,38 +171,9 @@ func (installer *Installer) installAURPackages(ctx context.Context, for _, name := range all { base := nameToBase[name] dir := pkgBuildDirsByBase[base] - args := []string{"--nobuild", "-fC"} - if installIncompatible { - args = append(args, "--ignorearch") - } - - // pkgver bump - if err := config.Runtime.CmdBuilder.Show( - config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, dir, args...)); err != nil { - if !lastLayer { - return fmt.Errorf("%s - %w", gotext.Get("error making: %s", base), err) - } - - installer.failedAndIngnored[name] = err - text.Errorln(gotext.Get("error making: %s", base), "-", err) - continue - } - - pkgdests, _, errList := parsePackageList(ctx, dir) - if errList != nil { - return errList - } - - args = []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} - - if installIncompatible { - args = append(args, "--ignorearch") - } - - if errMake := config.Runtime.CmdBuilder.Show( - config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, - dir, args...)); errMake != nil { + pkgdests, errMake := installer.buildPkg(ctx, dir, base, installIncompatible, cmdArgs.ExistsArg("needed")) + if errMake != nil { if !lastLayer { return fmt.Errorf("%s - %w", gotext.Get("error making: %s", base), errMake) } @@ -204,6 +183,11 @@ func (installer *Installer) installAURPackages(ctx context.Context, continue } + if len(pkgdests) == 0 { + text.Warnln(gotext.Get("nothing to install for %s", text.Cyan(base))) + continue + } + newPKGArchives, hasDebug, err := installer.getNewTargets(pkgdests, name) if err != nil { return err @@ -223,22 +207,89 @@ func (installer *Installer) installAURPackages(ctx context.Context, srcinfo := srcinfos[base] wg.Add(1) - go config.Runtime.VCSStore.Update(ctx, name, srcinfo.Source, &mux, &wg) + go installer.vcsStore.Update(ctx, name, srcinfo.Source, &mux, &wg) } wg.Wait() - if err := installPkgArchive(ctx, cmdArgs, pkgArchives); err != nil { + if err := installPkgArchive(ctx, installer.exeCmd, installer.targetMode, installer.vcsStore, cmdArgs, pkgArchives); err != nil { return fmt.Errorf("%s - %w", fmt.Sprintf(gotext.Get("error installing:")+" %v", pkgArchives), err) } - if err := setInstallReason(ctx, cmdArgs, deps, exps); err != nil { + if err := setInstallReason(ctx, installer.exeCmd, installer.targetMode, cmdArgs, deps, exps); err != nil { return fmt.Errorf("%s - %w", fmt.Sprintf(gotext.Get("error installing:")+" %v", pkgArchives), err) } return nil } +func (installer *Installer) buildPkg(ctx context.Context, + dir, base string, + installIncompatible, needed bool, +) (map[string]string, error) { + args := []string{"--nobuild", "-fC"} + + if installIncompatible { + args = append(args, "--ignorearch") + } + + // pkgver bump + if err := installer.exeCmd.Show( + installer.exeCmd.BuildMakepkgCmd(ctx, dir, args...)); err != nil { + return nil, err + } + + pkgdests, pkgVersion, errList := parsePackageList(ctx, installer.exeCmd, dir) + if errList != nil { + return nil, errList + } + + switch { + case needed && installer.pkgsAreAlreadyInstalled(pkgdests, pkgVersion): + args = []string{"-c", "--nobuild", "--noextract", "--ignorearch"} + pkgdests = map[string]string{} + text.Warnln(gotext.Get("%s is up to date -- skipping", text.Cyan(base+"-"+pkgVersion))) + case pkgsAreBuilt(pkgdests): + args = []string{"-c", "--nobuild", "--noextract", "--ignorearch"} + text.Warnln(gotext.Get("%s already made -- skipping build", text.Cyan(base+"-"+pkgVersion))) + default: + args = []string{"-cf", "--noconfirm", "--noextract", "--noprepare", "--holdver"} + if installIncompatible { + args = append(args, "--ignorearch") + } + } + + errMake := installer.exeCmd.Show( + installer.exeCmd.BuildMakepkgCmd(ctx, + dir, args...)) + if errMake != nil { + return nil, errMake + } + + return pkgdests, nil +} + +func (installer *Installer) pkgsAreAlreadyInstalled(pkgdests map[string]string, pkgVersion string) bool { + for pkgName := range pkgdests { + if !installer.dbExecutor.IsCorrectVersionInstalled(pkgName, pkgVersion) { + return false + } + } + + return true +} + +func pkgsAreBuilt(pkgdests map[string]string) bool { + for _, pkgdest := range pkgdests { + if _, err := os.Stat(pkgdest); err != nil { + text.Debugln("pkgIsBuilt:", pkgdest, "does not exist") + return false + } + } + + return true +} + func (*Installer) isDep(cmdArgs *parser.Arguments, aurExpNames mapset.Set[string], name string) bool { switch { case cmdArgs.ExistsArg("asdeps", "asdep"): @@ -279,7 +330,7 @@ func (installer *Installer) getNewTargets(pkgdests map[string]string, name strin return pkgArchives, ok, nil } -func (*Installer) installSyncPackages(ctx context.Context, cmdArgs *parser.Arguments, +func (installer *Installer) installSyncPackages(ctx context.Context, cmdArgs *parser.Arguments, syncDeps, // repo targets that are deps syncExp mapset.Set[string], // repo targets that are exp ) error { @@ -297,14 +348,14 @@ func (*Installer) installSyncPackages(ctx context.Context, cmdArgs *parser.Argum arguments.ClearTargets() arguments.AddTarget(repoTargets...) - errShow := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx, + errShow := installer.exeCmd.Show(installer.exeCmd.BuildPacmanCmd(ctx, arguments, config.Runtime.Mode, settings.NoConfirm)) - if errD := asdeps(ctx, cmdArgs, syncDeps.ToSlice()); errD != nil { + if errD := asdeps(ctx, installer.exeCmd, installer.targetMode, cmdArgs, syncDeps.ToSlice()); errD != nil { return errD } - if errE := asexp(ctx, cmdArgs, syncExp.ToSlice()); errE != nil { + if errE := asexp(ctx, installer.exeCmd, installer.targetMode, cmdArgs, syncExp.ToSlice()); errE != nil { return errE } diff --git a/aur_install_test.go b/aur_install_test.go new file mode 100644 index 00000000..538c3033 --- /dev/null +++ b/aur_install_test.go @@ -0,0 +1,179 @@ +package main + +import ( + "context" + "os" + "os/exec" + "strings" + "testing" + + gosrc "github.com/Morganamilo/go-srcinfo" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/Jguer/yay/v11/pkg/db/mock" + "github.com/Jguer/yay/v11/pkg/dep" + "github.com/Jguer/yay/v11/pkg/settings/exe" + "github.com/Jguer/yay/v11/pkg/settings/parser" + "github.com/Jguer/yay/v11/pkg/vcs" +) + +func ptrString(s string) *string { + return &s +} + +func TestInstaller_InstallNeeded(t *testing.T) { + t.Parallel() + + makepkgBin := t.TempDir() + "/makepkg" + pacmanBin := t.TempDir() + "/pacman" + 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()) + + type testCase struct { + desc string + isInstalled bool + isBuilt bool + wantShow []string + wantCapture []string + } + + testCases := []testCase{ + { + desc: "not installed and not built", + isInstalled: false, + isBuilt: false, + wantShow: []string{ + "makepkg --nobuild -fC --ignorearch", + "makepkg -cf --noconfirm --noextract --noprepare --holdver --ignorearch", + "pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst", + "pacman -D -q --asexplicit --config -- yay", + }, + wantCapture: []string{"makepkg --packagelist"}, + }, + { + desc: "not installed and built", + isInstalled: false, + isBuilt: true, + wantShow: []string{ + "makepkg --nobuild -fC --ignorearch", + "makepkg -c --nobuild --noextract --ignorearch", + "pacman -U --needed --config -- /testdir/yay-91.0.0-1-x86_64.pkg.tar.zst", + "pacman -D -q --asexplicit --config -- yay", + }, + wantCapture: []string{"makepkg --packagelist"}, + }, + { + desc: "installed", + isInstalled: true, + isBuilt: false, + wantShow: []string{ + "makepkg --nobuild -fC --ignorearch", + "makepkg -c --nobuild --noextract --ignorearch", + }, + wantCapture: []string{"makepkg --packagelist"}, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.desc, func(td *testing.T) { + tmpDir := td.TempDir() + pkgTar := tmpDir + "/yay-91.0.0-1-x86_64.pkg.tar.zst" + + captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) { + return pkgTar, "", nil + } + + i := 0 + showOverride := func(cmd *exec.Cmd) error { + i++ + if i == 2 { + if !tc.isBuilt { + f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666) + require.NoError(td, err) + require.NoError(td, f.Close()) + } + } + return nil + } + + // create a mock file + if tc.isBuilt { + f, err := os.OpenFile(pkgTar, os.O_RDONLY|os.O_CREATE, 0o666) + require.NoError(td, err) + require.NoError(td, f.Close()) + } + + isCorrectInstalledOverride := func(string, string) bool { + return tc.isInstalled + } + + mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFunc: isCorrectInstalledOverride} + mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride} + cmdBuilder := &exe.CmdBuilder{ + MakepkgBin: makepkgBin, + SudoBin: "su", + PacmanBin: pacmanBin, + Runner: mockRunner, + SudoLoopEnabled: false, + } + + cmdBuilder.Runner = mockRunner + + installer := NewInstaller(mockDB, cmdBuilder, &vcs.Mock{}, parser.ModeAny) + + cmdArgs := parser.MakeArguments() + cmdArgs.AddArg("needed") + cmdArgs.AddTarget("yay") + + pkgBuildDirs := map[string]string{ + "yay": tmpDir, + } + + srcInfos := map[string]*gosrc.Srcinfo{"yay": {}} + + targets := []map[string]*dep.InstallInfo{ + { + "yay": { + Source: dep.AUR, + Reason: dep.Explicit, + Version: "91.0.0-1", + SrcinfoPath: ptrString(tmpDir + "/.SRCINFO"), + AURBase: ptrString("yay"), + SyncDBName: nil, + }, + }, + } + + errI := installer.Install(context.Background(), cmdArgs, targets, pkgBuildDirs, srcInfos) + require.NoError(td, errI) + + require.Len(td, mockRunner.ShowCalls, len(tc.wantShow)) + require.Len(td, mockRunner.CaptureCalls, len(tc.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") + + // options are in a different order on different systems and on CI root user is used + assert.Subset(td, strings.Split(show, " "), strings.Split(tc.wantShow[i], " "), show) + } + + for i, call := range mockRunner.CaptureCalls { + capture := call.Args[0].(*exec.Cmd).String() + capture = strings.ReplaceAll(capture, tmpDir, "/testdir") // replace the temp dir with a static path + capture = strings.ReplaceAll(capture, makepkgBin, "makepkg") + capture = strings.ReplaceAll(capture, pacmanBin, "pacman") + assert.Subset(td, strings.Split(capture, " "), strings.Split(tc.wantCapture[i], " "), capture) + } + }) + } +} diff --git a/errors.go b/errors.go index be0d647a..39ab6ada 100644 --- a/errors.go +++ b/errors.go @@ -2,6 +2,14 @@ package main import "github.com/leonelquinteros/gotext" +type NoPkgDestsFoundError struct { + dir string +} + +func (e *NoPkgDestsFoundError) Error() string { + return gotext.Get("could not find any package archives listed in %s", e.dir) +} + type SetPkgReasonError struct { exp bool // explicit } diff --git a/install.go b/install.go index 667a32c3..81dbf548 100644 --- a/install.go +++ b/install.go @@ -27,9 +27,14 @@ import ( "github.com/Jguer/yay/v11/pkg/settings/parser" "github.com/Jguer/yay/v11/pkg/stringset" "github.com/Jguer/yay/v11/pkg/text" + "github.com/Jguer/yay/v11/pkg/vcs" ) -func setPkgReason(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string, exp bool) error { +func setPkgReason(ctx context.Context, + cmdBuilder exe.ICmdBuilder, + mode parser.TargetMode, + cmdArgs *parser.Arguments, pkgs []string, exp bool, +) error { if len(pkgs) == 0 { return nil } @@ -56,20 +61,26 @@ func setPkgReason(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string, cmdArgs.AddTarget(pkgName) } - if err := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx, - cmdArgs, config.Runtime.Mode, settings.NoConfirm)); err != nil { + if err := cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx, + cmdArgs, mode, settings.NoConfirm)); err != nil { return &SetPkgReasonError{exp: exp} } return nil } -func asdeps(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string) error { - return setPkgReason(ctx, cmdArgs, pkgs, false) +func asdeps(ctx context.Context, + cmdBuilder exe.ICmdBuilder, + mode parser.TargetMode, cmdArgs *parser.Arguments, pkgs []string, +) error { + return setPkgReason(ctx, cmdBuilder, mode, cmdArgs, pkgs, false) } -func asexp(ctx context.Context, cmdArgs *parser.Arguments, pkgs []string) error { - return setPkgReason(ctx, cmdArgs, pkgs, true) +func asexp(ctx context.Context, + cmdBuilder exe.ICmdBuilder, + mode parser.TargetMode, cmdArgs *parser.Arguments, pkgs []string, +) error { + return setPkgReason(ctx, cmdBuilder, mode, cmdArgs, pkgs, true) } // Install handles package installs. @@ -323,11 +334,11 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu } } - if errDeps := asdeps(ctx, cmdArgs, deps); errDeps != nil { + if errDeps := asdeps(ctx, config.Runtime.CmdBuilder, config.Runtime.Mode, cmdArgs, deps); errDeps != nil { return errDeps } - if errExp := asexp(ctx, cmdArgs, exp); errExp != nil { + if errExp := asexp(ctx, config.Runtime.CmdBuilder, config.Runtime.Mode, cmdArgs, exp); errExp != nil { return errExp } } @@ -487,9 +498,11 @@ nextpkg: return nil } -func parsePackageList(ctx context.Context, dir string) (pkgdests map[string]string, pkgVersion string, err error) { - stdout, stderr, err := config.Runtime.CmdBuilder.Capture( - config.Runtime.CmdBuilder.BuildMakepkgCmd(ctx, dir, "--packagelist")) +func parsePackageList(ctx context.Context, cmdBuilder exe.ICmdBuilder, + dir string, +) (pkgdests map[string]string, pkgVersion string, err error) { + stdout, stderr, err := cmdBuilder.Capture( + cmdBuilder.BuildMakepkgCmd(ctx, dir, "--packagelist")) if err != nil { return nil, "", fmt.Errorf("%s %s", stderr, err) } @@ -517,6 +530,10 @@ func parsePackageList(ctx context.Context, dir string) (pkgdests map[string]stri pkgdests[pkgName] = line } + if len(pkgdests) == 0 { + return nil, "", &NoPkgDestsFoundError{dir} + } + return pkgdests, pkgVersion, nil } @@ -644,8 +661,9 @@ func buildInstallPkgbuilds( if !satisfied || !config.BatchInstall { text.Debugln("non batch installing archives:", pkgArchives) - errArchive := installPkgArchive(ctx, cmdArgs, pkgArchives) - errReason := setInstallReason(ctx, cmdArgs, deps, exp) + errArchive := installPkgArchive(ctx, config.Runtime.CmdBuilder, + config.Runtime.Mode, config.Runtime.VCSStore, cmdArgs, pkgArchives) + errReason := setInstallReason(ctx, config.Runtime.CmdBuilder, config.Runtime.Mode, cmdArgs, deps, exp) deps = make([]string, 0) exp = make([]string, 0) @@ -678,7 +696,7 @@ func buildInstallPkgbuilds( return errors.New(gotext.Get("error making: %s", base.String())) } - pkgdests, pkgVersion, errList := parsePackageList(ctx, dir) + pkgdests, pkgVersion, errList := parsePackageList(ctx, config.Runtime.CmdBuilder, dir) if errList != nil { return errList } @@ -797,12 +815,12 @@ func buildInstallPkgbuilds( } text.Debugln("installing archives:", pkgArchives) - errArchive := installPkgArchive(ctx, cmdArgs, pkgArchives) + errArchive := installPkgArchive(ctx, config.Runtime.CmdBuilder, config.Runtime.Mode, config.Runtime.VCSStore, cmdArgs, pkgArchives) if errArchive != nil { go config.Runtime.VCSStore.RemovePackage([]string{do.Aur[len(do.Aur)-1].String()}) } - errReason := setInstallReason(ctx, cmdArgs, deps, exp) + errReason := setInstallReason(ctx, config.Runtime.CmdBuilder, config.Runtime.Mode, cmdArgs, deps, exp) if errReason != nil { go config.Runtime.VCSStore.RemovePackage([]string{do.Aur[len(do.Aur)-1].String()}) } @@ -812,7 +830,13 @@ func buildInstallPkgbuilds( return nil } -func installPkgArchive(ctx context.Context, cmdArgs *parser.Arguments, pkgArchives []string) error { +func installPkgArchive(ctx context.Context, + cmdBuilder exe.ICmdBuilder, + mode parser.TargetMode, + vcsStore vcs.Store, + cmdArgs *parser.Arguments, + pkgArchives []string, +) error { if len(pkgArchives) == 0 { return nil } @@ -833,28 +857,31 @@ func installPkgArchive(ctx context.Context, cmdArgs *parser.Arguments, pkgArchiv arguments.AddTarget(pkgArchives...) - if errShow := config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx, - arguments, config.Runtime.Mode, settings.NoConfirm)); errShow != nil { + if errShow := cmdBuilder.Show(cmdBuilder.BuildPacmanCmd(ctx, + arguments, mode, settings.NoConfirm)); errShow != nil { return errShow } - if errStore := config.Runtime.VCSStore.Save(); errStore != nil { + if errStore := vcsStore.Save(); errStore != nil { fmt.Fprintln(os.Stderr, errStore) } return nil } -func setInstallReason(ctx context.Context, cmdArgs *parser.Arguments, deps, exps []string) error { +func setInstallReason(ctx context.Context, + cmdBuilder exe.ICmdBuilder, mode parser.TargetMode, + cmdArgs *parser.Arguments, deps, exps []string, +) error { if len(deps)+len(exps) == 0 { return nil } - if errDeps := asdeps(ctx, cmdArgs, deps); errDeps != nil { + if errDeps := asdeps(ctx, cmdBuilder, mode, cmdArgs, deps); errDeps != nil { return errDeps } - return asexp(ctx, cmdArgs, exps) + return asexp(ctx, cmdBuilder, mode, cmdArgs, exps) } func doAddTarget(dp *dep.Pool, localNamesCache, remoteNamesCache stringset.StringSet, @@ -875,10 +902,7 @@ func doAddTarget(dp *dep.Pool, localNamesCache, remoteNamesCache stringset.Strin return deps, exp, pkgArchives, nil } - return deps, exp, pkgArchives, errors.New( - gotext.Get( - "the PKGDEST for %s is listed by makepkg but does not exist: %s", - name, pkgdest)) + return deps, exp, pkgArchives, &FindPkgDestError{pkgDest: pkgdest, name: name} } pkgArchives = append(pkgArchives, pkgdest) diff --git a/pkg/db/mock/executor.go b/pkg/db/mock/executor.go index d9c31619..cd22c405 100644 --- a/pkg/db/mock/executor.go +++ b/pkg/db/mock/executor.go @@ -16,6 +16,7 @@ type ( type DBExecutor struct { db.Executor + IsCorrectVersionInstalledFunc func(string, string) bool } func (t DBExecutor) AlpmArchitectures() ([]string, error) { @@ -31,6 +32,9 @@ func (t DBExecutor) Cleanup() { } func (t DBExecutor) IsCorrectVersionInstalled(s, s2 string) bool { + if t.IsCorrectVersionInstalledFunc != nil { + return t.IsCorrectVersionInstalledFunc(s, s2) + } panic("implement me") } diff --git a/pkg/settings/exe/mock.go b/pkg/settings/exe/mock.go new file mode 100644 index 00000000..5f35b27e --- /dev/null +++ b/pkg/settings/exe/mock.go @@ -0,0 +1,109 @@ +package exe + +import ( + "context" + "os/exec" + + "github.com/Jguer/yay/v11/pkg/settings/parser" +) + +type Call struct { + Res []interface{} + Args []interface{} +} + +type MockBuilder struct { + Runner Runner + BuildMakepkgCmdCalls []Call + BuildMakepkgCmdFn func(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd + BuildPacmanCmdFn func(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd +} + +type MockRunner struct { + ShowCalls []Call + CaptureCalls []Call + ShowFn func(cmd *exec.Cmd) error + CaptureFn func(cmd *exec.Cmd) (stdout string, stderr string, err error) +} + +func (m *MockBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd { + var res *exec.Cmd + if m.BuildMakepkgCmdFn != nil { + res = m.BuildMakepkgCmdFn(ctx, dir, extraArgs...) + } else { + res = exec.CommandContext(ctx, "makepkg", extraArgs...) + } + + m.BuildMakepkgCmdCalls = append(m.BuildMakepkgCmdCalls, Call{ + Res: []interface{}{res}, + Args: []interface{}{ + ctx, + dir, + extraArgs, + }, + }) + + return res +} + +func (m *MockBuilder) AddMakepkgFlag(flag string) { +} + +func (m *MockBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...string) *exec.Cmd { + return exec.CommandContext(ctx, "git", extraArgs...) +} + +func (m *MockBuilder) BuildPacmanCmd(ctx context.Context, args *parser.Arguments, mode parser.TargetMode, noConfirm bool) *exec.Cmd { + var res *exec.Cmd + + if m.BuildPacmanCmdFn != nil { + res = m.BuildPacmanCmdFn(ctx, args, mode, noConfirm) + } else { + res = exec.CommandContext(ctx, "pacman") + } + + return res +} + +func (m *MockBuilder) SetPacmanDBPath(path string) { +} + +func (m *MockBuilder) SudoLoop() { +} + +func (m *MockBuilder) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) { + return m.Runner.Capture(cmd) +} + +func (m *MockBuilder) Show(cmd *exec.Cmd) error { + return m.Runner.Show(cmd) +} + +func (m *MockRunner) Capture(cmd *exec.Cmd) (stdout, stderr string, err error) { + m.CaptureCalls = append(m.CaptureCalls, Call{ + Args: []interface{}{ + cmd, + }, + }) + + if m.CaptureFn != nil { + return m.CaptureFn(cmd) + } + + return "", "", nil +} + +func (m *MockRunner) Show(cmd *exec.Cmd) error { + var err error + if m.ShowFn != nil { + err = m.ShowFn(cmd) + } + + m.ShowCalls = append(m.ShowCalls, Call{ + Args: []interface{}{ + cmd, + }, + }) + + return err +} diff --git a/pkg/vcs/mock.go b/pkg/vcs/mock.go new file mode 100644 index 00000000..e15a3667 --- /dev/null +++ b/pkg/vcs/mock.go @@ -0,0 +1,25 @@ +package vcs + +import ( + "context" + "sync" + + gosrc "github.com/Morganamilo/go-srcinfo" +) + +type Mock struct{} + +func (m *Mock) Update(ctx context.Context, pkgName string, sources []gosrc.ArchString, mux sync.Locker, wg *sync.WaitGroup) { + wg.Done() +} + +func (m *Mock) Save() error { + return nil +} + +func (m *Mock) RemovePackage(pkgs []string) { +} + +func (m *Mock) Load() error { + return nil +} diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go index f8851ee0..25495af4 100644 --- a/pkg/vcs/vcs.go +++ b/pkg/vcs/vcs.go @@ -17,6 +17,15 @@ import ( "github.com/Jguer/yay/v11/pkg/text" ) +type Store interface { + Update(ctx context.Context, pkgName string, + sources []gosrc.ArchString, mux sync.Locker, wg *sync.WaitGroup, + ) + Save() error + RemovePackage(pkgs []string) + Load() error +} + // InfoStore is a collection of OriginInfoByURL by Package. // Containing a map of last commit SHAs of a repo. type InfoStore struct { diff --git a/sync.go b/sync.go index f816542f..b67224a4 100644 --- a/sync.go +++ b/sync.go @@ -58,14 +58,14 @@ func syncInstall(ctx context.Context, type OperationService struct { ctx context.Context - config *settings.Configuration + cfg *settings.Configuration dbExecutor db.Executor } -func NewOperationService(ctx context.Context, config *settings.Configuration, dbExecutor db.Executor) *OperationService { +func NewOperationService(ctx context.Context, cfg *settings.Configuration, dbExecutor db.Executor) *OperationService { return &OperationService{ ctx: ctx, - config: config, + cfg: cfg, dbExecutor: dbExecutor, } } @@ -79,7 +79,7 @@ func (o *OperationService) Run(ctx context.Context, return nil } preparer := NewPreparer(o.dbExecutor, config.Runtime.CmdBuilder, config) - installer := NewInstaller(o.dbExecutor) + installer := NewInstaller(o.dbExecutor, o.cfg.Runtime.CmdBuilder, o.cfg.Runtime.VCSStore, o.cfg.Runtime.Mode) pkgBuildDirs, err := preparer.Run(ctx, os.Stdout, targets) if err != nil {