]>
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 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
34 _config
->Set("quiet","1");
36 c0out
.rdbuf(cout
.rdbuf());
37 c1out
.rdbuf(cout
.rdbuf());
38 c2out
.rdbuf(cout
.rdbuf());
39 if (_config
->FindI("quiet",0) > 0)
40 c0out
.rdbuf(devnull
.rdbuf());
41 if (_config
->FindI("quiet",0) > 1)
42 c1out
.rdbuf(devnull
.rdbuf());
46 _config
->Set("APT::Color", "false");
47 _config
->Set("APT::Color::Highlight", "");
48 _config
->Set("APT::Color::Neutral", "");
51 _config
->CndSet("APT::Color::Highlight", "\x1B[32m");
52 _config
->CndSet("APT::Color::Neutral", "\x1B[0m");
54 _config
->CndSet("APT::Color::Red", "\x1B[31m");
55 _config
->CndSet("APT::Color::Green", "\x1B[32m");
56 _config
->CndSet("APT::Color::Yellow", "\x1B[33m");
57 _config
->CndSet("APT::Color::Blue", "\x1B[34m");
58 _config
->CndSet("APT::Color::Magenta", "\x1B[35m");
59 _config
->CndSet("APT::Color::Cyan", "\x1B[36m");
60 _config
->CndSet("APT::Color::White", "\x1B[37m");
66 static std::string
GetArchiveSuite(pkgCacheFile
&/*CacheFile*/, pkgCache::VerIterator ver
) /*{{{*/
68 std::string suite
= "";
69 if (ver
&& ver
.FileList() && ver
.FileList())
71 pkgCache::VerFileIterator VF
= ver
.FileList();
72 for (; VF
.end() == false ; ++VF
)
74 if(VF
.File() == NULL
|| VF
.File().Archive() == NULL
)
75 suite
= suite
+ "," + _("unknown");
77 suite
= suite
+ "," + VF
.File().Archive();
78 //suite = VF.File().Archive();
80 suite
= suite
.erase(0, 1);
85 static std::string
GetFlagsStr(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
87 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
88 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
90 std::string flags_str
;
91 if (state
.NowBroken())
93 if (P
.CurrentVer() && state
.Upgradable())
95 else if (P
.CurrentVer() != NULL
)
102 static std::string
GetCandidateVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
104 pkgPolicy
*policy
= CacheFile
.GetPolicy();
105 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
107 return cand
? cand
.VerStr() : "(none)";
110 static std::string
GetInstalledVersion(pkgCacheFile
&/*CacheFile*/, pkgCache::PkgIterator P
)/*{{{*/
112 pkgCache::VerIterator inst
= P
.CurrentVer();
114 return inst
? inst
.VerStr() : "(none)";
117 static std::string
GetVersion(pkgCacheFile
&/*CacheFile*/, pkgCache::VerIterator V
)/*{{{*/
119 pkgCache::PkgIterator P
= V
.ParentPkg();
120 if (V
== P
.CurrentVer())
122 std::string inst_str
= DeNull(V
.VerStr());
123 #if 0 // FIXME: do we want this or something like this?
124 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
125 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
126 if (state
.Upgradable())
127 return "**"+inst_str
;
133 return DeNull(V
.VerStr());
137 static std::string
GetArchitecture(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
139 pkgPolicy
*policy
= CacheFile
.GetPolicy();
140 pkgCache::VerIterator inst
= P
.CurrentVer();
141 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
143 return inst
? inst
.Arch() : cand
.Arch();
146 static std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)/*{{{*/
148 pkgPolicy
*policy
= CacheFile
.GetPolicy();
150 pkgCache::VerIterator ver
;
152 ver
= P
.CurrentVer();
154 ver
= policy
->GetCandidateVer(P
);
156 std::string ShortDescription
= "(none)";
159 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
160 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
162 ShortDescription
= parser
.ShortDesc();
164 return ShortDescription
;
167 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
, /*{{{*/
168 pkgCache::VerIterator V
, std::ostream
&out
,
169 bool include_summary
)
171 pkgCache::PkgIterator P
= V
.ParentPkg();
173 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
174 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
176 std::string suite
= GetArchiveSuite(CacheFile
, V
);
177 std::string name_str
= P
.Name();
179 if (_config
->FindB("APT::Cmd::use-format", false))
181 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
182 std::string output
= format
;
184 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
185 output
= SubstVar(output
, "${Package}", name_str
);
186 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
187 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
188 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
189 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
190 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
191 out
<< output
<< std::endl
;
193 // raring/linux-kernel version [upradable: new-version]
195 pkgPolicy
*policy
= CacheFile
.GetPolicy();
196 std::string VersionStr
= GetVersion(CacheFile
, V
);
197 std::string CandidateVerStr
= GetCandidateVersion(CacheFile
, P
);
198 std::string InstalledVerStr
= GetInstalledVersion(CacheFile
, P
);
199 std::string StatusStr
;
200 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
201 strprintf(StatusStr
, _("[installed,upgradable to: %s]"),
202 CandidateVerStr
.c_str());
203 } else if (P
.CurrentVer() == V
) {
204 if(!V
.Downloadable())
205 StatusStr
= _("[installed,local]");
207 if(V
.Automatic() && state
.Garbage
)
208 StatusStr
= _("[installed,auto-removable]");
209 else if (state
.Flags
& pkgCache::Flag::Auto
)
210 StatusStr
= _("[installed,automatic]");
212 StatusStr
= _("[installed]");
213 } else if (P
.CurrentVer() &&
214 policy
->GetCandidateVer(P
) == V
&&
215 state
.Upgradable()) {
216 strprintf(StatusStr
, _("[upgradable from: %s]"),
217 InstalledVerStr
.c_str());
219 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
220 StatusStr
= _("[residual-config]");
224 out
<< std::setiosflags(std::ios::left
)
225 << _config
->Find("APT::Color::Highlight", "")
227 << _config
->Find("APT::Color::Neutral", "")
231 << GetArchitecture(CacheFile
, P
);
233 out
<< " " << StatusStr
;
237 << " " << GetShortDescription(CacheFile
, records
, P
)
243 // ShowList - Show a list /*{{{*/
244 // ---------------------------------------------------------------------
245 /* This prints out a string of space separated words with a title and
246 a two space indent line wraped to the current screen width. */
247 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
249 if (List
.empty() == true)
251 // trim trailing space
252 int NonSpace
= List
.find_last_not_of(' ');
255 List
= List
.erase(NonSpace
+ 1);
256 if (List
.empty() == true)
260 // Acount for the leading space
261 int ScreenWidth
= ::ScreenWidth
- 3;
263 out
<< Title
<< endl
;
264 string::size_type Start
= 0;
265 string::size_type VersionsStart
= 0;
266 while (Start
< List
.size())
268 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
269 VersionsList
.size() > 0) {
270 string::size_type End
;
271 string::size_type VersionsEnd
;
273 End
= List
.find(' ',Start
);
274 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
276 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
277 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
280 if (End
== string::npos
|| End
< Start
)
281 End
= Start
+ ScreenWidth
;
284 VersionsStart
= VersionsEnd
+ 1;
286 string::size_type End
;
288 if (Start
+ ScreenWidth
>= List
.size())
291 End
= List
.rfind(' ',Start
+ScreenWidth
);
293 if (End
== string::npos
|| End
< Start
)
294 End
= Start
+ ScreenWidth
;
295 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
303 // ShowBroken - Debugging aide /*{{{*/
304 // ---------------------------------------------------------------------
305 /* This prints out the names of all the packages that are broken along
306 with the name of each each broken dependency and a quite version
309 The output looks like:
310 The following packages have unmet dependencies:
311 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
312 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
313 Depends: libsasl7 but it is not going to be installed
315 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
317 if (Cache
->BrokenCount() == 0)
320 out
<< _("The following packages have unmet dependencies:") << endl
;
321 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
323 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
327 if (Cache
[I
].NowBroken() == false)
332 if (Cache
[I
].InstBroken() == false)
336 // Print out each package and the failed dependencies
337 out
<< " " << I
.FullName(true) << " :";
338 unsigned const Indent
= I
.FullName(true).size() + 3;
340 pkgCache::VerIterator Ver
;
343 Ver
= I
.CurrentVer();
345 Ver
= Cache
[I
].InstVerIter(Cache
);
347 if (Ver
.end() == true)
353 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
355 // Compute a single dependency element (glob or)
356 pkgCache::DepIterator Start
;
357 pkgCache::DepIterator End
;
358 D
.GlobOr(Start
,End
); // advances D
360 if (Cache
->IsImportantDep(End
) == false)
365 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
370 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
378 for (unsigned J
= 0; J
!= Indent
; J
++)
382 if (FirstOr
== false)
384 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
388 out
<< ' ' << End
.DepType() << ": ";
391 out
<< Start
.TargetPkg().FullName(true);
393 // Show a quick summary of the version requirements
394 if (Start
.TargetVer() != 0)
395 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
397 /* Show a summary of the target package if possible. In the case
398 of virtual packages we show nothing */
399 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
400 if (Targ
->ProvidesList
== 0)
403 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
405 Ver
= Targ
.CurrentVer();
407 if (Ver
.end() == false)
410 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
412 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
416 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
418 if (Targ
->ProvidesList
== 0)
419 out
<< _("but it is not installable");
421 out
<< _("but it is a virtual package");
424 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
440 // ShowNew - Show packages to newly install /*{{{*/
441 // ---------------------------------------------------------------------
443 void ShowNew(ostream
&out
,CacheFile
&Cache
)
445 /* Print out a list of packages that are going to be installed extra
446 to what the user asked */
449 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
451 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
452 if (Cache
[I
].NewInstall() == true) {
453 List
+= I
.FullName(true) + " ";
454 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
458 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
461 // ShowDel - Show packages to delete /*{{{*/
462 // ---------------------------------------------------------------------
464 void ShowDel(ostream
&out
,CacheFile
&Cache
)
466 /* Print out a list of packages that are going to be removed extra
467 to what the user asked */
470 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
472 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
473 if (Cache
[I
].Delete() == true)
475 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
476 List
+= I
.FullName(true) + "* ";
478 List
+= I
.FullName(true) + " ";
480 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
484 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
487 // ShowKept - Show kept packages /*{{{*/
488 // ---------------------------------------------------------------------
490 void ShowKept(ostream
&out
,CacheFile
&Cache
)
494 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
496 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
499 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
500 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
503 List
+= I
.FullName(true) + " ";
504 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
506 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
509 // ShowUpgraded - Show upgraded packages /*{{{*/
510 // ---------------------------------------------------------------------
512 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
516 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
518 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
521 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
524 List
+= I
.FullName(true) + " ";
525 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
527 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
530 // ShowDowngraded - Show downgraded packages /*{{{*/
531 // ---------------------------------------------------------------------
533 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
537 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
539 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
542 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
545 List
+= I
.FullName(true) + " ";
546 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
548 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
551 // ShowHold - Show held but changed packages /*{{{*/
552 // ---------------------------------------------------------------------
554 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
558 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
560 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
561 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
562 I
->SelectedState
== pkgCache::State::Hold
) {
563 List
+= I
.FullName(true) + " ";
564 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
568 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
571 // ShowEssential - Show an essential package warning /*{{{*/
572 // ---------------------------------------------------------------------
573 /* This prints out a warning message that is not to be ignored. It shows
574 all essential packages and their dependents that are to be removed.
575 It is insanely risky to remove the dependents of an essential package! */
576 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
580 bool *Added
= new bool[Cache
->Head().PackageCount
];
581 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
584 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
586 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
587 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
588 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
591 // The essential package is being removed
592 if (Cache
[I
].Delete() == true)
594 if (Added
[I
->ID
] == false)
597 List
+= I
.FullName(true) + " ";
598 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
604 if (I
->CurrentVer
== 0)
607 // Print out any essential package depenendents that are to be removed
608 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
610 // Skip everything but depends
611 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
612 D
->Type
!= pkgCache::Dep::Depends
)
615 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
616 if (Cache
[P
].Delete() == true)
618 if (Added
[P
->ID
] == true)
623 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
625 //VersionsList += "\n"; ???
631 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
632 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
636 // Stats - Show some statistics /*{{{*/
637 // ---------------------------------------------------------------------
639 void Stats(ostream
&out
,pkgDepCache
&Dep
)
641 unsigned long Upgrade
= 0;
642 unsigned long Downgrade
= 0;
643 unsigned long Install
= 0;
644 unsigned long ReInstall
= 0;
645 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
647 if (Dep
[I
].NewInstall() == true)
651 if (Dep
[I
].Upgrade() == true)
654 if (Dep
[I
].Downgrade() == true)
658 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
662 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
666 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
668 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
670 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
671 Dep
.DelCount(),Dep
.KeepCount());
673 if (Dep
.BadCount() != 0)
674 ioprintf(out
,_("%lu not fully installed or removed.\n"),
678 // YnPrompt - Yes No Prompt. /*{{{*/
679 // ---------------------------------------------------------------------
680 /* Returns true on a Yes.*/
681 bool YnPrompt(bool Default
)
683 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
684 to have the help-message (hopefully) match the expected characters */
685 char * language
= getenv("LANGUAGE");
686 if (language
!= NULL
)
687 language
= strdup(language
);
688 if (language
!= NULL
)
689 unsetenv("LANGUAGE");
692 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
693 // e.g. "Do you want to continue? [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 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
699 // e.g. "Should this file be removed? [y/N] "
700 // The user has to answer with an input matching the
701 // YESEXPR/NOEXPR defined in your l10n.
702 c2out
<< " " << _("[y/N]") << " " << std::flush
;
704 if (language
!= NULL
)
706 setenv("LANGUAGE", language
, 0);
710 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
712 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
713 c1out
<< _("Y") << std::endl
;
716 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
718 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
719 c1out
<< _("N") << std::endl
;
723 char response
[1024] = "";
724 std::cin
.getline(response
, sizeof(response
));
729 if (strlen(response
) == 0)
735 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
736 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
740 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
741 return _error
->Error(_("Regex compilation error - %s"),Error
);
744 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
750 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
751 // ---------------------------------------------------------------------
752 /* Returns true on a Yes.*/
753 bool AnalPrompt(const char *Text
)
756 std::cin
.getline(Buf
,sizeof(Buf
));
757 if (strcmp(Buf
,Text
) == 0)