]> git.saurik.com Git - apt.git/blob - apt-private/private-output.cc
b77efff86a11693d8d2f0cfda5d2c7c475d87de1
[apt.git] / apt-private / private-output.cc
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>
10 #include <apt-pkg/depcache.h>
11 #include <apt-pkg/pkgcache.h>
12 #include <apt-pkg/cacheiterators.h>
13
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>
21 #include <iomanip>
22 #include <iostream>
23 #include <langinfo.h>
24 #include <unistd.h>
25 #include <signal.h>
26 #include <sys/ioctl.h>
27
28 #include <sstream>
29
30 #include <apti18n.h>
31 /*}}}*/
32
33 using namespace std;
34
35 std::ostream c0out(0);
36 std::ostream c1out(0);
37 std::ostream c2out(0);
38 std::ofstream devnull("/dev/null");
39
40
41 unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
42
43 // SigWinch - Window size change signal handler /*{{{*/
44 // ---------------------------------------------------------------------
45 /* */
46 static 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 /*}}}*/
57 bool InitOutput(std::basic_streambuf<char> * const out) /*{{{*/
58 {
59 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
60 _config->Set("quiet","1");
61
62 c0out.rdbuf(out);
63 c1out.rdbuf(out);
64 c2out.rdbuf(out);
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
70 // deal with window size changes
71 signal(SIGWINCH,SigWinch);
72 SigWinch(0);
73
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 }
95 /*}}}*/
96 static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
97 {
98 std::string suite = "";
99 if (ver && ver.FileList())
100 {
101 pkgCache::VerFileIterator VF = ver.FileList();
102 for (; VF.end() == false ; ++VF)
103 {
104 if(VF.File() == NULL || VF.File().Archive() == NULL)
105 suite = suite + "," + _("unknown");
106 else
107 suite = suite + "," + VF.File().Archive();
108 //suite = VF.File().Archive();
109 }
110 suite = suite.erase(0, 1);
111 }
112 return suite;
113 }
114 /*}}}*/
115 static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
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";
123 if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
124 flags_str = "g";
125 else if (P.CurrentVer() != NULL)
126 flags_str = "i";
127 else
128 flags_str = "-";
129 return flags_str;
130 }
131 /*}}}*/
132 static std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
133 {
134 pkgPolicy *policy = CacheFile.GetPolicy();
135 pkgCache::VerIterator cand = policy->GetCandidateVer(P);
136
137 return cand ? cand.VerStr() : "(none)";
138 }
139 /*}}}*/
140 static std::string GetInstalledVersion(pkgCacheFile &/*CacheFile*/, pkgCache::PkgIterator P)/*{{{*/
141 {
142 pkgCache::VerIterator inst = P.CurrentVer();
143
144 return inst ? inst.VerStr() : "(none)";
145 }
146 /*}}}*/
147 static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator V)/*{{{*/
148 {
149 pkgCache::PkgIterator P = V.ParentPkg();
150 if (V == P.CurrentVer())
151 {
152 std::string inst_str = DeNull(V.VerStr());
153 #if 0 // FIXME: do we want this or something like this?
154 pkgDepCache *DepCache = CacheFile.GetDepCache();
155 pkgDepCache::StateCache &state = (*DepCache)[P];
156 if (state.Upgradable())
157 return "**"+inst_str;
158 #endif
159 return inst_str;
160 }
161
162 if(V)
163 return DeNull(V.VerStr());
164 return "(none)";
165 }
166 /*}}}*/
167 static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
168 {
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();
189 }
190 /*}}}*/
191 static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
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 {
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 }
210 }
211 return ShortDescription;
212 }
213 /*}}}*/
214 static 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();
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;
237 }
238 /*}}}*/
239 void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
240 pkgCache::VerIterator const &V, std::ostream &out,
241 std::string const &format)
242 {
243 pkgCache::PkgIterator const P = V.ParentPkg();
244 pkgDepCache * const DepCache = CacheFile.GetDepCache();
245 pkgDepCache::StateCache const &state = (*DepCache)[P];
246
247 std::string output;
248 if (_config->FindB("APT::Cmd::use-format", false))
249 output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
250 else
251 output = format;
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)
270 {
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]");
282 }
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", ""));
292 output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
293 output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
294 output = SubstVar(output, "${ }${ }", "${ }");
295 output = SubstVar(output, "${ }\n", "\n");
296 output = SubstVar(output, "${ }", " ");
297 if (APT::String::Endswith(output, " ") == true)
298 output.erase(output.length() - 1);
299
300 out << output;
301 }
302 /*}}}*/
303 // ShowList - Show a list /*{{{*/
304 // ---------------------------------------------------------------------
305 /* This prints out a string of space separated words with a title and
306 a two space indent line wraped to the current screen width. */
307 bool ShowList(ostream &out,string Title,string List,string VersionsList)
308 {
309 if (List.empty() == true)
310 return true;
311 // trim trailing space
312 int NonSpace = List.find_last_not_of(' ');
313 if (NonSpace != -1)
314 {
315 List = List.erase(NonSpace + 1);
316 if (List.empty() == true)
317 return true;
318 }
319
320 // Acount for the leading space
321 int ScreenWidth = ::ScreenWidth - 3;
322
323 out << Title << endl;
324 string::size_type Start = 0;
325 string::size_type VersionsStart = 0;
326 while (Start < List.size())
327 {
328 if(_config->FindB("APT::Get::Show-Versions",false) == true &&
329 VersionsList.size() > 0) {
330 string::size_type End;
331 string::size_type VersionsEnd;
332
333 End = List.find(' ',Start);
334 VersionsEnd = VersionsList.find('\n', VersionsStart);
335
336 out << " " << string(List,Start,End - Start) << " (" <<
337 string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) <<
338 ")" << endl;
339
340 if (End == string::npos || End < Start)
341 End = Start + ScreenWidth;
342
343 Start = End + 1;
344 VersionsStart = VersionsEnd + 1;
345 } else {
346 string::size_type End;
347
348 if (Start + ScreenWidth >= List.size())
349 End = List.size();
350 else
351 End = List.rfind(' ',Start+ScreenWidth);
352
353 if (End == string::npos || End < Start)
354 End = Start + ScreenWidth;
355 out << " " << string(List,Start,End - Start) << endl;
356 Start = End + 1;
357 }
358 }
359
360 return false;
361 }
362 /*}}}*/
363 // ShowBroken - Debugging aide /*{{{*/
364 // ---------------------------------------------------------------------
365 /* This prints out the names of all the packages that are broken along
366 with the name of each each broken dependency and a quite version
367 description.
368
369 The output looks like:
370 The following packages have unmet dependencies:
371 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
372 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
373 Depends: libsasl7 but it is not going to be installed
374 */
375 static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
376 {
377 if (Now == true)
378 {
379 if ((*Cache)[Pkg].NowBroken() == false)
380 return;
381 }
382 else
383 {
384 if ((*Cache)[Pkg].InstBroken() == false)
385 return;
386 }
387
388 // Print out each package and the failed dependencies
389 out << " " << Pkg.FullName(true) << " :";
390 unsigned const Indent = Pkg.FullName(true).size() + 3;
391 bool First = true;
392 pkgCache::VerIterator Ver;
393
394 if (Now == true)
395 Ver = Pkg.CurrentVer();
396 else
397 Ver = (*Cache)[Pkg].InstVerIter(*Cache);
398
399 if (Ver.end() == true)
400 {
401 out << endl;
402 return;
403 }
404
405 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
406 {
407 // Compute a single dependency element (glob or)
408 pkgCache::DepIterator Start;
409 pkgCache::DepIterator End;
410 D.GlobOr(Start,End); // advances D
411
412 if ((*Cache)->IsImportantDep(End) == false)
413 continue;
414
415 if (Now == true)
416 {
417 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
418 continue;
419 }
420 else
421 {
422 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
423 continue;
424 }
425
426 bool FirstOr = true;
427 while (1)
428 {
429 if (First == false)
430 for (unsigned J = 0; J != Indent; J++)
431 out << ' ';
432 First = false;
433
434 if (FirstOr == false)
435 {
436 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
437 out << ' ';
438 }
439 else
440 out << ' ' << End.DepType() << ": ";
441 FirstOr = false;
442
443 out << Start.TargetPkg().FullName(true);
444
445 // Show a quick summary of the version requirements
446 if (Start.TargetVer() != 0)
447 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
448
449 /* Show a summary of the target package if possible. In the case
450 of virtual packages we show nothing */
451 pkgCache::PkgIterator Targ = Start.TargetPkg();
452 if (Targ->ProvidesList == 0)
453 {
454 out << ' ';
455 pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
456 if (Now == true)
457 Ver = Targ.CurrentVer();
458
459 if (Ver.end() == false)
460 {
461 if (Now == true)
462 ioprintf(out,_("but %s is installed"),Ver.VerStr());
463 else
464 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
465 }
466 else
467 {
468 if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
469 {
470 if (Targ->ProvidesList == 0)
471 out << _("but it is not installable");
472 else
473 out << _("but it is a virtual package");
474 }
475 else
476 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
477 }
478 }
479
480 if (Start != End)
481 out << _(" or");
482 out << endl;
483
484 if (Start == End)
485 break;
486 ++Start;
487 }
488 }
489 }
490 void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
491 {
492 if (Cache->BrokenCount() == 0)
493 return;
494
495 out << _("The following packages have unmet dependencies:") << endl;
496 SortedPackageUniverse Universe(Cache);
497 for (auto const &Pkg: Universe)
498 ShowBrokenPackage(out, &Cache, Pkg, Now);
499 }
500 void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
501 {
502 if (Cache->BrokenCount() == 0)
503 return;
504
505 out << _("The following packages have unmet dependencies:") << endl;
506 APT::PackageUniverse Universe(Cache);
507 for (auto const &Pkg: Universe)
508 ShowBrokenPackage(out, &Cache, Pkg, Now);
509 }
510 /*}}}*/
511 // ShowNew - Show packages to newly install /*{{{*/
512 void ShowNew(ostream &out,CacheFile &Cache)
513 {
514 SortedPackageUniverse Universe(Cache);
515 ShowList(out,_("The following NEW packages will be installed:"), Universe,
516 [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); },
517 &PrettyFullName,
518 CandidateVersion(&Cache));
519 }
520 /*}}}*/
521 // ShowDel - Show packages to delete /*{{{*/
522 void ShowDel(ostream &out,CacheFile &Cache)
523 {
524 SortedPackageUniverse Universe(Cache);
525 ShowList(out,_("The following packages will be REMOVED:"), Universe,
526 [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); },
527 [&Cache](pkgCache::PkgIterator const &Pkg)
528 {
529 std::string str = PrettyFullName(Pkg);
530 if (((*Cache)[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
531 str.append("*");
532 return str;
533 },
534 CandidateVersion(&Cache));
535 }
536 /*}}}*/
537 // ShowKept - Show kept packages /*{{{*/
538 void ShowKept(ostream &out,CacheFile &Cache)
539 {
540 SortedPackageUniverse Universe(Cache);
541 ShowList(out,_("The following packages have been kept back:"), Universe,
542 [&Cache](pkgCache::PkgIterator const &Pkg)
543 {
544 return Cache[Pkg].Upgrade() == false &&
545 Cache[Pkg].Upgradable() == true &&
546 Pkg->CurrentVer != 0 &&
547 Cache[Pkg].Delete() == false;
548 },
549 &PrettyFullName,
550 CurrentToCandidateVersion(&Cache));
551 }
552 /*}}}*/
553 // ShowUpgraded - Show upgraded packages /*{{{*/
554 void ShowUpgraded(ostream &out,CacheFile &Cache)
555 {
556 SortedPackageUniverse Universe(Cache);
557 ShowList(out,_("The following packages will be upgraded:"), Universe,
558 [&Cache](pkgCache::PkgIterator const &Pkg)
559 {
560 return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false;
561 },
562 &PrettyFullName,
563 CurrentToCandidateVersion(&Cache));
564 }
565 /*}}}*/
566 // ShowDowngraded - Show downgraded packages /*{{{*/
567 // ---------------------------------------------------------------------
568 /* */
569 bool ShowDowngraded(ostream &out,CacheFile &Cache)
570 {
571 SortedPackageUniverse Universe(Cache);
572 return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe,
573 [&Cache](pkgCache::PkgIterator const &Pkg)
574 {
575 return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false;
576 },
577 &PrettyFullName,
578 CurrentToCandidateVersion(&Cache));
579 }
580 /*}}}*/
581 // ShowHold - Show held but changed packages /*{{{*/
582 bool ShowHold(ostream &out,CacheFile &Cache)
583 {
584 SortedPackageUniverse Universe(Cache);
585 return ShowList(out,_("The following held packages will be changed:"), Universe,
586 [&Cache](pkgCache::PkgIterator const &Pkg)
587 {
588 return Pkg->SelectedState == pkgCache::State::Hold &&
589 Cache[Pkg].InstallVer != (pkgCache::Version *)Pkg.CurrentVer();
590 },
591 &PrettyFullName,
592 CurrentToCandidateVersion(&Cache));
593 }
594 /*}}}*/
595 // ShowEssential - Show an essential package warning /*{{{*/
596 // ---------------------------------------------------------------------
597 /* This prints out a warning message that is not to be ignored. It shows
598 all essential packages and their dependents that are to be removed.
599 It is insanely risky to remove the dependents of an essential package! */
600 struct APT_HIDDEN PrettyFullNameWithDue {
601 std::map<unsigned long long, pkgCache::PkgIterator> due;
602 PrettyFullNameWithDue() {}
603 std::string operator() (pkgCache::PkgIterator const &Pkg)
604 {
605 std::string const A = PrettyFullName(Pkg);
606 std::map<unsigned long long, pkgCache::PkgIterator>::const_iterator d = due.find(Pkg->ID);
607 if (d == due.end())
608 return A;
609
610 std::string const B = PrettyFullName(d->second);
611 std::ostringstream outstr;
612 ioprintf(outstr, _("%s (due to %s)"), A.c_str(), B.c_str());
613 return outstr.str();
614 }
615 };
616 bool ShowEssential(ostream &out,CacheFile &Cache)
617 {
618 std::vector<bool> Added(Cache->Head().PackageCount, false);
619 APT::PackageDeque pkglist;
620 PrettyFullNameWithDue withdue;
621
622 SortedPackageUniverse Universe(Cache);
623 for (pkgCache::PkgIterator const &I: Universe)
624 {
625 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
626 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
627 continue;
628
629 // The essential package is being removed
630 if (Cache[I].Delete() == false)
631 continue;
632
633 if (Added[I->ID] == false)
634 {
635 Added[I->ID] = true;
636 pkglist.insert(I);
637 }
638
639 if (I->CurrentVer == 0)
640 continue;
641
642 // Print out any essential package depenendents that are to be removed
643 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
644 {
645 // Skip everything but depends
646 if (D->Type != pkgCache::Dep::PreDepends &&
647 D->Type != pkgCache::Dep::Depends)
648 continue;
649
650 pkgCache::PkgIterator P = D.SmartTargetPkg();
651 if (Cache[P].Delete() == true)
652 {
653 if (Added[P->ID] == true)
654 continue;
655 Added[P->ID] = true;
656
657 pkglist.insert(P);
658 withdue.due[P->ID] = I;
659 }
660 }
661 }
662 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
663 "This should NOT be done unless you know exactly what you are doing!"),
664 pkglist, &AlwaysTrue, withdue, &EmptyString);
665 }
666 /*}}}*/
667 // Stats - Show some statistics /*{{{*/
668 // ---------------------------------------------------------------------
669 /* */
670 void Stats(ostream &out,pkgDepCache &Dep)
671 {
672 unsigned long Upgrade = 0;
673 unsigned long Downgrade = 0;
674 unsigned long Install = 0;
675 unsigned long ReInstall = 0;
676 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
677 {
678 if (Dep[I].NewInstall() == true)
679 Install++;
680 else
681 {
682 if (Dep[I].Upgrade() == true)
683 Upgrade++;
684 else
685 if (Dep[I].Downgrade() == true)
686 Downgrade++;
687 }
688
689 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
690 ReInstall++;
691 }
692
693 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
694 Upgrade,Install);
695
696 if (ReInstall != 0)
697 ioprintf(out,_("%lu reinstalled, "),ReInstall);
698 if (Downgrade != 0)
699 ioprintf(out,_("%lu downgraded, "),Downgrade);
700
701 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
702 Dep.DelCount(),Dep.KeepCount());
703
704 if (Dep.BadCount() != 0)
705 ioprintf(out,_("%lu not fully installed or removed.\n"),
706 Dep.BadCount());
707 }
708 /*}}}*/
709 // YnPrompt - Yes No Prompt. /*{{{*/
710 // ---------------------------------------------------------------------
711 /* Returns true on a Yes.*/
712 bool YnPrompt(bool Default)
713 {
714 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
715 to have the help-message (hopefully) match the expected characters */
716 char * language = getenv("LANGUAGE");
717 if (language != NULL)
718 language = strdup(language);
719 if (language != NULL)
720 unsetenv("LANGUAGE");
721
722 if (Default == true)
723 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
724 // e.g. "Do you want to continue? [Y/n] "
725 // The user has to answer with an input matching the
726 // YESEXPR/NOEXPR defined in your l10n.
727 c2out << " " << _("[Y/n]") << " " << std::flush;
728 else
729 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
730 // e.g. "Should this file be removed? [y/N] "
731 // The user has to answer with an input matching the
732 // YESEXPR/NOEXPR defined in your l10n.
733 c2out << " " << _("[y/N]") << " " << std::flush;
734
735 if (language != NULL)
736 {
737 setenv("LANGUAGE", language, 0);
738 free(language);
739 }
740
741 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
742 {
743 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
744 c1out << _("Y") << std::endl;
745 return true;
746 }
747 else if (_config->FindB("APT::Get::Assume-No",false) == true)
748 {
749 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
750 c1out << _("N") << std::endl;
751 return false;
752 }
753
754 char response[1024] = "";
755 std::cin.getline(response, sizeof(response));
756
757 if (!std::cin)
758 return false;
759
760 if (strlen(response) == 0)
761 return Default;
762
763 regex_t Pattern;
764 int Res;
765
766 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
767 REG_EXTENDED|REG_ICASE|REG_NOSUB);
768
769 if (Res != 0) {
770 char Error[300];
771 regerror(Res,&Pattern,Error,sizeof(Error));
772 return _error->Error(_("Regex compilation error - %s"),Error);
773 }
774
775 Res = regexec(&Pattern, response, 0, NULL, 0);
776 if (Res == 0)
777 return true;
778 return false;
779 }
780 /*}}}*/
781 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
782 // ---------------------------------------------------------------------
783 /* Returns true on a Yes.*/
784 bool AnalPrompt(const char *Text)
785 {
786 char Buf[1024];
787 std::cin.getline(Buf,sizeof(Buf));
788 if (strcmp(Buf,Text) == 0)
789 return true;
790 return false;
791 }
792 /*}}}*/
793
794 std::string PrettyFullName(pkgCache::PkgIterator const &Pkg)
795 {
796 return Pkg.FullName(true);
797 }
798 std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
799 {
800 return (*Cache)[Pkg].CandVersion;
801 }
802 std::function<std::string(pkgCache::PkgIterator const &)> CandidateVersion(pkgCacheFile * const Cache)
803 {
804 return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CandidateVersion), Cache, std::placeholders::_1);
805 }
806 std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
807 {
808 return std::string((*Cache)[Pkg].CurVersion) + " => " + (*Cache)[Pkg].CandVersion;
809 }
810 std::function<std::string(pkgCache::PkgIterator const &)> CurrentToCandidateVersion(pkgCacheFile * const Cache)
811 {
812 return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CurrentToCandidateVersion), Cache, std::placeholders::_1);
813 }
814 bool AlwaysTrue(pkgCache::PkgIterator const &)
815 {
816 return true;
817 }
818 std::string EmptyString(pkgCache::PkgIterator const &)
819 {
820 return std::string();
821 }
822