]> git.saurik.com Git - apt.git/commitdiff
show or-groups in not-installed recommends and suggests lists
authorDavid Kalnischkies <david@kalnischkies.de>
Mon, 13 Jul 2015 01:36:59 +0000 (03:36 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Mon, 10 Aug 2015 15:27:18 +0000 (17:27 +0200)
Further abstracting our new ShowList allows to use it for containers of
strings as well giving us the option to implement an or-groups display
for the recommends and suggests lists which is a nice trick given that
it also helps with migrating the last remaining other cases of old
ShowList.

18 files changed:
apt-pkg/cachefile.cc
apt-pkg/cachefile.h
apt-pkg/cacheset.cc
apt-pkg/cacheset.h
apt-pkg/depcache.cc
apt-private/private-cachefile.h
apt-private/private-download.cc
apt-private/private-download.h
apt-private/private-install.cc
apt-private/private-output.cc
apt-private/private-output.h
cmdline/apt-get.cc
test/integration/test-apt-showlist-orgroup-in-recommends [new file with mode: 0755]
test/integration/test-bug-470115-new-and-tighten-recommends
test/integration/test-bug-549968-install-depends-of-not-installed
test/integration/test-handling-broken-orgroups
test/integration/test-release-candidate-switching
test/integration/test-releasefile-verification

index 690776266c96e3d5741688f1b2632fe605300bc8..ed3c2dd0a538ae36db332850c6c666c3c193f7dd 100644 (file)
 #include <apti18n.h>
                                                                        /*}}}*/
 // CacheFile::CacheFile - Constructor                                  /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL),
-                               SrcList(NULL), Policy(NULL)
+pkgCacheFile::pkgCacheFile() : d(NULL), ExternOwner(false), Map(NULL), Cache(NULL),
+                               DCache(NULL), SrcList(NULL), Policy(NULL)
+{
+}
+pkgCacheFile::pkgCacheFile(pkgDepCache * const Owner) : d(NULL), ExternOwner(true),
+   Map(&Owner->GetCache().GetMap()), Cache(&Owner->GetCache()),
+   DCache(Owner), SrcList(NULL), Policy(NULL)
 {
 }
                                                                        /*}}}*/
@@ -47,12 +50,16 @@ pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL),
 /* */
 pkgCacheFile::~pkgCacheFile()
 {
-   delete DCache;
+   if (ExternOwner == false)
+   {
+      delete DCache;
+      delete Cache;
+      delete Map;
+   }
    delete Policy;
    delete SrcList;
-   delete Cache;
-   delete Map;
-   _system->UnLock(true);
+   if (ExternOwner == false)
+      _system->UnLock(true);
 }
                                                                        /*}}}*/
 // CacheFile::BuildCaches - Open and build the cache files             /*{{{*/
@@ -229,11 +236,16 @@ void pkgCacheFile::RemoveCaches()
 /* */
 void pkgCacheFile::Close()
 {
-   delete DCache;
+   if (ExternOwner == false)
+   {
+      delete DCache;
+      delete Cache;
+      delete Map;
+   }
+   else
+      ExternOwner = false;
    delete Policy;
-   delete Cache;
    delete SrcList;
-   delete Map;
    _system->UnLock(true);
 
    Map = NULL;
index 83dd90d3671b5eaa0bf8ed3b81e007af7f1c56fc..f4cadf5e6ad1f46ab6c0940fc876d60c886de250 100644 (file)
@@ -38,9 +38,9 @@ class pkgCacheFile
 {
    /** \brief dpointer placeholder (for later in case we need it) */
    void * const d;
+   bool ExternOwner;
 
    protected:
-   
    MMap *Map;
    pkgCache *Cache;
    pkgDepCache *DCache;
@@ -50,18 +50,18 @@ class pkgCacheFile
    pkgPolicy *Policy;
 
    // We look pretty much exactly like a pointer to a dep cache
-   inline operator pkgCache &() {return *Cache;};
-   inline operator pkgCache *() {return Cache;};
-   inline operator pkgDepCache &() {return *DCache;};
-   inline operator pkgDepCache *() {return DCache;};
-   inline operator pkgPolicy &() {return *Policy;};
-   inline operator pkgPolicy *() {return Policy;};
-   inline operator pkgSourceList &() {return *SrcList;};
-   inline operator pkgSourceList *() {return SrcList;};
-   inline pkgDepCache *operator ->() {return DCache;};
-   inline pkgDepCache &operator *() {return *DCache;};
-   inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];};
-   inline unsigned char &operator [](pkgCache::DepIterator const &I) {return (*DCache)[I];};
+   inline operator pkgCache &() const {return *Cache;};
+   inline operator pkgCache *() const {return Cache;};
+   inline operator pkgDepCache &() const {return *DCache;};
+   inline operator pkgDepCache *() const {return DCache;};
+   inline operator pkgPolicy &() const {return *Policy;};
+   inline operator pkgPolicy *() const {return Policy;};
+   inline operator pkgSourceList &() const {return *SrcList;};
+   inline operator pkgSourceList *() const {return SrcList;};
+   inline pkgDepCache *operator ->() const {return DCache;};
+   inline pkgDepCache &operator *() const {return *DCache;};
+   inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) const {return (*DCache)[I];};
+   inline unsigned char &operator [](pkgCache::DepIterator const &I) const {return (*DCache)[I];};
 
    bool BuildCaches(OpProgress *Progress = NULL,bool WithLock = true);
    APT_DEPRECATED bool BuildCaches(OpProgress &Progress,bool const &WithLock = true) { return BuildCaches(&Progress, WithLock); };
