]> git.saurik.com Git - apt.git/blame - apt-private/private-output.cc
Merge remote-tracking branch 'upstream/debian/sid' into debian/sid
[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>
b9179170 26
b9179170
MV
27#include <apti18n.h>
28 /*}}}*/
29
30using namespace std;
31
32std::ostream c0out(0);
33std::ostream c1out(0);
34std::ostream c2out(0);
35std::ofstream devnull("/dev/null");
3163087b
MV
36
37
b9179170
MV
38unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
39
3163087b
MV
40// SigWinch - Window size change signal handler /*{{{*/
41// ---------------------------------------------------------------------
42/* */
43static void SigWinch(int)
44{
45 // Riped from GNU ls
46#ifdef TIOCGWINSZ
47 struct winsize ws;
48
49 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
50 ScreenWidth = ws.ws_col - 1;
51#endif
52}
53 /*}}}*/
ee0167c4 54bool InitOutput() /*{{{*/
b9179170 55{
33b813ce
MV
56 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
57 _config->Set("quiet","1");
58
b9179170
MV
59 c0out.rdbuf(cout.rdbuf());
60 c1out.rdbuf(cout.rdbuf());
61 c2out.rdbuf(cout.rdbuf());
62 if (_config->FindI("quiet",0) > 0)
63 c0out.rdbuf(devnull.rdbuf());
64 if (_config->FindI("quiet",0) > 1)
65 c1out.rdbuf(devnull.rdbuf());
66
3163087b
MV
67 // deal with window size changes
68 signal(SIGWINCH,SigWinch);
69 SigWinch(0);
70
b9179170
MV
71 if(!isatty(1))
72 {
73 _config->Set("APT::Color", "false");
74 _config->Set("APT::Color::Highlight", "");
75 _config->Set("APT::Color::Neutral", "");
76 } else {
77 // Colors
78 _config->CndSet("APT::Color::Highlight", "\x1B[32m");
79 _config->CndSet("APT::Color::Neutral", "\x1B[0m");
80
81 _config->CndSet("APT::Color::Red", "\x1B[31m");
82 _config->CndSet("APT::Color::Green", "\x1B[32m");
83 _config->CndSet("APT::Color::Yellow", "\x1B[33m");
84 _config->CndSet("APT::Color::Blue", "\x1B[34m");
85 _config->CndSet("APT::Color::Magenta", "\x1B[35m");
86 _config->CndSet("APT::Color::Cyan", "\x1B[36m");
87 _config->CndSet("APT::Color::White", "\x1B[37m");
88 }
89
90 return true;
91}
ee0167c4 92 /*}}}*/
65512241 93static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
b9179170
MV
94{
95 std::string suite = "";
96 if (ver && ver.FileList() && ver.FileList())
97 {
98 pkgCache::VerFileIterator VF = ver.FileList();
99 for (; VF.end() == false ; ++VF)
100 {
960975a1
MV
101 if(VF.File() == NULL || VF.File().Archive() == NULL)
102 suite = suite + "," + _("unknown");
103 else
104 suite = suite + "," + VF.File().Archive();
b9179170
MV
105 //suite = VF.File().Archive();
106 }
107 suite = suite.erase(0, 1);
108 }
109 return suite;
110}
ee0167c4 111 /*}}}*/
c3ccac92 112static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
113{
114 pkgDepCache *DepCache = CacheFile.GetDepCache();
115 pkgDepCache::StateCache &state = (*DepCache)[P];
116
117 std::string flags_str;
118 if (state.NowBroken())
119 flags_str = "B";
120 if (P.CurrentVer() && state.Upgradable())
121 flags_str = "g";
122 else if (P.CurrentVer() != NULL)
123 flags_str = "i";
124 else
125 flags_str = "-";
126 return flags_str;
127}
ee0167c4 128 /*}}}*/
c3ccac92 129static std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
130{
131 pkgPolicy *policy = CacheFile.GetPolicy();
132 pkgCache::VerIterator cand = policy->GetCandidateVer(P);
133
134 return cand ? cand.VerStr() : "(none)";
135}
ee0167c4 136 /*}}}*/
65512241 137static std::string GetInstalledVersion(pkgCacheFile &/*CacheFile*/, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
138{
139 pkgCache::VerIterator inst = P.CurrentVer();
140
141 return inst ? inst.VerStr() : "(none)";
142}
ee0167c4 143 /*}}}*/
65512241 144static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator V)/*{{{*/
b9179170
MV
145{
146 pkgCache::PkgIterator P = V.ParentPkg();
147 if (V == P.CurrentVer())
148 {
14109555
MV
149 std::string inst_str = DeNull(V.VerStr());
150#if 0 // FIXME: do we want this or something like this?
b9179170
MV
151 pkgDepCache *DepCache = CacheFile.GetDepCache();
152 pkgDepCache::StateCache &state = (*DepCache)[P];
b9179170
MV
153 if (state.Upgradable())
154 return "**"+inst_str;
14109555 155#endif
b9179170
MV
156 return inst_str;
157 }
158
159 if(V)
160 return DeNull(V.VerStr());
161 return "(none)";
162}
ee0167c4 163 /*}}}*/
c3ccac92 164static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
165{
166 pkgPolicy *policy = CacheFile.GetPolicy();
167 pkgCache::VerIterator inst = P.CurrentVer();
168 pkgCache::VerIterator cand = policy->GetCandidateVer(P);
c3ccac92 169
c8259fcd
MV
170 // this may happen for packages in dpkg "deinstall ok config-file" state
171 if (inst.IsGood() == false && cand.IsGood() == false)
172 return P.VersionList().Arch();
173
b9179170
MV
174 return inst ? inst.Arch() : cand.Arch();
175}
ee0167c4 176 /*}}}*/
c3ccac92 177static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
b9179170
MV
178{
179 pkgPolicy *policy = CacheFile.GetPolicy();
180
181 pkgCache::VerIterator ver;
182 if (P.CurrentVer())
183 ver = P.CurrentVer();
184 else
185 ver = policy->GetCandidateVer(P);
186
187 std::string ShortDescription = "(none)";
188 if(ver)
189 {
190 pkgCache::DescIterator Desc = ver.TranslatedDescription();
191 pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
192
193 ShortDescription = parser.ShortDesc();
194 }
195 return ShortDescription;
196}
ee0167c4
DK
197 /*}}}*/
198void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
500347df
MV
199 pkgCache::VerIterator V, std::ostream &out,
200 bool include_summary)
b9179170
MV
201{
202 pkgCache::PkgIterator P = V.ParentPkg();
203
204 pkgDepCache *DepCache = CacheFile.GetDepCache();
205 pkgDepCache::StateCache &state = (*DepCache)[P];
206
207 std::string suite = GetArchiveSuite(CacheFile, V);
208 std::string name_str = P.Name();
209
210 if (_config->FindB("APT::Cmd::use-format", false))
211 {
212 std::string format = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
213 std::string output = format;
214
215 output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
216 output = SubstVar(output, "${Package}", name_str);
217 output = SubstVar(output, "${installed:Version}", GetInstalledVersion(CacheFile, P));
218 output = SubstVar(output, "${candidate:Version}", GetCandidateVersion(CacheFile, P));
219 output = SubstVar(output, "${Version}", GetVersion(CacheFile, V));
220 output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
221 output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
222 out << output << std::endl;
223 } else {
224 // raring/linux-kernel version [upradable: new-version]
225 // description
226 pkgPolicy *policy = CacheFile.GetPolicy();
4afa7d18
MV
227 std::string VersionStr = GetVersion(CacheFile, V);
228 std::string CandidateVerStr = GetCandidateVersion(CacheFile, P);
229 std::string InstalledVerStr = GetInstalledVersion(CacheFile, P);
230 std::string StatusStr;
b9179170 231 if(P.CurrentVer() == V && state.Upgradable()) {
4afa7d18
MV
232 strprintf(StatusStr, _("[installed,upgradable to: %s]"),
233 CandidateVerStr.c_str());
b9179170 234 } else if (P.CurrentVer() == V) {
b9179170 235 if(!V.Downloadable())
4afa7d18 236 StatusStr = _("[installed,local]");
b9179170
MV
237 else
238 if(V.Automatic() && state.Garbage)
4afa7d18 239 StatusStr = _("[installed,auto-removable]");
b9179170 240 else if (state.Flags & pkgCache::Flag::Auto)
4afa7d18 241 StatusStr = _("[installed,automatic]");
b9179170 242 else
4afa7d18 243 StatusStr = _("[installed]");
b9179170
MV
244 } else if (P.CurrentVer() &&
245 policy->GetCandidateVer(P) == V &&
246 state.Upgradable()) {
4afa7d18
MV
247 strprintf(StatusStr, _("[upgradable from: %s]"),
248 InstalledVerStr.c_str());
b9179170
MV
249 } else {
250 if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
4afa7d18 251 StatusStr = _("[residual-config]");
b9179170 252 else
4afa7d18 253 StatusStr = "";
b9179170 254 }
4afa7d18
MV
255 out << std::setiosflags(std::ios::left)
256 << _config->Find("APT::Color::Highlight", "")
257 << name_str
258 << _config->Find("APT::Color::Neutral", "")
259 << "/" << suite
260 << " "
261 << VersionStr << " "
262 << GetArchitecture(CacheFile, P);
263 if (StatusStr != "")
264 out << " " << StatusStr;
500347df
MV
265 if (include_summary)
266 {
267 out << std::endl
14109555 268 << " " << GetShortDescription(CacheFile, records, P)
500347df
MV
269 << std::endl;
270 }
b9179170
MV
271 }
272}
ee0167c4 273 /*}}}*/
b9179170
MV
274// ShowList - Show a list /*{{{*/
275// ---------------------------------------------------------------------
276/* This prints out a string of space separated words with a title and
277 a two space indent line wraped to the current screen width. */
278bool ShowList(ostream &out,string Title,string List,string VersionsList)
279{
280 if (List.empty() == true)
281 return true;
282 // trim trailing space
283 int NonSpace = List.find_last_not_of(' ');
284 if (NonSpace != -1)
285 {
286 List = List.erase(NonSpace + 1);
287 if (List.empty() == true)
288 return true;
289 }
290
291 // Acount for the leading space
292 int ScreenWidth = ::ScreenWidth - 3;
293
294 out << Title << endl;
295 string::size_type Start = 0;
296 string::size_type VersionsStart = 0;
297 while (Start < List.size())
298 {
299 if(_config->FindB("APT::Get::Show-Versions",false) == true &&
300 VersionsList.size() > 0) {
301 string::size_type End;
302 string::size_type VersionsEnd;
303
304 End = List.find(' ',Start);
305 VersionsEnd = VersionsList.find('\n', VersionsStart);
306
307 out << " " << string(List,Start,End - Start) << " (" <<
308 string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) <<
309 ")" << endl;
310
311 if (End == string::npos || End < Start)
312 End = Start + ScreenWidth;
313
314 Start = End + 1;
315 VersionsStart = VersionsEnd + 1;
316 } else {
317 string::size_type End;
318
319 if (Start + ScreenWidth >= List.size())
320 End = List.size();
321 else
322 End = List.rfind(' ',Start+ScreenWidth);
323
324 if (End == string::npos || End < Start)
325 End = Start + ScreenWidth;
326 out << " " << string(List,Start,End - Start) << endl;
327 Start = End + 1;
328 }
329 }
330
331 return false;
332}
333 /*}}}*/
334// ShowBroken - Debugging aide /*{{{*/
335// ---------------------------------------------------------------------
336/* This prints out the names of all the packages that are broken along
337 with the name of each each broken dependency and a quite version
338 description.
339
340 The output looks like:
341 The following packages have unmet dependencies:
342 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
343 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
344 Depends: libsasl7 but it is not going to be installed
345 */
346void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
347{
348 if (Cache->BrokenCount() == 0)
349 return;
350
351 out << _("The following packages have unmet dependencies:") << endl;
352 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
353 {
354 pkgCache::PkgIterator I(Cache,Cache.List[J]);
355
356 if (Now == true)
357 {
358 if (Cache[I].NowBroken() == false)
359 continue;
360 }
361 else
362 {
363 if (Cache[I].InstBroken() == false)
364 continue;
365 }
366
367 // Print out each package and the failed dependencies
368 out << " " << I.FullName(true) << " :";
369 unsigned const Indent = I.FullName(true).size() + 3;
370 bool First = true;
371 pkgCache::VerIterator Ver;
372
373 if (Now == true)
374 Ver = I.CurrentVer();
375 else
376 Ver = Cache[I].InstVerIter(Cache);
377
378 if (Ver.end() == true)
379 {
380 out << endl;
381 continue;
382 }
383
384 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
385 {
386 // Compute a single dependency element (glob or)
387 pkgCache::DepIterator Start;
388 pkgCache::DepIterator End;
389 D.GlobOr(Start,End); // advances D
390
391 if (Cache->IsImportantDep(End) == false)
392 continue;
393
394 if (Now == true)
395 {
396 if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
397 continue;
398 }
399 else
400 {
401 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
402 continue;
403 }
404
405 bool FirstOr = true;
406 while (1)
407 {
408 if (First == false)
409 for (unsigned J = 0; J != Indent; J++)
410 out << ' ';
411 First = false;
412
413 if (FirstOr == false)
414 {
415 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
416 out << ' ';
417 }
418 else
419 out << ' ' << End.DepType() << ": ";
420 FirstOr = false;
421
422 out << Start.TargetPkg().FullName(true);
423
424 // Show a quick summary of the version requirements
425 if (Start.TargetVer() != 0)
426 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
427
428 /* Show a summary of the target package if possible. In the case
429 of virtual packages we show nothing */
430 pkgCache::PkgIterator Targ = Start.TargetPkg();
431 if (Targ->ProvidesList == 0)
432 {
433 out << ' ';
434 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
435 if (Now == true)
436 Ver = Targ.CurrentVer();
437
438 if (Ver.end() == false)
439 {
440 if (Now == true)
441 ioprintf(out,_("but %s is installed"),Ver.VerStr());
442 else
443 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
444 }
445 else
446 {
447 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
448 {
449 if (Targ->ProvidesList == 0)
450 out << _("but it is not installable");
451 else
452 out << _("but it is a virtual package");
453 }
454 else
455 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
456 }
457 }
458
459 if (Start != End)
460 out << _(" or");
461 out << endl;
462
463 if (Start == End)
464 break;
465 ++Start;
466 }
467 }
468 }
469}
470 /*}}}*/
471// ShowNew - Show packages to newly install /*{{{*/
472// ---------------------------------------------------------------------
473/* */
474void ShowNew(ostream &out,CacheFile &Cache)
475{
476 /* Print out a list of packages that are going to be installed extra
477 to what the user asked */
478 string List;
479 string VersionsList;
480 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
481 {
482 pkgCache::PkgIterator I(Cache,Cache.List[J]);
483 if (Cache[I].NewInstall() == true) {
484 List += I.FullName(true) + " ";
485 VersionsList += string(Cache[I].CandVersion) + "\n";
486 }
487 }
488
489 ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
490}
491 /*}}}*/
492// ShowDel - Show packages to delete /*{{{*/
493// ---------------------------------------------------------------------
494/* */
495void ShowDel(ostream &out,CacheFile &Cache)
496{
497 /* Print out a list of packages that are going to be removed extra
498 to what the user asked */
499 string List;
500 string VersionsList;
501 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
502 {
503 pkgCache::PkgIterator I(Cache,Cache.List[J]);
504 if (Cache[I].Delete() == true)
505 {
506 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
507 List += I.FullName(true) + "* ";
508 else
509 List += I.FullName(true) + " ";
510
511 VersionsList += string(Cache[I].CandVersion)+ "\n";
512 }
513 }
514
515 ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
516}
517 /*}}}*/
518// ShowKept - Show kept packages /*{{{*/
519// ---------------------------------------------------------------------
520/* */
521void ShowKept(ostream &out,CacheFile &Cache)
522{
523 string List;
524 string VersionsList;
525 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
526 {
527 pkgCache::PkgIterator I(Cache,Cache.List[J]);
528
529 // Not interesting
530 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
531 I->CurrentVer == 0 || Cache[I].Delete() == true)
532 continue;
533
534 List += I.FullName(true) + " ";
535 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
536 }
537 ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
538}
539 /*}}}*/
540// ShowUpgraded - Show upgraded packages /*{{{*/
541// ---------------------------------------------------------------------
542/* */
543void ShowUpgraded(ostream &out,CacheFile &Cache)
544{
545 string List;
546 string VersionsList;
547 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
548 {
549 pkgCache::PkgIterator I(Cache,Cache.List[J]);
550
551 // Not interesting
552 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
553 continue;
554
555 List += I.FullName(true) + " ";
556 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
557 }
558 ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
559}
560 /*}}}*/
561// ShowDowngraded - Show downgraded packages /*{{{*/
562// ---------------------------------------------------------------------
563/* */
564bool ShowDowngraded(ostream &out,CacheFile &Cache)
565{
566 string List;
567 string VersionsList;
568 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
569 {
570 pkgCache::PkgIterator I(Cache,Cache.List[J]);
571
572 // Not interesting
573 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
574 continue;
575
576 List += I.FullName(true) + " ";
577 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
578 }
579 return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
580}
581 /*}}}*/
582// ShowHold - Show held but changed packages /*{{{*/
583// ---------------------------------------------------------------------
584/* */
585bool ShowHold(ostream &out,CacheFile &Cache)
586{
587 string List;
588 string VersionsList;
589 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
590 {
591 pkgCache::PkgIterator I(Cache,Cache.List[J]);
592 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
593 I->SelectedState == pkgCache::State::Hold) {
594 List += I.FullName(true) + " ";
595 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
596 }
597 }
598
599 return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
600}
601 /*}}}*/
602// ShowEssential - Show an essential package warning /*{{{*/
603// ---------------------------------------------------------------------
604/* This prints out a warning message that is not to be ignored. It shows
605 all essential packages and their dependents that are to be removed.
606 It is insanely risky to remove the dependents of an essential package! */
607bool ShowEssential(ostream &out,CacheFile &Cache)
608{
609 string List;
610 string VersionsList;
611 bool *Added = new bool[Cache->Head().PackageCount];
612 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
613 Added[I] = false;
614
615 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
616 {
617 pkgCache::PkgIterator I(Cache,Cache.List[J]);
618 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
619 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
620 continue;
621
622 // The essential package is being removed
623 if (Cache[I].Delete() == true)
624 {
625 if (Added[I->ID] == false)
626 {
627 Added[I->ID] = true;
628 List += I.FullName(true) + " ";
629 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
630 }
631 }
632 else
633 continue;
634
635 if (I->CurrentVer == 0)
636 continue;
637
638 // Print out any essential package depenendents that are to be removed
639 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
640 {
641 // Skip everything but depends
642 if (D->Type != pkgCache::Dep::PreDepends &&
643 D->Type != pkgCache::Dep::Depends)
644 continue;
645
646 pkgCache::PkgIterator P = D.SmartTargetPkg();
647 if (Cache[P].Delete() == true)
648 {
649 if (Added[P->ID] == true)
650 continue;
651 Added[P->ID] = true;
652
653 char S[300];
654 snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
655 List += S;
656 //VersionsList += "\n"; ???
657 }
658 }
659 }
660
661 delete [] Added;
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!"),List,VersionsList);
664}
665
666 /*}}}*/
667// Stats - Show some statistics /*{{{*/
668// ---------------------------------------------------------------------
669/* */
670void 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.*/
712bool 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.*/
784bool 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 /*}}}*/