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