@@ -85,6 +85,7 @@ class pkgCacheFile
    inline bool IsSrcListBuilt() const { return (SrcList != NULL); };
 
    pkgCacheFile();
+   explicit pkgCacheFile(pkgDepCache * const Owner);
    virtual ~pkgCacheFile();
 };
 
index a4e330a0a9525bb4f0614c12c4c38a8d9447f937..f5cf5215970f721182c28e62def1f7c2f5f4b947 100644 (file)
@@ -582,6 +582,116 @@ bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vc
        return found;
 }
                                                                        /*}}}*/
+// FromDependency - versions satisfying a given dependency             /*{{{*/
+bool VersionContainerInterface::FromDependency(VersionContainerInterface * const vci,
+                                              pkgCacheFile &Cache,
+                                              pkgCache::DepIterator const &D,
+                                              CacheSetHelper::VerSelector const selector,
+                                              CacheSetHelper &helper)
+{
+       bool found = false;
+       switch(selector) {
+       case CacheSetHelper::ALL:
+       {
+               pkgCache::PkgIterator const T = D.TargetPkg();
+               for (pkgCache::VerIterator Ver = T.VersionList(); Ver.end() == false; ++Ver)
+               {
+                  if (D.IsSatisfied(Ver) == true)
+                  {
+                     vci->insert(Ver);
+                     found = true;
+                  }
+                  for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv)
+                  {
+                     pkgCache::VerIterator const V = Prv.OwnerVer();
+                     if (unlikely(V.end() == true) || D.IsSatisfied(Prv) == false)
+                        continue;
+                     vci->insert(V);
+                     found = true;
+                  }
+               }
+               return found;
+       }
+       case CacheSetHelper::CANDANDINST:
+       {
+               found = FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper);
+               found &= FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper);
+               return found;
+       }
+       case CacheSetHelper::CANDIDATE:
+       {
+               pkgCache::PkgIterator const T = D.TargetPkg();
+               pkgCache::VerIterator const Cand = Cache[T].CandidateVerIter(Cache);
+               if (Cand.end() == false && D.IsSatisfied(Cand) == true)
+               {
+                  vci->insert(Cand);
+                  found = true;
+               }
+               for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv)
+               {
+                  pkgCache::VerIterator const V = Prv.OwnerVer();
+                  pkgCache::VerIterator const Cand = Cache[Prv.OwnerPkg()].CandidateVerIter(Cache);
+                  if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false)
+                     continue;
+                  vci->insert(Cand);
+                  found = true;
+               }
+               return found;
+       }
+       case CacheSetHelper::INSTALLED:
+       {
+               pkgCache::PkgIterator const T = D.TargetPkg();
+               pkgCache::VerIterator const Cand = T.CurrentVer();
+               if (Cand.end() == false && D.IsSatisfied(Cand) == true)
+               {
+                  vci->insert(Cand);
+                  found = true;
+               }
+               for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv)
+               {
+                  pkgCache::VerIterator const V = Prv.OwnerVer();
+                  pkgCache::VerIterator const Cand = Prv.OwnerPkg().CurrentVer();
+                  if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false)
+                     continue;
+                  vci->insert(Cand);
+                  found = true;
+               }
+               return found;
+       }
+       case CacheSetHelper::CANDINST:
+               return FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper) ||
+                  FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper);
+       case CacheSetHelper::INSTCAND:
+               return FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper) ||
+                  FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper);
+       case CacheSetHelper::NEWEST:
+       {
+               pkgCache::PkgIterator const T = D.TargetPkg();
+               pkgCache::VerIterator const Cand = T.VersionList();
+               if (Cand.end() == false && D.IsSatisfied(Cand) == true)
+               {
+                  vci->insert(Cand);
+                  found = true;
+               }
+               for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv)
+               {
+                  pkgCache::VerIterator const V = Prv.OwnerVer();
+                  pkgCache::VerIterator const Cand = Prv.OwnerPkg().VersionList();
+                  if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false)
+                     continue;
+                  vci->insert(Cand);
+                  found = true;
+               }
+               return found;
+       }
+       case CacheSetHelper::RELEASE:
+       case CacheSetHelper::VERSIONNUMBER:
+               // both make no sense here, so always false
+               return false;
+       }
+       return found;
+}
+                                                                       /*}}}*/
 // getCandidateVer - Returns the candidate version of the given package        /*{{{*/
 pkgCache::VerIterator VersionContainerInterface::getCandidateVer(pkgCacheFile &Cache,
                pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) {
index 0b9b9441c1fec24fab59cb6a9f3c0ca7ebf2497b..5455fe74b383a115acc5e1437d40be114948fbe9 100644 (file)
@@ -1068,7 +1068,7 @@ APT_IGNORE_DEPRECATED_POP
        static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
                                               CacheSetHelper::VerSelector const selector) {
                CacheSetHelper helper;
-               return FromPackage(Cache, D, selector, helper);
+               return FromDependency(Cache, D, selector, helper);
        }
 APT_IGNORE_DEPRECATED_PUSH
        static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
