]>
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>
10 #include <apt-pkg/depcache.h>
11 #include <apt-pkg/pkgcache.h>
12 #include <apt-pkg/cacheiterators.h>
14 #include <apt-private/private-output.h>
15 #include <apt-private/private-cachefile.h>
31 std::ostream
c0out(0);
32 std::ostream
c1out(0);
33 std::ostream
c2out(0);
34 std::ofstream
devnull("/dev/null");
35 unsigned int ScreenWidth
= 80 - 1; /* - 1 for the cursor */
37 bool InitOutput() /*{{{*/
39 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
40 _config
->Set("quiet","1");
42 c0out
.rdbuf(cout
.rdbuf());
43 c1out
.rdbuf(cout
.rdbuf());
44 c2out
.rdbuf(cout
.rdbuf());
45 if (_config
->FindI("quiet",0) > 0)
46 c0out
.rdbuf(devnull
.rdbuf());
47 if (_config
->FindI("quiet",0) > 1)
48 c1out
.rdbuf(devnull
.rdbuf());
52 _config
->Set("APT::Color", "false");
53 _config
->Set("APT::Color::Highlight", "");
54 _config
->Set("APT::Color::Neutral", "");
57 _config
->CndSet("APT::Color::Highlight", "\x1B[32m");
58 _config
->CndSet("APT::Color::Neutral", "\x1B[0m");
60 _config
->CndSet("APT::Color::Red", "\x1B[31m");
61 _config
->CndSet("APT::Color::Green", "\x1B[32m");
62 _config
->CndSet("APT::Color::Yellow", "\x1B[33m");
63 _config
->CndSet("APT::Color::Blue", "\x1B[34m");
64 _config
->CndSet("APT::Color::Magenta", "\x1B[35m");
65 _config
->CndSet("APT::Color::Cyan", "\x1B[36m");
66 _config
->CndSet("APT::Color::White", "\x1B[37m");
72 static std::string
GetArchiveSuite(pkgCacheFile
&/*CacheFile*/, pkgCache::VerIterator ver
) /*{{{*/
74 std::string suite
= "";
75 if (ver
&& ver
.FileList() && ver
.FileList())
77 pkgCache::VerFileIterator VF
= ver
.FileList();
78 for (; VF
.end() == false ; ++VF
)
80 if(VF
.File() == NULL
|| VF
.File().Archive() == NULL
)
81 suite
= suite
+ "," + _("unknown");
83 suite
= suite
+ "," + VF
.File().Archive();
84 //suite = VF.File().Archive();
86 suite
= suite
.erase(0, 1);
91 static std::string
GetFlagsStr(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
93 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
94 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
96 std::string flags_str
;
97 if (state
.NowBroken())
99 if (P
.CurrentVer() && state
.Upgradable())
101 else if (P
.CurrentVer() != NULL
)
108 static std::string
GetCandidateVersion(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
110 pkgPolicy
*policy
= CacheFile
.GetPolicy();
111 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
113 return cand
? cand
.VerStr() : "(none)";
116 static std::string
GetInstalledVersion(pkgCacheFile
&/*CacheFile*/, pkgCache::PkgIterator P
)/*{{{*/
118 pkgCache::VerIterator inst
= P
.CurrentVer();
120 return inst
? inst
.VerStr() : "(none)";
123 static std::string
GetVersion(pkgCacheFile
&/*CacheFile*/, pkgCache::VerIterator V
)/*{{{*/
125 pkgCache::PkgIterator P
= V
.ParentPkg();
126 if (V
== P
.CurrentVer())
128 std::string inst_str
= DeNull(V
.VerStr());
129 #if 0 // FIXME: do we want this or something like this?
130 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
131 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
132 if (state
.Upgradable())
133 return "**"+inst_str
;
139 return DeNull(V
.VerStr());
143 static std::string
GetArchitecture(pkgCacheFile
&CacheFile
, pkgCache::PkgIterator P
)/*{{{*/
145 pkgPolicy
*policy
= CacheFile
.GetPolicy();
146 pkgCache::VerIterator inst
= P
.CurrentVer();
147 pkgCache::VerIterator cand
= policy
->GetCandidateVer(P
);
149 return inst
? inst
.Arch() : cand
.Arch();
152 static std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)/*{{{*/
154 pkgPolicy
*policy
= CacheFile
.GetPolicy();
156 pkgCache::VerIterator ver
;
158 ver
= P
.CurrentVer();
160 ver
= policy
->GetCandidateVer(P
);
162 std::string ShortDescription
= "(none)";
165 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
166 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
168 ShortDescription
= parser
.ShortDesc();
170 return ShortDescription
;
173 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
, /*{{{*/
174 pkgCache::VerIterator V
, std::ostream
&out
,
175 bool include_summary
)
177 pkgCache::PkgIterator P
= V
.ParentPkg();
179 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
180 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
182 std::string suite
= GetArchiveSuite(CacheFile
, V
);
183 std::string name_str
= P
.Name();
185 if (_config
->FindB("APT::Cmd::use-format", false))
187 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
188 std::string output
= format
;
190 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
191 output
= SubstVar(output
, "${Package}", name_str
);
192 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
193 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
194 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
195 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
196 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
197 out
<< output
<< std::endl
;
199 // raring/linux-kernel version [upradable: new-version]
201 pkgPolicy
*policy
= CacheFile
.GetPolicy();
202 std::string VersionStr
= GetVersion(CacheFile
, V
);
203 std::string CandidateVerStr
= GetCandidateVersion(CacheFile
, P
);
204 std::string InstalledVerStr
= GetInstalledVersion(CacheFile
, P
);
205 std::string StatusStr
;
206 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
207 strprintf(StatusStr
, _("[installed,upgradable to: %s]"),
208 CandidateVerStr
.c_str());
209 } else if (P
.CurrentVer() == V
) {
210 if(!V
.Downloadable())
211 StatusStr
= _("[installed,local]");
213 if(V
.Automatic() && state
.Garbage
)
214 StatusStr
= _("[installed,auto-removable]");
215 else if (state
.Flags
& pkgCache::Flag::Auto
)
216 StatusStr
= _("[installed,automatic]");
218 StatusStr
= _("[installed]");
219 } else if (P
.CurrentVer() &&
220 policy
->GetCandidateVer(P
) == V
&&
221 state
.Upgradable()) {
222 strprintf(StatusStr
, _("[upgradable from: %s]"),
223 InstalledVerStr
.c_str());
225 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
226 StatusStr
= _("[residual-config]");
230 out
<< std::setiosflags(std::ios::left
)
231 << _config
->Find("APT::Color::Highlight", "")
233 << _config
->Find("APT::Color::Neutral", "")
237 << GetArchitecture(CacheFile
, P
);
239 out
<< " " << StatusStr
;
243 << " " << GetShortDescription(CacheFile
, records
, P
)
249 // ShowList - Show a list /*{{{*/
250 // ---------------------------------------------------------------------
251 /* This prints out a string of space separated words with a title and
252 a two space indent line wraped to the current screen width. */
253 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
255 if (List
.empty() == true)
257 // trim trailing space
258 int NonSpace
= List
.find_last_not_of(' ');
261 List
= List
.erase(NonSpace
+ 1);
262 if (List
.empty() == true)
266 // Acount for the leading space
267 int ScreenWidth
= ::ScreenWidth
- 3;
269 out
<< Title
<< endl
;
270 string::size_type Start
= 0;
271 string::size_type VersionsStart
= 0;
272 while (Start
< List
.size())
274 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
275 VersionsList
.size() > 0) {
276 string::size_type End
;
277 string::size_type VersionsEnd
;
279 End
= List
.find(' ',Start
);
280 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
282 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
283 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
286 if (End
== string::npos
|| End
< Start
)
287 End
= Start
+ ScreenWidth
;
290 VersionsStart
= VersionsEnd
+ 1;
292 string::size_type End
;
294 if (Start
+ ScreenWidth
>= List
.size())
297 End
= List
.rfind(' ',Start
+ScreenWidth
);
299 if (End
== string::npos
|| End
< Start
)
300 End
= Start
+ ScreenWidth
;
301 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
309 // ShowBroken - Debugging aide /*{{{*/
310 // ---------------------------------------------------------------------
311 /* This prints out the names of all the packages that are broken along
312 with the name of each each broken dependency and a quite version
315 The output looks like:
316 The following packages have unmet dependencies:
317 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
318 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
319 Depends: libsasl7 but it is not going to be installed
321 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
323 if (Cache
->BrokenCount() == 0)
326 out
<< _("The following packages have unmet dependencies:") << endl
;
327 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
329 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
333 if (Cache
[I
].NowBroken() == false)
338 if (Cache
[I
].InstBroken() == false)
342 // Print out each package and the failed dependencies
343 out
<< " " << I
.FullName(true) << " :";
344 unsigned const Indent
= I
.FullName(true).size() + 3;
346 pkgCache::VerIterator Ver
;
349 Ver
= I
.CurrentVer();
351 Ver
= Cache
[I
].InstVerIter(Cache
);
353 if (Ver
.end() == true)
359 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
361 // Compute a single dependency element (glob or)
362 pkgCache::DepIterator Start
;
363 pkgCache::DepIterator End
;
364 D
.GlobOr(Start
,End
); // advances D
366 if (Cache
->IsImportantDep(End
) == false)
371 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
376 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
384 for (unsigned J
= 0; J
!= Indent
; J
++)
388 if (FirstOr
== false)
390 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
394 out
<< ' ' << End
.DepType() << ": ";
397 out
<< Start
.TargetPkg().FullName(true);
399 // Show a quick summary of the version requirements
400 if (Start
.TargetVer() != 0)
401 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
403 /* Show a summary of the target package if possible. In the case
404 of virtual packages we show nothing */
405 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
406 if (Targ
->ProvidesList
== 0)
409 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
411 Ver
= Targ
.CurrentVer();
413 if (Ver
.end() == false)
416 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
418 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
422 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
424 if (Targ
->ProvidesList
== 0)
425 out
<< _("but it is not installable");
427 out
<< _("but it is a virtual package");
430 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
446 // ShowNew - Show packages to newly install /*{{{*/
447 // ---------------------------------------------------------------------
449 void ShowNew(ostream
&out
,CacheFile
&Cache
)
451 /* Print out a list of packages that are going to be installed extra
452 to what the user asked */
455 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
457 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
458 if (Cache
[I
].NewInstall() == true) {
459 List
+= I
.FullName(true) + " ";
460 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
464 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
467 // ShowDel - Show packages to delete /*{{{*/
468 // ---------------------------------------------------------------------
470 void ShowDel(ostream
&out
,CacheFile
&Cache
)
472 /* Print out a list of packages that are going to be removed extra
473 to what the user asked */
476 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
478 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
479 if (Cache
[I
].Delete() == true)
481 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
482 List
+= I
.FullName(true) + "* ";
484 List
+= I
.FullName(true) + " ";
486 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
490 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
493 // ShowKept - Show kept packages /*{{{*/
494 // ---------------------------------------------------------------------
496 void ShowKept(ostream
&out
,CacheFile
&Cache
)
500 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
502 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
505 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
506 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
509 List
+= I
.FullName(true) + " ";
510 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
512 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
515 // ShowUpgraded - Show upgraded packages /*{{{*/
516 // ---------------------------------------------------------------------
518 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
522 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
524 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
527 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
530 List
+= I
.FullName(true) + " ";
531 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
533 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
536 // ShowDowngraded - Show downgraded packages /*{{{*/
537 // ---------------------------------------------------------------------
539 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
543 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
545 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
548 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
551 List
+= I
.FullName(true) + " ";
552 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
554 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
557 // ShowHold - Show held but changed packages /*{{{*/
558 // ---------------------------------------------------------------------
560 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
564 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
566 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
567 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
568 I
->SelectedState
== pkgCache::State::Hold
) {
569 List
+= I
.FullName(true) + " ";
570 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
574 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
577 // ShowEssential - Show an essential package warning /*{{{*/
578 // ---------------------------------------------------------------------
579 /* This prints out a warning message that is not to be ignored. It shows
580 all essential packages and their dependents that are to be removed.
581 It is insanely risky to remove the dependents of an essential package! */
582 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
586 bool *Added
= new bool[Cache
->Head().PackageCount
];
587 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
590 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
592 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
593 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
594 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
597 // The essential package is being removed
598 if (Cache
[I
].Delete() == true)
600 if (Added
[I
->ID
] == false)
603 List
+= I
.FullName(true) + " ";
604 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
610 if (I
->CurrentVer
== 0)
613 // Print out any essential package depenendents that are to be removed
614 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
616 // Skip everything but depends
617 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
618 D
->Type
!= pkgCache::Dep::Depends
)
621 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
622 if (Cache
[P
].Delete() == true)
624 if (Added
[P
->ID
] == true)
629 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
631 //VersionsList += "\n"; ???
637 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
638 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
642 // Stats - Show some statistics /*{{{*/
643 // ---------------------------------------------------------------------
645 void Stats(ostream
&out
,pkgDepCache
&Dep
)
647 unsigned long Upgrade
= 0;
648 unsigned long Downgrade
= 0;
649 unsigned long Install
= 0;
650 unsigned long ReInstall
= 0;
651 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
653 if (Dep
[I
].NewInstall() == true)
657 if (Dep
[I
].Upgrade() == true)
660 if (Dep
[I
].Downgrade() == true)
664 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
668 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
672 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
674 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
676 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
677 Dep
.DelCount(),Dep
.KeepCount());
679 if (Dep
.BadCount() != 0)
680 ioprintf(out
,_("%lu not fully installed or removed.\n"),
684 // YnPrompt - Yes No Prompt. /*{{{*/
685 // ---------------------------------------------------------------------
686 /* Returns true on a Yes.*/
687 bool YnPrompt(bool Default
)
689 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
690 to have the help-message (hopefully) match the expected characters */
691 char * language
= getenv("LANGUAGE");
692 if (language
!= NULL
)
693 language
= strdup(language
);
694 if (language
!= NULL
)
695 unsetenv("LANGUAGE");
698 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
699 // e.g. "Do you want to continue? [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 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
705 // e.g. "Should this file be removed? [y/N] "
706 // The user has to answer with an input matching the
707 // YESEXPR/NOEXPR defined in your l10n.
708 c2out
<< " " << _("[y/N]") << " " << std::flush
;
710 if (language
!= NULL
)
712 setenv("LANGUAGE", language
, 0);
716 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
718 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
719 c1out
<< _("Y") << std::endl
;
722 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
724 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
725 c1out
<< _("N") << std::endl
;
729 char response
[1024] = "";
730 std::cin
.getline(response
, sizeof(response
));
735 if (strlen(response
) == 0)
741 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
742 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
746 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
747 return _error
->Error(_("Regex compilation error - %s"),Error
);
750 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
756 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
757 // ---------------------------------------------------------------------
758 /* Returns true on a Yes.*/
759 bool AnalPrompt(const char *Text
)
762 std::cin
.getline(Buf
,sizeof(Buf
));
763 if (strcmp(Buf
,Text
) == 0)