depCheck.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. package main
  2. import (
  3. "fmt"
  4. "strings"
  5. "sync"
  6. alpm "github.com/jguer/go-alpm"
  7. )
  8. func (dp *depPool) checkInnerConflict(name string, conflict string, conflicts mapStringSet) {
  9. for _, pkg := range dp.Aur {
  10. if pkg.Name == name {
  11. continue
  12. }
  13. if satisfiesAur(conflict, pkg) {
  14. conflicts.Add(name, pkg.Name)
  15. }
  16. }
  17. for _, pkg := range dp.Repo {
  18. if pkg.Name() == name {
  19. continue
  20. }
  21. if satisfiesRepo(conflict, pkg) {
  22. conflicts.Add(name, pkg.Name())
  23. }
  24. }
  25. }
  26. func (dp *depPool) checkForwardConflict(name string, conflict string, conflicts mapStringSet) {
  27. dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error {
  28. if pkg.Name() == name || dp.hasPackage(pkg.Name()) {
  29. return nil
  30. }
  31. if satisfiesRepo(conflict, &pkg) {
  32. n := pkg.Name()
  33. if n != conflict {
  34. n += " (" + conflict + ")"
  35. }
  36. conflicts.Add(name, n)
  37. }
  38. return nil
  39. })
  40. }
  41. func (dp *depPool) checkReverseConflict(name string, conflict string, conflicts mapStringSet) {
  42. for _, pkg := range dp.Aur {
  43. if pkg.Name == name {
  44. continue
  45. }
  46. if satisfiesAur(conflict, pkg) {
  47. if name != conflict {
  48. name += " (" + conflict + ")"
  49. }
  50. conflicts.Add(pkg.Name, name)
  51. }
  52. }
  53. for _, pkg := range dp.Repo {
  54. if pkg.Name() == name {
  55. continue
  56. }
  57. if satisfiesRepo(conflict, pkg) {
  58. if name != conflict {
  59. name += " (" + conflict + ")"
  60. }
  61. conflicts.Add(pkg.Name(), name)
  62. }
  63. }
  64. }
  65. func (dp *depPool) checkInnerConflicts(conflicts mapStringSet) {
  66. for _, pkg := range dp.Aur {
  67. for _, conflict := range pkg.Conflicts {
  68. dp.checkInnerConflict(pkg.Name, conflict, conflicts)
  69. }
  70. }
  71. for _, pkg := range dp.Repo {
  72. pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
  73. dp.checkInnerConflict(pkg.Name(), conflict.String(), conflicts)
  74. return nil
  75. })
  76. }
  77. }
  78. func (dp *depPool) checkForwardConflicts(conflicts mapStringSet) {
  79. for _, pkg := range dp.Aur {
  80. for _, conflict := range pkg.Conflicts {
  81. dp.checkForwardConflict(pkg.Name, conflict, conflicts)
  82. }
  83. }
  84. for _, pkg := range dp.Repo {
  85. pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
  86. dp.checkForwardConflict(pkg.Name(), conflict.String(), conflicts)
  87. return nil
  88. })
  89. }
  90. }
  91. func (dp *depPool) checkReverseConflicts(conflicts mapStringSet) {
  92. dp.LocalDb.PkgCache().ForEach(func(pkg alpm.Package) error {
  93. if dp.hasPackage(pkg.Name()) {
  94. return nil
  95. }
  96. pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
  97. dp.checkReverseConflict(pkg.Name(), conflict.String(), conflicts)
  98. return nil
  99. })
  100. return nil
  101. })
  102. }
  103. func (dp *depPool) CheckConflicts() (mapStringSet, error) {
  104. var wg sync.WaitGroup
  105. innerConflicts := make(mapStringSet)
  106. conflicts := make(mapStringSet)
  107. wg.Add(2)
  108. fmt.Println(bold(cyan("::") + bold(" Checking for conflicts...")))
  109. go func() {
  110. dp.checkForwardConflicts(conflicts)
  111. dp.checkReverseConflicts(conflicts)
  112. wg.Done()
  113. }()
  114. fmt.Println(bold(cyan("::") + bold(" Checking for inner conflicts...")))
  115. go func() {
  116. dp.checkInnerConflicts(innerConflicts)
  117. wg.Done()
  118. }()
  119. wg.Wait()
  120. if len(innerConflicts) != 0 {
  121. fmt.Println()
  122. fmt.Println(bold(red(arrow)), bold("Inner conflicts found:"))
  123. for name, pkgs := range innerConflicts {
  124. str := red(bold(smallArrow)) + " " + name + ":"
  125. for pkg := range pkgs {
  126. str += " " + cyan(pkg) + ","
  127. }
  128. str = strings.TrimSuffix(str, ",")
  129. fmt.Println(str)
  130. }
  131. }
  132. if len(conflicts) != 0 {
  133. fmt.Println()
  134. fmt.Println(bold(red(arrow)), bold("Package conflicts found:"))
  135. for name, pkgs := range conflicts {
  136. str := red(bold(smallArrow)) + " Installing " + cyan(name) + " will remove:"
  137. for pkg := range pkgs {
  138. str += " " + cyan(pkg) + ","
  139. }
  140. str = strings.TrimSuffix(str, ",")
  141. fmt.Println(str)
  142. }
  143. }
  144. // Add the inner conflicts to the conflicts
  145. // These are used to decide what to pass --ask to (if set) or don't pass --noconfirm to
  146. // As we have no idea what the order is yet we add every inner conflict to the slice
  147. for name, pkgs := range innerConflicts {
  148. conflicts[name] = make(stringSet)
  149. for pkg := range pkgs {
  150. conflicts[pkg] = make(stringSet)
  151. }
  152. }
  153. if len(conflicts) > 0 {
  154. if !config.UseAsk {
  155. if config.NoConfirm {
  156. return nil, fmt.Errorf("Package conflicts can not be resolved with noconfirm, aborting")
  157. }
  158. fmt.Println()
  159. fmt.Println(bold(red(arrow)), bold("Conflicting packages will have to be confirmed manually"))
  160. fmt.Println()
  161. }
  162. }
  163. return conflicts, nil
  164. }
  165. type missing struct {
  166. Good stringSet
  167. Missing map[string][][]string
  168. }
  169. func (dp *depPool) _checkMissing(dep string, stack []string, missing *missing) {
  170. if missing.Good.get(dep) {
  171. return
  172. }
  173. if trees, ok := missing.Missing[dep]; ok {
  174. for _, tree := range trees {
  175. if stringSliceEqual(tree, stack) {
  176. return
  177. }
  178. }
  179. missing.Missing[dep] = append(missing.Missing[dep], stack)
  180. return
  181. }
  182. aurPkg := dp.findSatisfierAur(dep)
  183. if aurPkg != nil {
  184. missing.Good.set(dep)
  185. for _, deps := range [3][]string{aurPkg.Depends, aurPkg.MakeDepends, aurPkg.CheckDepends} {
  186. for _, aurDep := range deps {
  187. if _, err := dp.LocalDb.PkgCache().FindSatisfier(aurDep); err == nil {
  188. missing.Good.set(aurDep)
  189. continue
  190. }
  191. dp._checkMissing(aurDep, append(stack, aurPkg.Name), missing)
  192. }
  193. }
  194. return
  195. }
  196. repoPkg := dp.findSatisfierRepo(dep)
  197. if repoPkg != nil {
  198. missing.Good.set(dep)
  199. repoPkg.Depends().ForEach(func(repoDep alpm.Depend) error {
  200. if _, err := dp.LocalDb.PkgCache().FindSatisfier(repoDep.String()); err == nil {
  201. missing.Good.set(repoDep.String())
  202. return nil
  203. }
  204. dp._checkMissing(repoDep.String(), append(stack, repoPkg.Name()), missing)
  205. return nil
  206. })
  207. return
  208. }
  209. missing.Missing[dep] = [][]string{stack}
  210. }
  211. func (dp *depPool) CheckMissing() error {
  212. missing := &missing{
  213. make(stringSet),
  214. make(map[string][][]string),
  215. }
  216. for _, target := range dp.Targets {
  217. dp._checkMissing(target.DepString(), make([]string, 0), missing)
  218. }
  219. if len(missing.Missing) == 0 {
  220. return nil
  221. }
  222. fmt.Println(bold(red(arrow+" Error: ")) + "Could not find all required packages:")
  223. for dep, trees := range missing.Missing {
  224. for _, tree := range trees {
  225. fmt.Print(" ", cyan(dep))
  226. if len(tree) == 0 {
  227. fmt.Print(" (Target")
  228. } else {
  229. fmt.Print(" (Wanted by: ")
  230. for n := 0; n < len(tree)-1; n++ {
  231. fmt.Print(cyan(tree[n]), " -> ")
  232. }
  233. fmt.Print(cyan(tree[len(tree)-1]))
  234. }
  235. fmt.Println(")")
  236. }
  237. }
  238. return fmt.Errorf("")
  239. }