@@ -1080,11 +1080,11 @@ APT_IGNORE_DEPRECATED_PUSH
        static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D,
                                               Version const &selector) {
                CacheSetHelper helper;
-               return FromPackage(Cache, D, (CacheSetHelper::VerSelector)selector, helper);
+               return FromDependency(Cache, D, (CacheSetHelper::VerSelector)selector, helper);
        }
 APT_IGNORE_DEPRECATED_POP
        static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) {
-               return FromPackage(Cache, D, CacheSetHelper::CANDIDATE);
+               return FromDependency(Cache, D, CacheSetHelper::CANDIDATE);
        }
                                                                        /*}}}*/
 };                                                                     /*}}}*/
index d01c142239b112cd569640d0fd0a6dd95631d459..0e972dbad65fde202f98272a7045cb5883c35636 100644 (file)
@@ -23,6 +23,7 @@
 #include <apt-pkg/cacheset.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
+#include <apt-pkg/cachefile.h>
 #include <apt-pkg/macros.h>
 
 #include <stdio.h>
@@ -1189,18 +1190,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
          fixing the problem for "positive" dependencies */
       if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer)
       {
-        APT::VersionList verlist;
-        pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this);
-        if (Cand.end() == false && Start.IsSatisfied(Cand) == true)
-           verlist.insert(Cand);
-        for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv)
-        {
-           pkgCache::VerIterator V = Prv.OwnerVer();
-           pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this);
-           if (Cand.end() == true || V != Cand || Start.IsSatisfied(Prv) == false)
-              continue;
-           verlist.insert(Cand);
-        }
+        pkgCacheFile CacheFile(this);
+        APT::VersionList verlist = APT::VersionList::FromDependency(CacheFile, Start, APT::CacheSetHelper::CANDIDATE);
         CompareProviders comp(Start);
 
         do {
index 4a68d973314d4f62dbb03dcdd09349f4d7396106..22185262930d43281519996e91a7bba343153f81 100644 (file)
@@ -61,7 +61,7 @@ class APT_PUBLIC CacheFile : public pkgCacheFile
 };
                                                                        /*}}}*/
 
-class APT_PUBLIC SortedPackageUniverse : public APT::PackageUniverse
+class SortedPackageUniverse : public APT::PackageUniverse
 {
    std::vector<map_pointer_t> &List;
    void LazyInit() const;
@@ -85,12 +85,12 @@ public:
    };
    typedef const_iterator iterator;
 
