]>
git.saurik.com Git - apt.git/blob - apt-private/private-output.cc
e9b8037daa7d718747945af7ce29e57a0165c260
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 if(VF
.File() == NULL
|| VF
.File().Archive() == NULL
)
72 suite
= suite
+ "," + _("unknown");
74 suite
= suite
+ "," + VF
.File().Archive();
75 //suite = VF.File().Archive();
77 suite
= suite
.erase(0, 1);
82 std::string
GetFlagsStr(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
84 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
85 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
87 std::string flags_str
;
88 if (state
.NowBroken())
90 if (P
.CurrentVer() && state
.Upgradable())
92 else if (P
.CurrentVer() != NULL
)
99 std::string
GetCandidateVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
101 pkgPolicy
*policy
= CacheFile
.GetPolicy();
102 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
104 return cand
? cand
.VerStr() : "(none)";
107 std::string
GetInstalledVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
109 pkgCache::VerIterator inst
= P
.CurrentVer();
111 return inst
? inst
.VerStr() : "(none)";
114 std::string
GetVersion(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)/*{{{*/
116 pkgCache::PkgIterator P
= V
.ParentPkg();
117 if (V
== P
.CurrentVer())
119 std::string inst_str
= DeNull(V
.VerStr());
120 #if 0 // FIXME: do we want this or something like this?
121 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
122 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
123 if (state
.Upgradable())
124 return "**"+inst_str
;
130 return DeNull(V
.VerStr());
134 std::string
GetArchitecture(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
136 pkgPolicy
*policy
= CacheFile
.GetPolicy();
137 pkgCache::VerIterator inst
= P
.CurrentVer();
138 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
140 return inst
? inst
.Arch() : cand
.Arch();
143 std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)/*{{{*/
145 pkgPolicy
*policy
= CacheFile
.GetPolicy();
147 pkgCache::VerIterator ver
;
149 ver
= P
.CurrentVer();
151 ver
= policy
->GetCandidateVer(P
);
153 std::string ShortDescription
= "(none)";
156 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
157 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
159 ShortDescription
= parser
.ShortDesc();
161 return ShortDescription
;
164 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
, /*{{{*/
165 pkgCache::VerIterator V
, std::ostream
&out
,
166 bool include_summary
)
168 pkgCache::PkgIterator P
= V
.ParentPkg();
170 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
171 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
173 std::string suite
= GetArchiveSuite(CacheFile
, V
);
174 std::string name_str
= P
.Name();
176 if (_config
->FindB("APT::Cmd::use-format", false))
178 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
179 std::string output
= format
;
181 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
182 output
= SubstVar(output
, "${Package}", name_str
);
183 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
184 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
185 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
186 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
187 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
188 out
<< output
<< std::endl
;
190 // raring/linux-kernel version [upradable: new-version]
192 pkgPolicy
*policy
= CacheFile
.GetPolicy();
193 out
<< std::setiosflags(std::ios::left
)
194 << _config
->Find("APT::Color::Highlight", "")
196 << _config
->Find("APT::Color::Neutral", "")
199 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
200 out
<< GetVersion(CacheFile
, V
)
202 << "[" << _("installed,upgradable to: ")
203 << GetCandidateVersion(CacheFile
, P
) << "]";
204 } else if (P
.CurrentVer() == V
) {
205 out
<< GetVersion(CacheFile
, V
)
207 if(!V
.Downloadable())
208 out
<< _("[installed,local]");
210 if(V
.Automatic() && state
.Garbage
)
211 out
<< _("[installed,auto-removable]");
212 else if (state
.Flags
& pkgCache::Flag::Auto
)
213 out
<< _("[installed,automatic]");
215 out
<< _("[installed]");
216 } else if (P
.CurrentVer() &&
217 policy
->GetCandidateVer(P
) == V
&&
218 state
.Upgradable()) {
219 out
<< GetVersion(CacheFile
, V
)
221 << _("[upgradable from: ")
222 << GetInstalledVersion(CacheFile
, P
) << "]";
224 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
225 out
<< GetVersion(CacheFile
, V
)
227 << _("[residual-config]");
229 out
<< GetVersion(CacheFile
, V
);
231 out
<< " " << GetArchitecture(CacheFile
, P
);
235 << " " << GetShortDescription(CacheFile
, records
, P
)
241 // ShowList - Show a list /*{{{*/
242 // ---------------------------------------------------------------------
243 /* This prints out a string of space separated words with a title and
244 a two space indent line wraped to the current screen width. */
245 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
247 if (List
.empty() == true)
249 // trim trailing space
250 int NonSpace
= List
.find_last_not_of(' ');
253 List
= List
.erase(NonSpace
+ 1);
254 if (List
.empty() == true)
258 // Acount for the leading space
259 int ScreenWidth
= ::ScreenWidth
- 3;
261 out
<< Title
<< endl
;
262 string::size_type Start
= 0;
263 string::size_type VersionsStart
= 0;
264 while (Start
< List
.size())
266 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
267 VersionsList
.size() > 0) {
268 string::size_type End
;
269 string::size_type VersionsEnd
;
271 End
= List
.find(' ',Start
);
272 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
274 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
275 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
278 if (End
== string::npos
|| End
< Start
)
279 End
= Start
+ ScreenWidth
;
282 VersionsStart
= VersionsEnd
+ 1;
284 string::size_type End
;
286 if (Start
+ ScreenWidth
>= List
.size())
289 End
= List
.rfind(' ',Start
+ScreenWidth
);
291 if (End
== string::npos
|| End
< Start
)
292 End
= Start
+ ScreenWidth
;
293 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
301 // ShowBroken - Debugging aide /*{{{*/
302 // ---------------------------------------------------------------------
303 /* This prints out the names of all the packages that are broken along
304 with the name of each each broken dependency and a quite version
307 The output looks like:
308 The following packages have unmet dependencies:
309 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
310 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
311 Depends: libsasl7 but it is not going to be installed
313 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
315 if (Cache
->BrokenCount() == 0)
318 out
<< _("The following packages have unmet dependencies:") << endl
;
319 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
321 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
325 if (Cache
[I
].NowBroken() == false)
330 if (Cache
[I
].InstBroken() == false)
334 // Print out each package and the failed dependencies
335 out
<< " " << I
.FullName(true) << " :";
336 unsigned const Indent
= I
.FullName(true).size() + 3;
338 pkgCache::VerIterator Ver
;
341 Ver
= I
.CurrentVer();
343 Ver
= Cache
[I
].InstVerIter(Cache
);
345 if (Ver
.end() == true)
351 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
353 // Compute a single dependency element (glob or)
354 pkgCache::DepIterator Start
;
355 pkgCache::DepIterator End
;
356 D
.GlobOr(Start
,End
); // advances D
358 if (Cache
->IsImportantDep(End
) == false)
363 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
368 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
376 for (unsigned J
= 0; J
!= Indent
; J
++)
380 if (FirstOr
== false)
382 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
386 out
<< ' ' << End
.DepType() << ": ";
389 out
<< Start
.TargetPkg().FullName(true);
391 // Show a quick summary of the version requirements
392 if (Start
.TargetVer() != 0)
393 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
395 /* Show a summary of the target package if possible. In the case
396 of virtual packages we show nothing */
397 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
398 if (Targ
->ProvidesList
== 0)
401 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
403 Ver
= Targ
.CurrentVer();
405 if (Ver
.end() == false)
408 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
410 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
414 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
416 if (Targ
->ProvidesList
== 0)
417 out
<< _("but it is not installable");
419 out
<< _("but it is a virtual package");
422 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
438 // ShowNew - Show packages to newly install /*{{{*/
439 // ---------------------------------------------------------------------
441 void ShowNew(ostream
&out
,CacheFile
&Cache
)
443 /* Print out a list of packages that are going to be installed extra
444 to what the user asked */
447 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
449 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
450 if (Cache
[I
].NewInstall() == true) {
451 List
+= I
.FullName(true) + " ";
452 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
456 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
459 // ShowDel - Show packages to delete /*{{{*/
460 // ---------------------------------------------------------------------
462 void ShowDel(ostream
&out
,CacheFile
&Cache
)
464 /* Print out a list of packages that are going to be removed extra
465 to what the user asked */
468 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
470 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
471 if (Cache
[I
].Delete() == true)
473 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
474 List
+= I
.FullName(true) + "* ";
476 List
+= I
.FullName(true) + " ";
478 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
482 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
485 // ShowKept - Show kept packages /*{{{*/
486 // ---------------------------------------------------------------------
488 void ShowKept(ostream
&out
,CacheFile
&Cache
)
492 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
494 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
497 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
498 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
501 List
+= I
.FullName(true) + " ";
502 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
504 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
507 // ShowUpgraded - Show upgraded packages /*{{{*/
508 // ---------------------------------------------------------------------
510 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
514 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
516 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
519 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
522 List
+= I
.FullName(true) + " ";
523 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
525 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
528 // ShowDowngraded - Show downgraded packages /*{{{*/
529 // ---------------------------------------------------------------------
531 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
535 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
537 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
540 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
543 List
+= I
.FullName(true) + " ";
544 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
546 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
549 // ShowHold - Show held but changed packages /*{{{*/
550 // ---------------------------------------------------------------------
552 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
556 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
558 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
559 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
560 I
->SelectedState
== pkgCache::State::Hold
) {
561 List
+= I
.FullName(true) + " ";
562 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
566 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
569 // ShowEssential - Show an essential package warning /*{{{*/
570 // ---------------------------------------------------------------------
571 /* This prints out a warning message that is not to be ignored. It shows
572 all essential packages and their dependents that are to be removed.
573 It is insanely risky to remove the dependents of an essential package! */
574 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
578 bool *Added
= new bool[Cache
->Head().PackageCount
];
579 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
582 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
584 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
585 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
586 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
589 // The essential package is being removed
590 if (Cache
[I
].Delete() == true)
592 if (Added
[I
->ID
] == false)
595 List
+= I
.FullName(true) + " ";
596 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
602 if (I
->CurrentVer
== 0)
605 // Print out any essential package depenendents that are to be removed
606 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
608 // Skip everything but depends
609 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
610 D
->Type
!= pkgCache::Dep::Depends
)
613 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
614 if (Cache
[P
].Delete() == true)
616 if (Added
[P
->ID
] == true)
621 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
623 //VersionsList += "\n"; ???
629 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
630 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
634 // Stats - Show some statistics /*{{{*/
635 // ---------------------------------------------------------------------
637 void Stats(ostream
&out
,pkgDepCache
&Dep
)
639 unsigned long Upgrade
= 0;
640 unsigned long Downgrade
= 0;
641 unsigned long Install
= 0;
642 unsigned long ReInstall
= 0;
643 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
645 if (Dep
[I
].NewInstall() == true)
649 if (Dep
[I
].Upgrade() == true)
652 if (Dep
[I
].Downgrade() == true)
656 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
660 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
664 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
666 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
668 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
669 Dep
.DelCount(),Dep
.KeepCount());
671 if (Dep
.BadCount() != 0)
672 ioprintf(out
,_("%lu not fully installed or removed.\n"),
676 // YnPrompt - Yes No Prompt. /*{{{*/
677 // ---------------------------------------------------------------------
678 /* Returns true on a Yes.*/
679 bool YnPrompt(bool Default
)
681 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
682 to have the help-message (hopefully) match the expected characters */
683 char * language
= getenv("LANGUAGE");
684 if (language
!= NULL
)
685 language
= strdup(language
);
686 if (language
!= NULL
)
687 unsetenv("LANGUAGE");
690 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
691 // e.g. "Do you want to continue? [Y/n] "
692 // The user has to answer with an input matching the
693 // YESEXPR/NOEXPR defined in your l10n.
694 c2out
<< " " << _("[Y/n]") << " " << std::flush
;
696 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
697 // e.g. "Should this file be removed? [y/N] "
698 // The user has to answer with an input matching the
699 // YESEXPR/NOEXPR defined in your l10n.
700 c2out
<< " " << _("[y/N]") << " " << std::flush
;
702 if (language
!= NULL
)
704 setenv("LANGUAGE", language
, 0);
708 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
710 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
711 c1out
<< _("Y") << std::endl
;
714 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
716 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
717 c1out
<< _("N") << std::endl
;
721 char response
[1024] = "";
722 std::cin
.getline(response
, sizeof(response
));
727 if (strlen(response
) == 0)
733 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
734 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
738 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
739 return _error
->Error(_("Regex compilation error - %s"),Error
);
742 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
748 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
749 // ---------------------------------------------------------------------
750 /* Returns true on a Yes.*/
751 bool AnalPrompt(const char *Text
)
754 std::cin
.getline(Buf
,sizeof(Buf
));
755 if (strcmp(Buf
,Text
) == 0)