]> git.saurik.com Git - apt.git/blame - apt-private/private-output.cc
Avoid yielding blank lines with APT::Cmd::use-format=true
[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";
7d1b93d9 121 if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
b9179170
MV
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));
6763aaec 223 out << output;
b9179170
MV
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;
7d1b93d9
MV
232 if(P.CurrentVer() == V && state.Upgradable() && state.CandidateVer != NULL)
233 {
4afa7d18
MV
234 strprintf(StatusStr, _("[installed,upgradable to: %s]"),
235 CandidateVerStr.c_str());
b9179170 236 } else if (P.CurrentVer() == V) {
b9179170 237 if(!V.Downloadable())
4afa7d18 238 StatusStr = _("[installed,local]");
b9179170
MV
239 else
240 if(V.Automatic() && state.Garbage)
4afa7d18 241 StatusStr = _("[installed,auto-removable]");
b9179170 242 else if (state.Flags & pkgCache::Flag::Auto)
4afa7d18 243 StatusStr = _("[installed,automatic]");
b9179170 244 else
4afa7d18 245 StatusStr = _("[installed]");
b9179170
MV
246 } else if (P.CurrentVer() &&
247 policy->GetCandidateVer(P) == V &&
248 state.Upgradable()) {
4afa7d18
MV
249 strprintf(StatusStr, _("[upgradable from: %s]"),
250 InstalledVerStr.c_str());
b9179170
MV
251 } else {
252 if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
4afa7d18 253 StatusStr = _("[residual-config]");
b9179170 254 else
4afa7d18 255 StatusStr = "";
b9179170 256 }
4afa7d18
MV
257 out << std::setiosflags(std::ios::left)
258 << _config->Find("APT::Color::Highlight", "")
259 << name_str
260 << _config->Find("APT::Color::Neutral", "")
261 << "/" << suite
262 << " "
263 << VersionStr << " "
264 << GetArchitecture(CacheFile, P);
265 if (StatusStr != "")
266 out << " " << StatusStr;
500347df
MV
267 if (include_summary)
268 {
269 out << std::endl
14109555 270 << " " << GetShortDescription(CacheFile, records, P)
500347df
MV
271 << std::endl;
272 }
b9179170
MV
273 }
274}
ee0167c4 275 /*}}}*/
b9179170
MV
276// ShowList - Show a list /*{{{*/
277// ---------------------------------------------------------------------
278/* This prints out a string of space separated words with a title and
279 a two space indent line wraped to the current screen width. */
280bool ShowList(ostream &out,string Title,string List,string VersionsList)
281{
282 if (List.empty() == true)
283 return true;
284 // trim trailing space
285 int NonSpace = List.find_last_not_of(' ');
286 if (NonSpace != -1)
287 {
288 List = List.erase(NonSpace + 1);
289 if (List.empty() == true)
290 return true;
291 }
292
293 // Acount for the leading space
294 int ScreenWidth = ::ScreenWidth - 3;
295
296 out << Title << endl;
297 string::size_type Start = 0;
298 string::size_type VersionsStart = 0;
299 while (Start < List.size())
300 {
301 if(_config->FindB("APT::Get::Show-Versions",false) == true &&
302 VersionsList.size() > 0) {
303 string::size_type End;
304 string::size_type VersionsEnd;
305
306 End = List.find(' ',Start);
307 VersionsEnd = VersionsList.find('\n', VersionsStart);
308
309 out << " " << string(List,Start,End - Start) << " (" <<
310 string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) <<
311 ")" << endl;
312
313 if (End == string::npos || End < Start)
314 End = Start + ScreenWidth;
315
316 Start = End + 1;
317 VersionsStart = VersionsEnd + 1;
318 } else {
319 string::size_type End;
320
321 if (Start + ScreenWidth >= List.size())
322 End = List.size();
323 else
324 End = List.rfind(' ',Start+ScreenWidth);
325
326 if (End == string::npos || End < Start)
327 End = Start + ScreenWidth;
328 out << " " << string(List,Start,End - Start) << endl;
329 Start = End + 1;
330 }
331 }
332
333 return false;
334}
335 /*}}}*/
336// ShowBroken - Debugging aide /*{{{*/
337// ---------------------------------------------------------------------
338/* This prints out the names of all the packages that are broken along
339 with the name of each each broken dependency and a quite version
340 description.
341
342 The output looks like:
343 The following packages have unmet dependencies:
344 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
345 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
346 Depends: libsasl7 but it is not going to be installed
347 */
d39d7f88 348static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
b9179170 349{
d39d7f88
DK
350 if (Now == true)
351 {
352 if ((*Cache)[Pkg].NowBroken() == false)
353 return;
354 }
355 else
356 {
357 if ((*Cache)[Pkg].InstBroken() == false)
358 return;
359 }
360
361 // Print out each package and the failed dependencies
362 out << " " << Pkg.FullName(true) << " :";
363 unsigned const Indent = Pkg.FullName(true).size() + 3;
364 bool First = true;
365 pkgCache::VerIterator Ver;
366
367 if (Now == true)
368 Ver = Pkg.CurrentVer();
369 else
370 Ver = (*Cache)[Pkg].InstVerIter(*Cache);
371
372 if (Ver.end() == true)
373 {
374 out << endl;
b9179170 375 return;
d39d7f88 376 }
b9179170 377
d39d7f88 378 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
b9179170 379 {
d39d7f88
DK
380 // Compute a single dependency element (glob or)
381 pkgCache::DepIterator Start;
382 pkgCache::DepIterator End;
383 D.GlobOr(Start,End); // advances D
384
385 if ((*Cache)->IsImportantDep(End) == false)
386 continue;
387
b9179170
MV
388 if (Now == true)
389 {
d39d7f88 390 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
b9179170
MV
391 continue;
392 }
393 else
394 {
d39d7f88 395 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
b9179170
MV
396 continue;
397 }
d39d7f88
DK
398
399 bool FirstOr = true;
400 while (1)
b9179170 401 {
d39d7f88
DK
402 if (First == false)
403 for (unsigned J = 0; J != Indent; J++)
404 out << ' ';
405 First = false;
b9179170 406
d39d7f88 407 if (FirstOr == false)
b9179170 408 {
d39d7f88
DK
409 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
410 out << ' ';
b9179170
MV
411 }
412 else
d39d7f88
DK
413 out << ' ' << End.DepType() << ": ";
414 FirstOr = false;
415
416 out << Start.TargetPkg().FullName(true);
417
418 // Show a quick summary of the version requirements
419 if (Start.TargetVer() != 0)
420 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
421
422 /* Show a summary of the target package if possible. In the case
423 of virtual packages we show nothing */
424 pkgCache::PkgIterator Targ = Start.TargetPkg();
425 if (Targ->ProvidesList == 0)
b9179170 426 {
d39d7f88
DK
427 out << ' ';
428 pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
429 if (Now == true)
430 Ver = Targ.CurrentVer();
b9179170 431
d39d7f88 432 if (Ver.end() == false)
b9179170 433 {
d39d7f88
DK
434 if (Now == true)
435 ioprintf(out,_("but %s is installed"),Ver.VerStr());
436 else
437 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
b9179170
MV
438 }
439 else
b9179170 440 {
d39d7f88 441 if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
b9179170 442 {
d39d7f88
DK
443 if (Targ->ProvidesList == 0)
444 out << _("but it is not installable");
b9179170 445 else
d39d7f88
DK
446 out << _("but it is a virtual package");
447 }
b9179170 448 else
d39d7f88 449 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
b9179170 450 }
d39d7f88
DK
451 }
452
453 if (Start != End)
454 out << _(" or");
455 out << endl;
456
457 if (Start == End)
458 break;
459 ++Start;
460 }
461 }
462}
463void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
464{
465 if (Cache->BrokenCount() == 0)
466 return;
467
468 out << _("The following packages have unmet dependencies:") << endl;
469 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
470 {
471 pkgCache::PkgIterator const I(Cache,Cache.List[J]);
472 ShowBrokenPackage(out, &Cache, I, Now);
473 }
474}
475void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
476{
477 if (Cache->BrokenCount() == 0)
478 return;
479
480 out << _("The following packages have unmet dependencies:") << endl;
481 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
482 ShowBrokenPackage(out, &Cache, Pkg, Now);
b9179170
MV
483}
484 /*}}}*/
485// ShowNew - Show packages to newly install /*{{{*/
486// ---------------------------------------------------------------------
487/* */
488void ShowNew(ostream &out,CacheFile &Cache)
489{
490 /* Print out a list of packages that are going to be installed extra
491 to what the user asked */
492 string List;
493 string VersionsList;
494 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
495 {
496 pkgCache::PkgIterator I(Cache,Cache.List[J]);
497 if (Cache[I].NewInstall() == true) {
498 List += I.FullName(true) + " ";
499 VersionsList += string(Cache[I].CandVersion) + "\n";
500 }
501 }
502
503 ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
504}
505 /*}}}*/
506// ShowDel - Show packages to delete /*{{{*/
507// ---------------------------------------------------------------------
508/* */
509void ShowDel(ostream &out,CacheFile &Cache)
510{
511 /* Print out a list of packages that are going to be removed extra
512 to what the user asked */
513 string List;
514 string VersionsList;
515 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
516 {
517 pkgCache::PkgIterator I(Cache,Cache.List[J]);
518 if (Cache[I].Delete() == true)
519 {
520 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
521 List += I.FullName(true) + "* ";
522 else
523 List += I.FullName(true) + " ";
524
525 VersionsList += string(Cache[I].CandVersion)+ "\n";
526 }
527 }
528
529 ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
530}
531 /*}}}*/
532// ShowKept - Show kept packages /*{{{*/
533// ---------------------------------------------------------------------
534/* */
535void ShowKept(ostream &out,CacheFile &Cache)
536{
537 string List;
538 string VersionsList;
539 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
540 {
541 pkgCache::PkgIterator I(Cache,Cache.List[J]);
542
543 // Not interesting
544 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
545 I->CurrentVer == 0 || Cache[I].Delete() == true)
546 continue;
547
548 List += I.FullName(true) + " ";
549 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
550 }
551 ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
552}
553 /*}}}*/
554// ShowUpgraded - Show upgraded packages /*{{{*/
555// ---------------------------------------------------------------------
556/* */
557void ShowUpgraded(ostream &out,CacheFile &Cache)
558{
559 string List;
560 string VersionsList;
561 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
562 {
563 pkgCache::PkgIterator I(Cache,Cache.List[J]);
564
565 // Not interesting
566 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
567 continue;
568
569 List += I.FullName(true) + " ";
570 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
571 }
572 ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
573}
574 /*}}}*/
575// ShowDowngraded - Show downgraded packages /*{{{*/
576// ---------------------------------------------------------------------
577/* */
578bool ShowDowngraded(ostream &out,CacheFile &Cache)
579{
580 string List;
581 string VersionsList;
582 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
583 {
584 pkgCache::PkgIterator I(Cache,Cache.List[J]);
585
586 // Not interesting
587 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
588 continue;
589
590 List += I.FullName(true) + " ";
591 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
592 }
593 return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
594}
595 /*}}}*/
596// ShowHold - Show held but changed packages /*{{{*/
597// ---------------------------------------------------------------------
598/* */
599bool ShowHold(ostream &out,CacheFile &Cache)
600{
601 string List;
602 string VersionsList;
603 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
604 {
605 pkgCache::PkgIterator I(Cache,Cache.List[J]);
606 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
607 I->SelectedState == pkgCache::State::Hold) {
608 List += I.FullName(true) + " ";
609 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
610 }
611 }
612
613 return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
614}
615 /*}}}*/
616// ShowEssential - Show an essential package warning /*{{{*/
617// ---------------------------------------------------------------------
618/* This prints out a warning message that is not to be ignored. It shows
619 all essential packages and their dependents that are to be removed.
620 It is insanely risky to remove the dependents of an essential package! */
621bool ShowEssential(ostream &out,CacheFile &Cache)
622{
623 string List;
624 string VersionsList;
625 bool *Added = new bool[Cache->Head().PackageCount];
626 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
627 Added[I] = false;
628
629 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
630 {
631 pkgCache::PkgIterator I(Cache,Cache.List[J]);
632 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
633 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
634 continue;
635
636 // The essential package is being removed
637 if (Cache[I].Delete() == true)
638 {
639 if (Added[I->ID] == false)
640 {
641 Added[I->ID] = true;
642 List += I.FullName(true) + " ";
643 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
644 }
645 }
646 else
647 continue;
648
649 if (I->CurrentVer == 0)
650 continue;
651
652 // Print out any essential package depenendents that are to be removed
653 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
654 {
655 // Skip everything but depends
656 if (D->Type != pkgCache::Dep::PreDepends &&
657 D->Type != pkgCache::Dep::Depends)
658 continue;
659
660 pkgCache::PkgIterator P = D.SmartTargetPkg();
661 if (Cache[P].Delete() == true)
662 {
663 if (Added[P->ID] == true)
664 continue;
665 Added[P->ID] = true;
666
667 char S[300];
668 snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
669 List += S;
670 //VersionsList += "\n"; ???
671 }
672 }
673 }
674
675 delete [] Added;
676 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
677 "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
678}
679
680 /*}}}*/
681// Stats - Show some statistics /*{{{*/
682// ---------------------------------------------------------------------
683/* */
684void Stats(ostream &out,pkgDepCache &Dep)
685{
686 unsigned long Upgrade = 0;
687 unsigned long Downgrade = 0;
688 unsigned long Install = 0;
689 unsigned long ReInstall = 0;
690 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
691 {
692 if (Dep[I].NewInstall() == true)
693 Install++;
694 else
695 {
696 if (Dep[I].Upgrade() == true)
697 Upgrade++;
698 else
699 if (Dep[I].Downgrade() == true)
700 Downgrade++;
701 }
702
703 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
704 ReInstall++;
705 }
706
707 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
708 Upgrade,Install);
709
710 if (ReInstall != 0)
711 ioprintf(out,_("%lu reinstalled, "),ReInstall);
712 if (Downgrade != 0)
713 ioprintf(out,_("%lu downgraded, "),Downgrade);
714
715 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
716 Dep.DelCount(),Dep.KeepCount());
717
718 if (Dep.BadCount() != 0)
719 ioprintf(out,_("%lu not fully installed or removed.\n"),
720 Dep.BadCount());
721}
722 /*}}}*/
723// YnPrompt - Yes No Prompt. /*{{{*/
724// ---------------------------------------------------------------------
725/* Returns true on a Yes.*/
726bool YnPrompt(bool Default)
727{
728 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
729 to have the help-message (hopefully) match the expected characters */
730 char * language = getenv("LANGUAGE");
731 if (language != NULL)
732 language = strdup(language);
733 if (language != NULL)
734 unsetenv("LANGUAGE");
735
736 if (Default == true)
737 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
738 // e.g. "Do you want to continue? [Y/n] "
739 // The user has to answer with an input matching the
740 // YESEXPR/NOEXPR defined in your l10n.
741 c2out << " " << _("[Y/n]") << " " << std::flush;
742 else
743 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
744 // e.g. "Should this file be removed? [y/N] "
745 // The user has to answer with an input matching the
746 // YESEXPR/NOEXPR defined in your l10n.
747 c2out << " " << _("[y/N]") << " " << std::flush;
748
749 if (language != NULL)
750 {
751 setenv("LANGUAGE", language, 0);
752 free(language);
753 }
754
755 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
756 {
757 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
758 c1out << _("Y") << std::endl;
759 return true;
760 }
761 else if (_config->FindB("APT::Get::Assume-No",false) == true)
762 {
763 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
764 c1out << _("N") << std::endl;
765 return false;
766 }
767
768 char response[1024] = "";
769 std::cin.getline(response, sizeof(response));
770
771 if (!std::cin)
772 return false;
773
774 if (strlen(response) == 0)
775 return Default;
776
777 regex_t Pattern;
778 int Res;
779
780 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
781 REG_EXTENDED|REG_ICASE|REG_NOSUB);
782
783 if (Res != 0) {
784 char Error[300];
785 regerror(Res,&Pattern,Error,sizeof(Error));
786 return _error->Error(_("Regex compilation error - %s"),Error);
787 }
788
789 Res = regexec(&Pattern, response, 0, NULL, 0);
790 if (Res == 0)
791 return true;
792 return false;
793}
794 /*}}}*/
795// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
796// ---------------------------------------------------------------------
797/* Returns true on a Yes.*/
798bool AnalPrompt(const char *Text)
799{
800 char Buf[1024];
801 std::cin.getline(Buf,sizeof(Buf));
802 if (strcmp(Buf,Text) == 0)
803 return true;
804 return false;
805}
806 /*}}}*/