-   APT_PUBLIC const_iterator begin() const { LazyInit(); return const_iterator(data(), List.begin()); }
-   APT_PUBLIC const_iterator end() const { LazyInit(); return const_iterator(data(), List.end()); }
-   APT_PUBLIC const_iterator cbegin() const { LazyInit(); return const_iterator(data(), List.begin()); }
-   APT_PUBLIC const_iterator cend() const { LazyInit(); return const_iterator(data(), List.end()); }
-   APT_PUBLIC iterator begin() { LazyInit(); return iterator(data(), List.begin()); }
-   APT_PUBLIC iterator end() { LazyInit(); return iterator(data(), List.end()); }
+   const_iterator begin() const { LazyInit(); return const_iterator(data(), List.begin()); }
+   const_iterator end() const { LazyInit(); return const_iterator(data(), List.end()); }
+   const_iterator cbegin() const { LazyInit(); return const_iterator(data(), List.begin()); }
+   const_iterator cend() const { LazyInit(); return const_iterator(data(), List.end()); }
+   iterator begin() { LazyInit(); return iterator(data(), List.begin()); }
+   iterator end() { LazyInit(); return iterator(data(), List.end()); }
 };
 
 #endif
index 37fae18e91633c9d22bd3bbff375744b9186566e..09914618760ef9311742efa0de46b18666f5aadb 100644 (file)
@@ -78,20 +78,23 @@ bool CheckDropPrivsMustBeDisabled(pkgAcquire &Fetcher)                      /*{{{*/
 // CheckAuth - check if each download comes form a trusted source      /*{{{*/
 bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser)
 {
-   std::string UntrustedList;
+   std::vector<std::string> UntrustedList;
    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
       if (!(*I)->IsTrusted())
-          UntrustedList += std::string((*I)->ShortDesc()) + " ";
+        UntrustedList.push_back((*I)->ShortDesc());
 
-   if (UntrustedList == "")
+   if (UntrustedList.empty())
       return true;
 
    return AuthPrompt(UntrustedList, PromptUser);
 }
 
-bool AuthPrompt(std::string const &UntrustedList, bool const PromptUser)
+bool AuthPrompt(std::vector<std::string> const &UntrustedList, bool const PromptUser)
 {
-   ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
+   ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"), UntrustedList,
+        [](std::string const&) { return true; },
+        [](std::string const&str) { return str; },
+        [](std::string const&) { return ""; });
 
    if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
    {
index 0a0ac6b95f7c151e36658de8e70e414355b416f8..0f3db5e7a0f67451f07a0a55a5cc537c3a963abf 100644 (file)
@@ -4,6 +4,7 @@
 #include <apt-pkg/macros.h>
 
 #include <string>
+#include <vector>
 
 class pkgAcquire;
 
@@ -14,7 +15,7 @@ APT_PUBLIC bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser);
 
 // show a authentication warning prompt and return true if the system
 // should continue
-APT_PUBLIC bool AuthPrompt(std::string const &UntrustedList, bool const PromptUser);
+APT_PUBLIC bool AuthPrompt(std::vector<std::string> const &UntrustedList, bool const PromptUser);
 
 APT_PUBLIC bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure);
 
index cdca457553a0fb067556f7f735eb12892b9e6b88..0b5e33ae5d70b09539deda2f347dae53f4f44992 100644 (file)
@@ -330,19 +330,17 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
    }
 
    std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
