upgrade.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package upgrade
  2. import (
  3. "fmt"
  4. "unicode"
  5. "github.com/Jguer/yay/v11/pkg/db"
  6. "github.com/Jguer/yay/v11/pkg/intrange"
  7. "github.com/Jguer/yay/v11/pkg/text"
  8. )
  9. // Filter decides if specific package should be included in theincluded in the results.
  10. type Filter func(*Upgrade) bool
  11. // Upgrade type describes a system upgrade.
  12. type Upgrade = db.Upgrade
  13. func StylizedNameWithRepository(u *Upgrade) string {
  14. return text.Bold(text.ColorHash(u.Repository)) + "/" + text.Bold(u.Name)
  15. }
  16. // upSlice is a slice of Upgrades.
  17. type UpSlice struct {
  18. Up []Upgrade
  19. Repos []string
  20. }
  21. func (u UpSlice) Len() int { return len(u.Up) }
  22. func (u UpSlice) Swap(i, j int) { u.Up[i], u.Up[j] = u.Up[j], u.Up[i] }
  23. func (u UpSlice) Less(i, j int) bool {
  24. if u.Up[i].Repository == u.Up[j].Repository {
  25. iRunes := []rune(u.Up[i].Name)
  26. jRunes := []rune(u.Up[j].Name)
  27. return text.LessRunes(iRunes, jRunes)
  28. }
  29. for _, db := range u.Repos {
  30. if db == u.Up[i].Repository {
  31. return true
  32. } else if db == u.Up[j].Repository {
  33. return false
  34. }
  35. }
  36. iRunes := []rune(u.Up[i].Repository)
  37. jRunes := []rune(u.Up[j].Repository)
  38. return text.LessRunes(iRunes, jRunes)
  39. }
  40. func GetVersionDiff(oldVersion, newVersion string) (left, right string) {
  41. if oldVersion == newVersion {
  42. return oldVersion + text.Red(""), newVersion + text.Green("")
  43. }
  44. diffPosition := 0
  45. checkWords := func(str string, index int, words ...string) bool {
  46. for _, word := range words {
  47. wordLength := len(word)
  48. nextIndex := index + 1
  49. if (index < len(str)-wordLength) &&
  50. (str[nextIndex:(nextIndex+wordLength)] == word) {
  51. return true
  52. }
  53. }
  54. return false
  55. }
  56. for index, char := range oldVersion {
  57. charIsSpecial := !(unicode.IsLetter(char) || unicode.IsNumber(char))
  58. if (index >= len(newVersion)) || (char != rune(newVersion[index])) {
  59. if charIsSpecial {
  60. diffPosition = index
  61. }
  62. break
  63. }
  64. if charIsSpecial ||
  65. (((index == len(oldVersion)-1) || (index == len(newVersion)-1)) &&
  66. ((len(oldVersion) != len(newVersion)) ||
  67. (oldVersion[index] == newVersion[index]))) ||
  68. checkWords(oldVersion, index, "rc", "pre", "alpha", "beta") {
  69. diffPosition = index + 1
  70. }
  71. }
  72. samePart := oldVersion[0:diffPosition]
  73. left = samePart + text.Red(oldVersion[diffPosition:])
  74. right = samePart + text.Green(newVersion[diffPosition:])
  75. return left, right
  76. }
  77. // Print prints the details of the packages to upgrade.
  78. func (u UpSlice) Print(logger *text.Logger) {
  79. longestName, longestVersion := 0, 0
  80. for k := range u.Up {
  81. upgrade := &u.Up[k]
  82. packNameLen := len(StylizedNameWithRepository(upgrade))
  83. packVersion, _ := GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)
  84. packVersionLen := len(packVersion)
  85. longestName = intrange.Max(packNameLen, longestName)
  86. longestVersion = intrange.Max(packVersionLen, longestVersion)
  87. }
  88. namePadding := fmt.Sprintf("%%-%ds ", longestName)
  89. versionPadding := fmt.Sprintf("%%-%ds", longestVersion)
  90. numberPadding := fmt.Sprintf("%%%dd ", len(fmt.Sprintf("%v", len(u.Up))))
  91. for k := range u.Up {
  92. upgrade := &u.Up[k]
  93. left, right := GetVersionDiff(upgrade.LocalVersion, upgrade.RemoteVersion)
  94. logger.Printf(text.Magenta(fmt.Sprintf(numberPadding, len(u.Up)-k)))
  95. logger.Printf(namePadding, StylizedNameWithRepository(upgrade))
  96. logger.Printf("%s -> %s\n", fmt.Sprintf(versionPadding, left), right)
  97. }
  98. }