pkgsublist.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * dselect - Debian package maintenance user interface
  3. * pkgsublist.cc - status modification and recursive package list handling
  4. *
  5. * Copyright © 1995 Ian Jackson <ian@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. pkg->clientdata->relations.terminate();
  73. }
  74. bool
  75. packagelist::alreadydone(doneent **done, void *check)
  76. {
  77. doneent *search = *done;
  78. while (search && search->dep != check)
  79. search = search->next;
  80. if (search)
  81. return true;
  82. debug(dbg_general, "packagelist[%p]::alreadydone(%p, %p) new",
  83. this, done, check);
  84. search= new doneent;
  85. search->next= *done;
  86. search->dep= check;
  87. *done= search;
  88. return false;
  89. }
  90. void packagelist::addunavailable(deppossi *possi) {
  91. debug(dbg_general, "packagelist[%p]::addunavail(%p)", this, possi);
  92. if (!recursive) return;
  93. if (alreadydone(&unavdone,possi)) return;
  94. assert(possi->up->up->clientdata);
  95. assert(possi->up->up->clientdata->uprec);
  96. varbuf& vb= possi->up->up->clientdata->relations;
  97. vb(possi->ed->name);
  98. vb(_(" does not appear to be available\n"));
  99. }
  100. bool
  101. packagelist::add(dependency *depends, showpriority displayimportance)
  102. {
  103. debug(dbg_general, "packagelist[%p]::add(dependency[%p])", this, depends);
  104. if (alreadydone(&depsdone, depends))
  105. return false;
  106. const char *comma= "";
  107. varbuf info;
  108. info(depends->up->set->name);
  109. info(' ');
  110. info(gettext(relatestrings[depends->type]));
  111. info(' ');
  112. deppossi *possi;
  113. for (possi=depends->list;
  114. possi;
  115. possi=possi->next, comma=(possi && possi->next ? ", " : _(" or "))) {
  116. info(comma);
  117. info(possi->ed->name);
  118. if (possi->verrel != DPKG_RELATION_NONE) {
  119. switch (possi->verrel) {
  120. case DPKG_RELATION_LE:
  121. info(" (<= ");
  122. break;
  123. case DPKG_RELATION_GE:
  124. info(" (>= ");
  125. break;
  126. case DPKG_RELATION_LT:
  127. info(" (<< ");
  128. break;
  129. case DPKG_RELATION_GT:
  130. info(" (>> ");
  131. break;
  132. case DPKG_RELATION_EQ:
  133. info(" (= ");
  134. break;
  135. default:
  136. internerr("unknown dpkg_relation %d", possi->verrel);
  137. }
  138. info(versiondescribe(&possi->version, vdew_nonambig));
  139. info(")");
  140. }
  141. }
  142. info('\n');
  143. add(depends->up,info.string(),displayimportance);
  144. for (possi=depends->list; possi; possi=possi->next) {
  145. add(&possi->ed->pkg, info.string(), displayimportance);
  146. if (depends->type != dep_provides) {
  147. /* Providers are not relevant if we are looking at a provider
  148. * relationship already. */
  149. deppossi *provider;
  150. for (provider = possi->ed->depended.available;
  151. provider;
  152. provider = provider->rev_next) {
  153. if (provider->up->type != dep_provides) continue;
  154. add(provider->up->up,info.string(),displayimportance);
  155. add(provider->up,displayimportance);
  156. }
  157. }
  158. }
  159. return true;
  160. }
  161. void repeatedlydisplay(packagelist *sub,
  162. showpriority initial,
  163. packagelist *unredisplay) {
  164. pkginfo **newl;
  165. keybindings *kb;
  166. debug(dbg_general, "repeatedlydisplay(packagelist[%p])", sub);
  167. if (sub->resolvesuggest() != 0 && sub->deletelessimp_anyleft(initial)) {
  168. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) once", sub);
  169. if (unredisplay) unredisplay->enddisplay();
  170. for (;;) {
  171. /* Reset manual_install flag now that resolvesuggest() has seen it. */
  172. manual_install = false;
  173. newl= sub->display();
  174. if (!newl) break;
  175. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) newl", sub);
  176. kb= sub->bindings; delete sub;
  177. sub= new packagelist(kb,newl);
  178. if (sub->resolvesuggest() <= 1) break;
  179. if (!sub->deletelessimp_anyleft(dp_must)) break;
  180. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) again", sub);
  181. }
  182. if (unredisplay) unredisplay->startdisplay();
  183. }
  184. debug(dbg_general, "repeatedlydisplay(packagelist[%p]) done", sub);
  185. delete sub;
  186. }
  187. int packagelist::deletelessimp_anyleft(showpriority than) {
  188. debug(dbg_general, "packagelist[%p]::dli_al(%d): nitems=%d",
  189. this, than, nitems);
  190. int insat, runthr;
  191. for (runthr=0, insat=0;
  192. runthr < nitems;
  193. runthr++) {
  194. if (table[runthr]->dpriority < than) {
  195. table[runthr]->free(recursive);
  196. } else {
  197. if (insat != runthr) table[insat]= table[runthr];
  198. insat++;
  199. }
  200. }
  201. nitems= insat;
  202. debug(dbg_general, "packagelist[%p]::dli_al(%d) done; nitems=%d",
  203. this, than, nitems);
  204. return nitems;
  205. }