]>
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 */
34 c0out
.rdbuf(cout
.rdbuf());
35 c1out
.rdbuf(cout
.rdbuf());
36 c2out
.rdbuf(cout
.rdbuf());
37 if (_config
->FindI("quiet",0) > 0)
38 c0out
.rdbuf(devnull
.rdbuf());
39 if (_config
->FindI("quiet",0) > 1)
40 c1out
.rdbuf(devnull
.rdbuf());
44 _config
->Set("APT::Color", "false");
45 _config
->Set("APT::Color::Highlight", "");
46 _config
->Set("APT::Color::Neutral", "");
49 _config
->CndSet("APT::Color::Highlight", "\x1B[32m");
50 _config
->CndSet("APT::Color::Neutral", "\x1B[0m");
52 _config
->CndSet("APT::Color::Red", "\x1B[31m");
53 _config
->CndSet("APT::Color::Green", "\x1B[32m");
54 _config
->CndSet("APT::Color::Yellow", "\x1B[33m");
55 _config
->CndSet("APT::Color::Blue", "\x1B[34m");
56 _config
->CndSet("APT::Color::Magenta", "\x1B[35m");
57 _config
->CndSet("APT::Color::Cyan", "\x1B[36m");
58 _config
->CndSet("APT::Color::White", "\x1B[37m");
64 std::string
GetArchiveSuite(pkgCacheFile
&CacheFile
, pkgCache::VerIterator ver
)
66 std::string suite
= "";
67 if (ver
&& ver
.FileList() && ver
.FileList())
69 pkgCache::VerFileIterator VF
= ver
.FileList();
70 for (; VF
.end() == false ; ++VF
)
72 // XXX: how to figure out the relevant suite? if its in multiple ones?
73 suite
= suite
+ "," + VF
.File().Archive();
74 //suite = VF.File().Archive();
76 suite
= suite
.erase(0, 1);
81 std::string
GetFlagsStr(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)
83 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
84 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
86 std::string flags_str
;
87 if (state
.NowBroken())
89 if (P
.CurrentVer() && state
.Upgradable())
91 else if (P
.CurrentVer() != NULL
)
98 std::string
GetCandidateVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)
100 pkgPolicy
*policy
= CacheFile
.GetPolicy();
101 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
103 return cand
? cand
.VerStr() : "(none)";
106 std::string
GetInstalledVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)
108 pkgCache::VerIterator inst
= P
.CurrentVer();
110 return inst
? inst
.VerStr() : "(none)";
113 std::string
GetVersion(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
115 pkgCache::PkgIterator P
= V
.ParentPkg();
116 if (V
== P
.CurrentVer())
118 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
119 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
120 std::string inst_str
= DeNull(V
.VerStr());
121 if (state
.Upgradable())
122 return "**"+inst_str
;
127 return DeNull(V
.VerStr());
131 std::string
GetArchitecture(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)
133 pkgPolicy
*policy
= CacheFile
.GetPolicy();
134 pkgCache::VerIterator inst
= P
.CurrentVer();
135 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
137 return inst
? inst
.Arch() : cand
.Arch();
140 std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)
142 pkgPolicy
*policy
= CacheFile
.GetPolicy();
144 pkgCache::VerIterator ver
;
146 ver
= P
.CurrentVer();
148 ver
= policy
->GetCandidateVer(P
);
150 std::string ShortDescription
= "(none)";
153 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
154 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
156 ShortDescription
= parser
.ShortDesc();
158 return ShortDescription
;
161 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
,
162 pkgCache::VerIterator V
, std::ostream
&out
)
164 pkgCache::PkgIterator P
= V
.ParentPkg();
166 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
167 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
169 std::string suite
= GetArchiveSuite(CacheFile
, V
);
170 std::string name_str
= P
.Name();
172 if (_config
->FindB("APT::Cmd::use-format", false))
174 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
175 std::string output
= format
;
177 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
178 output
= SubstVar(output
, "${Package}", name_str
);
179 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
180 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
181 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
182 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
183 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
184 out
<< output
<< std::endl
;
186 // raring/linux-kernel version [upradable: new-version]
188 pkgPolicy
*policy
= CacheFile
.GetPolicy();
189 out
<< std::setiosflags(std::ios::left
)
190 << _config
->Find("APT::Color::Highlight", "")
192 << _config
->Find("APT::Color::Neutral", "")
195 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
196 out
<< GetVersion(CacheFile
, V
)
198 << "[" << _("installed,upgradable to: ")
199 << GetCandidateVersion(CacheFile
, P
) << "]";
200 } else if (P
.CurrentVer() == V
) {
201 out
<< GetVersion(CacheFile
, V
)
203 if(!V
.Downloadable())
204 out
<< _("[installed,local]");
206 if(V
.Automatic() && state
.Garbage
)
207 out
<< _("[installed,auto-removable]");
208 else if (state
.Flags
& pkgCache::Flag::Auto
)
209 out
<< _("[installed,automatic]");
211 out
<< _("[installed]");
212 } else if (P
.CurrentVer() &&
213 policy
->GetCandidateVer(P
) == V
&&
214 state
.Upgradable()) {
215 out
<< GetVersion(CacheFile
, V
)
217 << _("[upgradable from: ")
218 << GetInstalledVersion(CacheFile
, P
) << "]";
220 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
221 out
<< GetVersion(CacheFile
, V
)
223 << _("[residual-config]");
225 out
<< GetVersion(CacheFile
, V
);
227 out
<< " " << GetArchitecture(CacheFile
, P
) << " ";
229 << " " << GetShortDescription(CacheFile
, records
, P
)
235 // ShowList - Show a list /*{{{*/
236 // ---------------------------------------------------------------------
237 /* This prints out a string of space separated words with a title and
238 a two space indent line wraped to the current screen width. */
239 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
241 if (List
.empty() == true)
243 // trim trailing space
244 int NonSpace
= List
.find_last_not_of(' ');
247 List
= List
.erase(NonSpace
+ 1);
248 if (List
.empty() == true)
252 // Acount for the leading space
253 int ScreenWidth
= ::ScreenWidth
- 3;
255 out
<< Title
<< endl
;
256 string::size_type Start
= 0;
257 string::size_type VersionsStart
= 0;
258 while (Start
< List
.size())
260 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
261 VersionsList
.size() > 0) {
262 string::size_type End
;
263 string::size_type VersionsEnd
;
265 End
= List
.find(' ',Start
);
266 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
268 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
269 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
272 if (End
== string::npos
|| End
< Start
)
273 End
= Start
+ ScreenWidth
;
276 VersionsStart
= VersionsEnd
+ 1;
278 string::size_type End
;
280 if (Start
+ ScreenWidth
>= List
.size())
283 End
= List
.rfind(' ',Start
+ScreenWidth
);
285 if (End
== string::npos
|| End
< Start
)
286 End
= Start
+ ScreenWidth
;
287 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
295 // ShowBroken - Debugging aide /*{{{*/
296 // ---------------------------------------------------------------------
297 /* This prints out the names of all the packages that are broken along
298 with the name of each each broken dependency and a quite version
301 The output looks like:
302 The following packages have unmet dependencies:
303 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
304 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
305 Depends: libsasl7 but it is not going to be installed
307 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
309 if (Cache
->BrokenCount() == 0)
312 out
<< _("The following packages have unmet dependencies:") << endl
;
313 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
315 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
319 if (Cache
[I
].NowBroken() == false)
324 if (Cache
[I
].InstBroken() == false)
328 // Print out each package and the failed dependencies
329 out
<< " " << I
.FullName(true) << " :";
330 unsigned const Indent
= I
.FullName(true).size() + 3;
332 pkgCache::VerIterator Ver
;
335 Ver
= I
.CurrentVer();
337 Ver
= Cache
[I
].InstVerIter(Cache
);
339 if (Ver
.end() == true)
345 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
347 // Compute a single dependency element (glob or)
348 pkgCache::DepIterator Start
;
349 pkgCache::DepIterator End
;
350 D
.GlobOr(Start
,End
); // advances D
352 if (Cache
->IsImportantDep(End
) == false)
357 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
362 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
370 for (unsigned J
= 0; J
!= Indent
; J
++)
374 if (FirstOr
== false)
376 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
380 out
<< ' ' << End
.DepType() << ": ";
383 out
<< Start
.TargetPkg().FullName(true);
385 // Show a quick summary of the version requirements
386 if (Start
.TargetVer() != 0)
387 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
389 /* Show a summary of the target package if possible. In the case
390 of virtual packages we show nothing */
391 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
392 if (Targ
->ProvidesList
== 0)
395 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
397 Ver
= Targ
.CurrentVer();
399 if (Ver
.end() == false)
402 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
404 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
408 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
410 if (Targ
->ProvidesList
== 0)
411 out
<< _("but it is not installable");
413 out
<< _("but it is a virtual package");
416 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
432 // ShowNew - Show packages to newly install /*{{{*/
433 // ---------------------------------------------------------------------
435 void ShowNew(ostream
&out
,CacheFile
&Cache
)
437 /* Print out a list of packages that are going to be installed extra
438 to what the user asked */
441 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
443 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
444 if (Cache
[I
].NewInstall() == true) {
445 List
+= I
.FullName(true) + " ";
446 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
450 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
453 // ShowDel - Show packages to delete /*{{{*/
454 // ---------------------------------------------------------------------
456 void ShowDel(ostream
&out
,CacheFile
&Cache
)
458 /* Print out a list of packages that are going to be removed extra
459 to what the user asked */
462 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
464 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
465 if (Cache
[I
].Delete() == true)
467 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
468 List
+= I
.FullName(true) + "* ";
470 List
+= I
.FullName(true) + " ";
472 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
476 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
479 // ShowKept - Show kept packages /*{{{*/
480 // ---------------------------------------------------------------------
482 void ShowKept(ostream
&out
,CacheFile
&Cache
)
486 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
488 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
491 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
492 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
495 List
+= I
.FullName(true) + " ";
496 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
498 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
501 // ShowUpgraded - Show upgraded packages /*{{{*/
502 // ---------------------------------------------------------------------
504 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
508 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
510 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
513 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
516 List
+= I
.FullName(true) + " ";
517 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
519 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
522 // ShowDowngraded - Show downgraded packages /*{{{*/
523 // ---------------------------------------------------------------------
525 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
529 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
531 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
534 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
537 List
+= I
.FullName(true) + " ";
538 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
540 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
543 // ShowHold - Show held but changed packages /*{{{*/
544 // ---------------------------------------------------------------------
546 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
550 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
552 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
553 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
554 I
->SelectedState
== pkgCache::State::Hold
) {
555 List
+= I
.FullName(true) + " ";
556 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
560 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
563 // ShowEssential - Show an essential package warning /*{{{*/
564 // ---------------------------------------------------------------------
565 /* This prints out a warning message that is not to be ignored. It shows
566 all essential packages and their dependents that are to be removed.
567 It is insanely risky to remove the dependents of an essential package! */
568 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
572 bool *Added
= new bool[Cache
->Head().PackageCount
];
573 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
576 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
578 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
579 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
580 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
583 // The essential package is being removed
584 if (Cache
[I
].Delete() == true)
586 if (Added
[I
->ID
] == false)
589 List
+= I
.FullName(true) + " ";
590 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
596 if (I
->CurrentVer
== 0)
599 // Print out any essential package depenendents that are to be removed
600 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
602 // Skip everything but depends
603 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
604 D
->Type
!= pkgCache::Dep::Depends
)
607 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
608 if (Cache
[P
].Delete() == true)
610 if (Added
[P
->ID
] == true)
615 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
617 //VersionsList += "\n"; ???
623 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
624 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
628 // Stats - Show some statistics /*{{{*/
629 // ---------------------------------------------------------------------
631 void Stats(ostream
&out
,pkgDepCache
&Dep
)
633 unsigned long Upgrade
= 0;
634 unsigned long Downgrade
= 0;
635 unsigned long Install
= 0;
636 unsigned long ReInstall
= 0;
637 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
639 if (Dep
[I
].NewInstall() == true)
643 if (Dep
[I
].Upgrade() == true)
646 if (Dep
[I
].Downgrade() == true)
650 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
654 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
658 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
660 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
662 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
663 Dep
.DelCount(),Dep
.KeepCount());
665 if (Dep
.BadCount() != 0)
666 ioprintf(out
,_("%lu not fully installed or removed.\n"),
670 // YnPrompt - Yes No Prompt. /*{{{*/
671 // ---------------------------------------------------------------------
672 /* Returns true on a Yes.*/
673 bool YnPrompt(bool Default
)
675 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
676 to have the help-message (hopefully) match the expected characters */
677 char * language
= getenv("LANGUAGE");
678 if (language
!= NULL
)
679 language
= strdup(language
);
680 if (language
!= NULL
)
681 unsetenv("LANGUAGE");
684 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
685 // e.g. "Do you want to continue? [Y/n] "
686 // The user has to answer with an input matching the
687 // YESEXPR/NOEXPR defined in your l10n.
688 c2out
<< " " << _("[Y/n]") << " " << std::flush
;
690 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
691 // e.g. "Should this file be removed? [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 if (language
!= NULL
)
698 setenv("LANGUAGE", language
, 0);
702 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
704 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
705 c1out
<< _("Y") << std::endl
;
708 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
710 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
711 c1out
<< _("N") << std::endl
;
715 char response
[1024] = "";
716 std::cin
.getline(response
, sizeof(response
));
721 if (strlen(response
) == 0)
727 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
728 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
732 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
733 return _error
->Error(_("Regex compilation error - %s"),Error
);
736 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
742 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
743 // ---------------------------------------------------------------------
744 /* Returns true on a Yes.*/
745 bool AnalPrompt(const char *Text
)
748 std::cin
.getline(Buf
,sizeof(Buf
));
749 if (strcmp(Buf
,Text
) == 0)