diff --git a/config.go b/config.go index 41633184..90d1ab6b 100644 --- a/config.go +++ b/config.go @@ -4,8 +4,6 @@ import ( "bufio" "fmt" "os" - "os/exec" - "strings" "github.com/leonelquinteros/gotext" @@ -27,70 +25,6 @@ var localePath = "/usr/share/locale" // YayConf holds the current config values for yay. var config *settings.Configuration -// Editor returns the preferred system editor. -func editor() (editor string, args []string) { - switch { - case config.Editor != "": - editor, err := exec.LookPath(config.Editor) - if err != nil { - fmt.Fprintln(os.Stderr, err) - } else { - return editor, strings.Fields(config.EditorFlags) - } - - fallthrough - case os.Getenv("EDITOR") != "": - if editorArgs := strings.Fields(os.Getenv("EDITOR")); len(editorArgs) != 0 { - editor, err := exec.LookPath(editorArgs[0]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - } else { - return editor, editorArgs[1:] - } - } - - fallthrough - case os.Getenv("VISUAL") != "": - if editorArgs := strings.Fields(os.Getenv("VISUAL")); len(editorArgs) != 0 { - editor, err := exec.LookPath(editorArgs[0]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - } else { - return editor, editorArgs[1:] - } - } - - fallthrough - default: - fmt.Fprintln(os.Stderr) - text.Errorln(gotext.Get("%s is not set", text.Bold(text.Cyan("$EDITOR")))) - text.Warnln(gotext.Get("Add %s or %s to your environment variables", text.Bold(text.Cyan("$EDITOR")), text.Bold(text.Cyan("$VISUAL")))) - - for { - text.Infoln(gotext.Get("Edit PKGBUILD with?")) - - editorInput, err := getInput("") - if err != nil { - fmt.Fprintln(os.Stderr, err) - continue - } - - editorArgs := strings.Fields(editorInput) - if len(editorArgs) == 0 { - continue - } - - editor, err := exec.LookPath(editorArgs[0]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - continue - } - - return editor, editorArgs[1:] - } - } -} - func getInput(defaultValue string) (string, error) { text.Info() diff --git a/diff.go b/diff_menu.go similarity index 74% rename from diff.go rename to diff_menu.go index 4acb700c..4ef3317c 100644 --- a/diff.go +++ b/diff_menu.go @@ -1,3 +1,4 @@ +// file dedicated to diff menu package main import ( @@ -10,6 +11,8 @@ 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/stringset" "github.com/Jguer/yay/v11/pkg/text" ) @@ -126,19 +129,48 @@ func gitUpdateSeenRef(ctx context.Context, path, name string) error { return nil } -func gitMerge(ctx context.Context, path, name string) error { - _, stderr, err := config.Runtime.CmdBuilder.Capture( - config.Runtime.CmdBuilder.BuildGitCmd(ctx, - filepath.Join(path, name), "reset", "--hard", "HEAD")) - if err != nil { - return fmt.Errorf(gotext.Get("error resetting %s: %s", name, stderr)) +func diffNumberMenu(bases []dep.Base, installed stringset.StringSet) ([]dep.Base, error) { + return editDiffNumberMenu(bases, installed, true) +} + +func updatePkgbuildSeenRef(ctx context.Context, bases []dep.Base) error { + var errMulti multierror.MultiError + + for _, base := range bases { + pkg := base.Pkgbase() + + if err := gitUpdateSeenRef(ctx, config.BuildDir, pkg); err != nil { + errMulti.Add(err) + } } - _, stderr, err = config.Runtime.CmdBuilder.Capture( - config.Runtime.CmdBuilder.BuildGitCmd(ctx, - filepath.Join(path, name), "merge", "--no-edit", "--ff")) - if err != nil { - return fmt.Errorf(gotext.Get("error merging %s: %s", name, stderr)) + return errMulti.Return() +} + +func diffMenu(ctx context.Context, diffMenuOption bool, bases []dep.Base, installed stringset.StringSet, cloned map[string]bool) error { + if !diffMenuOption { + return nil + } + + pkgbuildNumberMenu(bases, installed) + + toDiff, errMenu := diffNumberMenu(bases, installed) + if errMenu != nil || len(toDiff) == 0 { + return errMenu + } + + if errD := showPkgbuildDiffs(ctx, toDiff, cloned); errD != nil { + return errD + } + + fmt.Println() + + if !text.ContinueTask(gotext.Get("Proceed with install?"), true, false) { + return settings.ErrUserAbort{} + } + + if errUpd := updatePkgbuildSeenRef(ctx, toDiff); errUpd != nil { + return errUpd } return nil diff --git a/edit_menu.go b/edit_menu.go new file mode 100644 index 00000000..25d2801c --- /dev/null +++ b/edit_menu.go @@ -0,0 +1,210 @@ +// edit menu +package main + +import ( + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + gosrc "github.com/Morganamilo/go-srcinfo" + "github.com/leonelquinteros/gotext" + + "github.com/Jguer/yay/v11/pkg/dep" + "github.com/Jguer/yay/v11/pkg/intrange" + "github.com/Jguer/yay/v11/pkg/settings" + "github.com/Jguer/yay/v11/pkg/stringset" + "github.com/Jguer/yay/v11/pkg/text" +) + +// Editor returns the preferred system editor. +func editor() (editor string, args []string) { + switch { + case config.Editor != "": + editor, err := exec.LookPath(config.Editor) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } else { + return editor, strings.Fields(config.EditorFlags) + } + + fallthrough + case os.Getenv("EDITOR") != "": + if editorArgs := strings.Fields(os.Getenv("EDITOR")); len(editorArgs) != 0 { + editor, err := exec.LookPath(editorArgs[0]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } else { + return editor, editorArgs[1:] + } + } + + fallthrough + case os.Getenv("VISUAL") != "": + if editorArgs := strings.Fields(os.Getenv("VISUAL")); len(editorArgs) != 0 { + editor, err := exec.LookPath(editorArgs[0]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } else { + return editor, editorArgs[1:] + } + } + + fallthrough + default: + fmt.Fprintln(os.Stderr) + text.Errorln(gotext.Get("%s is not set", text.Bold(text.Cyan("$EDITOR")))) + text.Warnln(gotext.Get("Add %s or %s to your environment variables", text.Bold(text.Cyan("$EDITOR")), text.Bold(text.Cyan("$VISUAL")))) + + for { + text.Infoln(gotext.Get("Edit PKGBUILD with?")) + + editorInput, err := getInput("") + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + + editorArgs := strings.Fields(editorInput) + if len(editorArgs) == 0 { + continue + } + + editor, err := exec.LookPath(editorArgs[0]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + + return editor, editorArgs[1:] + } + } +} + +func editNumberMenu(bases []dep.Base, installed stringset.StringSet) ([]dep.Base, error) { + return editDiffNumberMenu(bases, installed, false) +} + +func editDiffNumberMenu(bases []dep.Base, installed stringset.StringSet, diff bool) ([]dep.Base, error) { + var ( + toEdit = make([]dep.Base, 0) + editInput string + err error + ) + + if diff { + text.Infoln(gotext.Get("Diffs to show?")) + text.Infoln(gotext.Get("%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)", text.Cyan(gotext.Get("[N]one")))) + + editInput, err = getInput(config.AnswerDiff) + if err != nil { + return nil, err + } + } else { + text.Infoln(gotext.Get("PKGBUILDs to edit?")) + text.Infoln(gotext.Get("%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)", text.Cyan(gotext.Get("[N]one")))) + editInput, err = getInput(config.AnswerEdit) + if err != nil { + return nil, err + } + } + + eInclude, eExclude, eOtherInclude, eOtherExclude := intrange.ParseNumberMenu(editInput) + eIsInclude := len(eExclude) == 0 && len(eOtherExclude) == 0 + + if eOtherInclude.Get("abort") || eOtherInclude.Get("ab") { + return nil, &settings.ErrUserAbort{} + } + + if !eOtherInclude.Get("n") && !eOtherInclude.Get("none") { + for i, base := range bases { + pkg := base.Pkgbase() + anyInstalled := base.AnyIsInSet(installed) + + if !eIsInclude && eExclude.Get(len(bases)-i) { + continue + } + + if anyInstalled && (eOtherInclude.Get("i") || eOtherInclude.Get("installed")) { + toEdit = append(toEdit, base) + continue + } + + if !anyInstalled && (eOtherInclude.Get("no") || eOtherInclude.Get("notinstalled")) { + toEdit = append(toEdit, base) + continue + } + + if eOtherInclude.Get("a") || eOtherInclude.Get("all") { + toEdit = append(toEdit, base) + continue + } + + if eIsInclude && (eInclude.Get(len(bases)-i) || eOtherInclude.Get(pkg)) { + toEdit = append(toEdit, base) + } + + if !eIsInclude && (!eExclude.Get(len(bases)-i) && !eOtherExclude.Get(pkg)) { + toEdit = append(toEdit, base) + } + } + } + + return toEdit, nil +} + +func editPkgbuilds(bases []dep.Base, srcinfos map[string]*gosrc.Srcinfo) error { + pkgbuilds := make([]string, 0, len(bases)) + + for _, base := range bases { + pkg := base.Pkgbase() + dir := filepath.Join(config.BuildDir, pkg) + pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD")) + + for _, splitPkg := range srcinfos[pkg].SplitPackages() { + if splitPkg.Install != "" { + pkgbuilds = append(pkgbuilds, filepath.Join(dir, splitPkg.Install)) + } + } + } + + if len(pkgbuilds) > 0 { + editor, editorArgs := editor() + editorArgs = append(editorArgs, pkgbuilds...) + editcmd := exec.Command(editor, editorArgs...) + editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr + + if err := editcmd.Run(); err != nil { + return errors.New(gotext.Get("editor did not exit successfully, aborting: %s", err)) + } + } + + return nil +} + +func editMenu(editMenuOption bool, bases []dep.Base, installed stringset.StringSet, srcinfos map[string]*gosrc.Srcinfo) error { + if !editMenuOption { + return nil + } + + pkgbuildNumberMenu(bases, installed) + + toEdit, errMenu := editNumberMenu(bases, installed) + if errMenu != nil || len(toEdit) == 0 { + return errMenu + } + + if errEdit := editPkgbuilds(toEdit, srcinfos); errEdit != nil { + return errEdit + } + + fmt.Println() + + if !text.ContinueTask(gotext.Get("Proceed with install?"), true, false) { + return settings.ErrUserAbort{} + } + + return nil +} diff --git a/install.go b/install.go index 441a75b0..c0b9de14 100644 --- a/install.go +++ b/install.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "os" - "os/exec" "path/filepath" "strconv" "strings" @@ -19,8 +18,6 @@ import ( "github.com/Jguer/yay/v11/pkg/db" "github.com/Jguer/yay/v11/pkg/dep" "github.com/Jguer/yay/v11/pkg/download" - "github.com/Jguer/yay/v11/pkg/intrange" - "github.com/Jguer/yay/v11/pkg/multierror" "github.com/Jguer/yay/v11/pkg/pgp" "github.com/Jguer/yay/v11/pkg/query" "github.com/Jguer/yay/v11/pkg/settings" @@ -251,40 +248,12 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu return errA } - var toDiff, toEdit []dep.Base - - if config.DiffMenu { - pkgbuildNumberMenu(do.Aur, remoteNamesCache) - - toDiff, err = diffNumberMenu(do.Aur, remoteNamesCache) - if err != nil { - return err + if errDiffMenu := diffMenu(ctx, config.DiffMenu, do.Aur, remoteNamesCache, cloned); errDiffMenu != nil { + if errors.As(errDiffMenu, &settings.ErrUserAbort{}) { + return errDiffMenu } - if len(toDiff) > 0 { - err = showPkgbuildDiffs(ctx, toDiff, cloned) - if err != nil { - return err - } - } - } - - if len(toDiff) > 0 { - oldValue := settings.NoConfirm - settings.NoConfirm = false - - fmt.Println() - - if !text.ContinueTask(gotext.Get("Proceed with install?"), true, settings.NoConfirm) { - return &settings.ErrUserAbort{} - } - - err = updatePkgbuildSeenRef(ctx, toDiff) - if err != nil { - text.Errorln(err.Error()) - } - - settings.NoConfirm = oldValue + text.Errorln(errDiffMenu) } if errM := mergePkgbuilds(ctx, do.Aur); errM != nil { @@ -296,33 +265,12 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu return err } - if config.EditMenu { - pkgbuildNumberMenu(do.Aur, remoteNamesCache) - - toEdit, err = editNumberMenu(do.Aur, remoteNamesCache) - if err != nil { - return err + if errEditMenu := editMenu(config.EditMenu, do.Aur, remoteNamesCache, srcinfos); errEditMenu != nil { + if errors.As(errEditMenu, &settings.ErrUserAbort{}) { + return errEditMenu } - if len(toEdit) > 0 { - err = editPkgbuilds(toEdit, srcinfos) - if err != nil { - return err - } - } - } - - if len(toEdit) > 0 { - oldValue := settings.NoConfirm - settings.NoConfirm = false - - fmt.Println() - - if !text.ContinueTask(gotext.Get("Proceed with install?"), true, settings.NoConfirm) { - return &settings.ErrUserAbort{} - } - - settings.NoConfirm = oldValue + text.Errorln(errEditMenu) } incompatible, err = getIncompatible(do.Aur, srcinfos, dbExecutor) @@ -578,125 +526,6 @@ func pkgbuildNumberMenu(bases []dep.Base, installed stringset.StringSet) { fmt.Print(toPrint) } -func editNumberMenu(bases []dep.Base, installed stringset.StringSet) ([]dep.Base, error) { - return editDiffNumberMenu(bases, installed, false) -} - -func diffNumberMenu(bases []dep.Base, installed stringset.StringSet) ([]dep.Base, error) { - return editDiffNumberMenu(bases, installed, true) -} - -func editDiffNumberMenu(bases []dep.Base, installed stringset.StringSet, diff bool) ([]dep.Base, error) { - var ( - toEdit = make([]dep.Base, 0) - editInput string - err error - ) - - if diff { - text.Infoln(gotext.Get("Diffs to show?")) - text.Infoln(gotext.Get("%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)", text.Cyan(gotext.Get("[N]one")))) - - editInput, err = getInput(config.AnswerDiff) - if err != nil { - return nil, err - } - } else { - text.Infoln(gotext.Get("PKGBUILDs to edit?")) - text.Infoln(gotext.Get("%s [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)", text.Cyan(gotext.Get("[N]one")))) - editInput, err = getInput(config.AnswerEdit) - if err != nil { - return nil, err - } - } - - eInclude, eExclude, eOtherInclude, eOtherExclude := intrange.ParseNumberMenu(editInput) - eIsInclude := len(eExclude) == 0 && len(eOtherExclude) == 0 - - if eOtherInclude.Get("abort") || eOtherInclude.Get("ab") { - return nil, &settings.ErrUserAbort{} - } - - if !eOtherInclude.Get("n") && !eOtherInclude.Get("none") { - for i, base := range bases { - pkg := base.Pkgbase() - anyInstalled := base.AnyIsInSet(installed) - - if !eIsInclude && eExclude.Get(len(bases)-i) { - continue - } - - if anyInstalled && (eOtherInclude.Get("i") || eOtherInclude.Get("installed")) { - toEdit = append(toEdit, base) - continue - } - - if !anyInstalled && (eOtherInclude.Get("no") || eOtherInclude.Get("notinstalled")) { - toEdit = append(toEdit, base) - continue - } - - if eOtherInclude.Get("a") || eOtherInclude.Get("all") { - toEdit = append(toEdit, base) - continue - } - - if eIsInclude && (eInclude.Get(len(bases)-i) || eOtherInclude.Get(pkg)) { - toEdit = append(toEdit, base) - } - - if !eIsInclude && (!eExclude.Get(len(bases)-i) && !eOtherExclude.Get(pkg)) { - toEdit = append(toEdit, base) - } - } - } - - return toEdit, nil -} - -func updatePkgbuildSeenRef(ctx context.Context, bases []dep.Base) error { - var errMulti multierror.MultiError - - for _, base := range bases { - pkg := base.Pkgbase() - - if err := gitUpdateSeenRef(ctx, config.BuildDir, pkg); err != nil { - errMulti.Add(err) - } - } - - return errMulti.Return() -} - -func editPkgbuilds(bases []dep.Base, srcinfos map[string]*gosrc.Srcinfo) error { - pkgbuilds := make([]string, 0, len(bases)) - - for _, base := range bases { - pkg := base.Pkgbase() - dir := filepath.Join(config.BuildDir, pkg) - pkgbuilds = append(pkgbuilds, filepath.Join(dir, "PKGBUILD")) - - for _, splitPkg := range srcinfos[pkg].SplitPackages() { - if splitPkg.Install != "" { - pkgbuilds = append(pkgbuilds, filepath.Join(dir, splitPkg.Install)) - } - } - } - - if len(pkgbuilds) > 0 { - editor, editorArgs := editor() - editorArgs = append(editorArgs, pkgbuilds...) - editcmd := exec.Command(editor, editorArgs...) - editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr - - if err := editcmd.Run(); err != nil { - return errors.New(gotext.Get("editor did not exit successfully, aborting: %s", err)) - } - } - - return nil -} - func parseSrcinfoFiles(bases []dep.Base, errIsFatal bool) (map[string]*gosrc.Srcinfo, error) { srcinfos := make(map[string]*gosrc.Srcinfo) @@ -748,6 +577,24 @@ func pkgbuildsToSkip(bases []dep.Base, targets stringset.StringSet) stringset.St return toSkip } +func gitMerge(ctx context.Context, path, name string) error { + _, stderr, err := config.Runtime.CmdBuilder.Capture( + config.Runtime.CmdBuilder.BuildGitCmd(ctx, + filepath.Join(path, name), "reset", "--hard", "HEAD")) + if err != nil { + return fmt.Errorf(gotext.Get("error resetting %s: %s", name, stderr)) + } + + _, stderr, err = config.Runtime.CmdBuilder.Capture( + config.Runtime.CmdBuilder.BuildGitCmd(ctx, + filepath.Join(path, name), "merge", "--no-edit", "--ff")) + if err != nil { + return fmt.Errorf(gotext.Get("error merging %s: %s", name, stderr)) + } + + return nil +} + func mergePkgbuilds(ctx context.Context, bases []dep.Base) error { for _, base := range bases { err := gitMerge(ctx, config.BuildDir, base.Pkgbase())