X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/d9e518c6f7dc0ad464495b586d1b8e115d54d41a..d8a57c1953b876917a9deb098d1ef3d2b093f3dc:/apt-private/private-output.cc diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 4e18030ab..301aa5519 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -25,6 +25,8 @@ #include #include +#include + #include /*}}}*/ @@ -199,10 +201,12 @@ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &reco std::string ShortDescription = "(none)"; if(ver) { - pkgCache::DescIterator Desc = ver.TranslatedDescription(); - pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); - - ShortDescription = parser.ShortDesc(); + pkgCache::DescIterator const Desc = ver.TranslatedDescription(); + if (Desc.end() == false) + { + pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); + ShortDescription = parser.ShortDesc(); + } } return ShortDescription; } @@ -222,11 +226,14 @@ static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &recor return EmptyDescription; pkgCache::DescIterator const Desc = ver.TranslatedDescription(); - pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); - std::string const longdesc = parser.LongDesc(); - if (longdesc.empty() == true) - return EmptyDescription; - return SubstVar(longdesc, "\n ", "\n "); + if (Desc.end() == false) + { + pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); + std::string const longdesc = parser.LongDesc(); + if (longdesc.empty() == false) + return SubstVar(longdesc, "\n ", "\n "); + } + return EmptyDescription; } /*}}}*/ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ @@ -283,7 +290,8 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", "")); output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", "")); output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); - output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P)); + if (output.find("${LongDescription}") != string::npos) + output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P)); output = SubstVar(output, "${ }${ }", "${ }"); output = SubstVar(output, "${ }\n", "\n"); output = SubstVar(output, "${ }", " "); @@ -293,66 +301,6 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ out << output; } /*}}}*/ -// ShowList - Show a list /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out a string of space separated words with a title and - a two space indent line wraped to the current screen width. */ -bool ShowList(ostream &out,string Title,string List,string VersionsList) -{ - if (List.empty() == true) - return true; - // trim trailing space - int NonSpace = List.find_last_not_of(' '); - if (NonSpace != -1) - { - List = List.erase(NonSpace + 1); - if (List.empty() == true) - return true; - } - - // Acount for the leading space - int ScreenWidth = ::ScreenWidth - 3; - - out << Title << endl; - string::size_type Start = 0; - string::size_type VersionsStart = 0; - while (Start < List.size()) - { - if(_config->FindB("APT::Get::Show-Versions",false) == true && - VersionsList.size() > 0) { - string::size_type End; - string::size_type VersionsEnd; - - End = List.find(' ',Start); - VersionsEnd = VersionsList.find('\n', VersionsStart); - - out << " " << string(List,Start,End - Start) << " (" << - string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) << - ")" << endl; - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - - Start = End + 1; - VersionsStart = VersionsEnd + 1; - } else { - string::size_type End; - - if (Start + ScreenWidth >= List.size()) - End = List.size(); - else - End = List.rfind(' ',Start+ScreenWidth); - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - out << " " << string(List,Start,End - Start) << endl; - Start = End + 1; - } - } - - return false; -} - /*}}}*/ // ShowBroken - Debugging aide /*{{{*/ // --------------------------------------------------------------------- /* This prints out the names of all the packages that are broken along @@ -486,11 +434,9 @@ void ShowBroken(ostream &out, CacheFile &Cache, bool const Now) return; out << _("The following packages have unmet dependencies:") << endl; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator const I(Cache,Cache.List[J]); - ShowBrokenPackage(out, &Cache, I, Now); - } + SortedPackageUniverse Universe(Cache); + for (auto const &Pkg: Universe) + ShowBrokenPackage(out, &Cache, Pkg, Now); } void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) { @@ -498,98 +444,64 @@ void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) return; out << _("The following packages have unmet dependencies:") << endl; - for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg) + APT::PackageUniverse Universe(Cache); + for (auto const &Pkg: Universe) ShowBrokenPackage(out, &Cache, Pkg, Now); } /*}}}*/ // ShowNew - Show packages to newly install /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowNew(ostream &out,CacheFile &Cache) { - /* Print out a list of packages that are going to be installed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].NewInstall() == true) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CandVersion) + "\n"; - } - } - - ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following NEW packages will be installed:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); }, + &PrettyFullName, + CandidateVersion(&Cache)); } /*}}}*/ // ShowDel - Show packages to delete /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowDel(ostream &out,CacheFile &Cache) { - /* Print out a list of packages that are going to be removed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].Delete() == true) - { - if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) - List += I.FullName(true) + "* "; - else - List += I.FullName(true) + " "; - - VersionsList += string(Cache[I].CandVersion)+ "\n"; - } - } - - ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following packages will be REMOVED:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); }, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + std::string str = PrettyFullName(Pkg); + if (((*Cache)[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) + str.append("*"); + return str; + }, + CandidateVersion(&Cache)); } /*}}}*/ // ShowKept - Show kept packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowKept(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false || - I->CurrentVer == 0 || Cache[I].Delete() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages have been kept back:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following packages have been kept back:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Cache[Pkg].Upgrade() == false && + Cache[Pkg].Upgradable() == true && + Pkg->CurrentVer != 0 && + Cache[Pkg].Delete() == false; + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowUpgraded - Show upgraded packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowUpgraded(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages will be upgraded:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following packages will be upgraded:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false; + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowDowngraded - Show downgraded packages /*{{{*/ @@ -597,74 +509,73 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) /* */ bool ShowDowngraded(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false; + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowHold - Show held but changed packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ bool ShowHold(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() && - I->SelectedState == pkgCache::State::Hold) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - } - - return ShowList(out,_("The following held packages will be changed:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + return ShowList(out,_("The following held packages will be changed:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Pkg->SelectedState == pkgCache::State::Hold && + Cache[Pkg].InstallVer != (pkgCache::Version *)Pkg.CurrentVer(); + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowEssential - Show an essential package warning /*{{{*/ // --------------------------------------------------------------------- /* This prints out a warning message that is not to be ignored. It shows - all essential packages and their dependents that are to be removed. + all essential packages and their dependents that are to be removed. It is insanely risky to remove the dependents of an essential package! */ +struct APT_HIDDEN PrettyFullNameWithDue { + std::map due; + PrettyFullNameWithDue() {} + std::string operator() (pkgCache::PkgIterator const &Pkg) + { + std::string const A = PrettyFullName(Pkg); + std::map::const_iterator d = due.find(Pkg->ID); + if (d == due.end()) + return A; + + std::string const B = PrettyFullName(d->second); + std::ostringstream outstr; + ioprintf(outstr, _("%s (due to %s)"), A.c_str(), B.c_str()); + return outstr.str(); + } +}; bool ShowEssential(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - bool *Added = new bool[Cache->Head().PackageCount]; - for (unsigned int I = 0; I != Cache->Head().PackageCount; I++) - Added[I] = false; - - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + std::vector Added(Cache->Head().PackageCount, false); + APT::PackageDeque pkglist; + PrettyFullNameWithDue withdue; + + SortedPackageUniverse Universe(Cache); + for (pkgCache::PkgIterator const &I: Universe) { - pkgCache::PkgIterator I(Cache,Cache.List[J]); if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential && (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) continue; - + // The essential package is being removed - if (Cache[I].Delete() == true) + if (Cache[I].Delete() == false) + continue; + + if (Added[I->ID] == false) { - if (Added[I->ID] == false) - { - Added[I->ID] = true; - List += I.FullName(true) + " "; - //VersionsList += string(Cache[I].CurVersion) + "\n"; ??? - } + Added[I->ID] = true; + pkglist.insert(I); } - else - continue; if (I->CurrentVer == 0) continue; @@ -676,27 +587,23 @@ bool ShowEssential(ostream &out,CacheFile &Cache) if (D->Type != pkgCache::Dep::PreDepends && D->Type != pkgCache::Dep::Depends) continue; - + pkgCache::PkgIterator P = D.SmartTargetPkg(); if (Cache[P].Delete() == true) { if (Added[P->ID] == true) continue; Added[P->ID] = true; - - char S[300]; - snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str()); - List += S; - //VersionsList += "\n"; ??? - } - } + + pkglist.insert(P); + withdue.due[P->ID] = I; + } + } } - - delete [] Added; return ShowList(out,_("WARNING: The following essential packages will be removed.\n" - "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList); + "This should NOT be done unless you know exactly what you are doing!"), + pkglist, &AlwaysTrue, withdue, &EmptyString); } - /*}}}*/ // Stats - Show some statistics /*{{{*/ // --------------------------------------------------------------------- @@ -743,8 +650,21 @@ void Stats(ostream &out,pkgDepCache &Dep) // YnPrompt - Yes No Prompt. /*{{{*/ // --------------------------------------------------------------------- /* Returns true on a Yes.*/ -bool YnPrompt(bool Default) +bool YnPrompt(char const * const Question, bool Default) { + auto const AssumeYes = _config->FindB("APT::Get::Assume-Yes",false); + auto const AssumeNo = _config->FindB("APT::Get::Assume-No",false); + // if we ask interactively, show warnings/notices before the question + if (AssumeYes == false && AssumeNo == false) + { + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(c2out); + else + _error->DumpErrors(c2out, GlobalError::DEBUG); + } + + c2out << Question << std::flush; + /* nl_langinfo does not support LANGUAGE setting, so we unset it here to have the help-message (hopefully) match the expected characters */ char * language = getenv("LANGUAGE"); @@ -772,13 +692,13 @@ bool YnPrompt(bool Default) free(language); } - if (_config->FindB("APT::Get::Assume-Yes",false) == true) + if (AssumeYes) { // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set c1out << _("Y") << std::endl; return true; } - else if (_config->FindB("APT::Get::Assume-No",false) == true) + else if (AssumeNo) { // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set c1out << _("N") << std::endl; @@ -815,8 +735,14 @@ bool YnPrompt(bool Default) // AnalPrompt - Annoying Yes No Prompt. /*{{{*/ // --------------------------------------------------------------------- /* Returns true on a Yes.*/ -bool AnalPrompt(const char *Text) +bool AnalPrompt(std::string const &Question, const char *Text) { + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(c2out); + else + _error->DumpErrors(c2out, GlobalError::DEBUG); + c2out << Question << std::flush; + char Buf[1024]; std::cin.getline(Buf,sizeof(Buf)); if (strcmp(Buf,Text) == 0) @@ -824,3 +750,33 @@ bool AnalPrompt(const char *Text) return false; } /*}}}*/ + +std::string PrettyFullName(pkgCache::PkgIterator const &Pkg) +{ + return Pkg.FullName(true); +} +std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg) +{ + return (*Cache)[Pkg].CandVersion; +} +std::function CandidateVersion(pkgCacheFile * const Cache) +{ + return std::bind(static_cast(&CandidateVersion), Cache, std::placeholders::_1); +} +std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg) +{ + return std::string((*Cache)[Pkg].CurVersion) + " => " + (*Cache)[Pkg].CandVersion; +} +std::function CurrentToCandidateVersion(pkgCacheFile * const Cache) +{ + return std::bind(static_cast(&CurrentToCandidateVersion), Cache, std::placeholders::_1); +} +bool AlwaysTrue(pkgCache::PkgIterator const &) +{ + return true; +} +std::string EmptyString(pkgCache::PkgIterator const &) +{ + return std::string(); +} +