-   if (disappearedPkgs.empty() == true)
-      return true;
-
-   std::string disappear;
-   for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
-       d != disappearedPkgs.end(); ++d)
-      disappear.append(*d).append(" ");
-
-   ShowList(c1out, P_("The following package disappeared from your system as\n"
-       "all files have been overwritten by other packages:",
-       "The following packages disappeared from your system as\n"
-       "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
-   c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
+   if (disappearedPkgs.empty() == false)
+   {
+      ShowList(c1out, P_("The following package disappeared from your system as\n"
+              "all files have been overwritten by other packages:",
+              "The following packages disappeared from your system as\n"
+              "all files have been overwritten by other packages:", disappearedPkgs.size()), disappearedPkgs,
+           [](std::string const &Pkg) { return Pkg.empty() == false; },
+           [](std::string const &Pkg) { return Pkg; },
+           [](std::string const &) { return std::string(); });
+      c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
+   }
 
    return true;
 }
@@ -699,8 +697,7 @@ bool DoInstall(CommandLine &CmdL)
 
    /* Print out a list of suggested and recommended packages */
    {
-      std::string SuggestsList, RecommendsList;
-      std::string SuggestsVersions, RecommendsVersions;
+      std::list<std::string> Recommends, Suggests, SingleRecommends, SingleSuggests;
       for (auto const &Pkg: Universe)
       {
         /* Just look at the ones we want to install */
@@ -714,77 +711,79 @@ bool DoInstall(CommandLine &CmdL)
            pkgCache::DepIterator Start;
            pkgCache::DepIterator End;
            D.GlobOr(Start,End); // advances D
+           if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests)
+              continue;
 
-           // FIXME: we really should display a or-group as a or-group to the user
-           //        the problem is that ShowList is incapable of doing this
-            std::string RecommendsOrList,RecommendsOrVersions;
-            std::string SuggestsOrList,SuggestsOrVersions;
-           bool foundInstalledInOrGroup = false;
-           for(;;)
            {
-              /* Skip if package is  installed already, or is about to be */
-              pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
-              if (TarPkg->SelectedState == pkgCache::State::Install ||
-                  TarPkg->SelectedState == pkgCache::State::Hold ||
-                  Cache[Start.TargetPkg()].Install())
-              {
-                 foundInstalledInOrGroup=true;
-                 break;
-              }
-
-              /* Skip if we already saw it */
-               std::string target = Start.TargetPkg().FullName(true) + " ";
-              if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
+              // Skip if we already saw this
+              std::string target;
+              for (pkgCache::DepIterator I = Start; I != D; ++I)
               {
-                 foundInstalledInOrGroup=true;
-                 break; 
+                 if (target.empty() == false)
+                    target.append(" | ");
+                 target.append(I.TargetPkg().FullName(true));
               }
+              std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? SingleRecommends : SingleSuggests;
+              if (std::find(Type.begin(), Type.end(), target) != Type.end())
+                 continue;
+              Type.push_back(target);
+           }
 
-              // this is a dep on a virtual pkg, check if any package that provides it
-              // should be installed
-              if(Start.TargetPkg().ProvidesList() != 0)
+           std::list<std::string> OrList;
+           bool foundInstalledInOrGroup = false;
+           for (pkgCache::DepIterator I = Start; I != D; ++I)
+           {
               {
-                 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
-                 for (; I.end() == false; ++I)
+                 // satisfying package is installed and not marked for deletion
+                 APT::VersionList installed = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::INSTALLED);
+                 if (std::find_if(installed.begin(), installed.end(),
+                          [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Delete() == false; }) != installed.end())
                  {
-                    pkgCache::PkgIterator Pkg = I.OwnerPkg();
-                    if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && 
-                        Pkg.CurrentVer() != 0)
-                       foundInstalledInOrGroup=true;
+                    foundInstalledInOrGroup = true;
+                    break;
                  }
               }
 
-              if (Start->Type == pkgCache::Dep::Suggests) 
-              {
-                 SuggestsOrList += target;
-                 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
-              }
-              
-              if (Start->Type == pkgCache::Dep::Recommends) 
               {
-                 RecommendsOrList += target;
-                 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+                 // satisfying package is upgraded to/new install
+                 APT::VersionList upgrades = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::CANDIDATE);
+                 if (std::find_if(upgrades.begin(), upgrades.end(),
+                          [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Upgrade(); }) != upgrades.end())
+                 {
+                    foundInstalledInOrGroup = true;
+                    break;
+                 }
               }
 
-              if (Start >= End)
-                 break;
-              ++Start;
+              if (OrList.empty())
+                 OrList.push_back(I.TargetPkg().FullName(true));
+              else
+                 OrList.push_back("| " + I.TargetPkg().FullName(true));
            }
-           
+
            if(foundInstalledInOrGroup == false)
            {
-              RecommendsList += RecommendsOrList;
-              RecommendsVersions += RecommendsOrVersions;
-              SuggestsList += SuggestsOrList;
-              SuggestsVersions += SuggestsOrVersions;
+              std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests;
+              std::move(OrList.begin(), OrList.end(), std::back_inserter(Type));
            }
-              
         }
       }
