Skip to content

Commit

Permalink
feat(upgrade): separate menu for pulled along dependencies (#2141)
Browse files Browse the repository at this point in the history
try separate menu for pulled along

use installed as term

fix order gap

fix tests

add aur db + aur scenario
  • Loading branch information
Jguer committed Apr 27, 2023
1 parent e634410 commit 49267b9
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 33 deletions.
5 changes: 2 additions & 3 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"net/http"
"os"
"strings"

alpm "github.com/Jguer/go-alpm/v2"
Expand Down Expand Up @@ -403,9 +402,9 @@ func displayNumberMenu(ctx context.Context, cfg *settings.Configuration, pkgS []
return nil
}

text.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))
cfg.Runtime.Logger.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))

numberBuf, err := text.GetInput(os.Stdin, "", false)
numberBuf, err := cfg.Runtime.Logger.GetInput("", false)
if err != nil {
return err
}
Expand Down
137 changes: 137 additions & 0 deletions cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package main

import (
"context"
"fmt"
"io"
"os"
"os/exec"
"strings"
"testing"

"github.com/Jguer/aur"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/Jguer/yay/v12/pkg/db/mock"
mockaur "github.com/Jguer/yay/v12/pkg/dep/mock"
"github.com/Jguer/yay/v12/pkg/query"
"github.com/Jguer/yay/v12/pkg/settings"
"github.com/Jguer/yay/v12/pkg/settings/exe"
"github.com/Jguer/yay/v12/pkg/settings/parser"
"github.com/Jguer/yay/v12/pkg/text"
"github.com/Jguer/yay/v12/pkg/vcs"
)

func TestYogurtMenuAURDB(t *testing.T) {
t.Skip("skip until Operation service is an interface")
t.Parallel()
makepkgBin := t.TempDir() + "/makepkg"
pacmanBin := t.TempDir() + "/pacman"
gitBin := t.TempDir() + "/git"
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())

captureOverride := func(cmd *exec.Cmd) (stdout string, stderr string, err error) {
return "", "", nil
}

showOverride := func(cmd *exec.Cmd) error {
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("Y")
cmdArgs.AddTarget("yay")

db := &mock.DBExecutor{
AlpmArchitecturesFn: func() ([]string, error) {
return []string{"x86_64"}, nil
},
RefreshHandleFn: func() error {
return nil
},
ReposFn: func() []string {
return []string{"aur"}
},
SyncPackagesFn: func(s ...string) []mock.IPackage {
return []mock.IPackage{
&mock.Package{
PName: "yay",
PBase: "yay",
PVersion: "10.0.0",
PDB: mock.NewDB("aur"),
},
}
},
LocalPackageFn: func(s string) mock.IPackage {
return nil
},
}
aurCache := &mockaur.MockAUR{
GetFn: func(ctx context.Context, query *aur.Query) ([]aur.Pkg, error) {
return []aur.Pkg{
{
Name: "yay",
PackageBase: "yay",
Version: "10.0.0",
},
}, nil
},
}
logger := text.NewLogger(io.Discard, os.Stderr, strings.NewReader("1\n"), true, "test")
cfg := &settings.Configuration{
NewInstallEngine: true,
RemoveMake: "no",
Runtime: &settings.Runtime{
Logger: logger,
CmdBuilder: cmdBuilder,
VCSStore: &vcs.Mock{},
QueryBuilder: query.NewSourceQueryBuilder(aurCache, logger, "votes", parser.ModeAny, "name",
true, false, true),
AURCache: aurCache,
},
}

err = handleCmd(context.Background(), cfg, cmdArgs, db)
require.NoError(t, err)

wantCapture := []string{}
wantShow := []string{
"pacman -S -y --config /etc/pacman.conf --",
"pacman -S -y -u --config /etc/pacman.conf --",
}

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, 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))
}
}
4 changes: 4 additions & 0 deletions pkg/db/mock/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type DBExecutor struct {
RefreshHandleFn func() error
ReposFn func() []string
SyncPackageFn func(string) IPackage
SyncPackagesFn func(...string) []IPackage
SyncSatisfierFn func(string) IPackage
SyncUpgradesFn func(bool) (map[string]db.SyncUpgrade, error)
}
Expand Down Expand Up @@ -170,6 +171,9 @@ func (t *DBExecutor) SyncPackage(s string) IPackage {
}

func (t *DBExecutor) SyncPackages(s ...string) []IPackage {
if t.SyncPackagesFn != nil {
return t.SyncPackagesFn(s...)
}
panic("implement me")
}

Expand Down
12 changes: 6 additions & 6 deletions pkg/query/query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,12 @@ func (s *SourceQueryBuilder) Results(dbExecutor db.Executor, verboseSearch Searc
}

