yay/pkg/menus/diff_menu.go

181 lines
4.8 KiB
Go
Raw Normal View History

// file dedicated to diff menu
2021-10-11 22:22:03 +02:00
package menus
import (
2021-08-12 18:56:23 +02:00
"context"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/leonelquinteros/gotext"
2021-09-08 22:28:08 +02:00
"github.com/Jguer/yay/v11/pkg/dep"
"github.com/Jguer/yay/v11/pkg/multierror"
"github.com/Jguer/yay/v11/pkg/settings"
2021-10-11 22:22:03 +02:00
"github.com/Jguer/yay/v11/pkg/settings/exe"
"github.com/Jguer/yay/v11/pkg/stringset"
2021-09-08 22:28:08 +02:00
"github.com/Jguer/yay/v11/pkg/text"
)
2021-10-11 22:22:03 +02:00
const (
gitEmptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
gitDiffRefName = "AUR_SEEN"
)
2021-10-11 22:22:03 +02:00
func showPkgbuildDiffs(ctx context.Context, cmdBuilder exe.ICmdBuilder, buildDir string, bases []dep.Base, cloned map[string]bool) error {
var errMulti multierror.MultiError
2021-08-11 20:13:28 +02:00
for _, base := range bases {
pkg := base.Pkgbase()
2021-10-11 22:22:03 +02:00
dir := filepath.Join(buildDir, pkg)
2021-08-11 20:13:28 +02:00
2021-10-11 22:22:03 +02:00
start, err := getLastSeenHash(ctx, cmdBuilder, buildDir, pkg)
if err != nil {
errMulti.Add(err)
2021-08-11 20:13:28 +02:00
continue
}
if cloned[pkg] {
start = gitEmptyTree
} else {
2021-10-11 22:22:03 +02:00
hasDiff, err := gitHasDiff(ctx, cmdBuilder, buildDir, pkg)
if err != nil {
errMulti.Add(err)
2021-08-11 20:13:28 +02:00
continue
}
if !hasDiff {
text.Warnln(gotext.Get("%s: No changes -- skipping", text.Cyan(base.String())))
2021-08-11 20:13:28 +02:00
continue
}
}
args := []string{
"diff",
start + "..HEAD@{upstream}", "--src-prefix",
dir + "/", "--dst-prefix", dir + "/", "--", ".", ":(exclude).SRCINFO",
}
if text.UseColor {
args = append(args, "--color=always")
} else {
args = append(args, "--color=never")
}
2021-08-11 20:13:28 +02:00
2021-10-11 22:22:03 +02:00
_ = cmdBuilder.Show(cmdBuilder.BuildGitCmd(ctx, dir, args...))
}
return errMulti.Return()
}
// Check whether or not a diff exists between the last reviewed diff and
2021-08-11 20:13:28 +02:00
// HEAD@{upstream}.
2021-10-11 22:22:03 +02:00
func gitHasDiff(ctx context.Context, cmdBuilder exe.ICmdBuilder, path, name string) (bool, error) {
if gitHasLastSeenRef(ctx, cmdBuilder, path, name) {
stdout, stderr, err := cmdBuilder.Capture(
cmdBuilder.BuildGitCmd(ctx, filepath.Join(path, name), "rev-parse", gitDiffRefName, "HEAD@{upstream}"))
if err != nil {
return false, fmt.Errorf("%s%s", stderr, err)
}
lines := strings.Split(stdout, "\n")
lastseen := lines[0]
upstream := lines[1]
2021-08-11 20:13:28 +02:00
return lastseen != upstream, nil
}
// If YAY_DIFF_REVIEW does not exists, we have never reviewed a diff for this package
// and should display it.
return true, nil
}
// Return wether or not we have reviewed a diff yet. It checks for the existence of
2021-08-11 20:13:28 +02:00
// YAY_DIFF_REVIEW in the git ref-list.
2021-10-11 22:22:03 +02:00
func gitHasLastSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, path, name string) bool {
_, _, err := cmdBuilder.Capture(
cmdBuilder.BuildGitCmd(ctx,
2021-08-12 18:56:23 +02:00
filepath.Join(path, name), "rev-parse", "--quiet", "--verify", gitDiffRefName))
2021-08-11 20:13:28 +02:00
return err == nil
}
// Returns the last reviewed hash. If YAY_DIFF_REVIEW exists it will return this hash.
// If it does not it will return empty tree as no diff have been reviewed yet.
2021-10-11 22:22:03 +02:00
func getLastSeenHash(ctx context.Context, cmdBuilder exe.ICmdBuilder, path, name string) (string, error) {
if gitHasLastSeenRef(ctx, cmdBuilder, path, name) {
stdout, stderr, err := cmdBuilder.Capture(
cmdBuilder.BuildGitCmd(ctx,
2021-08-12 18:56:23 +02:00
filepath.Join(path, name), "rev-parse", gitDiffRefName))
if err != nil {
return "", fmt.Errorf("%s %s", stderr, err)
}
lines := strings.Split(stdout, "\n")
2021-08-11 20:13:28 +02:00
return lines[0], nil
}
2021-08-11 20:13:28 +02:00
return gitEmptyTree, nil
}
// Update the YAY_DIFF_REVIEW ref to HEAD. We use this ref to determine which diff were
2021-08-11 20:13:28 +02:00
// reviewed by the user.
2021-10-11 22:22:03 +02:00
func gitUpdateSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, path, name string) error {
_, stderr, err := cmdBuilder.Capture(
cmdBuilder.BuildGitCmd(ctx,
2021-08-12 18:56:23 +02:00
filepath.Join(path, name), "update-ref", gitDiffRefName, "HEAD"))
if err != nil {
return fmt.Errorf("%s %s", stderr, err)
}
2021-08-11 20:13:28 +02:00
return nil
}
2021-10-11 22:22:03 +02:00
func updatePkgbuildSeenRef(ctx context.Context, cmdBuilder exe.ICmdBuilder, buildDir string, bases []dep.Base) error {
var errMulti multierror.MultiError
for _, base := range bases {
pkg := base.Pkgbase()
2021-10-11 22:22:03 +02:00
if err := gitUpdateSeenRef(ctx, cmdBuilder, buildDir, pkg); err != nil {
errMulti.Add(err)
}
}
return errMulti.Return()
}
2021-10-11 22:22:03 +02:00
func Diff(ctx context.Context, cmdBuilder exe.ICmdBuilder,
buildDir string, diffMenuOption bool, bases []dep.Base,
installed stringset.StringSet, cloned map[string]bool, noConfirm bool, diffDefaultAnswer string,
) error {
if !diffMenuOption {
return nil
}
toDiff, errMenu := selectionMenu(buildDir, bases, installed, gotext.Get("Diffs to show?"),
noConfirm, diffDefaultAnswer, nil)
if errMenu != nil || len(toDiff) == 0 {
return errMenu
}
2021-10-11 22:22:03 +02:00
if errD := showPkgbuildDiffs(ctx, cmdBuilder, buildDir, toDiff, cloned); errD != nil {
return errD
}
fmt.Println()
if !text.ContinueTask(os.Stdin, gotext.Get("Proceed with install?"), true, false) {
return settings.ErrUserAbort{}
}
2021-10-11 22:22:03 +02:00
if errUpd := updatePkgbuildSeenRef(ctx, cmdBuilder, buildDir, toDiff); errUpd != nil {
return errUpd
}
return nil
}