]>
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 std::string inst_str
= DeNull(V
.VerStr());
118 #if 0 // FIXME: do we want this or something like this?
119 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
120 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
121 if (state
.Upgradable())
122 return "**"+inst_str
;
128 return DeNull(V
.VerStr());
132 std::string
GetArchitecture(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
134 pkgPolicy
*policy
= CacheFile
.GetPolicy();
135 pkgCache::VerIterator inst
= P
.CurrentVer();
136 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
138 return inst
? inst
.Arch() : cand
.Arch();
141 std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)/*{{{*/
143 pkgPolicy
*policy
= CacheFile
.GetPolicy();
145 pkgCache::VerIterator ver
;
147 ver
= P
.CurrentVer();
149 ver
= policy
->GetCandidateVer(P
);
151 std::string ShortDescription
= "(none)";
154 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
155 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
157 ShortDescription
= parser
.ShortDesc();
159 return ShortDescription
;
162 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
, /*{{{*/
163 pkgCache::VerIterator V
, std::ostream
&out
,
164 bool include_summary
)
166 pkgCache::PkgIterator P
= V
.ParentPkg();
168 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
169 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
171 std::string suite
= GetArchiveSuite(CacheFile
, V
);
172 std::string name_str
= P
.Name();
174 if (_config
->FindB("APT::Cmd::use-format", false))
176 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
177 std::string output
= format
;
179 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
180 output
= SubstVar(output
, "${Package}", name_str
);
181 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
182 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
183 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
184 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
185 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
186 out
<< output
<< std::endl
;
188 // raring/linux-kernel version [upradable: new-version]
190 pkgPolicy
*policy
= CacheFile
.GetPolicy();
191 out
<< std::setiosflags(std::ios::left
)
192 << _config
->Find("APT::Color::Highlight", "")
194 << _config
->Find("APT::Color::Neutral", "")
197 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
198 out
<< GetVersion(CacheFile
, V
)
200 << "[" << _("installed,upgradable to: ")
201 << GetCandidateVersion(CacheFile
, P
) << "]";
202 } else if (P
.CurrentVer() == V
) {
203 out
<< GetVersion(CacheFile
, V
)
205 if(!V
.Downloadable())
206 out
<< _("[installed,local]");
208 if(V
.Automatic() && state
.Garbage
)
209 out
<< _("[installed,auto-removable]");
210 else if (state
.Flags
& pkgCache::Flag::Auto
)
211 out
<< _("[installed,automatic]");
213 out
<< _("[installed]");
214 } else if (P
.CurrentVer() &&
215 policy
->GetCandidateVer(P
) == V
&&
216 state
.Upgradable()) {
217 out
<< GetVersion(CacheFile
, V
)
219 << _("[upgradable from: ")
220 << GetInstalledVersion(CacheFile
, P
) << "]";
222 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
223 out
<< GetVersion(CacheFile
, V
)
225 << _("[residual-config]");
227 out
<< GetVersion(CacheFile
, V
);
229 out
<< " " << GetArchitecture(CacheFile
, P
);
233 << " " << GetShortDescription(CacheFile
, records
, P
)
239 // ShowList - Show a list /*{{{*/
240 // ---------------------------------------------------------------------
241 /* This prints out a string of space separated words with a title and
242 a two space indent line wraped to the current screen width. */
243 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
245 if (List
.empty() == true)
247 // trim trailing space
248 int NonSpace
= List
.find_last_not_of(' ');
251 List
= List
.erase(NonSpace
+ 1);
252 if (List
.empty() == true)
256 // Acount for the leading space
257 int ScreenWidth
= ::ScreenWidth
- 3;
259 out
<< Title
<< endl
;
260 string::size_type Start
= 0;
261 string::size_type VersionsStart
= 0;
262 while (Start
< List
.size())
264 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
265 VersionsList
.size() > 0) {
266 string::size_type End
;
267 string::size_type VersionsEnd
;
269 End
= List
.find(' ',Start
);
270 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
272 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
273 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
276 if (End
== string::npos
|| End
< Start
)
277 End
= Start
+ ScreenWidth
;
280 VersionsStart
= VersionsEnd
+ 1;
282 string::size_type End
;
284 if (Start
+ ScreenWidth
>= List
.size())
287 End
= List
.rfind(' ',Start
+ScreenWidth
);
289 if (End
== string::npos
|| End
< Start
)
290 End
= Start
+ ScreenWidth
;
291 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
299 // ShowBroken - Debugging aide /*{{{*/
300 // ---------------------------------------------------------------------
301 /* This prints out the names of all the packages that are broken along
302 with the name of each each broken dependency and a quite version
305 The output looks like:
306 The following packages have unmet dependencies:
307 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
308 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
309 Depends: libsasl7 but it is not going to be installed
311 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
313 if (Cache
->BrokenCount() == 0)
316 out
<< _("The following packages have unmet dependencies:") << endl
;
317 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
319 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
323 if (Cache
[I
].NowBroken() == false)
328 if (Cache
[I
].InstBroken() == false)
332 // Print out each package and the failed dependencies
333 out
<< " " << I
.FullName(true) << " :";
334 unsigned const Indent
= I
.FullName(true).size() + 3;
336 pkgCache::VerIterator Ver
;
339 Ver
= I
.CurrentVer();
341 Ver
= Cache
[I
].InstVerIter(Cache
);
343 if (Ver
.end() == true)
349 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
351 // Compute a single dependency element (glob or)
352 pkgCache::DepIterator Start
;
353 pkgCache::DepIterator End
;
354 D
.GlobOr(Start
,End
); // advances D
356 if (Cache
->IsImportantDep(End
) == false)
361 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
366 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
374 for (unsigned J
= 0; J
!= Indent
; J
++)
378 if (FirstOr
== false)
380 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
384 out
<< ' ' << End
.DepType() << ": ";
387 out
<< Start
.TargetPkg().FullName(true);
389 // Show a quick summary of the version requirements
390 if (Start
.TargetVer() != 0)
391 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
393 /* Show a summary of the target package if possible. In the case
394 of virtual packages we show nothing */
395 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
396 if (Targ
->ProvidesList
== 0)
399 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
401 Ver
= Targ
.CurrentVer();
403 if (Ver
.end() == false)
406 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
408 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
412 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
414 if (Targ
->ProvidesList
== 0)
415 out
<< _("but it is not installable");
417 out
<< _("but it is a virtual package");
420 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
436 // ShowNew - Show packages to newly install /*{{{*/
437 // ---------------------------------------------------------------------
439 void ShowNew(ostream
&out
,CacheFile
&Cache
)
441 /* Print out a list of packages that are going to be installed extra
442 to what the user asked */
445 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
447 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
448 if (Cache
[I
].NewInstall() == true) {
449 List
+= I
.FullName(true) + " ";
450 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
454 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
457 // ShowDel - Show packages to delete /*{{{*/
458 // ---------------------------------------------------------------------
460 void ShowDel(ostream
&out
,CacheFile
&Cache
)
462 /* Print out a list of packages that are going to be removed extra
463 to what the user asked */
466 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
468 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
469 if (Cache
[I
].Delete() == true)
471 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
472 List
+= I
.FullName(true) + "* ";
474 List
+= I
.FullName(true) + " ";
476 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
480 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
483 // ShowKept - Show kept packages /*{{{*/
484 // ---------------------------------------------------------------------
486 void ShowKept(ostream
&out
,CacheFile
&Cache
)
490 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
492 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
495 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
496 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
499 List
+= I
.FullName(true) + " ";
500 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
502 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
505 // ShowUpgraded - Show upgraded packages /*{{{*/
506 // ---------------------------------------------------------------------
508 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
512 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
514 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
517 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
520 List
+= I
.FullName(true) + " ";
521 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
523 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
526 // ShowDowngraded - Show downgraded packages /*{{{*/
527 // ---------------------------------------------------------------------
529 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
533 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
535 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
538 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
541 List
+= I
.FullName(true) + " ";
542 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
544 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
547 // ShowHold - Show held but changed packages /*{{{*/
548 // ---------------------------------------------------------------------
550 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
554 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
556 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
557 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
558 I
->SelectedState
== pkgCache::State::Hold
) {
559 List
+= I
.FullName(true) + " ";
560 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
564 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
567 // ShowEssential - Show an essential package warning /*{{{*/
568 // ---------------------------------------------------------------------
569 /* This prints out a warning message that is not to be ignored. It shows
570 all essential packages and their dependents that are to be removed.
571 It is insanely risky to remove the dependents of an essential package! */
572 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
576 bool *Added
= new bool[Cache
->Head().PackageCount
];
577 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
580 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
582 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
583 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
584 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
587 // The essential package is being removed
588 if (Cache
[I
].Delete() == true)
590 if (Added
[I
->ID
] == false)
593 List
+= I
.FullName(true) + " ";
594 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
600 if (I
->CurrentVer
== 0)
603 // Print out any essential package depenendents that are to be removed
604 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
606 // Skip everything but depends
607 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
608 D
->Type
!= pkgCache::Dep::Depends
)
611 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
612 if (Cache
[P
].Delete() == true)
614 if (Added
[P
->ID
] == true)
619 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
621 //VersionsList += "\n"; ???
627 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
628 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
632 // Stats - Show some statistics /*{{{*/
633 // ---------------------------------------------------------------------
635 void Stats(ostream
&out
,pkgDepCache
&Dep
)
637 unsigned long Upgrade
= 0;
638 unsigned long Downgrade
= 0;
639 unsigned long Install
= 0;
640 unsigned long ReInstall
= 0;
641 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
643 if (Dep
[I
].NewInstall() == true)
647 if (Dep
[I
].Upgrade() == true)
650 if (Dep
[I
].Downgrade() == true)
654 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
658 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
662 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
664 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
666 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
667 Dep
.DelCount(),Dep
.KeepCount());
669 if (Dep
.BadCount() != 0)
670 ioprintf(out
,_("%lu not fully installed or removed.\n"),
674 // YnPrompt - Yes No Prompt. /*{{{*/
675 // ---------------------------------------------------------------------
676 /* Returns true on a Yes.*/
677 bool YnPrompt(bool Default
)
679 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
680 to have the help-message (hopefully) match the expected characters */
681 char * language
= getenv("LANGUAGE");
682 if (language
!= NULL
)
683 language
= strdup(language
);
684 if (language
!= NULL
)
685 unsetenv("LANGUAGE");
688 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
689 // e.g. "Do you want to continue? [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 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
695 // e.g. "Should this file be removed? [y/N] "
696 // The user has to answer with an input matching the
697 // YESEXPR/NOEXPR defined in your l10n.
698 c2out
<< " " << _("[y/N]") << " " << std::flush
;
700 if (language
!= NULL
)
702 setenv("LANGUAGE", language
, 0);
706 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
708 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
709 c1out
<< _("Y") << std::endl
;
712 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
714 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
715 c1out
<< _("N") << std::endl
;
719 char response
[1024] = "";
720 std::cin
.getline(response
, sizeof(response
));
725 if (strlen(response
) == 0)
731 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
732 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
736 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
737 return _error
->Error(_("Regex compilation error - %s"),Error
);
740 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
746 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
747 // ---------------------------------------------------------------------
748 /* Returns true on a Yes.*/
749 bool AnalPrompt(const char *Text
)
752 std::cin
.getline(Buf
,sizeof(Buf
));
753 if (strcmp(Buf
,Text
) == 0)