Michael Vogt лет назад: 16
Родитель
Сommit
1b8ba3ba05

+ 54 - 0
apt-pkg/cachefilter.cc

@@ -0,0 +1,54 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/** \file cachefilter.h
+    Collection of functor classes */
+									/*}}}*/
+// Include Files							/*{{{*/
+#include <apt-pkg/cachefilter.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/pkgcache.h>
+
+#include <apti18n.h>
+
+#include <string>
+
+#include <regex.h>
+									/*}}}*/
+namespace APT {
+namespace CacheFilter {
+PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) {/*{{{*/
+	pattern = new regex_t;
+	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
+	if (Res == 0)
+		return;
+
+	delete pattern;
+	pattern = NULL;
+	char Error[300];
+	regerror(Res, pattern, Error, sizeof(Error));
+	_error->Error(_("Regex compilation error - %s"), Error);
+}
+									/*}}}*/
+bool PackageNameMatchesRegEx::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+	if (unlikely(pattern == NULL))
+		return false;
+	else
+		return regexec(pattern, Pkg.Name(), 0, 0, 0) == 0;
+}
+									/*}}}*/
+bool PackageNameMatchesRegEx::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/
+	if (unlikely(pattern == NULL))
+		return false;
+	else
+		return regexec(pattern, Grp.Name(), 0, 0, 0) == 0;
+}
+									/*}}}*/
+PackageNameMatchesRegEx::~PackageNameMatchesRegEx() {			/*{{{*/
+	if (pattern == NULL)
+		return;
+	regfree(pattern);
+	delete pattern;
+}
+									/*}}}*/
+}
+}

+ 29 - 0
apt-pkg/cachefilter.h

@@ -0,0 +1,29 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/** \file cachefilter.h
+   Collection of functor classes */
+									/*}}}*/
+#ifndef APT_CACHEFILTER_H
+#define APT_CACHEFILTER_H
+// Include Files							/*{{{*/
+#include <apt-pkg/pkgcache.h>
+
+#include <string>
+
+#include <regex.h>
+									/*}}}*/
+namespace APT {
+namespace CacheFilter {
+// PackageNameMatchesRegEx						/*{{{*/
+class PackageNameMatchesRegEx {
+	regex_t* pattern;
+public:
+	PackageNameMatchesRegEx(std::string const &Pattern);
+	bool operator() (pkgCache::PkgIterator const &Pkg);
+	bool operator() (pkgCache::GrpIterator const &Grp);
+	~PackageNameMatchesRegEx();
+};
+									/*}}}*/
+}
+}
+#endif

+ 5 - 2
apt-pkg/cacheiterators.h

@@ -115,8 +115,11 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
 	/** \brief find the package with the "best" architecture
 	/** \brief find the package with the "best" architecture
 
 
 	    The best architecture is either the "native" or the first
 	    The best architecture is either the "native" or the first
-	    in the list of Architectures which is not an end-Pointer */
-	PkgIterator FindPreferredPkg() const;
+	    in the list of Architectures which is not an end-Pointer
+
+	    \param PreferNonVirtual tries to respond with a non-virtual package
+		   and only if this fails returns the best virtual package */
+	PkgIterator FindPreferredPkg(bool const &PreferNonVirtual = true) const;
 	PkgIterator NextPkg(PkgIterator const &Pkg) const;
 	PkgIterator NextPkg(PkgIterator const &Pkg) const;
 
 
 	// Constructors
 	// Constructors

+ 12 - 16
cmdline/cacheset.cc

@@ -10,14 +10,14 @@
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/cachefilter.h>
+#include <apt-pkg/cacheset.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/versionmatch.h>
 #include <apt-pkg/versionmatch.h>
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 
 
-#include "cacheset.h"
-
 #include <vector>
 #include <vector>
 
 
 #include <regex.h>
 #include <regex.h>
@@ -97,22 +97,14 @@ PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, Cache
 			arch = "native";
 			arch = "native";
 	}
 	}
 
 
