]>
git.saurik.com Git - apt.git/blob - apt-private/private-output.cc
1 // Include files /*{{{*/
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>
17 #include "private-output.h"
18 #include "private-cachefile.h"
25 std::ostream
c0out(0);
26 std::ostream
c1out(0);
27 std::ostream
c2out(0);
28 std::ofstream
devnull("/dev/null");
29 unsigned int ScreenWidth
= 80 - 1; /* - 1 for the cursor */
31 bool InitOutput() /*{{{*/
33 c0out
.rdbuf(cout
.rdbuf());
34 c1out
.rdbuf(cout
.rdbuf());
35 c2out
.rdbuf(cout
.rdbuf());
36 if (_config
->FindI("quiet",0) > 0)
37 c0out
.rdbuf(devnull
.rdbuf());
38 if (_config
->FindI("quiet",0) > 1)
39 c1out
.rdbuf(devnull
.rdbuf());
43 _config
->Set("APT::Color", "false");
44 _config
->Set("APT::Color::Highlight", "");
45 _config
->Set("APT::Color::Neutral", "");
48 _config
->CndSet("APT::Color::Highlight", "\x1B[32m");
49 _config
->CndSet("APT::Color::Neutral", "\x1B[0m");
51 _config
->CndSet("APT::Color::Red", "\x1B[31m");
52 _config
->CndSet("APT::Color::Green", "\x1B[32m");
53 _config
->CndSet("APT::Color::Yellow", "\x1B[33m");
54 _config
->CndSet("APT::Color::Blue", "\x1B[34m");
55 _config
->CndSet("APT::Color::Magenta", "\x1B[35m");
56 _config
->CndSet("APT::Color::Cyan", "\x1B[36m");
57 _config
->CndSet("APT::Color::White", "\x1B[37m");
63 std::string
GetArchiveSuite(pkgCacheFile
&CacheFile
, pkgCache::VerIterator ver
) /*{{{*/
65 std::string suite
= "";
66 if (ver
&& ver
.FileList() && ver
.FileList())
68 pkgCache::VerFileIterator VF
= ver
.FileList();
69 for (; VF
.end() == false ; ++VF
)
71 // XXX: how to figure out the relevant suite? if its in multiple ones?
72 suite
= suite
+ "," + VF
.File().Archive();
73 //suite = VF.File().Archive();
75 suite
= suite
.erase(0, 1);
80 std::string
GetFlagsStr(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
82 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
83 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
85 std::string flags_str
;
86 if (state
.NowBroken())
88 if (P
.CurrentVer() && state
.Upgradable())
90 else if (P
.CurrentVer() != NULL
)
97 std::string
GetCandidateVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
99 pkgPolicy
*policy
= CacheFile
.GetPolicy();
100 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
102 return cand
? cand
.VerStr() : "(none)";
105 std::string
GetInstalledVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
107 pkgCache::VerIterator inst
= P
.CurrentVer();
109 return inst
? inst
.VerStr() : "(none)";
112 std::string
GetVersion(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)/*{{{*/
114 pkgCache::PkgIterator P
= V
.ParentPkg();
115 if (V
== P
.CurrentVer())
117 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
118 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
119 std::string inst_str
= DeNull(V
.VerStr());
120 if (state
.Upgradable())
121 return "**"+inst_str
;
126 return DeNull(V
.VerStr());
130 std::string
GetArchitecture(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
132 pkgPolicy
*policy
= CacheFile
.GetPolicy();
133 pkgCache::VerIterator inst
= P
.CurrentVer();
134 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
136 return inst
? inst
.Arch() : cand
.Arch();
139 std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)/*{{{*/
141 pkgPolicy
*policy
= CacheFile
.GetPolicy();
143 pkgCache::VerIterator ver
;
145 ver
= P
.CurrentVer();
147 ver
= policy
->GetCandidateVer(P
);
149 std::string ShortDescription
= "(none)";
152 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
153 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
155 ShortDescription
= parser
.ShortDesc();
157 return ShortDescription
;
160 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
, /*{{{*/
161 pkgCache::VerIterator V
, std::ostream
&out
)
163 pkgCache::PkgIterator P
= V
.ParentPkg();
165 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
166 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
168 std::string suite
= GetArchiveSuite(CacheFile
, V
);
169 std::string name_str
= P
.Name();
171 if (_config
->FindB("APT::Cmd::use-format", false))
173 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
174 std::string output
= format
;
176 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
177 output
= SubstVar(output
, "${Package}", name_str
);
178 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
179 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
180 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
181 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
182 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
183 out
<< output
<< std::endl
;
185 // raring/linux-kernel version [upradable: new-version]
187 pkgPolicy
*policy
= CacheFile
.GetPolicy();
188 out
<< std::setiosflags(std::ios::left
)
189 << _config
->Find("APT::Color::Highlight", "")
191 << _config
->Find("APT::Color::Neutral", "")
194 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
195 out
<< GetVersion(CacheFile
, V
)
197 << "[" << _("installed,upgradable to: ")
198 << GetCandidateVersion(CacheFile
, P
) << "]";
199 } else if (P
.CurrentVer() == V
) {
200 out
<< GetVersion(CacheFile
, V
)
202 if(!V
.Downloadable())
203 out
<< _("[installed,local]");
205 if(V
.Automatic() && state
.Garbage
)
206 out
<< _("[installed,auto-removable]");
207 else if (state
.Flags
& pkgCache::Flag::Auto
)
208 out
<< _("[installed,automatic]");
210 out
<< _("[installed]");
211 } else if (P
.CurrentVer() &&
212 policy
->GetCandidateVer(P
) == V
&&
213 state
.Upgradable()) {
214 out
<< GetVersion(CacheFile
, V
)
216 << _("[upgradable from: ")
217 << GetInstalledVersion(CacheFile
, P
) << "]";
219 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
220 out
<< GetVersion(CacheFile
, V
)
222 << _("[residual-config]");
224 out
<< GetVersion(CacheFile
, V
);
226 out
<< " " << GetArchitecture(CacheFile
, P
) << " ";
228 << " " << GetShortDescription(CacheFile
, records
, P
)
233 // ShowList - Show a list /*{{{*/
234 // ---------------------------------------------------------------------
235 /* This prints out a string of space separated words with a title and
236 a two space indent line wraped to the current screen width. */
237 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
239 if (List
.empty() == true)
241 // trim trailing space
242 int NonSpace
= List
.find_last_not_of(' ');
245 List
= List
.erase(NonSpace
+ 1);
246 if (List
.empty() == true)
250 // Acount for the leading space
251 int ScreenWidth
= ::ScreenWidth
- 3;
253 out
<< Title
<< endl
;
254 string::size_type Start
= 0;
255 string::size_type VersionsStart
= 0;
256 while (Start
< List
.size())
258 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
259 VersionsList
.size() > 0) {
260 string::size_type End
;
261 string::size_type VersionsEnd
;
263 End
= List
.find(' ',Start
);
264 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
266 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
267 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
270 if (End
== string::npos
|| End
< Start
)
271 End
= Start
+ ScreenWidth
;
274 VersionsStart
= VersionsEnd
+ 1;
276 string::size_type End
;
278 if (Start
+ ScreenWidth
>= List
.size())
281 End
= List
.rfind(' ',Start
+ScreenWidth
);
283 if (End
== string::npos
|| End
< Start
)
284 End
= Start
+ ScreenWidth
;
285 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
293 // ShowBroken - Debugging aide /*{{{*/
294 // ---------------------------------------------------------------------
295 /* This prints out the names of all the packages that are broken along
296 with the name of each each broken dependency and a quite version
299 The output looks like:
300 The following packages have unmet dependencies:
301 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
302 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
303 Depends: libsasl7 but it is not going to be installed
305 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
307 if (Cache
->BrokenCount() == 0)
310 out
<< _("The following packages have unmet dependencies:") << endl
;
311 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
313 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
317 if (Cache
[I
].NowBroken() == false)
322 if (Cache
[I
].InstBroken() == false)
326 // Print out each package and the failed dependencies
327 out
<< " " << I
.FullName(true) << " :";
328 unsigned const Indent
= I
.FullName(true).size() + 3;
330 pkgCache::VerIterator Ver
;
333 Ver
= I
.CurrentVer();
335 Ver
= Cache
[I
].InstVerIter(Cache
);
337 if (Ver
.end() == true)
343 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
345 // Compute a single dependency element (glob or)
346 pkgCache::DepIterator Start
;
347 pkgCache::DepIterator End
;
348 D
.GlobOr(Start
,End
); // advances D
350 if (Cache
->IsImportantDep(End
) == false)
355 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
360 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
368 for (unsigned J
= 0; J
!= Indent
; J
++)
372 if (FirstOr
== false)
374 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
378 out
<< ' ' << End
.DepType() << ": ";
381 out
<< Start
.TargetPkg().FullName(true);
383 // Show a quick summary of the version requirements
384 if (Start
.TargetVer() != 0)
385 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
387 /* Show a summary of the target package if possible. In the case
388 of virtual packages we show nothing */
389 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
390 if (Targ
->ProvidesList
== 0)
393 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
395 Ver
= Targ
.CurrentVer();
397 if (Ver
.end() == false)
400 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
402 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
406 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
408 if (Targ
->ProvidesList
== 0)
409 out
<< _("but it is not installable");
411 out
<< _("but it is a virtual package");
414 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
430 // ShowNew - Show packages to newly install /*{{{*/
431 // ---------------------------------------------------------------------
433 void ShowNew(ostream
&out
,CacheFile
&Cache
)
435 /* Print out a list of packages that are going to be installed extra
436 to what the user asked */
439 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
441 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
442 if (Cache
[I
].NewInstall() == true) {
443 List
+= I
.FullName(true) + " ";
444 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
448 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
451 // ShowDel - Show packages to delete /*{{{*/
452 // ---------------------------------------------------------------------
454 void ShowDel(ostream
&out
,CacheFile
&Cache
)
456 /* Print out a list of packages that are going to be removed extra
457 to what the user asked */
460 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
462 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
463 if (Cache
[I
].Delete() == true)
465 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
466 List
+= I
.FullName(true) + "* ";
468 List
+= I
.FullName(true) + " ";
470 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
474 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
477 // ShowKept - Show kept packages /*{{{*/
478 // ---------------------------------------------------------------------
480 void ShowKept(ostream
&out
,CacheFile
&Cache
)
484 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
486 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
489 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
490 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
493 List
+= I
.FullName(true) + " ";
494 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
496 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
499 // ShowUpgraded - Show upgraded packages /*{{{*/
500 // ---------------------------------------------------------------------
502 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
506 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
508 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
511 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
514 List
+= I
.FullName(true) + " ";
515 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
517 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
520 // ShowDowngraded - Show downgraded packages /*{{{*/
521 // ---------------------------------------------------------------------
523 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
527 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
529 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
532 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
535 List
+= I
.FullName(true) + " ";
536 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
538 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
541 // ShowHold - Show held but changed packages /*{{{*/
542 // ---------------------------------------------------------------------
544 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
548 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
550 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
551 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
552 I
->SelectedState
== pkgCache::State::Hold
) {
553 List
+= I
.FullName(true) + " ";
554 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
558 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
561 // ShowEssential - Show an essential package warning /*{{{*/
562 // ---------------------------------------------------------------------
563 /* This prints out a warning message that is not to be ignored. It shows
564 all essential packages and their dependents that are to be removed.
565 It is insanely risky to remove the dependents of an essential package! */
566 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
570 bool *Added
= new bool[Cache
->Head().PackageCount
];
571 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
574 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
576 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
577 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
578 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
581 // The essential package is being removed
582 if (Cache
[I
].Delete() == true)
584 if (Added
[I
->ID
] == false)
587 List
+= I
.FullName(true) + " ";
588 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
594 if (I
->CurrentVer
== 0)
597 // Print out any essential package depenendents that are to be removed
598 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
600 // Skip everything but depends
601 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
602 D
->Type
!= pkgCache::Dep::Depends
)
605 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
606 if (Cache
[P
].Delete() == true)
608 if (Added
[P
->ID
] == true)
613 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
615 //VersionsList += "\n"; ???
621 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
622 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
626 // Stats - Show some statistics /*{{{*/
627 // ---------------------------------------------------------------------
629 void Stats(ostream
&out
,pkgDepCache
&Dep
)
631 unsigned long Upgrade
= 0;
632 unsigned long Downgrade
= 0;
633 unsigned long Install
= 0;
634 unsigned long ReInstall
= 0;
635 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
637 if (Dep
[I
].NewInstall() == true)
641 if (Dep
[I
].Upgrade() == true)
644 if (Dep
[I
].Downgrade() == true)
648 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
652 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
656 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
658 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
660 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
661 Dep
.DelCount(),Dep
.KeepCount());
663 if (Dep
.BadCount() != 0)
664 ioprintf(out
,_("%lu not fully installed or removed.\n"),
668 // YnPrompt - Yes No Prompt. /*{{{*/
669 // ---------------------------------------------------------------------
670 /* Returns true on a Yes.*/
671 bool YnPrompt(bool Default
)
673 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
674 to have the help-message (hopefully) match the expected characters */
675 char * language
= getenv("LANGUAGE");
676 if (language
!= NULL
)
677 language
= strdup(language
);
678 if (language
!= NULL
)
679 unsetenv("LANGUAGE");
682 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
683 // e.g. "Do you want to continue? [Y/n] "
684 // The user has to answer with an input matching the
685 // YESEXPR/NOEXPR defined in your l10n.
686 c2out
<< " " << _("[Y/n]") << " " << std::flush
;
688 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
689 // e.g. "Should this file be removed? [y/N] "
690 // The user has to answer with an input matching the
691 // YESEXPR/NOEXPR defined in your l10n.
692 c2out
<< " " << _("[y/N]") << " " << std::flush
;
694 if (language
!= NULL
)
696 setenv("LANGUAGE", language
, 0);
700 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
702 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
703 c1out
<< _("Y") << std::endl
;
706 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
708 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
709 c1out
<< _("N") << std::endl
;
713 char response
[1024] = "";
714 std::cin
.getline(response
, sizeof(response
));
719 if (strlen(response
) == 0)
725 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
726 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
730 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
731 return _error
->Error(_("Regex compilation error - %s"),Error
);
734 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
740 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
741 // ---------------------------------------------------------------------
742 /* Returns true on a Yes.*/
743 bool AnalPrompt(const char *Text
)
746 std::cin
.getline(Buf
,sizeof(Buf
));
747 if (strcmp(Buf
,Text
) == 0)