pkgdepcon.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /*
  2. * dselect - Debian package maintenance user interface
  3. * pkgdepcon.cc - dependency and conflict resolution
  4. *
  5. * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
  6. * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
  7. *
  8. * This is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. */
  21. #include <config.h>
  22. #include <compat.h>
  23. #include <assert.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <dpkg/dpkg.h>
  27. #include <dpkg/dpkg-db.h>
  28. #include "dselect.h"
  29. #include "pkglist.h"
  30. bool
  31. packagelist::useavailable(pkginfo *pkg)
  32. {
  33. if (pkg->clientdata &&
  34. pkg->clientdata->selected == PKG_WANT_INSTALL &&
  35. pkg_is_informative(pkg, &pkg->available) &&
  36. (!(pkg->status == PKG_STAT_INSTALLED ||
  37. pkg->status == PKG_STAT_TRIGGERSAWAITED ||
  38. pkg->status == PKG_STAT_TRIGGERSPENDING) ||
  39. dpkg_version_compare(&pkg->available.version,
  40. &pkg->installed.version) > 0))
  41. return true;
  42. else
  43. return false;
  44. }
  45. pkgbin *
  46. packagelist::find_pkgbin(pkginfo *pkg)
  47. {
  48. pkgbin *r;
  49. r= useavailable(pkg) ? &pkg->available : &pkg->installed;
  50. debug(dbg_general, "packagelist[%p]::find_pkgbin(%s) useavailable=%d",
  51. this, pkgbin_name(pkg, r, pnaw_always), useavailable(pkg));
  52. return r;
  53. }
  54. int packagelist::checkdependers(pkginfo *pkg, int changemade) {
  55. struct deppossi *possi;
  56. for (possi = pkg->set->depended.available; possi; possi = possi->rev_next) {
  57. if (!useavailable(possi->up->up))
  58. continue;
  59. changemade = max(changemade, resolvedepcon(possi->up));
  60. }
  61. for (possi = pkg->set->depended.installed; possi; possi = possi->rev_next) {
  62. if (useavailable(possi->up->up))
  63. continue;
  64. changemade = max(changemade, resolvedepcon(possi->up));
  65. }
  66. return changemade;
  67. }
  68. int packagelist::resolvesuggest() {
  69. // We continually go around looking for things to change, but we may
  70. // only change the ‘suggested’ value if we also increase the ‘priority’
  71. // Return 2 if we made a change due to a Recommended, Depends or Conficts,
  72. // or 1 if we offered or made a change because of an Optional line.
  73. debug(dbg_general, "packagelist[%p]::resolvesuggest()", this);
  74. int changemade, maxchangemade;
  75. maxchangemade= 0;
  76. for (;;) {
  77. changemade= 0;
  78. int index;
  79. for (index=0; index<nitems; index++) {
  80. if (!table[index]->pkg->set->name)
  81. continue;
  82. debug(dbg_depcon, "packagelist[%p]::resolvesuggest() loop[%i] %s / %d",
  83. this, index, pkg_name(table[index]->pkg, pnaw_always), changemade);
  84. dependency *depends;
  85. for (depends = find_pkgbin(table[index]->pkg)->depends;
  86. depends;
  87. depends= depends->next) {
  88. changemade = max(changemade, resolvedepcon(depends));
  89. }
  90. changemade= checkdependers(table[index]->pkg,changemade);
  91. for (depends = find_pkgbin(table[index]->pkg)->depends;
  92. depends;
  93. depends= depends->next) {
  94. if (depends->type != dep_provides) continue;
  95. changemade = checkdependers(&depends->list->ed->pkg, changemade);
  96. }
  97. debug(dbg_depcon, "packagelist[%p]::resolvesuggest() loop[%i] %s / -> %d",
  98. this, index, pkg_name(table[index]->pkg, pnaw_always), changemade);
  99. }
  100. if (!changemade) break;
  101. maxchangemade = max(maxchangemade, changemade);
  102. }
  103. debug(dbg_general, "packagelist[%p]::resolvesuggest() done; maxchangemade=%d",
  104. this, maxchangemade);
  105. return maxchangemade;
  106. }
  107. static bool
  108. dep_update_best_to_change_stop(perpackagestate *& best, pkginfo *trythis)
  109. {
  110. // There's no point trying to select a pure virtual package.
  111. if (!trythis->clientdata)
  112. return false;
  113. debug(dbg_depcon, "update_best_to_change(best=%s{%d}, test=%s{%d});",
  114. best ? pkg_name(best->pkg, pnaw_always) : "",
  115. best ? (int)best->spriority : -1,
  116. trythis->set->name, trythis->clientdata->spriority);
  117. // If the problem is caused by us deselecting one of these packages
  118. // we should not try to select another one instead.
  119. if (trythis->clientdata->spriority == sp_deselecting)
  120. return true;
  121. // If we haven't found anything yet then this is our best so far.
  122. if (!best) goto yes;
  123. // If only one of the packages is available, use that one
  124. if (!pkg_is_informative(trythis, &trythis->available) &&
  125. pkg_is_informative(best->pkg, &best->pkg->available))
  126. return false;
  127. if (pkg_is_informative(trythis, &trythis->available) &&
  128. !pkg_is_informative(best->pkg, &best->pkg->available))
  129. goto yes;
  130. // Select the package with the lowest priority (ie, the one of whom
  131. // we were least sure we wanted it deselected).
  132. if (trythis->clientdata->spriority > best->spriority)
  133. return false;
  134. if (trythis->clientdata->spriority < best->spriority) goto yes;
  135. // Pick the package with the must fundamental recommendation level.
  136. if (trythis->priority > best->pkg->priority)
  137. return false;
  138. if (trythis->priority < best->pkg->priority) goto yes;
  139. // If we're still unsure we'll change the first one in the list.
  140. return false;
  141. yes:
  142. debug(dbg_depcon, "update_best_to_change(); yes");
  143. best = trythis->clientdata;
  144. return false;
  145. }
  146. int
  147. packagelist::deselect_one_of(pkginfo *per, pkginfo *ped, dependency *dep)
  148. {
  149. perpackagestate *er= per->clientdata;
  150. perpackagestate *ed= ped->clientdata;
  151. if (!er || !would_like_to_install(er->selected,per) ||
  152. !ed || !would_like_to_install(ed->selected,ped)) return 0;
  153. add(dep, dp_must);
  154. er= per->clientdata; // these can be changed by add
  155. ed= ped->clientdata;
  156. debug(dbg_depcon,
  157. "packagelist[%p]::deselect_one_of(): er %s{%d} ed %s{%d} [%p]",
  158. this, pkg_name(er->pkg, pnaw_always), er->spriority,
  159. pkg_name(ed->pkg, pnaw_always), ed->spriority, dep);
  160. perpackagestate *best;
  161. // Try not keep packages needing reinstallation.
  162. if (per->eflag & PKG_EFLAG_REINSTREQ)
  163. best = ed;
  164. else if (ped->eflag & PKG_EFLAG_REINSTREQ)
  165. best = er;
  166. else if (er->spriority < ed->spriority) best= er; // We'd rather change the
  167. else if (er->spriority > ed->spriority) best= ed; // one with the lowest priority.
  168. // ... failing that the one with the highest priority
  169. else if (er->pkg->priority > ed->pkg->priority)
  170. best = er;
  171. else if (er->pkg->priority < ed->pkg->priority)
  172. best = ed;
  173. else best= ed; // ... failing that, the second
  174. debug(dbg_depcon, "packagelist[%p]::deselect_one_of(): best %s{%d}",
  175. this, pkg_name(best->pkg, pnaw_always), best->spriority);
  176. if (best->spriority >= sp_deselecting) return 0;
  177. best->suggested=
  178. best->pkg->status == PKG_STAT_NOTINSTALLED
  179. ? PKG_WANT_PURGE : PKG_WANT_DEINSTALL; // FIXME: configurable.
  180. best->selected= best->suggested;
  181. best->spriority= sp_deselecting;
  182. return 2;
  183. }
  184. int packagelist::resolvedepcon(dependency *depends) {
  185. perpackagestate *best, *fixbyupgrade;
  186. deppossi *possi, *provider;
  187. bool foundany;
  188. int rc;
  189. if (debug_has_flag(dbg_depcon)) {
  190. varbuf pkg_names;
  191. for (possi = depends->list; possi; possi = possi->next) {
  192. pkg_names(' ');
  193. pkg_names(possi->ed->name);
  194. }
  195. debug(dbg_depcon,
  196. "packagelist[%p]::resolvedepcon([%p] %s --%s-->%s); (ing)->want=%s",
  197. this, depends, pkg_name(depends->up, pnaw_always),
  198. relatestrings[depends->type],
  199. pkg_names.string(), depends->up->clientdata ?
  200. wantstrings[depends->up->clientdata->suggested] : "(no clientdata)");
  201. }
  202. if (!depends->up->clientdata) return 0;
  203. switch (depends->type) {
  204. case dep_provides:
  205. case dep_replaces:
  206. return 0;
  207. case dep_enhances:
  208. case dep_suggests:
  209. case dep_recommends:
  210. case dep_depends:
  211. case dep_predepends:
  212. if (would_like_to_install(depends->up->clientdata->selected,depends->up) <= 0)
  213. return 0;
  214. fixbyupgrade = nullptr;
  215. possi = depends->list;
  216. while (possi && !deppossatisfied(possi, &fixbyupgrade))
  217. possi = possi->next;
  218. debug(dbg_depcon, "packagelist[%p]::resolvedepcon([%p]): depends found %s",
  219. this, depends, possi ? possi->ed->name : "[none]");
  220. if (possi) return 0;
  221. // Ensures all in the recursive list; adds info strings; ups priorities
  222. switch (depends->type) {
  223. case dep_enhances:
  224. case dep_suggests:
  225. rc = add(depends, dp_may);
  226. return rc;
  227. case dep_recommends:
  228. rc = add(depends, dp_should);
  229. break;
  230. default:
  231. rc = add(depends, dp_must);
  232. }
  233. if (fixbyupgrade) {
  234. debug(dbg_depcon,
  235. "packagelist[%p]::resolvedepcon([%p]): fixbyupgrade %s",
  236. this, depends, pkg_name(fixbyupgrade->pkg, pnaw_always));
  237. best= fixbyupgrade;
  238. } else {
  239. best = nullptr;
  240. for (possi= depends->list;
  241. possi;
  242. possi= possi->next) {
  243. foundany = false;
  244. if (possi->ed->pkg.clientdata)
  245. foundany = true;
  246. if (dep_update_best_to_change_stop(best, &possi->ed->pkg))
  247. goto mustdeselect;
  248. for (provider = possi->ed->depended.available;
  249. provider;
  250. provider = provider->rev_next) {
  251. if (provider->up->type != dep_provides) continue;
  252. if (provider->up->up->clientdata)
  253. foundany = true;
  254. if (dep_update_best_to_change_stop(best, provider->up->up)) goto mustdeselect;
  255. }
  256. if (!foundany) addunavailable(possi);
  257. }
  258. if (!best) {
  259. debug(dbg_depcon,
  260. "packagelist[%p]::resolvedepcon([%p]): mustdeselect nobest",
  261. this, depends);
  262. return rc;
  263. }
  264. }
  265. debug(dbg_depcon,
  266. "packagelist[%p]::resolvedepcon([%p]): select best=%s{%d}",
  267. this, depends, pkg_name(best->pkg, pnaw_always), best->spriority);
  268. if (best->spriority >= sp_selecting)
  269. return rc;
  270. /* Always select depends. Only select recommends if we got here because
  271. * of a manually-initiated install request. */
  272. if (depends->type != dep_recommends || manual_install) {
  273. best->selected = best->suggested = PKG_WANT_INSTALL;
  274. best->spriority= sp_selecting;
  275. }
  276. return rc ? 2 : 0;
  277. mustdeselect:
  278. best= depends->up->clientdata;
  279. debug(dbg_depcon,
  280. "packagelist[%p]::resolvedepcon([%p]): mustdeselect best=%s{%d}",
  281. this, depends, pkg_name(best->pkg, pnaw_always), best->spriority);
  282. if (best->spriority >= sp_deselecting)
  283. return rc;
  284. /* Always remove depends, but never remove recommends. */
  285. if (depends->type != dep_recommends) {
  286. best->selected= best->suggested=
  287. best->pkg->status == PKG_STAT_NOTINSTALLED
  288. ? PKG_WANT_PURGE : PKG_WANT_DEINSTALL; // FIXME: configurable
  289. best->spriority= sp_deselecting;
  290. }
  291. return rc ? 2 : 0;
  292. case dep_conflicts:
  293. case dep_breaks:
  294. debug(dbg_depcon, "packagelist[%p]::resolvedepcon([%p]): conflict",
  295. this, depends);
  296. if (would_like_to_install(depends->up->clientdata->selected,depends->up) == 0)
  297. return 0;
  298. debug(dbg_depcon,
  299. "packagelist[%p]::resolvedepcon([%p]): conflict installing 1",
  300. this, depends);
  301. if (!deppossatisfied(depends->list, nullptr))
  302. return 0;
  303. debug(dbg_depcon,
  304. "packagelist[%p]::resolvedepcon([%p]): conflict satisfied - ouch",
  305. this, depends);
  306. if (depends->up->set != depends->list->ed) {
  307. rc = deselect_one_of(depends->up, &depends->list->ed->pkg, depends);
  308. if (rc)
  309. return rc;
  310. }
  311. for (provider = depends->list->ed->depended.available;
  312. provider;
  313. provider = provider->rev_next) {
  314. if (provider->up->type != dep_provides) continue;
  315. if (provider->up->up == depends->up) continue; // conflicts & provides same thing
  316. rc = deselect_one_of(depends->up, provider->up->up, depends);
  317. if (rc)
  318. return rc;
  319. }
  320. debug(dbg_depcon, "packagelist[%p]::resolvedepcon([%p]): no desel",
  321. this, depends);
  322. return 0;
  323. default:
  324. internerr("unknown deptype %d", depends->type);
  325. }
  326. /* never reached, make gcc happy */
  327. return 1;
  328. }
  329. bool
  330. packagelist::deppossatisfied(deppossi *possi, perpackagestate **fixbyupgrade)
  331. {
  332. // ‘satisfied’ here for Conflicts and Breaks means that the
  333. // restriction is violated ie that the target package is wanted
  334. int would;
  335. pkgwant want = PKG_WANT_PURGE;
  336. if (possi->ed->pkg.clientdata) {
  337. want = possi->ed->pkg.clientdata->selected;
  338. would = would_like_to_install(want, &possi->ed->pkg);
  339. } else {
  340. would= 0;
  341. }
  342. if ((possi->up->type == dep_conflicts || possi->up->type == dep_breaks)
  343. ? possi->up->up->set != possi->ed && would != 0
  344. : would > 0) {
  345. // If it's to be installed or left installed, then either it's of
  346. // the right version, and therefore OK, or a version must have
  347. // been specified, in which case we don't need to look at the rest
  348. // anyway.
  349. if (useavailable(&possi->ed->pkg)) {
  350. assert(want == PKG_WANT_INSTALL);
  351. return versionsatisfied(&possi->ed->pkg.available, possi);
  352. } else {
  353. if (versionsatisfied(&possi->ed->pkg.installed, possi))
  354. return true;
  355. if (want == PKG_WANT_HOLD && fixbyupgrade && !*fixbyupgrade &&
  356. versionsatisfied(&possi->ed->pkg.available, possi) &&
  357. dpkg_version_compare(&possi->ed->pkg.available.version,
  358. &possi->ed->pkg.installed.version) > 1)
  359. *fixbyupgrade = possi->ed->pkg.clientdata;
  360. return false;
  361. }
  362. }
  363. deppossi *provider;
  364. for (provider = possi->ed->depended.installed;
  365. provider;
  366. provider = provider->rev_next) {
  367. if (provider->up->type == dep_provides &&
  368. ((possi->up->type != dep_conflicts && possi->up->type != dep_breaks) ||
  369. provider->up->up->set != possi->up->up->set) &&
  370. provider->up->up->clientdata &&
  371. !useavailable(provider->up->up) &&
  372. would_like_to_install(provider->up->up->clientdata->selected,
  373. provider->up->up) &&
  374. pkg_virtual_deppossi_satisfied(possi, provider))
  375. return true;
  376. }
  377. for (provider = possi->ed->depended.available;
  378. provider;
  379. provider = provider->rev_next) {
  380. if (provider->up->type != dep_provides ||
  381. ((possi->up->type == dep_conflicts || possi->up->type == dep_breaks) &&
  382. provider->up->up->set == possi->up->up->set) ||
  383. !provider->up->up->clientdata ||
  384. !would_like_to_install(provider->up->up->clientdata->selected,
  385. provider->up->up) ||
  386. !pkg_virtual_deppossi_satisfied(possi, provider))
  387. continue;
  388. if (useavailable(provider->up->up))
  389. return true;
  390. if (fixbyupgrade && !*fixbyupgrade &&
  391. (!(provider->up->up->status == PKG_STAT_INSTALLED ||
  392. provider->up->up->status == PKG_STAT_TRIGGERSPENDING ||
  393. provider->up->up->status == PKG_STAT_TRIGGERSAWAITED) ||
  394. dpkg_version_compare(&provider->up->up->available.version,
  395. &provider->up->up->installed.version) > 1))
  396. *fixbyupgrade = provider->up->up->clientdata;
  397. }
  398. return false;
  399. }