From d39d7f885d61bfe296c131c83bdc042a2ab6b0d7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 17 Jun 2014 17:45:33 +0200 Subject: show our broken packages message in 'apt' solver --- apt-private/private-output.cc | 204 ++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 96 deletions(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 8f190a551..158bd5c71 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -344,129 +344,141 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList) Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed Depends: libsasl7 but it is not going to be installed */ -void ShowBroken(ostream &out,CacheFile &Cache,bool Now) +static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now) { - if (Cache->BrokenCount() == 0) + if (Now == true) + { + if ((*Cache)[Pkg].NowBroken() == false) + return; + } + else + { + if ((*Cache)[Pkg].InstBroken() == false) + return; + } + + // Print out each package and the failed dependencies + out << " " << Pkg.FullName(true) << " :"; + unsigned const Indent = Pkg.FullName(true).size() + 3; + bool First = true; + pkgCache::VerIterator Ver; + + if (Now == true) + Ver = Pkg.CurrentVer(); + else + Ver = (*Cache)[Pkg].InstVerIter(*Cache); + + if (Ver.end() == true) + { + out << endl; return; + } - out << _("The following packages have unmet dependencies:") << endl; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - + // Compute a single dependency element (glob or) + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); // advances D + + if ((*Cache)->IsImportantDep(End) == false) + continue; + if (Now == true) { - if (Cache[I].NowBroken() == false) + if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow) continue; } else { - if (Cache[I].InstBroken() == false) + if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) continue; } - - // Print out each package and the failed dependencies - out << " " << I.FullName(true) << " :"; - unsigned const Indent = I.FullName(true).size() + 3; - bool First = true; - pkgCache::VerIterator Ver; - - if (Now == true) - Ver = I.CurrentVer(); - else - Ver = Cache[I].InstVerIter(Cache); - - if (Ver.end() == true) - { - out << endl; - continue; - } - - for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) + + bool FirstOr = true; + while (1) { - // Compute a single dependency element (glob or) - pkgCache::DepIterator Start; - pkgCache::DepIterator End; - D.GlobOr(Start,End); // advances D + if (First == false) + for (unsigned J = 0; J != Indent; J++) + out << ' '; + First = false; - if (Cache->IsImportantDep(End) == false) - continue; - - if (Now == true) + if (FirstOr == false) { - if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow) - continue; + for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) + out << ' '; } else + out << ' ' << End.DepType() << ": "; + FirstOr = false; + + out << Start.TargetPkg().FullName(true); + + // Show a quick summary of the version requirements + if (Start.TargetVer() != 0) + out << " (" << Start.CompType() << " " << Start.TargetVer() << ")"; + + /* Show a summary of the target package if possible. In the case + of virtual packages we show nothing */ + pkgCache::PkgIterator Targ = Start.TargetPkg(); + if (Targ->ProvidesList == 0) { - if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) - continue; - } - - bool FirstOr = true; - while (1) - { - if (First == false) - for (unsigned J = 0; J != Indent; J++) - out << ' '; - First = false; + out << ' '; + pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache); + if (Now == true) + Ver = Targ.CurrentVer(); - if (FirstOr == false) + if (Ver.end() == false) { - for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) - out << ' '; + if (Now == true) + ioprintf(out,_("but %s is installed"),Ver.VerStr()); + else + ioprintf(out,_("but %s is to be installed"),Ver.VerStr()); } else - out << ' ' << End.DepType() << ": "; - FirstOr = false; - - out << Start.TargetPkg().FullName(true); - - // Show a quick summary of the version requirements - if (Start.TargetVer() != 0) - out << " (" << Start.CompType() << " " << Start.TargetVer() << ")"; - - /* Show a summary of the target package if possible. In the case - of virtual packages we show nothing */ - pkgCache::PkgIterator Targ = Start.TargetPkg(); - if (Targ->ProvidesList == 0) { - out << ' '; - pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache); - if (Now == true) - Ver = Targ.CurrentVer(); - - if (Ver.end() == false) + if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true) { - if (Now == true) - ioprintf(out,_("but %s is installed"),Ver.VerStr()); + if (Targ->ProvidesList == 0) + out << _("but it is not installable"); else - ioprintf(out,_("but %s is to be installed"),Ver.VerStr()); - } + out << _("but it is a virtual package"); + } else - { - if (Cache[Targ].CandidateVerIter(Cache).end() == true) - { - if (Targ->ProvidesList == 0) - out << _("but it is not installable"); - else - out << _("but it is a virtual package"); - } - else - out << (Now?_("but it is not installed"):_("but it is not going to be installed")); - } + out << (Now?_("but it is not installed"):_("but it is not going to be installed")); } - - if (Start != End) - out << _(" or"); - out << endl; - - if (Start == End) - break; - ++Start; - } - } - } + } + + if (Start != End) + out << _(" or"); + out << endl; + + if (Start == End) + break; + ++Start; + } + } +} +void ShowBroken(ostream &out, CacheFile &Cache, bool const Now) +{ + if (Cache->BrokenCount() == 0) + 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); + } +} +void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) +{ + if (Cache->BrokenCount() == 0) + return; + + out << _("The following packages have unmet dependencies:") << endl; + for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg) + ShowBrokenPackage(out, &Cache, Pkg, Now); } /*}}}*/ // ShowNew - Show packages to newly install /*{{{*/ -- cgit v1.2.3 From 7d1b93d94083a3856efc821bacd9e91f80bbf760 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 8 Jul 2014 16:06:56 +0200 Subject: Only show packages as upgradable if the have a CandidateVer != 0 Closes: #753297 --- apt-private/private-output.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 158bd5c71..7f8922138 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -118,7 +118,7 @@ static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P) std::string flags_str; if (state.NowBroken()) flags_str = "B"; - if (P.CurrentVer() && state.Upgradable()) + if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL) flags_str = "g"; else if (P.CurrentVer() != NULL) flags_str = "i"; @@ -229,7 +229,8 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ std::string CandidateVerStr = GetCandidateVersion(CacheFile, P); std::string InstalledVerStr = GetInstalledVersion(CacheFile, P); std::string StatusStr; - if(P.CurrentVer() == V && state.Upgradable()) { + if(P.CurrentVer() == V && state.Upgradable() && state.CandidateVer != NULL) + { strprintf(StatusStr, _("[installed,upgradable to: %s]"), CandidateVerStr.c_str()); } else if (P.CurrentVer() == V) { -- cgit v1.2.3 From 6763aaec8ddded31057733f53c63f15e6b949bd9 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Tue, 2 Sep 2014 16:34:05 +0200 Subject: Avoid yielding blank lines with APT::Cmd::use-format=true --- apt-private/private-output.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 7f8922138..8f1fb886e 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -220,7 +220,7 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ output = SubstVar(output, "${Version}", GetVersion(CacheFile, V)); output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V)); - out << output << std::endl; + out << output; } else { // raring/linux-kernel version [upradable: new-version] // description -- cgit v1.2.3 From d059cc2668f284a7db77a15d1d742326d464e963 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 5 Sep 2014 12:03:28 +0200 Subject: Fix incorrect upgradable listing in "apt list" (thanks to Michael Musenbrock) The "apt list" command was using only the pkgDepCache but not the pkgPolicy to figure out if a package is upgradable. This lead to incorrect display of upgradable package when the user used the policy to pin-down packages. Thanks to Michael Musenbrock for the initial patch. Closes: #753297 --- apt-private/private-output.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 8f1fb886e..2120b7a83 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -229,7 +229,10 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ std::string CandidateVerStr = GetCandidateVersion(CacheFile, P); std::string InstalledVerStr = GetInstalledVersion(CacheFile, P); std::string StatusStr; - if(P.CurrentVer() == V && state.Upgradable() && state.CandidateVer != NULL) + if(P.CurrentVer() == V && + state.Upgradable() && + state.CandidateVer != NULL && + policy->GetCandidateVer(P) != P.CurrentVer()) { strprintf(StatusStr, _("[installed,upgradable to: %s]"), CandidateVerStr.c_str()); -- cgit v1.2.3 From 592d06b6f3c2ef2ae47c38005ae3c4e96a0841f2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 5 Sep 2014 12:50:15 +0200 Subject: Ensure we have a Policy in CacheFile.BuildDepCache() This partly reverts d059cc2 and fixes bug #753297 in a more general way by ensuring that CacheFile.BuildDepCache() builds a pkgPolicy if there isn't one already. --- apt-private/private-output.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 2120b7a83..522f7682d 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -229,10 +229,7 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ std::string CandidateVerStr = GetCandidateVersion(CacheFile, P); std::string InstalledVerStr = GetInstalledVersion(CacheFile, P); std::string StatusStr; - if(P.CurrentVer() == V && - state.Upgradable() && - state.CandidateVer != NULL && - policy->GetCandidateVer(P) != P.CurrentVer()) + if(P.CurrentVer() == V && state.Upgradable()) { strprintf(StatusStr, _("[installed,upgradable to: %s]"), CandidateVerStr.c_str()); -- cgit v1.2.3 From 2409df55f65c4937ceda21ba069eec769af9e460 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 1 Sep 2014 21:43:15 +0200 Subject: use a format string in ListSingleVersion The method already deals with a format string, but had an else path doing a hardcoded format as well. This is changed now to use the same code for both - the format in the second case is still fixed though. Git-Dch: Ignore --- apt-private/private-output.cc | 147 +++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 72 deletions(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 522f7682d..7be56de2e 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -164,15 +164,26 @@ static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator /*}}}*/ static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/ { - pkgPolicy *policy = CacheFile.GetPolicy(); - pkgCache::VerIterator inst = P.CurrentVer(); - pkgCache::VerIterator cand = policy->GetCandidateVer(P); - - // this may happen for packages in dpkg "deinstall ok config-file" state - if (inst.IsGood() == false && cand.IsGood() == false) - return P.VersionList().Arch(); - - return inst ? inst.Arch() : cand.Arch(); + if (P->CurrentVer == 0) + { + pkgDepCache * const DepCache = CacheFile.GetDepCache(); + pkgDepCache::StateCache const &state = (*DepCache)[P]; + if (state.CandidateVer != NULL) + { + pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer); + return CandV.Arch(); + } + else + { + pkgCache::VerIterator const V = P.VersionList(); + if (V.end() == false) + return V.Arch(); + else + return P.Arch(); + } + } + else + return P.CurrentVer().Arch(); } /*}}}*/ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/ @@ -200,77 +211,69 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ pkgCache::VerIterator V, std::ostream &out, bool include_summary) { - pkgCache::PkgIterator P = V.ParentPkg(); - - pkgDepCache *DepCache = CacheFile.GetDepCache(); - pkgDepCache::StateCache &state = (*DepCache)[P]; - - std::string suite = GetArchiveSuite(CacheFile, V); - std::string name_str = P.Name(); + pkgCache::PkgIterator const P = V.ParentPkg(); + pkgDepCache * const DepCache = CacheFile.GetDepCache(); + pkgDepCache::StateCache const &state = (*DepCache)[P]; + std::string output; if (_config->FindB("APT::Cmd::use-format", false)) + output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}"); + else { - std::string format = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}"); - std::string output = format; - - output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P)); - output = SubstVar(output, "${Package}", name_str); - output = SubstVar(output, "${installed:Version}", GetInstalledVersion(CacheFile, P)); - output = SubstVar(output, "${candidate:Version}", GetCandidateVersion(CacheFile, P)); - output = SubstVar(output, "${Version}", GetVersion(CacheFile, V)); - output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); - output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V)); - out << output; - } else { - // raring/linux-kernel version [upradable: new-version] + // linux-kernel/unstable version [installed,upradable to: new-version] // description - pkgPolicy *policy = CacheFile.GetPolicy(); - std::string VersionStr = GetVersion(CacheFile, V); - std::string CandidateVerStr = GetCandidateVersion(CacheFile, P); - std::string InstalledVerStr = GetInstalledVersion(CacheFile, P); - std::string StatusStr; - if(P.CurrentVer() == V && state.Upgradable()) + output = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture} ${apt:Status}"; + } + + // FIXME: some of these names are really icky – and all is nowhere documented + output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P)); + output = SubstVar(output, "${Package}", P.Name()); + std::string const ArchStr = GetArchitecture(CacheFile, P); + output = SubstVar(output, "${Architecture}", ArchStr); + std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P); + output = SubstVar(output, "${installed:Version}", InstalledVerStr); + std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P); + output = SubstVar(output, "${candidate:Version}", CandidateVerStr); + std::string const VersionStr = GetVersion(CacheFile, V); + output = SubstVar(output, "${Version}", VersionStr); + output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V)); + + std::string StatusStr = ""; + if (P->CurrentVer != 0) + { + if (P.CurrentVer() == V) { - strprintf(StatusStr, _("[installed,upgradable to: %s]"), - CandidateVerStr.c_str()); - } else if (P.CurrentVer() == V) { - if(!V.Downloadable()) - StatusStr = _("[installed,local]"); - else - if(V.Automatic() && state.Garbage) - StatusStr = _("[installed,auto-removable]"); - else if (state.Flags & pkgCache::Flag::Auto) - StatusStr = _("[installed,automatic]"); - else - StatusStr = _("[installed]"); - } else if (P.CurrentVer() && - policy->GetCandidateVer(P) == V && - state.Upgradable()) { - strprintf(StatusStr, _("[upgradable from: %s]"), - InstalledVerStr.c_str()); - } else { - if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles) - StatusStr = _("[residual-config]"); - else - StatusStr = ""; + if (state.Upgradable() && state.CandidateVer != NULL) + strprintf(StatusStr, _("[installed,upgradable to: %s]"), + CandidateVerStr.c_str()); + else if (V.Downloadable() == false) + StatusStr = _("[installed,local]"); + else if(V.Automatic() == true && state.Garbage == true) + StatusStr = _("[installed,auto-removable]"); + else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) + StatusStr = _("[installed,automatic]"); + else + StatusStr = _("[installed]"); } - out << std::setiosflags(std::ios::left) - << _config->Find("APT::Color::Highlight", "") - << name_str - << _config->Find("APT::Color::Neutral", "") - << "/" << suite - << " " - << VersionStr << " " - << GetArchitecture(CacheFile, P); - if (StatusStr != "") - out << " " << StatusStr; + else if (state.CandidateVer == V && state.Upgradable()) + strprintf(StatusStr, _("[upgradable from: %s]"), + InstalledVerStr.c_str()); + } + else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles) + StatusStr = _("[residual-config]"); + output = SubstVar(output, "${apt:Status}", StatusStr); + output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", "")); + output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", "")); + + output = APT::String::Strip(output); + if (_config->FindB("APT::Cmd::use-format", false) == false) + { if (include_summary) - { - out << std::endl - << " " << GetShortDescription(CacheFile, records, P) - << std::endl; - } + output += "\n ${Description}\n"; } + output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); + + out << output; } /*}}}*/ // ShowList - Show a list /*{{{*/ -- cgit v1.2.3 From 1a68655de92fd036ebc7c920bc2e5e88c54eb34e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 2 Sep 2014 14:32:48 +0200 Subject: implement --full in apt search --- apt-private/private-output.cc | 45 +++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'apt-private/private-output.cc') diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 7be56de2e..fc76a05bc 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -207,9 +207,31 @@ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &reco return ShortDescription; } /*}}}*/ +static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/ +{ + pkgPolicy *policy = CacheFile.GetPolicy(); + + pkgCache::VerIterator ver; + if (P->CurrentVer != 0) + ver = P.CurrentVer(); + else + ver = policy->GetCandidateVer(P); + + std::string const EmptyDescription = "(none)"; + if(ver.end() == true) + 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 "); +} + /*}}}*/ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ - pkgCache::VerIterator V, std::ostream &out, - bool include_summary) + pkgCache::VerIterator const &V, std::ostream &out, + std::string const &format) { pkgCache::PkgIterator const P = V.ParentPkg(); pkgDepCache * const DepCache = CacheFile.GetDepCache(); @@ -219,11 +241,7 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ if (_config->FindB("APT::Cmd::use-format", false)) output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}"); else - { - // linux-kernel/unstable version [installed,upradable to: new-version] - // description - output = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture} ${apt:Status}"; - } + output = format; // FIXME: some of these names are really icky – and all is nowhere documented output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P)); @@ -264,14 +282,13 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ output = SubstVar(output, "${apt:Status}", StatusStr); output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", "")); output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", "")); - - output = APT::String::Strip(output); - if (_config->FindB("APT::Cmd::use-format", false) == false) - { - if (include_summary) - output += "\n ${Description}\n"; - } output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); + output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P)); + output = SubstVar(output, "${ }${ }", "${ }"); + output = SubstVar(output, "${ }\n", "\n"); + output = SubstVar(output, "${ }", " "); + if (APT::String::Endswith(output, " ") == true) + output.erase(output.length() - 1); out << output; } -- cgit v1.2.3