]>
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
,
162 bool include_summary
)
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
) << " ";
231 << " " << GetShortDescription(CacheFile
, records
, P
)
237 // ShowList - Show a list /*{{{*/
238 // ---------------------------------------------------------------------
239 /* This prints out a string of space separated words with a title and
240 a two space indent line wraped to the current screen width. */
241 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
243 if (List
.empty() == true)
245 // trim trailing space
246 int NonSpace
= List
.find_last_not_of(' ');
249 List
= List
.erase(NonSpace
+ 1);
250 if (List
.empty() == true)
254 // Acount for the leading space
255 int ScreenWidth
= ::ScreenWidth
- 3;
257 out
<< Title
<< endl
;
258 string::size_type Start
= 0;
259 string::size_type VersionsStart
= 0;
260 while (Start
< List
.size())
262 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
263 VersionsList
.size() > 0) {
264 string::size_type End
;
265 string::size_type VersionsEnd
;
267 End
= List
.find(' ',Start
);
268 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
270 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
271 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
274 if (End
== string::npos
|| End
< Start
)
275 End
= Start
+ ScreenWidth
;
278 VersionsStart
= VersionsEnd
+ 1;
280 string::size_type End
;
282 if (Start
+ ScreenWidth
>= List
.size())
285 End
= List
.rfind(' ',Start
+ScreenWidth
);
287 if (End
== string::npos
|| End
< Start
)
288 End
= Start
+ ScreenWidth
;
289 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
297 // ShowBroken - Debugging aide /*{{{*/
298 // ---------------------------------------------------------------------
299 /* This prints out the names of all the packages that are broken along
300 with the name of each each broken dependency and a quite version
303 The output looks like:
304 The following packages have unmet dependencies:
305 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
306 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
307 Depends: libsasl7 but it is not going to be installed
309 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
311 if (Cache
->BrokenCount() == 0)
314 out
<< _("The following packages have unmet dependencies:") << endl
;
315 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
317 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
321 if (Cache
[I
].NowBroken() == false)
326 if (Cache
[I
].InstBroken() == false)
330 // Print out each package and the failed dependencies
331 out
<< " " << I
.FullName(true) << " :";
332 unsigned const Indent
= I
.FullName(true).size() + 3;
334 pkgCache::VerIterator Ver
;
337 Ver
= I
.CurrentVer();
339 Ver
= Cache
[I
].InstVerIter(Cache
);
341 if (Ver
.end() == true)
347 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
349 // Compute a single dependency element (glob or)
350 pkgCache::DepIterator Start
;
351 pkgCache::DepIterator End
;
352 D
.GlobOr(Start
,End
); // advances D
354 if (Cache
->IsImportantDep(End
) == false)
359 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
364 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
372 for (unsigned J
= 0; J
!= Indent
; J
++)
376 if (FirstOr
== false)
378 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
382 out
<< ' ' << End
.DepType() << ": ";
385 out
<< Start
.TargetPkg().FullName(true);
387 // Show a quick summary of the version requirements
388 if (Start
.TargetVer() != 0)
389 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
391 /* Show a summary of the target package if possible. In the case
392 of virtual packages we show nothing */
393 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
394 if (Targ
->ProvidesList
== 0)
397 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
399 Ver
= Targ
.CurrentVer();
401 if (Ver
.end() == false)
404 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
406 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
410 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
412 if (Targ
->ProvidesList
== 0)
413 out
<< _("but it is not installable");
415 out
<< _("but it is a virtual package");
418 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
434 // ShowNew - Show packages to newly install /*{{{*/
435 // ---------------------------------------------------------------------
437 void ShowNew(ostream
&out
,CacheFile
&Cache
)
439 /* Print out a list of packages that are going to be installed extra
440 to what the user asked */
443 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
445 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
446 if (Cache
[I
].NewInstall() == true) {
447 List
+= I
.FullName(true) + " ";
448 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
452 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
455 // ShowDel - Show packages to delete /*{{{*/
456 // ---------------------------------------------------------------------
458 void ShowDel(ostream
&out
,CacheFile
&Cache
)
460 /* Print out a list of packages that are going to be removed extra
461 to what the user asked */
464 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
466 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
467 if (Cache
[I
].Delete() == true)
469 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
470 List
+= I
.FullName(true) + "* ";
472 List
+= I
.FullName(true) + " ";
474 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
478 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
481 // ShowKept - Show kept packages /*{{{*/
482 // ---------------------------------------------------------------------
484 void ShowKept(ostream
&out
,CacheFile
&Cache
)
488 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
490 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
493 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
494 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
497 List
+= I
.FullName(true) + " ";
498 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
500 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
503 // ShowUpgraded - Show upgraded packages /*{{{*/
504 // ---------------------------------------------------------------------
506 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
510 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
512 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
515 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
518 List
+= I
.FullName(true) + " ";
519 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
521 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
524 // ShowDowngraded - Show downgraded packages /*{{{*/
525 // ---------------------------------------------------------------------
527 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
531 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
533 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
536 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
539 List
+= I
.FullName(true) + " ";
540 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
542 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
545 // ShowHold - Show held but changed packages /*{{{*/
546 // ---------------------------------------------------------------------
548 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
552 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
554 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
555 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
556 I
->SelectedState
== pkgCache::State::Hold
) {
557 List
+= I
.FullName(true) + " ";
558 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
562 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
565 // ShowEssential - Show an essential package warning /*{{{*/
566 // ---------------------------------------------------------------------
567 /* This prints out a warning message that is not to be ignored. It shows
568 all essential packages and their dependents that are to be removed.
569 It is insanely risky to remove the dependents of an essential package! */
570 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
574 bool *Added
= new bool[Cache
->Head().PackageCount
];
575 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
578 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
580 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
581 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
582 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
585 // The essential package is being removed
586 if (Cache
[I
].Delete() == true)
588 if (Added
[I
->ID
] == false)
591 List
+= I
.FullName(true) + " ";
592 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
598 if (I
->CurrentVer
== 0)
601 // Print out any essential package depenendents that are to be removed
602 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
604 // Skip everything but depends
605 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
606 D
->Type
!= pkgCache::Dep::Depends
)
609 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
610 if (Cache
[P
].Delete() == true)
612 if (Added
[P
->ID
] == true)
617 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
619 //VersionsList += "\n"; ???
625 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
626 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
630 // Stats - Show some statistics /*{{{*/
631 // ---------------------------------------------------------------------
633 void Stats(ostream
&out
,pkgDepCache
&Dep
)
635 unsigned long Upgrade
= 0;
636 unsigned long Downgrade
= 0;
637 unsigned long Install
= 0;
638 unsigned long ReInstall
= 0;
639 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
641 if (Dep
[I
].NewInstall() == true)
645 if (Dep
[I
].Upgrade() == true)
648 if (Dep
[I
].Downgrade() == true)
652 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
656 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
660 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
662 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
664 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
665 Dep
.DelCount(),Dep
.KeepCount());
667 if (Dep
.BadCount() != 0)
668 ioprintf(out
,_("%lu not fully installed or removed.\n"),
672 // YnPrompt - Yes No Prompt. /*{{{*/
673 // ---------------------------------------------------------------------
674 /* Returns true on a Yes.*/
675 bool YnPrompt(bool Default
)
677 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
678 to have the help-message (hopefully) match the expected characters */
679 char * language
= getenv("LANGUAGE");
680 if (language
!= NULL
)
681 language
= strdup(language
);
682 if (language
!= NULL
)
683 unsetenv("LANGUAGE");
686 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
687 // e.g. "Do you want to continue? [Y/n] "
688 // The user has to answer with an input matching the
689 // YESEXPR/NOEXPR defined in your l10n.
690 c2out
<< " " << _("[Y/n]") << " " << std::flush
;
692 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
693 // e.g. "Should this file be removed? [y/N] "
694 // The user has to answer with an input matching the
695 // YESEXPR/NOEXPR defined in your l10n.
696 c2out
<< " " << _("[y/N]") << " " << std::flush
;
698 if (language
!= NULL
)
700 setenv("LANGUAGE", language
, 0);
704 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
706 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
707 c1out
<< _("Y") << std::endl
;
710 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
712 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
713 c1out
<< _("N") << std::endl
;
717 char response
[1024] = "";
718 std::cin
.getline(response
, sizeof(response
));
723 if (strlen(response
) == 0)
729 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
730 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
734 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
735 return _error
->Error(_("Regex compilation error - %s"),Error
);
738 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
744 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
745 // ---------------------------------------------------------------------
746 /* Returns true on a Yes.*/
747 bool AnalPrompt(const char *Text
)
750 std::cin
.getline(Buf
,sizeof(Buf
));
751 if (strcmp(Buf
,Text
) == 0)