]>
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 // this may happen for packages in dpkg "deinstall ok config-file" state
150 if (inst
.IsGood() == false && cand
.IsGood() == false)
151 return P
.VersionList().Arch();
153 return inst
? inst
.Arch() : cand
.Arch();
156 static std::string
GetShortDescription(pkgCacheFile
&CacheFile
, pkgRecords
&records
, pkgCache::PkgIterator P
)/*{{{*/
158 pkgPolicy
*policy
= CacheFile
.GetPolicy();
160 pkgCache::VerIterator ver
;
162 ver
= P
.CurrentVer();
164 ver
= policy
->GetCandidateVer(P
);
166 std::string ShortDescription
= "(none)";
169 pkgCache::DescIterator Desc
= ver
.TranslatedDescription();
170 pkgRecords::Parser
& parser
= records
.Lookup(Desc
.FileList());
172 ShortDescription
= parser
.ShortDesc();
174 return ShortDescription
;
177 void ListSingleVersion(pkgCacheFile
&CacheFile
, pkgRecords
&records
, /*{{{*/
178 pkgCache::VerIterator V
, std::ostream
&out
,
179 bool include_summary
)
181 pkgCache::PkgIterator P
= V
.ParentPkg();
183 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
184 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
186 std::string suite
= GetArchiveSuite(CacheFile
, V
);
187 std::string name_str
= P
.Name();
189 if (_config
->FindB("APT::Cmd::use-format", false))
191 std::string format
= _config
->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
192 std::string output
= format
;
194 output
= SubstVar(output
, "${db::Status-Abbrev}", GetFlagsStr(CacheFile
, P
));
195 output
= SubstVar(output
, "${Package}", name_str
);
196 output
= SubstVar(output
, "${installed:Version}", GetInstalledVersion(CacheFile
, P
));
197 output
= SubstVar(output
, "${candidate:Version}", GetCandidateVersion(CacheFile
, P
));
198 output
= SubstVar(output
, "${Version}", GetVersion(CacheFile
, V
));
199 output
= SubstVar(output
, "${Description}", GetShortDescription(CacheFile
, records
, P
));
200 output
= SubstVar(output
, "${Origin}", GetArchiveSuite(CacheFile
, V
));
201 out
<< output
<< std::endl
;
203 // raring/linux-kernel version [upradable: new-version]
205 pkgPolicy
*policy
= CacheFile
.GetPolicy();
206 std::string VersionStr
= GetVersion(CacheFile
, V
);
207 std::string CandidateVerStr
= GetCandidateVersion(CacheFile
, P
);
208 std::string InstalledVerStr
= GetInstalledVersion(CacheFile
, P
);
209 std::string StatusStr
;
210 if(P
.CurrentVer() == V
&& state
.Upgradable()) {
211 strprintf(StatusStr
, _("[installed,upgradable to: %s]"),
212 CandidateVerStr
.c_str());
213 } else if (P
.CurrentVer() == V
) {
214 if(!V
.Downloadable())
215 StatusStr
= _("[installed,local]");
217 if(V
.Automatic() && state
.Garbage
)
218 StatusStr
= _("[installed,auto-removable]");
219 else if (state
.Flags
& pkgCache::Flag::Auto
)
220 StatusStr
= _("[installed,automatic]");
222 StatusStr
= _("[installed]");
223 } else if (P
.CurrentVer() &&
224 policy
->GetCandidateVer(P
) == V
&&
225 state
.Upgradable()) {
226 strprintf(StatusStr
, _("[upgradable from: %s]"),
227 InstalledVerStr
.c_str());
229 if (V
.ParentPkg()->CurrentState
== pkgCache::State::ConfigFiles
)
230 StatusStr
= _("[residual-config]");
234 out
<< std::setiosflags(std::ios::left
)
235 << _config
->Find("APT::Color::Highlight", "")
237 << _config
->Find("APT::Color::Neutral", "")
241 << GetArchitecture(CacheFile
, P
);
243 out
<< " " << StatusStr
;
247 << " " << GetShortDescription(CacheFile
, records
, P
)
253 // ShowList - Show a list /*{{{*/
254 // ---------------------------------------------------------------------
255 /* This prints out a string of space separated words with a title and
256 a two space indent line wraped to the current screen width. */
257 bool ShowList(ostream
&out
,string Title
,string List
,string VersionsList
)
259 if (List
.empty() == true)
261 // trim trailing space
262 int NonSpace
= List
.find_last_not_of(' ');
265 List
= List
.erase(NonSpace
+ 1);
266 if (List
.empty() == true)
270 // Acount for the leading space
271 int ScreenWidth
= ::ScreenWidth
- 3;
273 out
<< Title
<< endl
;
274 string::size_type Start
= 0;
275 string::size_type VersionsStart
= 0;
276 while (Start
< List
.size())
278 if(_config
->FindB("APT::Get::Show-Versions",false) == true &&
279 VersionsList
.size() > 0) {
280 string::size_type End
;
281 string::size_type VersionsEnd
;
283 End
= List
.find(' ',Start
);
284 VersionsEnd
= VersionsList
.find('\n', VersionsStart
);
286 out
<< " " << string(List
,Start
,End
- Start
) << " (" <<
287 string(VersionsList
,VersionsStart
,VersionsEnd
- VersionsStart
) <<
290 if (End
== string::npos
|| End
< Start
)
291 End
= Start
+ ScreenWidth
;
294 VersionsStart
= VersionsEnd
+ 1;
296 string::size_type End
;
298 if (Start
+ ScreenWidth
>= List
.size())
301 End
= List
.rfind(' ',Start
+ScreenWidth
);
303 if (End
== string::npos
|| End
< Start
)
304 End
= Start
+ ScreenWidth
;
305 out
<< " " << string(List
,Start
,End
- Start
) << endl
;
313 // ShowBroken - Debugging aide /*{{{*/
314 // ---------------------------------------------------------------------
315 /* This prints out the names of all the packages that are broken along
316 with the name of each each broken dependency and a quite version
319 The output looks like:
320 The following packages have unmet dependencies:
321 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
322 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
323 Depends: libsasl7 but it is not going to be installed
325 void ShowBroken(ostream
&out
,CacheFile
&Cache
,bool Now
)
327 if (Cache
->BrokenCount() == 0)
330 out
<< _("The following packages have unmet dependencies:") << endl
;
331 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
333 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
337 if (Cache
[I
].NowBroken() == false)
342 if (Cache
[I
].InstBroken() == false)
346 // Print out each package and the failed dependencies
347 out
<< " " << I
.FullName(true) << " :";
348 unsigned const Indent
= I
.FullName(true).size() + 3;
350 pkgCache::VerIterator Ver
;
353 Ver
= I
.CurrentVer();
355 Ver
= Cache
[I
].InstVerIter(Cache
);
357 if (Ver
.end() == true)
363 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false;)
365 // Compute a single dependency element (glob or)
366 pkgCache::DepIterator Start
;
367 pkgCache::DepIterator End
;
368 D
.GlobOr(Start
,End
); // advances D
370 if (Cache
->IsImportantDep(End
) == false)
375 if ((Cache
[End
] & pkgDepCache::DepGNow
) == pkgDepCache::DepGNow
)
380 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
388 for (unsigned J
= 0; J
!= Indent
; J
++)
392 if (FirstOr
== false)
394 for (unsigned J
= 0; J
!= strlen(End
.DepType()) + 3; J
++)
398 out
<< ' ' << End
.DepType() << ": ";
401 out
<< Start
.TargetPkg().FullName(true);
403 // Show a quick summary of the version requirements
404 if (Start
.TargetVer() != 0)
405 out
<< " (" << Start
.CompType() << " " << Start
.TargetVer() << ")";
407 /* Show a summary of the target package if possible. In the case
408 of virtual packages we show nothing */
409 pkgCache::PkgIterator Targ
= Start
.TargetPkg();
410 if (Targ
->ProvidesList
== 0)
413 pkgCache::VerIterator Ver
= Cache
[Targ
].InstVerIter(Cache
);
415 Ver
= Targ
.CurrentVer();
417 if (Ver
.end() == false)
420 ioprintf(out
,_("but %s is installed"),Ver
.VerStr());
422 ioprintf(out
,_("but %s is to be installed"),Ver
.VerStr());
426 if (Cache
[Targ
].CandidateVerIter(Cache
).end() == true)
428 if (Targ
->ProvidesList
== 0)
429 out
<< _("but it is not installable");
431 out
<< _("but it is a virtual package");
434 out
<< (Now
?_("but it is not installed"):_("but it is not going to be installed"));
450 // ShowNew - Show packages to newly install /*{{{*/
451 // ---------------------------------------------------------------------
453 void ShowNew(ostream
&out
,CacheFile
&Cache
)
455 /* Print out a list of packages that are going to be installed extra
456 to what the user asked */
459 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
461 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
462 if (Cache
[I
].NewInstall() == true) {
463 List
+= I
.FullName(true) + " ";
464 VersionsList
+= string(Cache
[I
].CandVersion
) + "\n";
468 ShowList(out
,_("The following NEW packages will be installed:"),List
,VersionsList
);
471 // ShowDel - Show packages to delete /*{{{*/
472 // ---------------------------------------------------------------------
474 void ShowDel(ostream
&out
,CacheFile
&Cache
)
476 /* Print out a list of packages that are going to be removed extra
477 to what the user asked */
480 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
482 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
483 if (Cache
[I
].Delete() == true)
485 if ((Cache
[I
].iFlags
& pkgDepCache::Purge
) == pkgDepCache::Purge
)
486 List
+= I
.FullName(true) + "* ";
488 List
+= I
.FullName(true) + " ";
490 VersionsList
+= string(Cache
[I
].CandVersion
)+ "\n";
494 ShowList(out
,_("The following packages will be REMOVED:"),List
,VersionsList
);
497 // ShowKept - Show kept packages /*{{{*/
498 // ---------------------------------------------------------------------
500 void ShowKept(ostream
&out
,CacheFile
&Cache
)
504 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
506 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
509 if (Cache
[I
].Upgrade() == true || Cache
[I
].Upgradable() == false ||
510 I
->CurrentVer
== 0 || Cache
[I
].Delete() == true)
513 List
+= I
.FullName(true) + " ";
514 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
516 ShowList(out
,_("The following packages have been kept back:"),List
,VersionsList
);
519 // ShowUpgraded - Show upgraded packages /*{{{*/
520 // ---------------------------------------------------------------------
522 void ShowUpgraded(ostream
&out
,CacheFile
&Cache
)
526 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
528 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
531 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
534 List
+= I
.FullName(true) + " ";
535 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
537 ShowList(out
,_("The following packages will be upgraded:"),List
,VersionsList
);
540 // ShowDowngraded - Show downgraded packages /*{{{*/
541 // ---------------------------------------------------------------------
543 bool ShowDowngraded(ostream
&out
,CacheFile
&Cache
)
547 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
549 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
552 if (Cache
[I
].Downgrade() == false || Cache
[I
].NewInstall() == true)
555 List
+= I
.FullName(true) + " ";
556 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
558 return ShowList(out
,_("The following packages will be DOWNGRADED:"),List
,VersionsList
);
561 // ShowHold - Show held but changed packages /*{{{*/
562 // ---------------------------------------------------------------------
564 bool ShowHold(ostream
&out
,CacheFile
&Cache
)
568 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
570 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
571 if (Cache
[I
].InstallVer
!= (pkgCache::Version
*)I
.CurrentVer() &&
572 I
->SelectedState
== pkgCache::State::Hold
) {
573 List
+= I
.FullName(true) + " ";
574 VersionsList
+= string(Cache
[I
].CurVersion
) + " => " + Cache
[I
].CandVersion
+ "\n";
578 return ShowList(out
,_("The following held packages will be changed:"),List
,VersionsList
);
581 // ShowEssential - Show an essential package warning /*{{{*/
582 // ---------------------------------------------------------------------
583 /* This prints out a warning message that is not to be ignored. It shows
584 all essential packages and their dependents that are to be removed.
585 It is insanely risky to remove the dependents of an essential package! */
586 bool ShowEssential(ostream
&out
,CacheFile
&Cache
)
590 bool *Added
= new bool[Cache
->Head().PackageCount
];
591 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
594 for (unsigned J
= 0; J
< Cache
->Head().PackageCount
; J
++)
596 pkgCache::PkgIterator
I(Cache
,Cache
.List
[J
]);
597 if ((I
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
598 (I
->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
601 // The essential package is being removed
602 if (Cache
[I
].Delete() == true)
604 if (Added
[I
->ID
] == false)
607 List
+= I
.FullName(true) + " ";
608 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
614 if (I
->CurrentVer
== 0)
617 // Print out any essential package depenendents that are to be removed
618 for (pkgCache::DepIterator D
= I
.CurrentVer().DependsList(); D
.end() == false; ++D
)
620 // Skip everything but depends
621 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
622 D
->Type
!= pkgCache::Dep::Depends
)
625 pkgCache::PkgIterator P
= D
.SmartTargetPkg();
626 if (Cache
[P
].Delete() == true)
628 if (Added
[P
->ID
] == true)
633 snprintf(S
,sizeof(S
),_("%s (due to %s) "),P
.FullName(true).c_str(),I
.FullName(true).c_str());
635 //VersionsList += "\n"; ???
641 return ShowList(out
,_("WARNING: The following essential packages will be removed.\n"
642 "This should NOT be done unless you know exactly what you are doing!"),List
,VersionsList
);
646 // Stats - Show some statistics /*{{{*/
647 // ---------------------------------------------------------------------
649 void Stats(ostream
&out
,pkgDepCache
&Dep
)
651 unsigned long Upgrade
= 0;
652 unsigned long Downgrade
= 0;
653 unsigned long Install
= 0;
654 unsigned long ReInstall
= 0;
655 for (pkgCache::PkgIterator I
= Dep
.PkgBegin(); I
.end() == false; ++I
)
657 if (Dep
[I
].NewInstall() == true)
661 if (Dep
[I
].Upgrade() == true)
664 if (Dep
[I
].Downgrade() == true)
668 if (Dep
[I
].Delete() == false && (Dep
[I
].iFlags
& pkgDepCache::ReInstall
) == pkgDepCache::ReInstall
)
672 ioprintf(out
,_("%lu upgraded, %lu newly installed, "),
676 ioprintf(out
,_("%lu reinstalled, "),ReInstall
);
678 ioprintf(out
,_("%lu downgraded, "),Downgrade
);
680 ioprintf(out
,_("%lu to remove and %lu not upgraded.\n"),
681 Dep
.DelCount(),Dep
.KeepCount());
683 if (Dep
.BadCount() != 0)
684 ioprintf(out
,_("%lu not fully installed or removed.\n"),
688 // YnPrompt - Yes No Prompt. /*{{{*/
689 // ---------------------------------------------------------------------
690 /* Returns true on a Yes.*/
691 bool YnPrompt(bool Default
)
693 /* nl_langinfo does not support LANGUAGE setting, so we unset it here
694 to have the help-message (hopefully) match the expected characters */
695 char * language
= getenv("LANGUAGE");
696 if (language
!= NULL
)
697 language
= strdup(language
);
698 if (language
!= NULL
)
699 unsetenv("LANGUAGE");
702 // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
703 // e.g. "Do you want to continue? [Y/n] "
704 // The user has to answer with an input matching the
705 // YESEXPR/NOEXPR defined in your l10n.
706 c2out
<< " " << _("[Y/n]") << " " << std::flush
;
708 // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
709 // e.g. "Should this file be removed? [y/N] "
710 // The user has to answer with an input matching the
711 // YESEXPR/NOEXPR defined in your l10n.
712 c2out
<< " " << _("[y/N]") << " " << std::flush
;
714 if (language
!= NULL
)
716 setenv("LANGUAGE", language
, 0);
720 if (_config
->FindB("APT::Get::Assume-Yes",false) == true)
722 // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
723 c1out
<< _("Y") << std::endl
;
726 else if (_config
->FindB("APT::Get::Assume-No",false) == true)
728 // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
729 c1out
<< _("N") << std::endl
;
733 char response
[1024] = "";
734 std::cin
.getline(response
, sizeof(response
));
739 if (strlen(response
) == 0)
745 Res
= regcomp(&Pattern
, nl_langinfo(YESEXPR
),
746 REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
750 regerror(Res
,&Pattern
,Error
,sizeof(Error
));
751 return _error
->Error(_("Regex compilation error - %s"),Error
);
754 Res
= regexec(&Pattern
, response
, 0, NULL
, 0);
760 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
761 // ---------------------------------------------------------------------
762 /* Returns true on a Yes.*/
763 bool AnalPrompt(const char *Text
)
766 std::cin
.getline(Buf
,sizeof(Buf
));
767 if (strcmp(Buf
,Text
) == 0)