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