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