-
-      ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
-      ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
-
+      auto always_true = [](std::string const&) { return true; };
+      auto string_ident = [](std::string const&str) { return str; };
+      auto verbose_show_candidate =
+        [&Cache](std::string str)
+        {
+           if (APT::String::Startswith(str, "| "))
+              str.erase(0, 2);
+           pkgCache::PkgIterator const Pkg = Cache->FindPkg(str);
+           if (Pkg.end() == true)
+              return "";
+           return (*Cache)[Pkg].CandVersion;
+        };
+      ShowList(c1out,_("Suggested packages:"), Suggests,
+           always_true, string_ident, verbose_show_candidate);
+      ShowList(c1out,_("Recommended packages:"), Recommends,
+           always_true, string_ident, verbose_show_candidate);
    }
 
    // See if we need to prompt
@@ -792,7 +791,7 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
 
-   return InstallPackages(Cache,false);   
+   return InstallPackages(Cache,false);
 }
                                                                        /*}}}*/
 
index b77efff86a11693d8d2f0cfda5d2c7c475d87de1..b8e6dec029b30287b485497d5c1cf7b2c0a0ffe0 100644 (file)
@@ -300,66 +300,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
index b9151b245a0426d9c7732f071c08e041ad75897e..4930fd981d58f89dcf765d20214a70754ad72b51 100644 (file)
@@ -34,11 +34,11 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
 APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool const Now);
 APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache, bool const Now);
 
-template<class Container> APT_PUBLIC bool ShowList(std::ostream &out, std::string const &Title,
+template<class Container, class PredicateC, class DisplayP, class DisplayV> APT_PUBLIC bool ShowList(std::ostream &out, std::string const &Title,
       Container const &cont,
-      std::function<bool(pkgCache::PkgIterator const &)> Predicate,
-      std::function<std::string(pkgCache::PkgIterator const &)> PkgDisplay,
-      std::function<std::string(pkgCache::PkgIterator const &)> VerboseDisplay)
+      PredicateC Predicate,
+      DisplayP PkgDisplay,
+      DisplayV VerboseDisplay)
 {
    size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3 : 0;
    int ScreenUsed = 0;
@@ -88,8 +88,6 @@ template<class Container> APT_PUBLIC bool ShowList(std::ostream &out, std::strin
    }
    return true;
 }
-APT_DEPRECATED APT_PUBLIC bool ShowList(std::ostream &out, std::string Title, std::string List,
-              std::string VersionsList);
 
 void ShowNew(std::ostream &out,CacheFile &Cache);
 void ShowDel(std::ostream &out,CacheFile &Cache);
@@ -106,12 +104,12 @@ void Stats(std::ostream &out, pkgDepCache &Dep);
 bool YnPrompt(bool Default=true);
 bool AnalPrompt(const char *Text);
 
-APT_PUBLIC std::string PrettyFullName(pkgCache::PkgIterator const &Pkg);
-APT_PUBLIC std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg);
-APT_PUBLIC std::function<std::string(pkgCache::PkgIterator const &)> CandidateVersion(pkgCacheFile * const Cache);
-APT_PUBLIC std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg);
-APT_PUBLIC std::function<std::string(pkgCache::PkgIterator const &)> CurrentToCandidateVersion(pkgCacheFile * const Cache);
-APT_PUBLIC std::string EmptyString(pkgCache::PkgIterator const &);
-APT_PUBLIC bool AlwaysTrue(pkgCache::PkgIterator const &);
+std::string PrettyFullName(pkgCache::PkgIterator const &Pkg);
+std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg);
+std::function<std::string(pkgCache::PkgIterator const &)> CandidateVersion(pkgCacheFile * const Cache);
+std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg);
+std::function<std::string(pkgCache::PkgIterator const &)> CurrentToCandidateVersion(pkgCacheFile * const Cache);
+std::string EmptyString(pkgCache::PkgIterator const &);
+bool AlwaysTrue(pkgCache::PkgIterator const &);
 
 #endif
index 6fefbde47a6faaa59c32a768adc497f4f707d10f..ca96509984f3b6c1fae20e96bfce77fc7402f6df 100644 (file)
@@ -742,7 +742,7 @@ static bool DoSource(CommandLine &CmdL)
 
    // Load the requestd sources into the fetcher
    unsigned J = 0;
