diff.go 3.8 KB

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