]>
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 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 std::string VersionStr
= GetVersion(CacheFile
, V
);
194 std::string CandidateVerStr
= GetCandidateVersion(CacheFile
, P
);
195 std::string InstalledVerStr
= GetInstalledVersion(CacheFile
, P
);
196 std::string StatusStr
;
197 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
198 strprintf(StatusStr
, _("[installed,upgradable to: %s]"),
199 CandidateVerStr
.c_str());
200 } else if (P
.CurrentVer() == V
) {
201 if(!V
.Downloadable())
202 StatusStr
= _("[installed,local]");
204 if(V
.Automatic() && state
.Garbage
)
205 StatusStr
= _("[installed,auto-removable]");
206 else if (state
.Flags
& pkgCache::Flag::Auto
)
207 StatusStr
= _("[installed,automatic]");
209 StatusStr
= _("[installed]");
210 } else if (P
.CurrentVer() &&
211 policy
->GetCandidateVer(P
) == V
&&
212 state
.Upgradable()) {
213 strprintf(StatusStr
, _("[upgradable from: %s]"),
214 InstalledVerStr
.c_str());
216 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
217 StatusStr
= _("[residual-config]");
221 out
<< std::setiosflags(std::ios::left
)
222 << _config
->Find("APT::Color::Highlight", "")
224 << _config
->Find("APT::Color::Neutral", "")
228 << GetArchitecture(CacheFile
, P
);
230 out
<< " " << StatusStr
;
234 << " " << GetShortDescription(CacheFile
, records
, P
)
240 // ShowList - Show a list /*{{{*/
241 // ---------------------------------------------------------------------
242 /* This prints out a string of space separated words with a title and
243 a two space indent line wraped to the current screen width. */
244 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
246 if (List
.empty() == true)
248 // trim trailing space
249 int NonSpace
= List
.find_last_not_of(' ');
252 List
= List
.erase(NonSpace
+ 1);
253 if (List
.empty() == true)
257 // Acount for the leading space
258 int ScreenWidth
= ::ScreenWidth
- 3;
260 out
<< Title
<< endl
;
261 string::size_type Start
= 0;
262 string::size_type VersionsStart
= 0;
263 while (Start
< List
.size())
265 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
266 VersionsList
.size() > 0) {
267 string::size_type End
;
268 string::size_type VersionsEnd
;
270 End
= List
.find(' ',Start
);
271 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
273 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
274 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
277 if (End
== string::npos
|| End
< Start
)
278 End
= Start
+ ScreenWidth
;
281 VersionsStart
= VersionsEnd
+ 1;
283 string::size_type End
;
285 if (Start
+ ScreenWidth
>= List
.size())
288 End
= List
.rfind(' ',Start
+ScreenWidth
);
290 if (End
== string::npos
|| End
< Start
)
291 End
= Start
+ ScreenWidth
;
292 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
300 // ShowBroken - Debugging aide /*{{{*/
301 // ---------------------------------------------------------------------
302 /* This prints out the names of all the packages that are broken along
303 with the name of each each broken dependency and a quite version
306 The output looks like:
307 The following packages have unmet dependencies:
308 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
309 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
310 Depends: libsasl7 but it is not going to be installed
312 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
314 if (Cache
->BrokenCount() == 0)
317 out
<< _("The following packages have unmet dependencies:") << endl
;
318 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
320 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
324 if (Cache
[I
].NowBroken() == false)
329 if (Cache
[I
].InstBroken() == false)
333 // Print out each package and the failed dependencies
334 out
<< " " << I
.FullName(true) << " :";
335 unsigned const Indent
= I
.FullName(true).size() + 3;
337 pkgCache::VerIterator Ver
;
340 Ver
= I
.CurrentVer();
342 Ver
= Cache
[I
].InstVerIter(Cache
);
344 if (Ver
.end() == true)
350 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
352 // Compute a single dependency element (glob or)
353 pkgCache::DepIterator Start
;
354 pkgCache::DepIterator End
;
355 D
.GlobOr(Start
,End
); // advances D
357 if (Cache
->IsImportantDep(End
) == false)
362 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
367 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
375 for (unsigned J
= 0; J
!= Indent
; J
++)
379 if (FirstOr
== false)
381 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
385 out
<< ' ' << End
.DepType() << ": ";
388 out
<< Start
.TargetPkg().FullName(true);
390 // Show a quick summary of the version requirements
391 if (Start
.TargetVer() != 0)
392 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
394 /* Show a summary of the target package if possible. In the case
395 of virtual packages we show nothing */
396 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
397 if (Targ
->ProvidesList
== 0)
400 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
402 Ver
= Targ
.CurrentVer();
404 if (Ver
.end() == false)
407 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
409 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
413 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
415 if (Targ
->ProvidesList
== 0)
416 out
<< _("but it is not installable");
418 out
<< _("but it is a virtual package");
421 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
437 // ShowNew - Show packages to newly install /*{{{*/
438 // ---------------------------------------------------------------------
440 void ShowNew(ostream
&out
,CacheFile
&Cache
)
442 /* Print out a list of packages that are going to be installed extra
443 to what the user asked */
446 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
448 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
449 if (Cache
[I
].NewInstall() == true) {
450 List
+= I
.FullName(true) + " ";
451 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
455 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
458 // ShowDel - Show packages to delete /*{{{*/
459 // ---------------------------------------------------------------------
461 void ShowDel(ostream
&out
,CacheFile
&Cache
)
463 /* Print out a list of packages that are going to be removed extra
464 to what the user asked */
467 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
469 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
470 if (Cache
[I
].Delete() == true)
472 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
473 List
+= I
.FullName(true) + "* ";
475 List
+= I
.FullName(true) + " ";
477 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
481 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
484 // ShowKept - Show kept packages /*{{{*/
485 // ---------------------------------------------------------------------
487 void ShowKept(ostream
&out
,CacheFile
&Cache
)
491 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
493 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
496 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
497 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
500 List
+= I
.FullName(true) + " ";
501 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
503 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
506 // ShowUpgraded - Show upgraded packages /*{{{*/
507 // ---------------------------------------------------------------------
509 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
513 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
515 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
518 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
521 List
+= I
.FullName(true) + " ";
522 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
524 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
527 // ShowDowngraded - Show downgraded packages /*{{{*/
528 // ---------------------------------------------------------------------
530 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
534 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
536 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
539 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
542 List
+= I
.FullName(true) + " ";
543 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
545 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
548 // ShowHold - Show held but changed packages /*{{{*/
549 // ---------------------------------------------------------------------
551 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
555 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
557 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
558 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
559 I
->SelectedState
== pkgCache::State::Hold
) {
560 List
+= I
.FullName(true) + " ";
561 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
565 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
568 // ShowEssential - Show an essential package warning /*{{{*/
569 // ---------------------------------------------------------------------
570 /* This prints out a warning message that is not to be ignored. It shows
571 all essential packages and their dependents that are to be removed.
572 It is insanely risky to remove the dependents of an essential package! */
573 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
577 bool *Added
= new bool[Cache
->Head().PackageCount
];
578 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
581 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
583 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
584 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
585 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
588 // The essential package is being removed
589 if (Cache
[I
].Delete() == true)
591 if (Added
[I
->ID
] == false)
594 List
+= I
.FullName(true) + " ";
595 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
601 if (I
->CurrentVer
== 0)
604 // Print out any essential package depenendents that are to be removed
605 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
607 // Skip everything but depends
608 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
609 D
->Type
!= pkgCache::Dep::Depends
)
612 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
613 if (Cache
[P
].Delete() == true)
615 if (Added
[P
->ID
] == true)
620 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
622 //VersionsList += "\n"; ???
628 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
629 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
633 // Stats - Show some statistics /*{{{*/
634 // ---------------------------------------------------------------------
636 void Stats(ostream
&out
,pkgDepCache
&Dep
)
638 unsigned long Upgrade
= 0;
639 unsigned long Downgrade
= 0;
640 unsigned long Install
= 0;
641 unsigned long ReInstall
= 0;
642 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
644 if (Dep
[I
].NewInstall() == true)
648 if (Dep
[I
].Upgrade() == true)
651 if (Dep
[I
].Downgrade() == true)
655 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
659 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
663 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
665 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
667 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
668 Dep
.DelCount(),Dep
.KeepCount());
670 if (Dep
.BadCount() != 0)
671 ioprintf(out
,_("%lu not fully installed or removed.\n"),
675 // YnPrompt - Yes No Prompt. /*{{{*/
676 // ---------------------------------------------------------------------
677 /* Returns true on a Yes.*/
678 bool YnPrompt(bool Default
)
680 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
681 to have the help-message (hopefully) match the expected characters */
682 char * language
= getenv("LANGUAGE");
683 if (language
!= NULL
)
684 language
= strdup(language
);
685 if (language
!= NULL
)
686 unsetenv("LANGUAGE");
689 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
690 // e.g. "Do you want to continue? [Y/n] "
691 // The user has to answer with an input matching the
692 // YESEXPR/NOEXPR defined in your l10n.
693 c2out
<< " " << _("[Y/n]") << " " << std::flush
;
695 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
696 // e.g. "Should this file be removed? [y/N] "
697 // The user has to answer with an input matching the
698 // YESEXPR/NOEXPR defined in your l10n.
699 c2out
<< " " << _("[y/N]") << " " << std::flush
;
701 if (language
!= NULL
)
703 setenv("LANGUAGE", language
, 0);
707 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
709 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
710 c1out
<< _("Y") << std::endl
;
713 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
715 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
716 c1out
<< _("N") << std::endl
;
720 char response
[1024] = "";
721 std::cin
.getline(response
, sizeof(response
));
726 if (strlen(response
) == 0)
732 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
733 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
737 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
738 return _error
->Error(_("Regex compilation error - %s"),Error
);
741 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
747 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
748 // ---------------------------------------------------------------------
749 /* Returns true on a Yes.*/
750 bool AnalPrompt(const char *Text
)
753 std::cin
.getline(Buf
,sizeof(Buf
));
754 if (strcmp(Buf
,Text
) == 0)