-   std::string UntrustedList;
+   std::vector<std::string> UntrustedList;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
    {
       string Src;
@@ -756,8 +756,8 @@ static bool DoSource(CommandLine &CmdL)
       }
 
       if (Last->Index().IsTrusted() == false)
-         UntrustedList += Src + " ";
-      
+         UntrustedList.push_back(Src);
+
       string srec = Last->AsStr();
       string::size_type pos = srec.find("\nVcs-");
       while (pos != string::npos)
@@ -884,7 +884,7 @@ static bool DoSource(CommandLine &CmdL)
    CheckDropPrivsMustBeDisabled(Fetcher);
 
    // check authentication status of the source as well
-   if (UntrustedList != "" && !AuthPrompt(UntrustedList, false))
+   if (UntrustedList.empty() == false && AuthPrompt(UntrustedList, false) == false)
       return false;
 
    // Run it
diff --git a/test/integration/test-apt-showlist-orgroup-in-recommends b/test/integration/test-apt-showlist-orgroup-in-recommends
new file mode 100755 (executable)
index 0000000..bce421a
--- /dev/null
@@ -0,0 +1,158 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'i386'
+
+# simple case
+insertinstalledpackage 'aaa' 'all' '1'
+insertinstalledpackage 'ddd' 'all' '1'
+insertpackage 'unstable' 'aaa' 'all' '1'
+insertpackage 'unstable' 'ddd' 'all' '1'
+insertpackage 'unstable' 'yyy' 'all' '1'
+insertpackage 'unstable' 'zzz' 'all' '1'
+insertpackage 'unstable' 'simple' 'all' '1' 'Recommends: aaa, bbb
+Suggests: ccc, ddd'
+insertpackage 'unstable' 'orgroup' 'all' '1' 'Recommends: aaa | bbb
+Suggests: ccc | ddd'
+insertpackage 'unstable' 'orgroup2' 'all' '1' 'Recommends: xxx | yyy
+Suggests: yyy | zzz'
+insertpackage 'unstable' 'orgroup3' 'all' '1' 'Recommends: xxx | yyy
+Suggests: yyy | zzz'
+insertpackage 'unstable' 'orgroup4' 'all' '1' 'Recommends: xxx
+Suggests: zzz'
+insertpackage 'unstable' 'versionedor' 'all' '1' 'Recommends: aaa (>> 2) | bbb
+Suggests: ccc | ddd (>> 2)'
+
+setupaptarchive
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  ccc
+Recommended packages:
+  bbb
+The following NEW packages will be installed:
+  simple
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst simple (1 unstable [all])
+Conf simple (1 unstable [all])' aptget install simple -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  ccc
+Recommended packages:
+  aaa bbb
+The following packages will be REMOVED:
+  aaa
+The following NEW packages will be installed:
+  simple
+0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
+Remv aaa [1]
+Inst simple (1 unstable [all])
+Conf simple (1 unstable [all])' aptget install simple aaa- -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  orgroup
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup (1 unstable [all])
+Conf orgroup (1 unstable [all])' aptget install orgroup -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Recommended packages:
+  aaa | bbb
+The following packages will be REMOVED:
+  aaa
+The following NEW packages will be installed:
+  orgroup
+0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
+Remv aaa [1]
+Inst orgroup (1 unstable [all])
+Conf orgroup (1 unstable [all])' aptget install orgroup aaa- -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  yyy | zzz
+Recommended packages:
+  xxx | yyy
+The following NEW packages will be installed:
+  orgroup2
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup2 (1 unstable [all])
+Conf orgroup2 (1 unstable [all])' aptget install orgroup2 -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  yyy | zzz
+Recommended packages:
+  xxx | yyy
+The following NEW packages will be installed:
+  orgroup2 orgroup3
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup2 (1 unstable [all])
+Inst orgroup3 (1 unstable [all])
+Conf orgroup2 (1 unstable [all])
+Conf orgroup3 (1 unstable [all])' aptget install orgroup2 orgroup3 -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  yyy | zzz zzz
+Recommended packages:
+  xxx | yyy xxx
+The following NEW packages will be installed:
+  orgroup2 orgroup4
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup2 (1 unstable [all])
+Inst orgroup4 (1 unstable [all])
+Conf orgroup2 (1 unstable [all])
+Conf orgroup4 (1 unstable [all])' aptget install orgroup2 orgroup4 -s --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+   yyy (1)
+   | zzz (1)
+   zzz (1)
+Recommended packages:
+   xxx
+   | yyy (1)
+   xxx
+The following NEW packages will be installed:
+   orgroup2 (1)
+   orgroup4 (1)
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup2 (1 unstable [all])
+Inst orgroup4 (1 unstable [all])
+Conf orgroup2 (1 unstable [all])
+Conf orgroup4 (1 unstable [all])' aptget install orgroup2 orgroup4 -s -V --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+   zzz (1)
+Recommended packages:
+   xxx
+The following NEW packages will be installed:
+   orgroup2 (1)
+   orgroup4 (1)
+   yyy (1)
+0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup2 (1 unstable [all])
+Inst orgroup4 (1 unstable [all])
+Inst yyy (1 unstable [all])
+Conf orgroup2 (1 unstable [all])
+Conf orgroup4 (1 unstable [all])
+Conf yyy (1 unstable [all])' aptget install orgroup2 orgroup4 yyy -s -V --no-install-recommends
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  ccc | ddd
+Recommended packages:
+  aaa | bbb
+The following NEW packages will be installed:
+  versionedor
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst versionedor (1 unstable [all])
+Conf versionedor (1 unstable [all])' aptget install versionedor -s --no-install-recommends
index 0970e2f23bb7229a27b43e6b03534ef76a844c01..80f699ef3b168098359054ccab499950779042cf 100755 (executable)
@@ -165,6 +165,8 @@ Conf upgrade-over-new (2 unstable [all])' aptget install upgrade-over-new -s
 # the user doesn't seem to need it so avoid upgrading it
 testsuccessequal 'Reading package lists...
 Building dependency tree...