pkg := s.queryMap[s.results[i].source][s.results[i].name]
if s.results[i].source == sourceAUR {
aurPkg := pkg.(aur.Pkg)
toPrint += aurPkgSearchString(&aurPkg, dbExecutor, s.singleLineResults)
} else {
syncPkg := pkg.(alpm.IPackage)
toPrint += syncPkgSearchString(syncPkg, dbExecutor, s.singleLineResults)

switch pPkg := pkg.(type) {
case aur.Pkg:
toPrint += aurPkgSearchString(&pPkg, dbExecutor, s.singleLineResults)
case alpm.IPackage:
toPrint += syncPkgSearchString(pPkg, dbExecutor, s.singleLineResults)
}

s.logger.Println(toPrint)
Expand Down
2 changes: 2 additions & 0 deletions pkg/settings/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"os"
"path/filepath"
"time"

"github.com/leonelquinteros/gotext"

Expand Down Expand Up @@ -68,6 +69,7 @@ func BuildRuntime(cfg *Configuration, cmdArgs *parser.Arguments, version string)
metadata.WithCacheFilePath(filepath.Join(cfg.BuildDir, "aur.json")),
metadata.WithRequestEditorFn(userAgentFn),
metadata.WithBaseURL(cfg.AURURL),
metadata.WithCustomCacheValidity(100000*time.Hour),
metadata.WithDebugLogger(logger.Debugln),
)
if errAURCache != nil {
Expand Down
40 changes: 29 additions & 11 deletions pkg/upgrade/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,21 +262,43 @@ func (u *UpgradeService) GraphUpgrades(ctx context.Context,
// userExcludeUpgrades asks the user which packages to exclude from the upgrade and
// removes them from the graph
func (u *UpgradeService) UserExcludeUpgrades(graph *topo.Graph[string, *dep.InstallInfo]) ([]string, error) {
allUpLen := graph.Len()
if allUpLen == 0 {
if graph.Len() == 0 {
return []string{}, nil
}
aurUp, repoUp := u.graphToUpSlice(graph)

sort.Sort(repoUp)
sort.Sort(aurUp)

allUp := UpSlice{Up: append(repoUp.Up, aurUp.Up...), Repos: append(repoUp.Repos, aurUp.Repos...)}
allUp := UpSlice{Repos: append(repoUp.Repos, aurUp.Repos...)}
for _, up := range repoUp.Up {
if up.LocalVersion == "" && up.Reason != alpm.PkgReasonExplicit {
allUp.PulledDeps = append(allUp.PulledDeps, up)
} else {
allUp.Up = append(allUp.Up, up)
}
}

for _, up := range aurUp.Up {
if up.LocalVersion == "" && up.Reason != alpm.PkgReasonExplicit {
allUp.PulledDeps = append(allUp.PulledDeps, up)
} else {
allUp.Up = append(allUp.Up, up)
}
}

if len(allUp.PulledDeps) > 0 {
u.log.Printf("%s"+text.Bold(" %d ")+"%s\n", text.Bold(text.Cyan("::")),
len(allUp.PulledDeps), text.Bold(gotext.Get("%s will also be installed for this operation",
gotext.GetN("dependency", "dependencies", len(allUp.PulledDeps)))))
allUp.PrintDeps(u.log)
}

u.log.Printf("%s"+text.Bold(" %d ")+"%s\n", text.Bold(text.Cyan("::")), allUpLen, text.Bold(gotext.Get("Packages to upgrade/install.")))
u.log.Printf("%s"+text.Bold(" %d ")+"%s\n", text.Bold(text.Cyan("::")),
len(allUp.Up), text.Bold(gotext.Get("%s to upgrade/install.", gotext.GetN("package", "packages", len(allUp.Up)))))
allUp.Print(u.log)

u.log.Infoln(gotext.Get("Packages to exclude: (eg: \"1 2 3\", \"1-3\", \"^4\" or repo name)"))
u.log.Infoln(gotext.Get("%s to exclude: (eg: \"1 2 3\", \"1-3\", \"^4\" or repo name)", gotext.GetN("package", "packages", len(allUp.Up))))
u.log.Warnln(gotext.Get("Excluding packages may cause partial upgrades and break systems"))

numbers, err := u.log.GetInput(u.cfg.AnswerUpgrade, settings.NoConfirm)
Expand All @@ -292,24 +314,20 @@ func (u *UpgradeService) UserExcludeUpgrades(graph *topo.Graph[string, *dep.Inst
excluded := make([]string, 0)
for i := range allUp.Up {
up := &allUp.Up[i]
// choices do not apply to non-installed packages
if up.LocalVersion == "" {
continue
}

if isInclude && otherExclude.Get(up.Repository) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
continue
}

if isInclude && exclude.Get(allUpLen-i) {
if isInclude && exclude.Get(len(allUp.Up)-i) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
continue
}

if !isInclude && !(include.Get(allUpLen-i) || otherInclude.Get(up.Repository)) {
if !isInclude && !(include.Get(len(allUp.Up)-i) || otherInclude.Get(up.Repository)) {
u.log.Debugln("pruning", up.Name)
excluded = append(excluded, graph.Prune(up.Name)...)
continue
Expand Down
14 changes: 5 additions & 9 deletions pkg/upgrade/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ func TestUpgradeService_GraphUpgrades(t *testing.T) {
{
name: "exclude linux",
fields: fields{
input: strings.NewReader("4\n"),
input: strings.NewReader("3\n"),
output: io.Discard,
noConfirm: false,
},
Expand All @@ -301,7 +301,7 @@ func TestUpgradeService_GraphUpgrades(t *testing.T) {
{
name: "only linux",
fields: fields{
input: strings.NewReader("^4\n"),
input: strings.NewReader("^3\n"),
output: io.Discard,
noConfirm: false,
},
Expand Down Expand Up @@ -642,7 +642,6 @@ func TestUpgradeService_GraphUpgrades_zfs_dkms(t *testing.T) {
}
type fields struct {
input io.Reader
output io.Writer
noConfirm bool
devel bool
}
Expand All @@ -664,7 +663,6 @@ func TestUpgradeService_GraphUpgrades_zfs_dkms(t *testing.T) {
name: "no input",
fields: fields{
input: strings.NewReader("\n"),
output: io.Discard,
noConfirm: false,
},
args: args{
Expand All @@ -684,7 +682,6 @@ func TestUpgradeService_GraphUpgrades_zfs_dkms(t *testing.T) {
name: "no input - inverted order",
fields: fields{
input: strings.NewReader("\n"),
output: io.Discard,
noConfirm: false,
},
args: args{
Expand Down Expand Up @@ -742,16 +739,15 @@ func TestUpgradeService_GraphUpgrades_zfs_dkms(t *testing.T) {
ReposFn: func() []string { return []string{"core"} },
}

logger := text.NewLogger(io.Discard, os.Stderr,
tt.fields.input, true, "test")
grapher := dep.NewGrapher(dbExe, mockAUR,
false, true, false, false, false, text.NewLogger(tt.fields.output, os.Stderr,
tt.fields.input, true, "test"))
false, true, false, false, false, logger)

cfg := &settings.Configuration{
Devel: tt.fields.devel, Mode: parser.ModeAny,
}

logger := text.NewLogger(tt.fields.output, os.Stderr,
tt.fields.input, true, "test")
u := &UpgradeService{
log: logger,
grapher: grapher,
Expand Down
36 changes: 34 additions & 2 deletions pkg/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ func StylizedNameWithRepository(u *Upgrade) string {

// upSlice is a slice of Upgrades.
type UpSlice struct {
Up []Upgrade
Repos []string
Up []Upgrade
Repos []string
PulledDeps []Upgrade
}

func (u UpSlice) Len() int { return len(u.Up) }
Expand Down Expand Up @@ -84,3 +85,34 @@ func (u UpSlice) Print(logger *text.Logger) {
}
}
}

func (u UpSlice) PrintDeps(logger *text.Logger) {
longestName, longestVersion := 0, 0

for k := range u.PulledDeps {
upgrade := &u.PulledDeps[k]
packNameLen := len(StylizedNameWithRepository(upgrade))
packVersion, _ := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)
packVersionLen := len(packVersion)
longestName = intrange.Max(packNameLen, longestName)
longestVersion = intrange.Max(packVersionLen, longestVersion)
}

lenUp := len(u.PulledDeps)
longestNumber := len(fmt.Sprintf("%v", lenUp))
namePadding := fmt.Sprintf(" %s%%-%ds ", strings.Repeat(" ", longestNumber), longestName)
versionPadding := fmt.Sprintf("%%-%ds", longestVersion)

for k := range u.PulledDeps {
upgrade := &u.PulledDeps[k]
left, right := query.GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)

logger.Printf(namePadding, StylizedNameWithRepository(upgrade))
logger.Printf("%s -> %s\n", fmt.Sprintf(versionPadding, left), right)
if upgrade.Extra != "" {
logger.Println(strings.Repeat(" ", longestNumber), strings.ToLower(upgrade.Extra))
}
}

logger.Println()
}

0 comments on commit 49267b9

Please sign in to comment.