pkgsublist.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * dselect - Debian package maintenance user interface
  3. * pkgsublist.cc - status modification and recursive package list handling
  4. *
  5. * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
  6. * Copyright © 2007-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/i18n.h>
  27. #include <dpkg/dpkg.h>
  28. #include <dpkg/dpkg-db.h>
  29. #include "dselect.h"
  30. #include "bindings.h"
  31. void packagelist::add(pkginfo *pkg) {
  32. debug(dbg_general, "packagelist[%p]::add(pkginfo %s)",
  33. this, pkg_name(pkg, pnaw_always));
  34. if (!recursive || // never add things to top level
  35. !pkg->clientdata || // don't add pure virtual packages
  36. pkg->clientdata->uprec) // don't add ones already in the recursive list
  37. return;
  38. debug(dbg_general, "packagelist[%p]::add(pkginfo %s) adding",
  39. this, pkg_name(pkg, pnaw_always));
  40. perpackagestate *state= &datatable[nitems];
  41. state->pkg= pkg;
  42. state->direct= state->original= pkg->clientdata->selected;
  43. state->suggested= state->selected= pkg->clientdata->selected;
  44. state->spriority= sp_inherit; state->dpriority= dp_none;
  45. state->uprec= pkg->clientdata;
  46. state->relations.init();
  47. pkg->clientdata= state;
  48. table[nitems]= state;
  49. nitems++;
  50. }
  51. void
  52. packagelist::add(pkginfo *pkg, pkgwant nw)
  53. {
  54. debug(dbg_general, "packagelist[%p]::add(pkginfo %s, %s)",
  55. this, pkg_name(pkg, pnaw_always), wantstrings[nw]);
  56. add(pkg); if (!pkg->clientdata) return;
  57. pkg->clientdata->direct= nw;
  58. selpriority np;
  59. np= would_like_to_install(nw,pkg) ? sp_selecting : sp_deselecting;
  60. if (pkg->clientdata->spriority > np) return;
  61. debug(dbg_general, "packagelist[%p]::add(pkginfo %s, %s) setting",
  62. this, pkg_name(pkg, pnaw_always), wantstrings[nw]);
  63. pkg->clientdata->suggested= pkg->clientdata->selected= nw;
  64. pkg->clientdata->spriority= np;
  65. }
  66. void packagelist::add(pkginfo *pkg, const char *extrainfo, showpriority showimp) {
  67. debug(dbg_general, "packagelist[%p]::add(pkginfo %s, ..., showpriority %d)",
  68. this, pkg_name(pkg, pnaw_always), showimp);
  69. add(pkg); if (!pkg->clientdata) return;
  70. if (pkg->clientdata->dpriority < showimp) pkg->clientdata->dpriority= showimp;
  71. pkg->clientdata->relations(extrainfo);
  72. }
  73. bool
  74. packagelist::alreadydone(doneent **done, void *check)
  75. {
  76. doneent *search = *done;
  77. while (search && search->dep != check)
  78. search = search->next;
  79. if (search)
  80. return true;
  81. debug(dbg_general, "packagelist[%p]::alreadydone(%p, %p) new",
  82. this, done, check);
  83. search= new doneent;
  84. search->next= *done;
  85. search->dep= check;
  86. *done= search;
  87. return false;
  88. }
  89. void packagelist::addunavailable(deppossi *possi) {
  90. debug(dbg_general, "packagelist[%p]::addunavail(%p)", this, possi);
  91. if (!recursive) return;
  92. if (alreadydone(&unavdone,possi)) return;
  93. assert(possi->up->up->clientdata);
  94. assert(possi->up->up->clientdata->uprec);
  95. varbuf& vb= possi->up->up->clientdata->relations;
  96. vb(possi->ed->name);
  97. vb(_(" does not appear to be available\n"));
  98. }
  99. bool
  100. packagelist::add(dependency *depends, showpriority displayimportance)
  101. {
  102. debug(dbg_general, "packagelist[%p]::add(dependency[%p])", this, depends);
  103. if (alreadydone(&depsdone, depends))
  104. return false;
  105. const char *comma= "";
  106. varbuf depinfo;
  107. depinfo(depends->up->set->name);
  108. depinfo(' ');
  109. depinfo(gettext(relatestrings[depends->type]));
  110. depinfo(' ');
  111. deppossi *possi;
  112. for (possi=depends->list;
  113. possi;
  114. possi=possi->next, comma=(possi && possi->next ? ", " : _(" or "))) {
  115. depinfo(comma);
  116. depinfo(possi->ed->name);
  117. if (possi->verrel != DPKG_RELATION_NONE) {
  118. switch (possi->verrel) {
  119. case DPKG_RELATION_LE:
  120. depinfo(" (<= ");
  121. break;
  122. case DPKG_RELATION_GE:
  123. depinfo(" (>= ");
  124. break;
  125. case DPKG_RELATION_LT:
  126. depinfo(" (<< ");
  127. break;
  128. case DPKG_RELATION_GT:
  129. depinfo(" (>> ");
  130. break;
  131. case DPKG_RELATION_EQ:
  132. depinfo(" (= ");
  133. break;
  134. default:
  135. internerr("unknown dpkg_relation %d", possi->verrel);
  136. }
  137. depinfo(versiondescribe(&possi->version, vdew_nonambig));
  138. depinfo(")");
  139. }
  140. }
  141. depinfo('\n');
  142. add(depends->up, depinfo.string(), displayimportance);
  143. for (possi=depends->list; possi; possi=possi->next) {
  144. add(&possi->ed->pkg, depinfo.string(), displayimportance);
  145. if (depends->type != dep_provides) {
  146. /* Providers are not relevant if we are looking at a provider
  147. * relationship already. */
  148. deppossi *provider;
  149. for (provider = possi->ed->depended.available;
  150. provider;
  151. provider = provider->rev_next) {
  152. if (provider->up->type != dep_provides) continue;
  153. add(provider->up->up, depinfo.string(), displayimportance);
  154. add(provider->up,displayimportance);
  155. }
  156. }
  157. }
  158. return true;
  159. }
  160. void repeatedlydisplay(packagelist *sub,
  161. showpriority initial,
  162. packagelist *unredisplay) {
  163. pkginfo **newl;
  164. keybindings *kb;
  165. debug(dbg_general, "repeatedlydisplay(packagelist[%p])", sub);
  166. if (sub->resolvesuggest() != 0 && sub->deletelessimp_anyleft(initial)) {
  167. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) once", sub);
  168. if (unredisplay) unredisplay->enddisplay();
  169. for (;;) {
  170. /* Reset manual_install flag now that resolvesuggest() has seen it. */
  171. manual_install = false;
  172. newl= sub->display();
  173. if (!newl) break;
  174. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) newl", sub);
  175. kb= sub->bindings; delete sub;
  176. sub= new packagelist(kb,newl);
  177. if (sub->resolvesuggest() <= 1) break;
  178. if (!sub->deletelessimp_anyleft(dp_must)) break;
  179. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) again", sub);
  180. }
  181. if (unredisplay) unredisplay->startdisplay();
  182. }
  183. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) done", sub);
  184. delete sub;
  185. }
  186. int packagelist::deletelessimp_anyleft(showpriority than) {
  187. debug(dbg_general, "packagelist[%p]::dli_al(%d): nitems=%d",
  188. this, than, nitems);
  189. int insat, runthr;
  190. for (runthr=0, insat=0;
  191. runthr < nitems;
  192. runthr++) {
  193. if (table[runthr]->dpriority < than) {
  194. table[runthr]->free(recursive);
  195. } else {
  196. if (insat != runthr) table[insat]= table[runthr];
  197. insat++;
  198. }
  199. }
  200. nitems= insat;
  201. debug(dbg_general, "packagelist[%p]::dli_al(%d) done; nitems=%d",
  202. this, than, nitems);
  203. return nitems;
  204. }