+Recommended packages:
+  cool
 The following packages will be upgraded:
   now-satisfiable
 1 upgraded, 0 newly installed, 0 to remove and 12 not upgraded.
index 3ff4807def59051b224a6eafc5044c1e7f8de663..1d969fea2105dd6fee67fdd7070dc0790f49310f 100755 (executable)
@@ -19,6 +19,8 @@ Building dependency tree...
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
     Ignore MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) as its mode (Keep) is protected
 Package 'extracoolstuff' is not installed, so not removed
+Recommended packages:
+  extracoolstuff
 The following NEW packages will be installed:
   coolstuff
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
index 149f05fa9989ba8499fb716610748eb044837cbc..15964a270b6d49fc7422ffaddab43eeba88da4b8 100755 (executable)
@@ -63,7 +63,7 @@ E: Unable to correct problems, you have held broken packages.' aptget install co
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 Recommended packages:
-  cool2 stuff2
+  cool2 stuff2
 The following NEW packages will be installed:
   coolstuff-brokenrec
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
index a1a6a6142e6e5ea7d10c0e3001e43fd074781547..510a8e0780a2593599957c63a803099fb8d82041 100755 (executable)
@@ -370,7 +370,7 @@ The following extra packages will be installed:
 Recommended packages:
    amarok-utils (2.3.1-1+sid)
    phonon-backend-xine (4.6.0really4.4.2-1+sid)
-   phonon-backend ()
+   | phonon-backend
    libmtp8 (0.3.1+sid)
    libc6 (2.11.2-7+sid)
 The following NEW packages will be installed:
index 759242514b90a605f37e1ac75e1432108574fa1b..06701c62307f1addcd1bf6d6b4707af68037d78e 100755 (executable)
@@ -36,7 +36,7 @@ installaptold() {
        testsuccessequal 'Reading package lists...
 Building dependency tree...
 Suggested packages:
-  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+  aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt
 The following NEW packages will be installed:
   apt
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
@@ -49,7 +49,7 @@ installaptnew() {
        testsuccessequal 'Reading package lists...
 Building dependency tree...
 Suggested packages:
-  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+  aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt
 The following NEW packages will be installed:
   apt
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
@@ -62,7 +62,7 @@ failaptold() {
        testfailureequal 'Reading package lists...
 Building dependency tree...
 Suggested packages:
-  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+  aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt
 The following NEW packages will be installed:
   apt
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
@@ -76,7 +76,7 @@ failaptnew() {
        testfailureequal 'Reading package lists...
 Building dependency tree...
 Suggested packages:
-  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+  aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt
 The following NEW packages will be installed:
   apt
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.