diff.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "path/filepath"
  6. "strings"
  7. "github.com/leonelquinteros/gotext"
  8. "github.com/Jguer/yay/v11/pkg/dep"
  9. "github.com/Jguer/yay/v11/pkg/multierror"
  10. "github.com/Jguer/yay/v11/pkg/text"
  11. )
  12. const gitDiffRefName = "AUR_SEEN"
  13. func showPkgbuildDiffs(ctx context.Context, bases []dep.Base, cloned map[string]bool) error {
  14. var errMulti multierror.MultiError
  15. for _, base := range bases {
  16. pkg := base.Pkgbase()
  17. dir := filepath.Join(config.BuildDir, pkg)
  18. start, err := getLastSeenHash(ctx, config.BuildDir, pkg)
  19. if err != nil {
  20. errMulti.Add(err)
  21. continue
  22. }
  23. if cloned[pkg] {
  24. start = gitEmptyTree
  25. } else {
  26. hasDiff, err := gitHasDiff(ctx, config.BuildDir, pkg)
  27. if err != nil {
  28. errMulti.Add(err)
  29. continue
  30. }
  31. if !hasDiff {
  32. text.Warnln(gotext.Get("%s: No changes -- skipping", text.Cyan(base.String())))
  33. continue
  34. }
  35. }
  36. args := []string{
  37. "diff",
  38. start + "..HEAD@{upstream}", "--src-prefix",
  39. dir + "/", "--dst-prefix", dir + "/", "--", ".", ":(exclude).SRCINFO",
  40. }
  41. if text.UseColor {
  42. args = append(args, "--color=always")
  43. } else {
  44. args = append(args, "--color=never")
  45. }
  46. _ = config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildGitCmd(ctx, dir, args...))
  47. }
  48. return errMulti.Return()
  49. }
  50. // Check whether or not a diff exists between the last reviewed diff and
  51. // HEAD@{upstream}.
  52. func gitHasDiff(ctx context.Context, path, name string) (bool, error) {
  53. if gitHasLastSeenRef(ctx, path, name) {
  54. stdout, stderr, err := config.Runtime.CmdBuilder.Capture(
  55. config.Runtime.CmdBuilder.BuildGitCmd(ctx, filepath.Join(path, name), "rev-parse", gitDiffRefName, "HEAD@{upstream}"))
  56. if err != nil {
  57. return false, fmt.Errorf("%s%s", stderr, err)
  58. }
  59. lines := strings.Split(stdout, "\n")
  60. lastseen := lines[0]
  61. upstream := lines[1]
  62. return lastseen != upstream, nil
  63. }
  64. // If YAY_DIFF_REVIEW does not exists, we have never reviewed a diff for this package
  65. // and should display it.
  66. return true, nil
  67. }
  68. // Return wether or not we have reviewed a diff yet. It checks for the existence of
  69. // YAY_DIFF_REVIEW in the git ref-list.
  70. func gitHasLastSeenRef(ctx context.Context, path, name string) bool {
  71. _, _, err := config.Runtime.CmdBuilder.Capture(
  72. config.Runtime.CmdBuilder.BuildGitCmd(ctx,
  73. filepath.Join(path, name), "rev-parse", "--quiet", "--verify", gitDiffRefName))
  74. return err == nil
  75. }
  76. // Returns the last reviewed hash. If YAY_DIFF_REVIEW exists it will return this hash.
  77. // If it does not it will return empty tree as no diff have been reviewed yet.
  78. func getLastSeenHash(ctx context.Context, path, name string) (string, error) {
  79. if gitHasLastSeenRef(ctx, path, name) {
  80. stdout, stderr, err := config.Runtime.CmdBuilder.Capture(
  81. config.Runtime.CmdBuilder.BuildGitCmd(ctx,
  82. filepath.Join(path, name), "rev-parse", gitDiffRefName))
  83. if err != nil {
  84. return "", fmt.Errorf("%s %s", stderr, err)
  85. }
  86. lines := strings.Split(stdout, "\n")
  87. return lines[0], nil
  88. }
  89. return gitEmptyTree, nil
  90. }
  91. // Update the YAY_DIFF_REVIEW ref to HEAD. We use this ref to determine which diff were
  92. // reviewed by the user.
  93. func gitUpdateSeenRef(ctx context.Context, path, name string) error {
  94. _, stderr, err := config.Runtime.CmdBuilder.Capture(
  95. config.Runtime.CmdBuilder.BuildGitCmd(ctx,
  96. filepath.Join(path, name), "update-ref", gitDiffRefName, "HEAD"))
  97. if err != nil {
  98. return fmt.Errorf("%s %s", stderr, err)
  99. }
  100. return nil
  101. }
  102. func gitMerge(ctx context.Context, path, name string) error {
  103. _, stderr, err := config.Runtime.CmdBuilder.Capture(
  104. config.Runtime.CmdBuilder.BuildGitCmd(ctx,
  105. filepath.Join(path, name), "reset", "--hard", "HEAD"))
  106. if err != nil {
  107. return fmt.Errorf(gotext.Get("error resetting %s: %s", name, stderr))
  108. }
  109. _, stderr, err = config.Runtime.CmdBuilder.Capture(
  110. config.Runtime.CmdBuilder.BuildGitCmd(ctx,
  111. filepath.Join(path, name), "merge", "--no-edit", "--ff"))
  112. if err != nil {
  113. return fmt.Errorf(gotext.Get("error merging %s: %s", name, stderr))
  114. }
  115. return nil
  116. }