-	regex_t Pattern;
-	int Res;
-	if ((Res = regcomp(&Pattern, pattern.c_str() , REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) {
-		char Error[300];
-		regerror(Res, &Pattern, Error, sizeof(Error));
-		_error->Error(_("Regex compilation error - %s"), Error);
-		return PackageSet(REGEX);
-	}
-
 	if (unlikely(Cache.GetPkgCache() == 0))
 	if (unlikely(Cache.GetPkgCache() == 0))
 		return PackageSet(REGEX);
 		return PackageSet(REGEX);
 
 
+	APT::CacheFilter::PackageNameMatchesRegEx regexfilter(pattern);
+
 	PackageSet pkgset(REGEX);
 	PackageSet pkgset(REGEX);
-	for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp)
-	{
-		if (regexec(&Pattern, Grp.Name(), 0, 0, 0) != 0)
+	for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp) {
+		if (regexfilter(Grp) == false)
 			continue;
 			continue;
 		pkgCache::PkgIterator Pkg = Grp.FindPkg(arch);
 		pkgCache::PkgIterator Pkg = Grp.FindPkg(arch);
 		if (Pkg.end() == true) {
 		if (Pkg.end() == true) {
@@ -128,7 +120,6 @@ PackageSet PackageSet::FromRegEx(pkgCacheFile &Cache, std::string pattern, Cache
 
 
 		pkgset.insert(Pkg);
 		pkgset.insert(Pkg);
 	}
 	}
-	regfree(&Pattern);
 
 
 	if (pkgset.empty() == true)
 	if (pkgset.empty() == true)
 		return helper.canNotFindRegEx(Cache, pattern);
 		return helper.canNotFindRegEx(Cache, pattern);
@@ -332,7 +323,12 @@ APT::VersionSet VersionSet::FromString(pkgCacheFile &Cache, std::string pkg,
 			V = getInstalledVer(Cache, P, helper);
 			V = getInstalledVer(Cache, P, helper);
 		else if (ver == "candidate")
 		else if (ver == "candidate")
 			V = getCandidateVer(Cache, P, helper);
 			V = getCandidateVer(Cache, P, helper);
-		else {
+		else if (ver == "newest") {
+			if (P->VersionList != 0)
+				V = P.VersionList();
+			else
+				V = helper.canNotFindNewestVer(Cache, P);
+		} else {
 			pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
 			pkgVersionMatch Match(ver, (verIsRel == true ? pkgVersionMatch::Release :
 					pkgVersionMatch::Version));
 					pkgVersionMatch::Version));
 			V = Match.Find(P);
 			V = Match.Find(P);

cmdline/cacheset.h → apt-pkg/cacheset.h


+ 4 - 4
apt-pkg/depcache.cc

@@ -338,7 +338,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
    /* Check simple depends. A depends -should- never self match but 
    /* Check simple depends. A depends -should- never self match but 
       we allow it anyhow because dpkg does. Technically it is a packaging
       we allow it anyhow because dpkg does. Technically it is a packaging
       bug. Conflicts may never self match */
       bug. Conflicts may never self match */
-   if (Dep.TargetPkg() != Dep.ParentPkg() || 
+   if (Dep.TargetPkg()->Group != Dep.ParentPkg()->Group ||
        (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
        (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
    {
    {
       PkgIterator Pkg = Dep.TargetPkg();
       PkgIterator Pkg = Dep.TargetPkg();
@@ -367,9 +367,9 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
    PkgIterator Pkg = Dep.ParentPkg();
    PkgIterator Pkg = Dep.ParentPkg();
    for (; P.end() != true; P++)
    for (; P.end() != true; P++)
    {
    {
-      /* Provides may never be applied against the same package if it is
-         a conflicts. See the comment above. */
-      if (P.OwnerPkg() == Pkg &&
+      /* Provides may never be applied against the same package (or group)
+         if it is a conflicts. See the comment above. */
+      if (P.OwnerPkg()->Group == Pkg->Group &&
 	  (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
 	  (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
 	 continue;
 	 continue;
       
       

+ 3 - 2
apt-pkg/makefile

@@ -35,14 +35,15 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
 	 srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
 	 srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
 	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
-	 aptconfiguration.cc
+	 aptconfiguration.cc cachefilter.cc cacheset.cc
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.h \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
 	  pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
-	  vendorlist.h cdrom.h indexcopy.h aptconfiguration.h
+	  vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
+	  cachefilter.h cacheset.h
 
 
 # Source code for the debian specific components
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..
 # In theory the deb headers do not need to be exported..

+ 5 - 3
apt-pkg/pkgcache.cc

@@ -349,19 +349,21 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
 // GrpIterator::FindPreferredPkg - Locate the "best" package		/*{{{*/
 // GrpIterator::FindPreferredPkg - Locate the "best" package		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Returns an End-Pointer on error, pointer to the package otherwise */
 /* Returns an End-Pointer on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg() const {
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const {
 	pkgCache::PkgIterator Pkg = FindPkg("native");
 	pkgCache::PkgIterator Pkg = FindPkg("native");
-	if (Pkg.end() == false)
+	if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
 		return Pkg;
 		return Pkg;
 
 
 	std::vector<std::string> const archs = APT::Configuration::getArchitectures();
 	std::vector<std::string> const archs = APT::Configuration::getArchitectures();
 	for (std::vector<std::string>::const_iterator a = archs.begin();
 	for (std::vector<std::string>::const_iterator a = archs.begin();
 	     a != archs.end(); ++a) {
 	     a != archs.end(); ++a) {
 		Pkg = FindPkg(*a);
 		Pkg = FindPkg(*a);
-		if (Pkg.end() == false)
+		if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
 			return Pkg;
 			return Pkg;
 	}
 	}
 
 
+	if (PreferNonVirtual == true)
+		return FindPreferredPkg(false);
 	return PkgIterator(*Owner, 0);
 	return PkgIterator(*Owner, 0);
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 105 - 133
cmdline/apt-cache.cc

@@ -17,6 +17,7 @@
 #include <cassert>
 #include <cassert>
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefile.h>
+#include <apt-pkg/cacheset.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/progress.h>
 #include <apt-pkg/progress.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sourcelist.h>
@@ -30,8 +31,6 @@
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
 
 
-#include "cacheset.h"
-
 #include <config.h>
 #include <config.h>
 #include <apti18n.h>
 #include <apti18n.h>
 
 
@@ -552,72 +551,98 @@ bool DumpAvail(CommandLine &Cmd)
    return !_error->PendingError();
    return !_error->PendingError();
 }
 }
 									/*}}}*/
 									/*}}}*/
-// Depends - Print out a dependency tree				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool Depends(CommandLine &CmdL)
+// ShowDepends - Helper for printing out a dependency tree		/*{{{*/
+class CacheSetHelperDepends: public APT::CacheSetHelper {
+public:
+   APT::PackageSet virtualPkgs;
+
+   virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+      virtualPkgs.insert(Pkg);
+      return pkgCache::VerIterator(Cache, 0);
+   }
+
+   virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+      virtualPkgs.insert(Pkg);
+      return pkgCache::VerIterator(Cache, 0);
+   }
+
+   CacheSetHelperDepends() : CacheSetHelper(false) {}
+};
+bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
 {
 {
    pkgCacheFile CacheFile;
    pkgCacheFile CacheFile;
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgCache *Cache = CacheFile.GetPkgCache();
    if (unlikely(Cache == NULL))
    if (unlikely(Cache == NULL))
       return false;
       return false;
 
 
-   SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
-
-   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
-   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
-      Colours[Pkg->ID] = 1;
-
-   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
-   bool Installed = _config->FindB("APT::Cache::Installed",false);
-   bool Important = _config->FindB("APT::Cache::Important",false);
-   bool DidSomething;
-   do
+   CacheSetHelperDepends helper;
+   APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
+   if (verset.empty() == true && helper.virtualPkgs.empty() == true)
+      return false;
+   std::vector<bool> Shown(Cache->Head().PackageCount);
+
+   bool const Recurse = _config->FindB("APT::Cache::RecurseDepends", false);
+   bool const Installed = _config->FindB("APT::Cache::Installed", false);
+   bool const Important = _config->FindB("APT::Cache::Important", false);
+   bool const ShowDepType = _config->FindB("APT::Cache::ShowDependencyType", RevDepends == false);
+   bool const ShowPreDepends = _config->FindB("APT::Cache::ShowPre-Depends", true);
+   bool const ShowDepends = _config->FindB("APT::Cache::ShowDepends", true);
+   bool const ShowRecommends = _config->FindB("APT::Cache::ShowRecommends", Important == false);
+   bool const ShowSuggests = _config->FindB("APT::Cache::ShowSuggests", Important == false);
+   bool const ShowReplaces = _config->FindB("APT::Cache::ShowReplaces", Important == false);
+   bool const ShowConflicts = _config->FindB("APT::Cache::ShowConflicts", Important == false);
+   bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
+   bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
+   bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
+
+   while (verset.empty() != true)
    {
    {
-      DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-	 if (Colours[Pkg->ID] != 1)
-	    continue;
-	 Colours[Pkg->ID] = 2;
-	 DidSomething = true;
-	 
-	 pkgCache::VerIterator Ver = Pkg.VersionList();
-	 if (Ver.end() == true)
-	 {
-	    cout << '<' << Pkg.FullName(true) << '>' << endl;
-	    continue;
-	 }
-	 
+      pkgCache::VerIterator Ver = *verset.begin();
+      verset.erase(verset.begin());
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+      Shown[Pkg->ID] = true;
+
 	 cout << Pkg.FullName(true) << endl;
 	 cout << Pkg.FullName(true) << endl;
-	 
-	 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
+
+	 if (RevDepends == true)
+	    cout << "Reverse Depends:" << endl;
+	 for (pkgCache::DepIterator D = RevDepends ? Pkg.RevDependsList() : Ver.DependsList();
+	      D.end() == false; D++)
 	 {
 	 {
-	    // Important deps only
-	    if (Important == true)
-	       if (D->Type != pkgCache::Dep::PreDepends &&
-		   D->Type != pkgCache::Dep::Depends)
-		  continue;
-		  
-	    pkgCache::PkgIterator Trg = D.TargetPkg();
+	    switch (D->Type) {
+	    case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
+	    case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
+	    case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
+	    case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
+	    case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break;
+	    case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
+	    case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
+	    case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
+	    }
+
+	    pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
 
 
 	    if((Installed && Trg->CurrentVer != 0) || !Installed)
 	    if((Installed && Trg->CurrentVer != 0) || !Installed)
 	      {
 	      {
 
 
-		if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
+		if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or && ShowOnlyFirstOr == false)
 		  cout << " |";
 		  cout << " |";
 		else
 		else
 		  cout << "  ";
 		  cout << "  ";
 	    
 	    
 		// Show the package
 		// Show the package
+		if (ShowDepType == true)
+		  cout << D.DepType() << ": ";
 		if (Trg->VersionList == 0)
 		if (Trg->VersionList == 0)
-		  cout << D.DepType() << ": <" << Trg.FullName(true) << ">" << endl;
+		  cout << "<" << Trg.FullName(true) << ">" << endl;
 		else
 		else
-		  cout << D.DepType() << ": " << Trg.FullName(true) << endl;
+		  cout << Trg.FullName(true) << endl;
 	    
 	    
-		if (Recurse == true)
-		  Colours[D.TargetPkg()->ID]++;
+		if (Recurse == true && Shown[Trg->ID] == false)
+		{
+		  Shown[Trg->ID] = true;
+		  verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::VersionSet::CANDIDATE, helper));
+		}
 
 
 	      }
 	      }
 	    
 	    
@@ -631,101 +656,40 @@ bool Depends(CommandLine &CmdL)
 		   V->ParentPkg == D->Package)
 		   V->ParentPkg == D->Package)
 		  continue;
 		  continue;
 	       cout << "    " << V.ParentPkg().FullName(true) << endl;
 	       cout << "    " << V.ParentPkg().FullName(true) << endl;
-	       
-	       if (Recurse == true)
-		  Colours[D.ParentPkg()->ID]++;
+
+		if (Recurse == true && Shown[V.ParentPkg()->ID] == false)
+		{
+		  Shown[V.ParentPkg()->ID] = true;
+		  verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::VersionSet::CANDIDATE, helper));
+		}
 	    }
 	    }
+
+	    if (ShowOnlyFirstOr == true)
+	       while ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) ++D;
 	 }
 	 }
-      }      
-   }   
-   while (DidSomething == true);
-   
+   }
+
+   for (APT::PackageSet::const_iterator Pkg = helper.virtualPkgs.begin();
+	Pkg != helper.virtualPkgs.end(); ++Pkg)
+      cout << '<' << Pkg.FullName(true) << '>' << endl;
+
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// RDepends - Print out a reverse dependency tree - mbc			/*{{{*/
+// Depends - Print out a dependency tree				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool Depends(CommandLine &CmdL)
+{
+   return ShowDepends(CmdL, false);
+}
+									/*}}}*/
+// RDepends - Print out a reverse dependency tree			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 bool RDepends(CommandLine &CmdL)
 bool RDepends(CommandLine &CmdL)
 {
 {
-   pkgCacheFile CacheFile;
-   pkgCache *Cache = CacheFile.GetPkgCache();
-   if (unlikely(Cache == NULL))
-      return false;
-
-   SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
-
-   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
-   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
-      Colours[Pkg->ID] = 1;
-
-   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
-   bool Installed = _config->FindB("APT::Cache::Installed",false);
-   bool DidSomething;
-   do
-   {
-      DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-	 if (Colours[Pkg->ID] != 1)
-	    continue;
-	 Colours[Pkg->ID] = 2;
-	 DidSomething = true;
-	 
-	 pkgCache::VerIterator Ver = Pkg.VersionList();
-	 if (Ver.end() == true)
-	 {
-	    cout << '<' << Pkg.FullName(true) << '>' << endl;
-	    continue;
-	 }
-	 
-	 cout << Pkg.FullName(true) << endl;
-	 
-	 cout << "Reverse Depends:" << endl;
-	 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
-	 {	    
-	    // Show the package
-	    pkgCache::PkgIterator Trg = D.ParentPkg();
-
-	    if((Installed && Trg->CurrentVer != 0) || !Installed)
-	      {
-
-		if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
-		  cout << " |";
-		else
-		  cout << "  ";
-
-		if (Trg->VersionList == 0)
-		  cout << D.DepType() << ": <" << Trg.FullName(true) << ">" << endl;
-		else
-		  cout << Trg.FullName(true) << endl;
-
-		if (Recurse == true)
-		  Colours[D.ParentPkg()->ID]++;
-
-	      }
-	    
-	    // Display all solutions
-	    SPtrArray<pkgCache::Version *> List = D.AllTargets();
-	    pkgPrioSortList(*Cache,List);
-	    for (pkgCache::Version **I = List; *I != 0; I++)
-	    {
-	       pkgCache::VerIterator V(*Cache,*I);
-	       if (V != Cache->VerP + V.ParentPkg()->VersionList ||
-		   V->ParentPkg == D->Package)
-		  continue;
-	       cout << "    " << V.ParentPkg().FullName(true) << endl;
-	       
-	       if (Recurse == true)
-		  Colours[D.ParentPkg()->ID]++;
-	    }
-	 }
-      }      
-   }   
-   while (DidSomething == true);
-   
-   return true;
+   return ShowDepends(CmdL, true);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // xvcg - Generate a graph for xvcg					/*{{{*/
 // xvcg - Generate a graph for xvcg					/*{{{*/
@@ -1820,6 +1784,14 @@ int main(int argc,const char *argv[])					/*{{{*/
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {'o',"option",0,CommandLine::ArbItem},
       {0,"installed","APT::Cache::Installed",0},
       {0,"installed","APT::Cache::Installed",0},
+      {0,"pre-depends","APT::Cache::ShowPreDepends",0},
+      {0,"depends","APT::Cache::ShowDepends",0},
+      {0,"recommends","APT::Cache::ShowRecommends",0},
+      {0,"suggests","APT::Cache::ShowSuggests",0},
+      {0,"replaces","APT::Cache::ShowReplaces",0},
+      {0,"breaks","APT::Cache::ShowBreaks",0},
+      {0,"conflicts","APT::Cache::ShowConflicts",0},
+      {0,"enhances","APT::Cache::ShowEnhances",0},
       {0,0,0,0}};
       {0,0,0,0}};
    CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
    CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
                                     {"add",&DoAdd},
                                     {"add",&DoAdd},

+ 1 - 1
cmdline/apt-get.cc

@@ -40,6 +40,7 @@
 #include <apt-pkg/srcrecords.h>
 #include <apt-pkg/srcrecords.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefile.h>
+#include <apt-pkg/cacheset.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
 #include <apt-pkg/versionmatch.h>
@@ -48,7 +49,6 @@
 #include <apti18n.h>
 #include <apti18n.h>
 
 
 #include "acqprogress.h"
 #include "acqprogress.h"
-#include "cacheset.h"
 
 
 #include <set>
 #include <set>
 #include <locale.h>
 #include <locale.h>

+ 2 - 2
cmdline/makefile

@@ -9,14 +9,14 @@ include ../buildlib/defaults.mak
 PROGRAM=apt-cache
 PROGRAM=apt-cache
 SLIBS = -lapt-pkg $(INTLLIBS)
 SLIBS = -lapt-pkg $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-cache.cc cacheset.cc
+SOURCE = apt-cache.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)
 
 
 # The apt-get program
 # The apt-get program
 PROGRAM=apt-get
 PROGRAM=apt-get
 SLIBS = -lapt-pkg -lutil $(INTLLIBS)
 SLIBS = -lapt-pkg -lutil $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 LIB_MAKES = apt-pkg/makefile
-SOURCE = apt-get.cc acqprogress.cc cacheset.cc
+SOURCE = apt-get.cc acqprogress.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)
 
 
 # The apt-config program
 # The apt-config program

+ 17 - 1
debian/changelog

@@ -1,5 +1,6 @@
 apt (0.7.26~exp11) experimental; urgency=low
 apt (0.7.26~exp11) experimental; urgency=low
 
 
+  [ Julian Andres Klode ]
   * apt-pkg/deb/dpkgpm.cc:
   * apt-pkg/deb/dpkgpm.cc:
     - Write architecture information to history file.
     - Write architecture information to history file.
     - Add to history whether a change was automatic or not.
     - Add to history whether a change was automatic or not.
@@ -12,7 +13,22 @@ apt (0.7.26~exp11) experimental; urgency=low
     - Use link() instead of rename() for creating the CD database backup;
     - Use link() instead of rename() for creating the CD database backup;
       otherwise there would be a short time without any database.
       otherwise there would be a short time without any database.
 
 
- -- Julian Andres Klode <jak@debian.org>  Wed, 21 Jul 2010 17:09:11 +0200
+  [ David Kalnischkies ]
+  * apt-pkg/depcache.cc:
+    - handle "circular" conflicts for "all" packages correctly
+  * cmdline/apt-cache.cc:
+    - be able to omit dependency types in (r)depends (Closes: #319006)
+    - show in (r)depends the canidate per default instead of newest
+    - share the (r)depends code instead of codecopy
+  * apt-pkg/cacheset.cc:
+    - move them back to the library as they look stable now
+    - add a 'newest' pseudo target release as in pkg/newest
+  * apt-pkg/pkgcache.cc:
+    - prefer non-virtual packages in FindPreferredPkg (Closes: #590041)
+  * test/integration/*:
+    - add with bug#590041 testcase a small test "framework"
+
+ -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 26 Jul 2010 12:40:44 +0200
 
 
 apt (0.7.26~exp10) experimental; urgency=low
 apt (0.7.26~exp10) experimental; urgency=low
 
 

+ 14 - 0
doc/apt-cache.8.xml

@@ -309,6 +309,20 @@ Reverse Provides:
      Configuration Item: <literal>APT::Cache::Important</literal>.</para></listitem>
      Configuration Item: <literal>APT::Cache::Important</literal>.</para></listitem>
      </varlistentry>
      </varlistentry>
 
 
+     <varlistentry><term><option>--no-pre-depends</option></term>
+		   <term><option>--no-depends</option></term>
+		   <term><option>--no-recommends</option></term>
+		   <term><option>--no-suggests</option></term>
+		   <term><option>--no-conflicts</option></term>
+		   <term><option>--no-breaks</option></term>
+		   <term><option>--no-replaces</option></term>
+		   <term><option>--no-enhances</option></term>
+		   <listitem><para>Per default the <literal>depends</literal> and
+     <literal>rdepends</literal> print all dependencies. This can be twicked with
+     these flags which will omit the specified dependency type.
+     Configuration Item: <literal>APT::Cache::Show<replaceable>DependencyType</replaceable></literal>
+     e.g. <literal>APT::Cache::ShowRecommends</literal>.</para></listitem>
+     </varlistentry>
      <varlistentry><term><option>-f</option></term><term><option>--full</option></term>
      <varlistentry><term><option>-f</option></term><term><option>--full</option></term>
      <listitem><para>Print full package records when searching. 
      <listitem><para>Print full package records when searching. 
      Configuration Item: <literal>APT::Cache::ShowFull</literal>.</para></listitem>
      Configuration Item: <literal>APT::Cache::ShowFull</literal>.</para></listitem>

+ 170 - 0
test/integration/framework

@@ -0,0 +1,170 @@
+#!/bin/sh -- # no runable script, just for vi
+
+# we all like colorful messages
+CERROR="" # red
+CWARNING="" # yellow
+CMSG="" # green
+CINFO="" # light blue
+CDEBUG="" # blue
+CNORMAL="" # default system console color
+CDONE="" # green
+CPASS="" # green
+CFAIL="" # red
+CCMD="" # pink
+
+msgdie() { echo "${CERROR}E: $1${CNORMAL}" >&2; exit 1; }
+msgwarn() { echo "${CWARNING}W: $1${CNORMAL}" >&2; }
+msgmsg() { echo "${CMSG}$1${CNORMAL}" >&2; }
+msginfo() { echo "${CINFO}I: $1${CNORMAL}" >&2; }
+msgdebug() { echo "${CDEBUG}D: $1${CNORMAL}" >&2; }
+msgdone() { echo "${CDONE}DONE${CNORMAL}" >&2; }
+msgnwarn() { echo -n "${CWARNING}W: $1${CNORMAL}" >&2; }
+msgnmsg() { echo -n "${CMSG}$1${CNORMAL}" >&2; }
+msgninfo() { echo -n "${CINFO}I: $1${CNORMAL}" >&2; }
+msgndebug() { echo -n "${CDEBUG}D: $1${CNORMAL}" >&2; }
+msgtest() { echo -n "${CINFO}$1 ${CCMD}$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} …${CNORMAL} " >&2; }
+msgpass() { echo "${CPASS}PASS${CNORMAL}" >&2; }
+msgskip() { echo "${CWARNING}SKIP${CNORMAL}" >&2; }
+msgfail() { echo "${CFAIL}FAIL${CNORMAL}" >&2; }
+
+# enable / disable Debugging
+msginfo() { true; }
+msgdebug() { true; }
+msgninfo() { true; }
+msgndebug() { true; }
+msgdone() { if [ "$1" = "debug" -o "$1" = "info" ]; then true; else echo "${CDONE}DONE${CNORMAL}" >&2; fi }
+
+runapt() {
+	msgdebug "Executing: ${CCMD}$*${CDEBUG} "
+	APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/$*
+}
+aptconfig() { runapt apt-config $*; }
+aptcache() { runapt apt-cache $*; }
+aptget() { runapt apt-get $*; }
+aptftparchive() { runapt apt-ftparchive $*; }
+
+setupenvironment() {
+	local TMPWORKINGDIRECTORY=$(mktemp -d)
+	msgninfo "Preparing environment for ${CCMD}$0${CINFO} in ${TMPWORKINGDIRECTORY}… "
+	BUILDDIRECTORY=$(readlink -f $(dirname $0)/../../build/bin)
+	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
+	local OLDWORKINGDIRECTORY=$(pwd)
+	trap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+	cd $TMPWORKINGDIRECTORY
+	mkdir rootdir aptarchive
+	cd rootdir
+	mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d var/cache var/lib/dpkg
+	mkdir -p var/cache/apt/archives/partial var/lib/apt/lists/partial
+	touch var/lib/dpkg/status
+	mkdir -p usr/lib/apt
+	ln -s ${BUILDDIRECTORY}/methods usr/lib/apt/methods
+	cd ..
+	echo "RootDir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf
+	echo "Debug::NoLocking \"true\";" >> aptconfig.conf
+	echo "APT::Get::Show-User-Simulation-Note \"false\";" >> aptconfig.conf
+	export LC_ALL=C
+	msgdone "info"
+}
+
+configarchitecture() {
+	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
+	echo "APT::Architecture \"$1\";" > $CONFFILE
+	shift
+	while [ -n "$1" ]; do
+		echo "APT::Architectures:: \"$1\";" >> $CONFFILE
+		shift
+	done
+}
+
+buildflataptarchive() {
+	msginfo "Build APT archive for ${CCMD}$0${CINFO}…"
+	cd aptarchive
+	APTARCHIVE=$(readlink -f .)
+	if [ -f Packages ]; then
+		msgninfo "\tPackages file… "
+		cat Packages | gzip > Packages.gz
+		cat Packages | bzip2 > Packages.bz2
+		cat Packages | lzma > Packages.lzma
+		msgdone "info"
+	fi
+	if [ -f Sources ]; then
+		msgninfo "\tSources file… "
+		cat Sources | gzip > Sources.gz
+		cat Sources | bzip2 > Sources.bz2
+		cat Sources | lzma > Sources.lzma
+		msgdone "info"
+	fi
+	cd ..
+	aptftparchive release . > Release
+}
+
+setupflataptarchive() {
+	buildflataptarchive
+	APTARCHIVE=$(readlink -f ./aptarchive)
+	if [ -f ${APTARCHIVE}/Packages ]; then
+		msgninfo "\tadd deb sources.list line… "
+		echo "deb file://$APTARCHIVE /" > rootdir/etc/apt/sources.list.d/apt-test-archive-deb.list
+		msgdone "info"
+	else
+		rm -f rootdir/etc/apt/sources.list.d/apt-test-archive-deb.list
+	fi
+	if [ -f ${APTARCHIVE}/Sources ]; then
+		msgninfo "\tadd deb-src sources.list line… "
+		echo "deb-src file://$APTARCHIVE /" > rootdir/etc/apt/sources.list.d/apt-test-archive-deb-src.list
+		msgdone "info"
+	else
+		rm -f rootdir/etc/apt/sources.list.d/apt-test-archive-deb-src.list
+	fi
+	aptget update -qq
+}
+
+diff() {
+	local DIFFTEXT="$($(which diff) -u $* | sed -e '/^---/ d' -e '/^+++/ d' -e '/^@@/ d')"
+	if [ -n "$DIFFTEXT" ]; then
+		echo
+		echo "$DIFFTEXT"
+		return 1
+	else
+		return 0
+	fi
+}
+
+testequal() {
+	local COMPAREFILE=$(mktemp)
+	echo "$1" > $COMPAREFILE
+	shift
+	msgtest "Test for equality of" "$*"
+	$* 2>&1 | diff $COMPAREFILE - && msgpass || msgfail
+}
+
+testshowvirtual() {
+	local VIRTUAL="E: Can't select versions from package '$1' as it purely virtual"
+	local PACKAGE="$1"
+	shift
+	while [ -n "$1" ]; do
+		VIRTUAL="${VIRTUAL}
+E: Can't select versions from package '$1' as it purely virtual"
+		PACKAGE="${PACKAGE} $1"
+		shift
+	done
+	msgtest "Test for virtual packages" "apt-cache show $PACKAGE"
+	VIRTUAL="${VIRTUAL}
+E: No packages found"
+	local COMPAREFILE=$(mktemp)
+	local ARCH=$(dpkg-architecture -qDEB_HOST_ARCH_CPU)
+	eval `apt-config shell ARCH APT::Architecture`
+	echo "$VIRTUAL" | sed -e "s/:$ARCH//" -e 's/:all//' > $COMPAREFILE
+	aptcache show $PACKAGE 2>&1 | diff $COMPAREFILE - && msgpass || msgfail
+}
+
+testnopackage() {
+	msgtest "Test for non-existent packages" "apt-cache show $*"
+	local SHOWPKG="$(aptcache show $* 2>&1 | grep '^Package: ')"
+	if [ -n "$SHOWPKG" ]; then
+		echo
+		echo "$SHOWPKG"
+		msgfail
+		return 1
+	fi
+	msgpass
+}

+ 8 - 0
test/integration/run-tests

@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+local DIR=$(readlink -f $(dirname $0))
+for testcase in $(run-parts --list $DIR | grep '/test-'); do
+	echo "\033[1;32mRun Testcase \033[1;35m$(basename ${testcase})\033[0m"
+	${testcase}
+done

+ 51 - 0
test/integration/test-bug-590041-prefer-non-virtual-packages

@@ -0,0 +1,51 @@
+#!/bin/sh
+set -e
+
+. $(readlink -f $(dirname $0))/framework
+setupenvironment
+configarchitecture "i386" "armel"
+
+pkglibc6="Package: libc6
+Architecture: armel
+Version: 2.11.2-2~0.3
+Description: Embedded GNU C Library: Shared libraries
+Filename: pool/main/e/eglibc/libc6_2.11.2-2_armel.deb
+Installed-Size: 9740
+MD5sum: f5b878ce5fb8aa01a7927fa1460df537
+Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
+Priority: required
+SHA1: 0464d597dfbf949e8c17a42325b1f93fb4914afd
+SHA256: faca4a3d9ccff57568abf41f6cb81ddd835be7b5d8b0161e2d5f9a7f26aae3c0
+Section: libs
+Size: 4178958
+"
+
+pkglibdb1="Package: libdb1
+Architecture: i386
+Version: 2.1.3-13~0.3
+Replaces: libc6 (<< 2.2.5-13~0.3)
+Description: The Berkeley database routines [glibc 2.0/2.1 compatibility]
+Filename: pool/main/d/db1-compat/libdb1-compat_2.1.3-13_armel.deb
+Installed-Size: 136
+MD5sum: 4043f176ab2b40b0c01bc1211b8c103c
+Maintainer: Colin Watson <cjwatson@debian.org>
+Priority: extra
+SHA1: b9396fdd2e3e8d1d4ba9e74e7346075852d85666
+SHA256: f17decaa28d1db3eeb9eb17bebe50d437d293a509bcdd7cdfd3ebb56f5de3cea
+Section: oldlibs
+Size: 44168
+"
+
+cat <<-EOF >aptarchive/Packages
+$pkglibc6
+$pkglibdb1
+EOF
+
+setupflataptarchive
+
+testshowvirtual libc6:i386
+testequal "$pkglibc6" aptcache show libc6:armel
+testequal "$pkglibc6" aptcache show libc6
+testequal "$pkglibdb1" aptcache show libdb1:i386
+testnopackage libdb1:armel
+testequal "$pkglibdb1" aptcache show libdb1

+ 6 - 5
test/libapt/run-tests.sh

@@ -1,11 +1,12 @@
 #!/bin/sh
 #!/bin/sh
 set -e
 set -e
 
 
-echo "Compiling the tests ..."
-test -d '../../build/obj/test/libapt/' || mkdir -p '../../build/obj/test/libapt/'
-make
-echo "Running all testcases ..."
-LDPATH=$(pwd)/../../build/bin
+local DIR=$(readlink -f $(dirname $0))
+echo "Compiling the tests …"
+test -d "$DIR/../../build/obj/test/libapt/" || mkdir -p "$DIR/../../build/obj/test/libapt/"
+$(cd $DIR && make)
+echo "Running all testcases …"
+LDPATH="$DIR/../../build/bin"
 EXT="_libapt_test"
 EXT="_libapt_test"
 for testapp in $(ls ${LDPATH}/*$EXT)
 for testapp in $(ls ${LDPATH}/*$EXT)
 do
 do