]> git.saurik.com Git - apt.git/blame - apt-private/private-output.cc
ensure FileFd doesn't try to open /dev/null as atomic and co
[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));
1a68655d
DK
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);
2409df55
DK
299
300 out << output;
b9179170 301}
ee0167c4 302 /*}}}*/
b9179170
MV
303// ShowBroken - Debugging aide /*{{{*/
304// ---------------------------------------------------------------------
305/* This prints out the names of all the packages that are broken along
306 with the name of each each broken dependency and a quite version
307 description.
308
309 The output looks like:
310 The following packages have unmet dependencies:
311 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
312 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
313 Depends: libsasl7 but it is not going to be installed
314 */
d39d7f88 315static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
b9179170 316{
d39d7f88
DK
317 if (Now == true)
318 {
319 if ((*Cache)[Pkg].NowBroken() == false)
320 return;
321 }
322 else
323 {
324 if ((*Cache)[Pkg].InstBroken() == false)
325 return;
326 }
327
328 // Print out each package and the failed dependencies
329 out << " " << Pkg.FullName(true) << " :";
330 unsigned const Indent = Pkg.FullName(true).size() + 3;
331 bool First = true;
332 pkgCache::VerIterator Ver;
333
334 if (Now == true)
335 Ver = Pkg.CurrentVer();
336 else
337 Ver = (*Cache)[Pkg].InstVerIter(*Cache);
338
339 if (Ver.end() == true)
340 {
341 out << endl;
b9179170 342 return;
d39d7f88 343 }
b9179170 344
d39d7f88 345 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
b9179170 346 {
d39d7f88
DK
347 // Compute a single dependency element (glob or)
348 pkgCache::DepIterator Start;
349 pkgCache::DepIterator End;
350 D.GlobOr(Start,End); // advances D
351
352 if ((*Cache)->IsImportantDep(End) == false)
353 continue;
354
b9179170
MV
355 if (Now == true)
356 {
d39d7f88 357 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
b9179170
MV
358 continue;
359 }
360 else
361 {
d39d7f88 362 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
b9179170
MV
363 continue;
364 }
d39d7f88
DK
365
366 bool FirstOr = true;
367 while (1)
b9179170 368 {
d39d7f88
DK
369 if (First == false)
370 for (unsigned J = 0; J != Indent; J++)
371 out << ' ';
372 First = false;
b9179170 373
d39d7f88 374 if (FirstOr == false)
b9179170 375 {
d39d7f88
DK
376 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
377 out << ' ';
b9179170
MV
378 }
379 else
d39d7f88
DK
380 out << ' ' << End.DepType() << ": ";
381 FirstOr = false;
382
383 out << Start.TargetPkg().FullName(true);
384
385 // Show a quick summary of the version requirements
386 if (Start.TargetVer() != 0)
387 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
388
389 /* Show a summary of the target package if possible. In the case
390 of virtual packages we show nothing */
391 pkgCache::PkgIterator Targ = Start.TargetPkg();
392 if (Targ->ProvidesList == 0)
b9179170 393 {
d39d7f88
DK
394 out << ' ';
395 pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
396 if (Now == true)
397 Ver = Targ.CurrentVer();
b9179170 398
d39d7f88 399 if (Ver.end() == false)
b9179170 400 {
d39d7f88
DK
401 if (Now == true)
402 ioprintf(out,_("but %s is installed"),Ver.VerStr());
403 else
404 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
b9179170
MV
405 }
406 else
b9179170 407 {
d39d7f88 408 if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
b9179170 409 {
d39d7f88
DK
410 if (Targ->ProvidesList == 0)
411 out << _("but it is not installable");
b9179170 412 else
d39d7f88
DK
413 out << _("but it is a virtual package");
414 }
b9179170 415 else
d39d7f88 416 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
b9179170 417 }
d39d7f88
DK
418 }
419
420 if (Start != End)
421 out << _(" or");
422 out << endl;
423
424 if (Start == End)
425 break;
426 ++Start;
427 }
428 }
429}
430void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
431{
432 if (Cache->BrokenCount() == 0)
433 return;
434
435 out << _("The following packages have unmet dependencies:") << endl;
a0c19a21
DK
436 SortedPackageUniverse Universe(Cache);
437 for (auto const &Pkg: Universe)
438 ShowBrokenPackage(out, &Cache, Pkg, Now);
d39d7f88
DK
439}
440void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
441{
442 if (Cache->BrokenCount() == 0)
443 return;
444
445 out << _("The following packages have unmet dependencies:") << endl;
a0c19a21
DK
446 APT::PackageUniverse Universe(Cache);
447 for (auto const &Pkg: Universe)
d39d7f88 448 ShowBrokenPackage(out, &Cache, Pkg, Now);
b9179170
MV
449}
450 /*}}}*/
451// ShowNew - Show packages to newly install /*{{{*/
b9179170
MV
452void ShowNew(ostream &out,CacheFile &Cache)
453{
a0c19a21
DK
454 SortedPackageUniverse Universe(Cache);
455 ShowList(out,_("The following NEW packages will be installed:"), Universe,
456 [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); },
457 &PrettyFullName,
458 CandidateVersion(&Cache));
b9179170
MV
459}
460 /*}}}*/
461// ShowDel - Show packages to delete /*{{{*/
b9179170
MV
462void ShowDel(ostream &out,CacheFile &Cache)
463{
a0c19a21
DK
464 SortedPackageUniverse Universe(Cache);
465 ShowList(out,_("The following packages will be REMOVED:"), Universe,
466 [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); },
467 [&Cache](pkgCache::PkgIterator const &Pkg)
468 {
469 std::string str = PrettyFullName(Pkg);
470 if (((*Cache)[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
471 str.append("*");
472 return str;
473 },
474 CandidateVersion(&Cache));
b9179170
MV
475}
476 /*}}}*/
477// ShowKept - Show kept packages /*{{{*/
b9179170
MV
478void ShowKept(ostream &out,CacheFile &Cache)
479{
a0c19a21
DK
480 SortedPackageUniverse Universe(Cache);
481 ShowList(out,_("The following packages have been kept back:"), Universe,
482 [&Cache](pkgCache::PkgIterator const &Pkg)
483 {
484 return Cache[Pkg].Upgrade() == false &&
485 Cache[Pkg].Upgradable() == true &&
486 Pkg->CurrentVer != 0 &&
487 Cache[Pkg].Delete() == false;
488 },
489 &PrettyFullName,
490 CurrentToCandidateVersion(&Cache));
b9179170
MV
491}
492 /*}}}*/
493// ShowUpgraded - Show upgraded packages /*{{{*/
b9179170
MV
494void ShowUpgraded(ostream &out,CacheFile &Cache)
495{
a0c19a21
DK
496 SortedPackageUniverse Universe(Cache);
497 ShowList(out,_("The following packages will be upgraded:"), Universe,
498 [&Cache](pkgCache::PkgIterator const &Pkg)
499 {
500 return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false;
501 },
502 &PrettyFullName,
503 CurrentToCandidateVersion(&Cache));
b9179170
MV
504}
505 /*}}}*/
506// ShowDowngraded - Show downgraded packages /*{{{*/
507// ---------------------------------------------------------------------
508/* */
509bool ShowDowngraded(ostream &out,CacheFile &Cache)
510{
a0c19a21
DK
511 SortedPackageUniverse Universe(Cache);
512 return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe,
513 [&Cache](pkgCache::PkgIterator const &Pkg)
514 {
515 return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false;
516 },
517 &PrettyFullName,
518 CurrentToCandidateVersion(&Cache));
b9179170
MV
519}
520 /*}}}*/
521// ShowHold - Show held but changed packages /*{{{*/
b9179170
MV
522bool ShowHold(ostream &out,CacheFile &Cache)
523{
a0c19a21
DK
524 SortedPackageUniverse Universe(Cache);
525 return ShowList(out,_("The following held packages will be changed:"), Universe,
526 [&Cache](pkgCache::PkgIterator const &Pkg)
527 {
528 return Pkg->SelectedState == pkgCache::State::Hold &&
529 Cache[Pkg].InstallVer != (pkgCache::Version *)Pkg.CurrentVer();
530 },
531 &PrettyFullName,
532 CurrentToCandidateVersion(&Cache));
b9179170
MV
533}
534 /*}}}*/
535// ShowEssential - Show an essential package warning /*{{{*/
536// ---------------------------------------------------------------------
537/* This prints out a warning message that is not to be ignored. It shows
a0c19a21 538 all essential packages and their dependents that are to be removed.
b9179170 539 It is insanely risky to remove the dependents of an essential package! */
a0c19a21
DK
540struct APT_HIDDEN PrettyFullNameWithDue {
541 std::map<unsigned long long, pkgCache::PkgIterator> due;
542 PrettyFullNameWithDue() {}
543 std::string operator() (pkgCache::PkgIterator const &Pkg)
544 {
545 std::string const A = PrettyFullName(Pkg);
546 std::map<unsigned long long, pkgCache::PkgIterator>::const_iterator d = due.find(Pkg->ID);
547 if (d == due.end())
548 return A;
549
550 std::string const B = PrettyFullName(d->second);
551 std::ostringstream outstr;
552 ioprintf(outstr, _("%s (due to %s)"), A.c_str(), B.c_str());
553 return outstr.str();
554 }
555};
b9179170
MV
556bool ShowEssential(ostream &out,CacheFile &Cache)
557{
a0c19a21
DK
558 std::vector<bool> Added(Cache->Head().PackageCount, false);
559 APT::PackageDeque pkglist;
560 PrettyFullNameWithDue withdue;
561
562 SortedPackageUniverse Universe(Cache);
563 for (pkgCache::PkgIterator const &I: Universe)
b9179170 564 {
b9179170
MV
565 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
566 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
567 continue;
a0c19a21 568
b9179170 569 // The essential package is being removed
a0c19a21
DK
570 if (Cache[I].Delete() == false)
571 continue;
572
573 if (Added[I->ID] == false)
b9179170 574 {
a0c19a21
DK
575 Added[I->ID] = true;
576 pkglist.insert(I);
b9179170 577 }
b9179170
MV
578
579 if (I->CurrentVer == 0)
580 continue;
581
582 // Print out any essential package depenendents that are to be removed
583 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
584 {
585 // Skip everything but depends
586 if (D->Type != pkgCache::Dep::PreDepends &&
587 D->Type != pkgCache::Dep::Depends)
588 continue;
a0c19a21 589
b9179170
MV
590 pkgCache::PkgIterator P = D.SmartTargetPkg();
591 if (Cache[P].Delete() == true)
592 {
593 if (Added[P->ID] == true)
594 continue;
595 Added[P->ID] = true;
a0c19a21
DK
596
597 pkglist.insert(P);
598 withdue.due[P->ID] = I;
599 }
600 }
b9179170 601 }
b9179170 602 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
a0c19a21
DK
603 "This should NOT be done unless you know exactly what you are doing!"),
604 pkglist, &AlwaysTrue, withdue, &EmptyString);
b9179170 605}
b9179170
MV
606 /*}}}*/
607// Stats - Show some statistics /*{{{*/
608// ---------------------------------------------------------------------
609/* */
610void Stats(ostream &out,pkgDepCache &Dep)
611{
612 unsigned long Upgrade = 0;
613 unsigned long Downgrade = 0;
614 unsigned long Install = 0;
615 unsigned long ReInstall = 0;
616 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
617 {
618 if (Dep[I].NewInstall() == true)
619 Install++;
620 else
621 {
622 if (Dep[I].Upgrade() == true)
623 Upgrade++;
624 else
625 if (Dep[I].Downgrade() == true)
626 Downgrade++;
627 }
628
629 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
630 ReInstall++;
631 }
632
633 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
634 Upgrade,Install);
635
636 if (ReInstall != 0)
637 ioprintf(out,_("%lu reinstalled, "),ReInstall);
638 if (Downgrade != 0)
639 ioprintf(out,_("%lu downgraded, "),Downgrade);
640
641 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
642 Dep.DelCount(),Dep.KeepCount());
643
644 if (Dep.BadCount() != 0)
645 ioprintf(out,_("%lu not fully installed or removed.\n"),
646 Dep.BadCount());
647}
648 /*}}}*/
649// YnPrompt - Yes No Prompt. /*{{{*/
650// ---------------------------------------------------------------------
651/* Returns true on a Yes.*/
652bool YnPrompt(bool Default)
653{
654 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
655 to have the help-message (hopefully) match the expected characters */
656 char * language = getenv("LANGUAGE");
657 if (language != NULL)
658 language = strdup(language);
659 if (language != NULL)
660 unsetenv("LANGUAGE");
661
662 if (Default == true)
663 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
664 // e.g. "Do you want to continue? [Y/n] "
665 // The user has to answer with an input matching the
666 // YESEXPR/NOEXPR defined in your l10n.
667 c2out << " " << _("[Y/n]") << " " << std::flush;
668 else
669 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
670 // e.g. "Should this file be removed? [y/N] "
671 // The user has to answer with an input matching the
672 // YESEXPR/NOEXPR defined in your l10n.
673 c2out << " " << _("[y/N]") << " " << std::flush;
674
675 if (language != NULL)
676 {
677 setenv("LANGUAGE", language, 0);
678 free(language);
679 }
680
681 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
682 {
683 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
684 c1out << _("Y") << std::endl;
685 return true;
686 }
687 else if (_config->FindB("APT::Get::Assume-No",false) == true)
688 {
689 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
690 c1out << _("N") << std::endl;
691 return false;
692 }
693
694 char response[1024] = "";
695 std::cin.getline(response, sizeof(response));
696
697 if (!std::cin)
698 return false;
699
700 if (strlen(response) == 0)
701 return Default;
702
703 regex_t Pattern;
704 int Res;
705
706 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
707 REG_EXTENDED|REG_ICASE|REG_NOSUB);
708
709 if (Res != 0) {
710 char Error[300];
711 regerror(Res,&Pattern,Error,sizeof(Error));
712 return _error->Error(_("Regex compilation error - %s"),Error);
713 }
714
715 Res = regexec(&Pattern, response, 0, NULL, 0);
716 if (Res == 0)
717 return true;
718 return false;
719}
720 /*}}}*/
721// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
722// ---------------------------------------------------------------------
723/* Returns true on a Yes.*/
724bool AnalPrompt(const char *Text)
725{
726 char Buf[1024];
727 std::cin.getline(Buf,sizeof(Buf));
728 if (strcmp(Buf,Text) == 0)
729 return true;
730 return false;
731}
732 /*}}}*/
a0c19a21
DK
733
734std::string PrettyFullName(pkgCache::PkgIterator const &Pkg)
735{
736 return Pkg.FullName(true);
737}
738std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
739{
740 return (*Cache)[Pkg].CandVersion;
741}
742std::function<std::string(pkgCache::PkgIterator const &)> CandidateVersion(pkgCacheFile * const Cache)
743{
744 return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CandidateVersion), Cache, std::placeholders::_1);
745}
746std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg)
747{
748 return std::string((*Cache)[Pkg].CurVersion) + " => " + (*Cache)[Pkg].CandVersion;
749}
750std::function<std::string(pkgCache::PkgIterator const &)> CurrentToCandidateVersion(pkgCacheFile * const Cache)
751{
752 return std::bind(static_cast<std::string(*)(pkgCacheFile * const, pkgCache::PkgIterator const&)>(&CurrentToCandidateVersion), Cache, std::placeholders::_1);
753}
754bool AlwaysTrue(pkgCache::PkgIterator const &)
755{
756 return true;
757}
758std::string EmptyString(pkgCache::PkgIterator const &)
759{
760 return std::string();
761}
762