depCheck.go 6.3 KB

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