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