releasing package apt version 1.0.5
[ntk/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 */
d39d7f88 347static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
b9179170 348{
d39d7f88
DK
349 if (Now == true)
350 {
351 if ((*Cache)[Pkg].NowBroken() == false)
352 return;
353 }
354 else
355 {
356 if ((*Cache)[Pkg].InstBroken() == false)
357 return;
358 }
359
360 // Print out each package and the failed dependencies
361 out << " " << Pkg.FullName(true) << " :";
362 unsigned const Indent = Pkg.FullName(true).size() + 3;
363 bool First = true;
364 pkgCache::VerIterator Ver;
365
366 if (Now == true)
367 Ver = Pkg.CurrentVer();
368 else
369 Ver = (*Cache)[Pkg].InstVerIter(*Cache);
370
371 if (Ver.end() == true)
372 {
373 out << endl;
b9179170 374 return;
d39d7f88 375 }
b9179170 376
d39d7f88 377 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
b9179170 378 {
d39d7f88
DK
379 // Compute a single dependency element (glob or)
380 pkgCache::DepIterator Start;
381 pkgCache::DepIterator End;
382 D.GlobOr(Start,End); // advances D
383
384 if ((*Cache)->IsImportantDep(End) == false)
385 continue;
386
b9179170
MV
387 if (Now == true)
388 {
d39d7f88 389 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
b9179170
MV
390 continue;
391 }
392 else
393 {
d39d7f88 394 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
b9179170
MV
395 continue;
396 }
d39d7f88
DK
397
398 bool FirstOr = true;
399 while (1)
b9179170 400 {
d39d7f88
DK
401 if (First == false)
402 for (unsigned J = 0; J != Indent; J++)
403 out << ' ';
404 First = false;
b9179170 405
d39d7f88 406 if (FirstOr == false)
b9179170 407 {
d39d7f88
DK
408 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
409 out << ' ';
b9179170
MV
410 }
411 else
d39d7f88
DK
412 out << ' ' << End.DepType() << ": ";
413 FirstOr = false;
414
415 out << Start.TargetPkg().FullName(true);
416
417 // Show a quick summary of the version requirements
418 if (Start.TargetVer() != 0)
419 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
420
421 /* Show a summary of the target package if possible. In the case
422 of virtual packages we show nothing */
423 pkgCache::PkgIterator Targ = Start.TargetPkg();
424 if (Targ->ProvidesList == 0)
b9179170 425 {
d39d7f88
DK
426 out << ' ';
427 pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
428 if (Now == true)
429 Ver = Targ.CurrentVer();
b9179170 430
d39d7f88 431 if (Ver.end() == false)
b9179170 432 {
d39d7f88
DK
433 if (Now == true)
434 ioprintf(out,_("but %s is installed"),Ver.VerStr());
435 else
436 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
b9179170
MV
437 }
438 else
b9179170 439 {
d39d7f88 440 if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
b9179170 441 {
d39d7f88
DK
442 if (Targ->ProvidesList == 0)
443 out << _("but it is not installable");
b9179170 444 else
d39d7f88
DK
445 out << _("but it is a virtual package");
446 }
b9179170 447 else
d39d7f88 448 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
b9179170 449 }
d39d7f88
DK
450 }
451
452 if (Start != End)
453 out << _(" or");
454 out << endl;
455
456 if (Start == End)
457 break;
458 ++Start;
459 }
460 }
461}
462void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
463{
464 if (Cache->BrokenCount() == 0)
465 return;
466
467 out << _("The following packages have unmet dependencies:") << endl;
468 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
469 {
470 pkgCache::PkgIterator const I(Cache,Cache.List[J]);
471 ShowBrokenPackage(out, &Cache, I, Now);
472 }
473}
474void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
475{
476 if (Cache->BrokenCount() == 0)
477 return;
478
479 out << _("The following packages have unmet dependencies:") << endl;
480 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
481 ShowBrokenPackage(out, &Cache, Pkg, Now);
b9179170
MV
482}
483 /*}}}*/
484// ShowNew - Show packages to newly install /*{{{*/
485// ---------------------------------------------------------------------
486/* */
487void ShowNew(ostream &out,CacheFile &Cache)
488{
489 /* Print out a list of packages that are going to be installed extra
490 to what the user asked */
491 string List;
492 string VersionsList;
493 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
494 {
495 pkgCache::PkgIterator I(Cache,Cache.List[J]);
496 if (Cache[I].NewInstall() == true) {
497 List += I.FullName(true) + " ";
498 VersionsList += string(Cache[I].CandVersion) + "\n";
499 }
500 }
501
502 ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
503}
504 /*}}}*/
505// ShowDel - Show packages to delete /*{{{*/
506// ---------------------------------------------------------------------
507/* */
508void ShowDel(ostream &out,CacheFile &Cache)
509{
510 /* Print out a list of packages that are going to be removed 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].Delete() == true)
518 {
519 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
520 List += I.FullName(true) + "* ";
521 else
522 List += I.FullName(true) + " ";
523
524 VersionsList += string(Cache[I].CandVersion)+ "\n";
525 }
526 }
527
528 ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
529}
530 /*}}}*/
531// ShowKept - Show kept packages /*{{{*/
532// ---------------------------------------------------------------------
533/* */
534void ShowKept(ostream &out,CacheFile &Cache)
535{
536 string List;
537 string VersionsList;
538 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
539 {
540 pkgCache::PkgIterator I(Cache,Cache.List[J]);
541
542 // Not interesting
543 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
544 I->CurrentVer == 0 || Cache[I].Delete() == true)
545 continue;
546
547 List += I.FullName(true) + " ";
548 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
549 }
550 ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
551}
552 /*}}}*/
553// ShowUpgraded - Show upgraded packages /*{{{*/
554// ---------------------------------------------------------------------
555/* */
556void ShowUpgraded(ostream &out,CacheFile &Cache)
557{
558 string List;
559 string VersionsList;
560 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
561 {
562 pkgCache::PkgIterator I(Cache,Cache.List[J]);
563
564 // Not interesting
565 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == 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 will be upgraded:"),List,VersionsList);
572}
573 /*}}}*/
574// ShowDowngraded - Show downgraded packages /*{{{*/
575// ---------------------------------------------------------------------
576/* */
577bool ShowDowngraded(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].Downgrade() == 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 return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
593}
594 /*}}}*/
595// ShowHold - Show held but changed packages /*{{{*/
596// ---------------------------------------------------------------------
597/* */
598bool ShowHold(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 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
606 I->SelectedState == pkgCache::State::Hold) {
607 List += I.FullName(true) + " ";
608 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
609 }
610 }
611
612 return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
613}
614 /*}}}*/
615// ShowEssential - Show an essential package warning /*{{{*/
616// ---------------------------------------------------------------------
617/* This prints out a warning message that is not to be ignored. It shows
618 all essential packages and their dependents that are to be removed.
619 It is insanely risky to remove the dependents of an essential package! */
620bool ShowEssential(ostream &out,CacheFile &Cache)
621{
622 string List;
623 string VersionsList;
624 bool *Added = new bool[Cache->Head().PackageCount];
625 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
626 Added[I] = false;
627
628 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
629 {
630 pkgCache::PkgIterator I(Cache,Cache.List[J]);
631 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
632 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
633 continue;
634
635 // The essential package is being removed
636 if (Cache[I].Delete() == true)
637 {
638 if (Added[I->ID] == false)
639 {
640 Added[I->ID] = true;
641 List += I.FullName(true) + " ";
642 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
643 }
644 }
645 else
646 continue;
647
648 if (I->CurrentVer == 0)
649 continue;
650
651 // Print out any essential package depenendents that are to be removed
652 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
653 {
654 // Skip everything but depends
655 if (D->Type != pkgCache::Dep::PreDepends &&
656 D->Type != pkgCache::Dep::Depends)
657 continue;
658
659 pkgCache::PkgIterator P = D.SmartTargetPkg();
660 if (Cache[P].Delete() == true)
661 {
662 if (Added[P->ID] == true)
663 continue;
664 Added[P->ID] = true;
665
666 char S[300];
667 snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
668 List += S;
669 //VersionsList += "\n"; ???
670 }
671 }
672 }
673
674 delete [] Added;
675 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
676 "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
677}
678
679 /*}}}*/
680// Stats - Show some statistics /*{{{*/
681// ---------------------------------------------------------------------
682/* */
683void Stats(ostream &out,pkgDepCache &Dep)
684{
685 unsigned long Upgrade = 0;
686 unsigned long Downgrade = 0;
687 unsigned long Install = 0;
688 unsigned long ReInstall = 0;
689 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
690 {
691 if (Dep[I].NewInstall() == true)
692 Install++;
693 else
694 {
695 if (Dep[I].Upgrade() == true)
696 Upgrade++;
697 else
698 if (Dep[I].Downgrade() == true)
699 Downgrade++;
700 }
701
702 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
703 ReInstall++;
704 }
705
706 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
707 Upgrade,Install);
708
709 if (ReInstall != 0)
710 ioprintf(out,_("%lu reinstalled, "),ReInstall);
711 if (Downgrade != 0)
712 ioprintf(out,_("%lu downgraded, "),Downgrade);
713
714 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
715 Dep.DelCount(),Dep.KeepCount());
716
717 if (Dep.BadCount() != 0)
718 ioprintf(out,_("%lu not fully installed or removed.\n"),
719 Dep.BadCount());
720}
721 /*}}}*/
722// YnPrompt - Yes No Prompt. /*{{{*/
723// ---------------------------------------------------------------------
724/* Returns true on a Yes.*/
725bool YnPrompt(bool Default)
726{
727 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
728 to have the help-message (hopefully) match the expected characters */
729 char * language = getenv("LANGUAGE");
730 if (language != NULL)
731 language = strdup(language);
732 if (language != NULL)
733 unsetenv("LANGUAGE");
734
735 if (Default == true)
736 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
737 // e.g. "Do you want to continue? [Y/n] "
738 // The user has to answer with an input matching the
739 // YESEXPR/NOEXPR defined in your l10n.
740 c2out << " " << _("[Y/n]") << " " << std::flush;
741 else
742 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
743 // e.g. "Should this file be removed? [y/N] "
744 // The user has to answer with an input matching the
745 // YESEXPR/NOEXPR defined in your l10n.
746 c2out << " " << _("[y/N]") << " " << std::flush;
747
748 if (language != NULL)
749 {
750 setenv("LANGUAGE", language, 0);
751 free(language);
752 }
753
754 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
755 {
756 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
757 c1out << _("Y") << std::endl;
758 return true;
759 }
760 else if (_config->FindB("APT::Get::Assume-No",false) == true)
761 {
762 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
763 c1out << _("N") << std::endl;
764 return false;
765 }
766
767 char response[1024] = "";
768 std::cin.getline(response, sizeof(response));
769
770 if (!std::cin)
771 return false;
772
773 if (strlen(response) == 0)
774 return Default;
775
776 regex_t Pattern;
777 int Res;
778
779 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
780 REG_EXTENDED|REG_ICASE|REG_NOSUB);
781
782 if (Res != 0) {
783 char Error[300];
784 regerror(Res,&Pattern,Error,sizeof(Error));
785 return _error->Error(_("Regex compilation error - %s"),Error);
786 }
787
788 Res = regexec(&Pattern, response, 0, NULL, 0);
789 if (Res == 0)
790 return true;
791 return false;
792}
793 /*}}}*/
794// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
795// ---------------------------------------------------------------------
796/* Returns true on a Yes.*/
797bool AnalPrompt(const char *Text)
798{
799 char Buf[1024];
800 std::cin.getline(Buf,sizeof(Buf));
801 if (strcmp(Buf,Text) == 0)
802 return true;
803 return false;
804}
805 /*}}}*/