You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

private-output.cc 24 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. // Include files /*{{{*/
  2. #include <config.h>
  3. #include <apt-pkg/cachefile.h>
  4. #include <apt-pkg/configuration.h>
  5. #include <apt-pkg/depcache.h>
  6. #include <apt-pkg/error.h>
  7. #include <apt-pkg/pkgcache.h>
  8. #include <apt-pkg/pkgrecords.h>
  9. #include <apt-pkg/policy.h>
  10. #include <apt-pkg/strutl.h>
  11. #include <apt-private/private-cachefile.h>
  12. #include <apt-private/private-output.h>
  13. #include <iomanip>
  14. #include <iostream>
  15. #include <langinfo.h>
  16. #include <regex.h>
  17. #include <signal.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <sys/ioctl.h>
  22. #include <unistd.h>
  23. #include <sstream>
  24. #include <apti18n.h>
  25. /*}}}*/
  26. using namespace std;
  27. std::ostream c0out(0);
  28. std::ostream c1out(0);
  29. std::ostream c2out(0);
  30. std::ofstream devnull("/dev/null");
  31. unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
  32. // SigWinch - Window size change signal handler /*{{{*/
  33. // ---------------------------------------------------------------------
  34. /* */
  35. static void SigWinch(int)
  36. {
  37. // Riped from GNU ls
  38. #ifdef TIOCGWINSZ
  39. struct winsize ws;
  40. if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
  41. ScreenWidth = ws.ws_col - 1;
  42. #endif
  43. }
  44. /*}}}*/
  45. bool InitOutput(std::basic_streambuf<char> * const out) /*{{{*/
  46. {
  47. if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
  48. _config->Set("quiet","1");
  49. c0out.rdbuf(out);
  50. c1out.rdbuf(out);
  51. c2out.rdbuf(out);
  52. if (_config->FindI("quiet",0) > 0)
  53. c0out.rdbuf(devnull.rdbuf());
  54. if (_config->FindI("quiet",0) > 1)
  55. c1out.rdbuf(devnull.rdbuf());
  56. // deal with window size changes
  57. auto cols = getenv("COLUMNS");
  58. if (cols != nullptr)
  59. {
  60. char * colends;
  61. auto const sw = strtoul(cols, &colends, 10);
  62. if (*colends != '\0' || sw == 0)
  63. {
  64. _error->Warning("Environment variable COLUMNS was ignored as it has an invalid value: \"%s\"", cols);
  65. cols = nullptr;
  66. }
  67. else
  68. ScreenWidth = sw;
  69. }
  70. if (cols == nullptr)
  71. {
  72. signal(SIGWINCH,SigWinch);
  73. SigWinch(0);
  74. }
  75. if(!isatty(1))
  76. {
  77. _config->Set("APT::Color", "false");
  78. _config->Set("APT::Color::Highlight", "");
  79. _config->Set("APT::Color::Neutral", "");
  80. } else {
  81. // Colors
  82. _config->CndSet("APT::Color::Highlight", "\x1B[32m");
  83. _config->CndSet("APT::Color::Neutral", "\x1B[0m");
  84. _config->CndSet("APT::Color::Red", "\x1B[31m");
  85. _config->CndSet("APT::Color::Green", "\x1B[32m");
  86. _config->CndSet("APT::Color::Yellow", "\x1B[33m");
  87. _config->CndSet("APT::Color::Blue", "\x1B[34m");
  88. _config->CndSet("APT::Color::Magenta", "\x1B[35m");
  89. _config->CndSet("APT::Color::Cyan", "\x1B[36m");
  90. _config->CndSet("APT::Color::White", "\x1B[37m");
  91. }
  92. return true;
  93. }
  94. /*}}}*/
  95. static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
  96. {
  97. std::string suite = "";
  98. if (ver && ver.FileList())
  99. {
  100. pkgCache::VerFileIterator VF = ver.FileList();
  101. for (; VF.end() == false ; ++VF)
  102. {
  103. if(VF.File() == NULL || VF.File().Archive() == NULL)
  104. suite = suite + "," + _("unknown");
  105. else
  106. suite = suite + "," + VF.File().Archive();
  107. //suite = VF.File().Archive();
  108. }
  109. suite = suite.erase(0, 1);
  110. }
  111. return suite;
  112. }
  113. /*}}}*/
  114. static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
  115. {
  116. pkgDepCache *DepCache = CacheFile.GetDepCache();
  117. pkgDepCache::StateCache &state = (*DepCache)[P];
  118. std::string flags_str;
  119. if (state.NowBroken())
  120. flags_str = "B";
  121. if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
  122. flags_str = "g";
  123. else if (P.CurrentVer() != NULL)
  124. flags_str = "i";
  125. else
  126. flags_str = "-";
  127. return flags_str;
  128. }
  129. /*}}}*/
  130. static std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
  131. {
  132. pkgPolicy *policy = CacheFile.GetPolicy();
  133. pkgCache::VerIterator cand = policy->GetCandidateVer(P);
  134. return cand ? cand.VerStr() : "(none)";
  135. }
  136. /*}}}*/
  137. static std::string GetInstalledVersion(pkgCacheFile &/*CacheFile*/, pkgCache::PkgIterator P)/*{{{*/
  138. {
  139. pkgCache::VerIterator inst = P.CurrentVer();
  140. return inst ? inst.VerStr() : "(none)";
  141. }
  142. /*}}}*/
  143. static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator V)/*{{{*/
  144. {
  145. pkgCache::PkgIterator P = V.ParentPkg();
  146. if (V == P.CurrentVer())
  147. {
  148. std::string inst_str = DeNull(V.VerStr());
  149. #if 0 // FIXME: do we want this or something like this?
  150. pkgDepCache *DepCache = CacheFile.GetDepCache();
  151. pkgDepCache::StateCache &state = (*DepCache)[P];
  152. if (state.Upgradable())
  153. return "**"+inst_str;
  154. #endif
  155. return inst_str;
  156. }
  157. if(V)
  158. return DeNull(V.VerStr());
  159. return "(none)";
  160. }
  161. /*}}}*/
  162. static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
  163. {
  164. if (P->CurrentVer == 0)
  165. {
  166. pkgDepCache * const DepCache = CacheFile.GetDepCache();
  167. pkgDepCache::StateCache const &state = (*DepCache)[P];
  168. if (state.CandidateVer != NULL)
  169. {
  170. pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer);
  171. return CandV.Arch();
  172. }
  173. else
  174. {
  175. pkgCache::VerIterator const V = P.VersionList();
  176. if (V.end() == false)
  177. return V.Arch();
  178. else
  179. return P.Arch();
  180. }
  181. }
  182. else
  183. return P.CurrentVer().Arch();
  184. }
  185. /*}}}*/
  186. static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
  187. {
  188. pkgPolicy *policy = CacheFile.GetPolicy();
  189. pkgCache::VerIterator ver;
  190. if (P.CurrentVer())
  191. ver = P.CurrentVer();
  192. else
  193. ver = policy->GetCandidateVer(P);
  194. std::string ShortDescription = "(none)";
  195. if(ver)
  196. {
  197. pkgCache::DescIterator const Desc = ver.TranslatedDescription();
  198. if (Desc.end() == false)
  199. {
  200. pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
  201. ShortDescription = parser.ShortDesc();
  202. }
  203. }
  204. return ShortDescription;
  205. }
  206. /*}}}*/
  207. static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
  208. {
  209. pkgPolicy *policy = CacheFile.GetPolicy();
  210. pkgCache::VerIterator ver;
  211. if (P->CurrentVer != 0)
  212. ver = P.CurrentVer();
  213. else
  214. ver = policy->GetCandidateVer(P);
  215. std::string const EmptyDescription = "(none)";
  216. if(ver.end() == true)
  217. return EmptyDescription;
  218. pkgCache::DescIterator const Desc = ver.TranslatedDescription();
  219. if (Desc.end() == false)
  220. {
  221. pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
  222. std::string const longdesc = parser.LongDesc();
  223. if (longdesc.empty() == false)
  224. return SubstVar(longdesc, "\n ", "\n ");
  225. }
  226. return EmptyDescription;
  227. }
  228. /*}}}*/
  229. void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
  230. pkgCache::VerIterator const &V, std::ostream &out,
  231. std::string const &format)
  232. {
  233. pkgCache::PkgIterator const P = V.ParentPkg();
  234. pkgDepCache * const DepCache = CacheFile.GetDepCache();
  235. pkgDepCache::StateCache const &state = (*DepCache)[P];
  236. std::string output;
  237. if (_config->FindB("APT::Cmd::use-format", false))
  238. output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
  239. else
  240. output = format;
  241. // FIXME: some of these names are really icky – and all is nowhere documented
  242. output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
  243. output = SubstVar(output, "${Package}", P.Name());
  244. std::string const ArchStr = GetArchitecture(CacheFile, P);
  245. output = SubstVar(output, "${Architecture}", ArchStr);
  246. std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P);
  247. output = SubstVar(output, "${installed:Version}", InstalledVerStr);
  248. std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P);
  249. output = SubstVar(output, "${candidate:Version}", CandidateVerStr);
  250. std::string const VersionStr = GetVersion(CacheFile, V);
  251. output = SubstVar(output, "${Version}", VersionStr);
  252. output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
  253. std::string StatusStr = "";
  254. if (P->CurrentVer != 0)
  255. {
  256. if (P.CurrentVer() == V)
  257. {
  258. if (state.Upgradable() && state.CandidateVer != NULL)
  259. strprintf(StatusStr, _("[installed,upgradable to: %s]"),
  260. CandidateVerStr.c_str());
  261. else if (V.Downloadable() == false)
  262. StatusStr = _("[installed,local]");
  263. else if(V.Automatic() == true && state.Garbage == true)
  264. StatusStr = _("[installed,auto-removable]");
  265. else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
  266. StatusStr = _("[installed,automatic]");
  267. else
  268. StatusStr = _("[installed]");
  269. }
  270. else if (state.CandidateVer == V && state.Upgradable())
  271. strprintf(StatusStr, _("[upgradable from: %s]"),
  272. InstalledVerStr.c_str());
  273. }
  274. else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
  275. StatusStr = _("[residual-config]");
  276. output = SubstVar(output, "${apt:Status}", StatusStr);
  277. output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", ""));
  278. output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", ""));
  279. output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
  280. if (output.find("${LongDescription}") != string::npos)
  281. output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
  282. output = SubstVar(output, "${ }${ }", "${ }");
  283. output = SubstVar(output, "${ }\n", "\n");
  284. output = SubstVar(output, "${ }", " ");
  285. if (APT::String::Endswith(output, " ") == true)
  286. output.erase(output.length() - 1);
  287. out << output;
  288. }
  289. /*}}}*/
  290. // ShowBroken - Debugging aide /*{{{*/
  291. // ---------------------------------------------------------------------
  292. /* This prints out the names of all the packages that are broken along
  293. with the name of each broken dependency and a quite version
  294. description.
  295. The output looks like:
  296. The following packages have unmet dependencies:
  297. exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
  298. Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
  299. Depends: libsasl7 but it is not going to be installed
  300. */
  301. static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
  302. {
  303. if (Now == true)
  304. {
  305. if ((*Cache)[Pkg].NowBroken() == false)
  306. return;
  307. }
  308. else
  309. {
  310. if ((*Cache)[Pkg].InstBroken() == false)
  311. return;
  312. }
  313. // Print out each package and the failed dependencies
  314. out << " " << Pkg.FullName(true) << " :";
  315. unsigned const Indent = Pkg.FullName(true).size() + 3;
  316. bool First = true;
  317. pkgCache::VerIterator Ver;
  318. if (Now == true)
  319. Ver = Pkg.CurrentVer();
  320. else
  321. Ver = (*Cache)[Pkg].InstVerIter(*Cache);
  322. if (Ver.end() == true)
  323. {
  324. out << endl;
  325. return;
  326. }
  327. for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
  328. {
  329. // Compute a single dependency element (glob or)
  330. pkgCache::DepIterator Start;
  331. pkgCache::DepIterator End;
  332. D.GlobOr(Start,End); // advances D
  333. if ((*Cache)->IsImportantDep(End) == false)
  334. continue;
  335. if (Now == true)
  336. {
  337. if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
  338. continue;
  339. }
  340. else
  341. {
  342. if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
  343. continue;
  344. }
  345. bool FirstOr = true;
  346. while (1)
  347. {
  348. if (First == false)
  349. for (unsigned J = 0; J != Indent; J++)
  350. out << ' ';
  351. First = false;
  352. if (FirstOr == false)
  353. {
  354. for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
  355. out << ' ';
  356. }
  357. else
  358. out << ' ' << End.DepType() << ": ";
  359. FirstOr = false;
  360. out << Start.TargetPkg().FullName(true);
  361. // Show a quick summary of the version requirements
  362. if (Start.TargetVer() != 0)
  363. out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
  364. /* Show a summary of the target package if possible. In the case
  365. of virtual packages we show nothing */
  366. pkgCache::PkgIterator Targ = Start.TargetPkg();
  367. if (Targ->ProvidesList == 0)
  368. {
  369. out << ' ';
  370. pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
  371. if (Now == true)
  372. Ver = Targ.CurrentVer();
  373. if (Ver.end() == false)
  374. {
  375. if (Now == true)
  376. ioprintf(out,_("but %s is installed"),Ver.VerStr());
  377. else
  378. ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
  379. }
  380. else
  381. {
  382. if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
  383. {
  384. if (Targ->ProvidesList == 0)
  385. out << _("but it is not installable");
  386. else
  387. out << _("but it is a virtual package");
  388. }
  389. else
  390. out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
  391. }
  392. }
  393. if (Start != End)
  394. out << _(" or");
  395. out << endl;
  396. if (Start == End)
  397. break;
  398. ++Start;
  399. }
  400. }
  401. }
  402. void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
  403. {
  404. if (Cache->BrokenCount() == 0)
  405. return;
  406. out << _("The following packages have unmet dependencies:") << endl;
  407. SortedPackageUniverse Universe(Cache);
  408. for (auto const &Pkg: Universe)
  409. ShowBrokenPackage(out, &Cache, Pkg, Now);
  410. }
  411. void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
  412. {
  413. if (Cache->BrokenCount() == 0)
  414. return;
  415. out << _("The following packages have unmet dependencies:") << endl;
  416. APT::PackageUniverse Universe(Cache);
  417. for (auto const &Pkg: Universe)
  418. ShowBrokenPackage(out, &Cache, Pkg, Now);
  419. }
  420. /*}}}*/
  421. // ShowNew - Show packages to newly install /*{{{*/
  422. void ShowNew(ostream &out,CacheFile &Cache)
  423. {
  424. SortedPackageUniverse Universe(Cache);
  425. ShowList(out,_("The following NEW packages will be installed:"), Universe,
  426. [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); },
  427. &PrettyFullName,
  428. CandidateVersion(&Cache));
  429. }
  430. /*}}}*/
  431. // ShowDel - Show packages to delete /*{{{*/
  432. void ShowDel(ostream &out,CacheFile &Cache)
  433. {
  434. SortedPackageUniverse Universe(Cache);
  435. ShowList(out,_("The following packages will be REMOVED:"), Universe,
  436. [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); },
  437. [&Cache](pkgCache::PkgIterator const &Pkg)
  438. {
  439. std::string str = PrettyFullName(Pkg);
  440. if (((*Cache)[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
  441. str.append("*");
  442. return str;
  443. },
  444. CandidateVersion(&Cache));
  445. }
  446. /*}}}*/
  447. // ShowKept - Show kept packages /*{{{*/
  448. void ShowKept(ostream &out,CacheFile &Cache)
  449. {
  450. SortedPackageUniverse Universe(Cache);
  451. ShowList(out,_("The following packages have been kept back:"), Universe,
  452. [&Cache](pkgCache::PkgIterator const &Pkg)
  453. {
  454. return Cache[Pkg].Upgrade() == false &&
  455. Cache[Pkg].Upgradable() == true &&
  456. Pkg->CurrentVer != 0 &&
  457. Cache[Pkg].Delete() == false;
  458. },
  459. &PrettyFullName,
  460. CurrentToCandidateVersion(&Cache));
  461. }
  462. /*}}}*/
  463. // ShowUpgraded - Show upgraded packages /*{{{*/
  464. void ShowUpgraded(ostream &out,CacheFile &Cache)
  465. {
  466. SortedPackageUniverse Universe(Cache);
  467. ShowList(out,_("The following packages will be upgraded:"), Universe,
  468. [&Cache](pkgCache::PkgIterator const &Pkg)
  469. {
  470. return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false;
  471. },
  472. &PrettyFullName,
  473. CurrentToCandidateVersion(&Cache));
  474. }
  475. /*}}}*/
  476. // ShowDowngraded - Show downgraded packages /*{{{*/
  477. // ---------------------------------------------------------------------
  478. /* */
  479. bool ShowDowngraded(ostream &out,CacheFile &Cache)
  480. {
  481. SortedPackageUniverse Universe(Cache);
  482. return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe,
  483. [&Cache](pkgCache::PkgIterator const &Pkg)
  484. {
  485. return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false;
  486. },
  487. &PrettyFullName,
  488. CurrentToCandidateVersion(&Cache));
  489. }
  490. /*}}}*/
  491. // ShowHold - Show held but changed packages /*{{{*/
  492. bool ShowHold(ostream &out,CacheFile &Cache)
  493. {
  494. SortedPackageUniverse Universe(Cache);
  495. return ShowList(out,_("The following held packages will be changed:"), Universe,
  496. [&Cache](pkgCache::PkgIterator const &Pkg)
  497. {
  498. return Pkg->SelectedState == pkgCache::State::Hold &&
  499. Cache[Pkg].InstallVer != (pkgCache::Version *)Pkg.CurrentVer();
  500. },
  501. &PrettyFullName,
  502. CurrentToCandidateVersion(&Cache));
  503. }
  504. /*}}}*/
  505. // ShowEssential - Show an essential package warning /*{{{*/
  506. // ---------------------------------------------------------------------
  507. /* This prints out a warning message that is not to be ignored. It shows
  508. all essential packages and their dependents that are to be removed.
  509. It is insanely risky to remove the dependents of an essential package! */
  510. struct APT_HIDDEN PrettyFullNameWithDue {
  511. std::map<unsigned long long, pkgCache::PkgIterator> due;
  512. PrettyFullNameWithDue() {}
  513. std::string operator() (pkgCache::PkgIterator const &Pkg)
  514. {
  515. std::string const A = PrettyFullName(Pkg);
  516. std::map<unsigned long long, pkgCache::PkgIterator>::const_iterator d = due.find(Pkg->ID);
  517. if (d == due.end())
  518. return A;
  519. std::string const B = PrettyFullName(d->second);
  520. std::ostringstream outstr;
  521. ioprintf(outstr, _("%s (due to %s)"), A.c_str(), B.c_str());
  522. return outstr.str();
  523. }
  524. };
  525. bool ShowEssential(ostream &out,CacheFile &Cache)
  526. {
  527. std::vector<bool> Added(Cache->Head().PackageCount, false);
  528. APT::PackageDeque pkglist;
  529. PrettyFullNameWithDue withdue;
  530. SortedPackageUniverse Universe(Cache);
  531. for (pkgCache::PkgIterator const &I: Universe)
  532. {
  533. if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
  534. (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
  535. continue;
  536. // The essential package is being removed
  537. if (Cache[I].Delete() == false)
  538. continue;
  539. if (Added[I->ID] == false)
  540. {
  541. Added[I->ID] = true;
  542. pkglist.insert(I);
  543. }
  544. if (I->CurrentVer == 0)
  545. continue;
  546. // Print out any essential package depenendents that are to be removed
  547. for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
  548. {
  549. // Skip everything but depends
  550. if (D->Type != pkgCache::Dep::PreDepends &&
  551. D->Type != pkgCache::Dep::Depends)
  552. continue;
  553. pkgCache::PkgIterator P = D.SmartTargetPkg();
  554. if (Cache[P].Delete() == true)
  555. {
  556. if (Added[P->ID] == true)
  557. continue;
  558. Added[P->ID] = true;
  559. pkglist.insert(P);
  560. withdue.due[P->ID] = I;
  561. }
  562. }
  563. }
  564. return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
  565. "This should NOT be done unless you know exactly what you are doing!"),
  566. pkglist, &AlwaysTrue, withdue, &EmptyString);
  567. }
  568. /*}}}*/
  569. // Stats - Show some statistics /*{{{*/
  570. // ---------------------------------------------------------------------
  571. /* */
  572. void Stats(ostream &out,pkgDepCache &Dep)
  573. {
  574. unsigned long Upgrade = 0;
  575. unsigned long Downgrade = 0;
  576. unsigned long Install = 0;
  577. unsigned long ReInstall = 0;
  578. for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
  579. {
  580. if (Dep[I].NewInstall() == true)
  581. Install++;
  582. else
  583. {
  584. if (Dep[I].Upgrade() == true)
  585. Upgrade++;
  586. else
  587. if (Dep[I].Downgrade() == true)
  588. Downgrade++;
  589. }
  590. if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
  591. ReInstall++;
  592. }
  593. ioprintf(out,_("%lu upgraded, %lu newly installed, "),
  594. Upgrade,Install);
  595. if (ReInstall != 0)
  596. ioprintf(out,_("%lu reinstalled, "),ReInstall);
  597. if (Downgrade != 0)
  598. ioprintf(out,_("%lu downgraded, "),Downgrade);
  599. ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
  600. Dep.DelCount(),Dep.KeepCount());
  601. if (Dep.BadCount() != 0)
  602. ioprintf(out,_("%lu not fully installed or removed.\n"),
  603. Dep.BadCount());
  604. }
  605. /*}}}*/
  606. // YnPrompt - Yes No Prompt. /*{{{*/
  607. // ---------------------------------------------------------------------
  608. /* Returns true on a Yes.*/
  609. bool YnPrompt(char const * const Question, bool const Default, bool const ShowGlobalErrors, std::ostream &c1o, std::ostream &c2o)
  610. {
  611. auto const AssumeYes = _config->FindB("APT::Get::Assume-Yes",false);
  612. auto const AssumeNo = _config->FindB("APT::Get::Assume-No",false);
  613. // if we ask interactively, show warnings/notices before the question
  614. if (ShowGlobalErrors == true && AssumeYes == false && AssumeNo == false)
  615. {
  616. if (_config->FindI("quiet",0) > 0)
  617. _error->DumpErrors(c2o);
  618. else
  619. _error->DumpErrors(c2o, GlobalError::DEBUG);
  620. }
  621. c2o << Question << std::flush;
  622. /* nl_langinfo does not support LANGUAGE setting, so we unset it here
  623. to have the help-message (hopefully) match the expected characters */
  624. char * language = getenv("LANGUAGE");
  625. if (language != NULL)
  626. language = strdup(language);
  627. if (language != NULL)
  628. unsetenv("LANGUAGE");
  629. if (Default == true)
  630. // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
  631. // e.g. "Do you want to continue? [Y/n] "
  632. // The user has to answer with an input matching the
  633. // YESEXPR/NOEXPR defined in your l10n.
  634. c2o << " " << _("[Y/n]") << " " << std::flush;
  635. else
  636. // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
  637. // e.g. "Should this file be removed? [y/N] "
  638. // The user has to answer with an input matching the
  639. // YESEXPR/NOEXPR defined in your l10n.
  640. c2o << " " << _("[y/N]") << " " << std::flush;
  641. if (language != NULL)
  642. {
  643. setenv("LANGUAGE", language, 0);
  644. free(language);
  645. }
  646. if (AssumeYes)
  647. {
  648. // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
  649. c1o << _("Y") << std::endl;
  650. return true;
  651. }
  652. else if (AssumeNo)
  653. {
  654. // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
  655. c1o << _("N") << std::endl;
  656. return false;
  657. }
  658. char response[1024] = "";
  659. std::cin.getline(response, sizeof(response));
  660. if (!std::cin)
  661. return false;
  662. if (strlen(response) == 0)
  663. return Default;
  664. regex_t Pattern;
  665. int Res;
  666. Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
  667. REG_EXTENDED|REG_ICASE|REG_NOSUB);
  668. if (Res != 0) {
  669. char Error[300];
  670. regerror(Res,&Pattern,Error,sizeof(Error));
  671. return _error->Error(_("Regex compilation error - %s"),Error);
  672. }
  673. Res = regexec(&Pattern, response, 0, NULL, 0);
  674. if (Res == 0)
  675. return true;
  676. return false;
  677. }
  678. bool YnPrompt(char const * const Question, bool const Default)
  679. {
  680. return YnPrompt(Question, Default, true, c1out, c2out);
  681. }
  682. /*}}}*/
  683. // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
  684. // ---------------------------------------------------------------------
  685. /* Returns true on a Yes.*/
  686. bool AnalPrompt(std::string const &Question, const char *Text)
  687. {
  688. if (_config->FindI("quiet",0) > 0)
  689. _error->DumpErrors(c2out);
  690. else
  691. _error->DumpErrors(c2out, GlobalError::DEBUG);
  692. c2out << Question << std::flush;
  693. char Buf[1024];
  694. std::cin.getline(Buf,sizeof(Buf));
  695. if (strcmp(Buf,Text) == 0)
  696. return true;
  697. return false;
  698. }
  699. /*}}}*/
  700. std::string PrettyFullName(pkgCache::PkgIterator const &Pkg)
  701. {
  702. return Pkg.FullName(true);
  703. }
  704. std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
  705. {
  706. return (*Cache)[Pkg].CandVersion;
  707. }
  708. std::function<std::string(pkgCache::PkgIterator const &)> CandidateVersion(pkgCacheFile * const Cache)
  709. {
  710. return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CandidateVersion), Cache, std::placeholders::_1);
  711. }
  712. std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
  713. {
  714. return std::string((*Cache)[Pkg].CurVersion) + " => " + (*Cache)[Pkg].CandVersion;
  715. }
  716. std::function<std::string(pkgCache::PkgIterator const &)> CurrentToCandidateVersion(pkgCacheFile * const Cache)
  717. {
  718. return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CurrentToCandidateVersion), Cache, std::placeholders::_1);
  719. }
  720. bool AlwaysTrue(pkgCache::PkgIterator const &)
  721. {
  722. return true;
  723. }
  724. std::string EmptyString(pkgCache::PkgIterator const &)
  725. {
  726. return std::string();
  727. }