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