private-output.cc 25 KB

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