Explorar el Código

hide implicit deps in apt-cache again by default

Before MultiArch implicits weren't a thing, so they were hidden by
default by definition. Adding them for MultiArch solved many problems,
but having no reliable way of detecting which dependency (and provides)
is implicit or not causes problems everytime we want to output
dependencies without confusing our observers with unneeded
implementation details.

The really notworthy point here is actually that we keep now a better
record of how a dependency came to be so that we can later reason about
it more easily, but that is hidden so deep down in the library internals
that change is more the problems it solves than the change itself.
David Kalnischkies hace 11 años
padre
commit
8c7af4d4c9

+ 16 - 2
apt-pkg/cacheiterators.h

@@ -295,7 +295,16 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> {
 	bool IsNegative() const APT_PURE;
 	bool IsNegative() const APT_PURE;
 	bool IsIgnorable(PrvIterator const &Prv) const APT_PURE;
 	bool IsIgnorable(PrvIterator const &Prv) const APT_PURE;
 	bool IsIgnorable(PkgIterator const &Pkg) const APT_PURE;
 	bool IsIgnorable(PkgIterator const &Pkg) const APT_PURE;
-	bool IsMultiArchImplicit() const APT_PURE;
+	/* MultiArch can be translated to SingleArch for an resolver and we did so,
+	   by adding dependencies to help the resolver understand the problem, but
+	   sometimes it is needed to identify these to ignore them… */
+	inline bool IsMultiArchImplicit() const APT_PURE {
+		return (S2->CompareOp & pkgCache::Dep::MultiArchImplicit) == pkgCache::Dep::MultiArchImplicit;
+	}
+	/* This covers additionally negative dependencies, which aren't arch-specific,
+	   but change architecture nontheless as a Conflicts: foo does applies for all archs */
+	bool IsImplicit() const APT_PURE;
+
 	bool IsSatisfied(VerIterator const &Ver) const APT_PURE;
 	bool IsSatisfied(VerIterator const &Ver) const APT_PURE;
 	bool IsSatisfied(PrvIterator const &Prv) const APT_PURE;
 	bool IsSatisfied(PrvIterator const &Prv) const APT_PURE;
 	void GlobOr(DepIterator &Start,DepIterator &End);
 	void GlobOr(DepIterator &Start,DepIterator &End);
@@ -367,7 +376,12 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 	inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);}
 	inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);}
 	inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);}
 	inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);}
 
 
-	bool IsMultiArchImplicit() const APT_PURE;
+	/* MultiArch can be translated to SingleArch for an resolver and we did so,
+	   by adding provides to help the resolver understand the problem, but
+	   sometimes it is needed to identify these to ignore them… */
+	bool IsMultiArchImplicit() const APT_PURE
+	{ return (S->Flags & pkgCache::Flag::MultiArchImplicit) == pkgCache::Flag::MultiArchImplicit; }
+
 
 
 	inline PrvIterator() : Iterator<Provides, PrvIterator>(), Type(PrvVer) {}
 	inline PrvIterator() : Iterator<Provides, PrvIterator>(), Type(PrvVer) {}
 	inline PrvIterator(pkgCache &Owner, Provides *Trg, Version*) :
 	inline PrvIterator(pkgCache &Owner, Provides *Trg, Version*) :

+ 4 - 4
apt-pkg/deb/deblistparser.cc

@@ -812,7 +812,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
 	 // … but this is probably the best thing to do.
 	 // … but this is probably the best thing to do.
 	 if (Arch == "native")
 	 if (Arch == "native")
 	    Arch = _config->Find("APT::Architecture");
 	    Arch = _config->Find("APT::Architecture");
-	 if (NewDepends(Ver,Package,Arch,Version,Op,Type) == false)
+	 if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false)
 	    return false;
 	    return false;
       }
       }
       else
       else
@@ -858,13 +858,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
 	 } else if (archfound != string::npos) {
 	 } else if (archfound != string::npos) {
 	    string OtherArch = Package.substr(archfound+1, string::npos);
 	    string OtherArch = Package.substr(archfound+1, string::npos);
 	    Package = Package.substr(0, archfound);
 	    Package = Package.substr(0, archfound);
-	    if (NewProvides(Ver, Package, OtherArch, Version) == false)
+	    if (NewProvides(Ver, Package, OtherArch, Version, pkgCache::Flag::ArchSpecific) == false)
 	       return false;
 	       return false;
 	 } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
 	 } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
 	    if (NewProvidesAllArch(Ver, Package, Version) == false)
 	    if (NewProvidesAllArch(Ver, Package, Version) == false)
 	       return false;
 	       return false;
 	 } else {
 	 } else {
-	    if (NewProvides(Ver, Package, Arch, Version) == false)
+	    if (NewProvides(Ver, Package, Arch, Version, 0) == false)
 	       return false;
 	       return false;
 	 }
 	 }
 
 
@@ -890,7 +890,7 @@ bool debListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const
    for (std::vector<string>::const_iterator a = Architectures.begin();
    for (std::vector<string>::const_iterator a = Architectures.begin();
 	a != Architectures.end(); ++a)
 	a != Architectures.end(); ++a)
    {
    {
-      if (NewProvides(Ver, Package, *a, Version) == false)
+      if (NewProvides(Ver, Package, *a, Version, pkgCache::Flag::MultiArchImplicit) == false)
 	 return false;
 	 return false;
    }
    }
    return true;
    return true;

+ 4 - 4
apt-pkg/edsp.cc

@@ -102,11 +102,11 @@ static void WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &
    bool orGroup = false;
    bool orGroup = false;
    for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep)
    for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep)
    {
    {
-      if (Dep.IsMultiArchImplicit() == true)
+      if (Dep.IsImplicit() == true)
 	 continue;
 	 continue;
       if (orGroup == false)
       if (orGroup == false)
 	 dependencies[Dep->Type].append(", ");
 	 dependencies[Dep->Type].append(", ");
-      dependencies[Dep->Type].append(Dep.TargetPkg().Name());
+      dependencies[Dep->Type].append(Dep.TargetPkg().FullName((Dep->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific));
       if (Dep->Version != 0)
       if (Dep->Version != 0)
 	 dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")");
 	 dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")");
       if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
       if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
@@ -140,7 +140,7 @@ static void WriteScenarioLimitedDependency(FILE* output,
    bool orGroup = false;
    bool orGroup = false;
    for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep)
    for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep)
    {
    {
-      if (Dep.IsMultiArchImplicit() == true)
+      if (Dep.IsImplicit() == true)
 	 continue;
 	 continue;
       if (orGroup == false)
       if (orGroup == false)
       {
       {
@@ -156,7 +156,7 @@ static void WriteScenarioLimitedDependency(FILE* output,
 	 orGroup = false;
 	 orGroup = false;
 	 continue;
 	 continue;
       }
       }
-      dependencies[Dep->Type].append(Dep.TargetPkg().Name());
+      dependencies[Dep->Type].append(Dep.TargetPkg().FullName((Dep->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific));
       if (Dep->Version != 0)
       if (Dep->Version != 0)
 	 dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")");
 	 dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")");
       if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
       if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)

+ 16 - 45
apt-pkg/pkgcache.cc

@@ -727,21 +727,7 @@ bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const
    // ignore group-conflict on a M-A:same package - but not our implicit dependencies
    // ignore group-conflict on a M-A:same package - but not our implicit dependencies
    // so that we can have M-A:same packages conflicting with their own real name
    // so that we can have M-A:same packages conflicting with their own real name
    if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
    if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
-   {
-      // Replaces: ${self}:other ( << ${binary:Version})
-      if (S2->Type == pkgCache::Dep::Replaces)
-      {
-	 if (S2->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0)
-	    return false;
-      }
-      // Breaks: ${self}:other (!= ${binary:Version})
-      else if (S2->Type == pkgCache::Dep::DpkgBreaks)
-      {
-	 if (S2->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0)
-	    return false;
-      }
-      return true;
-   }
+      return IsMultiArchImplicit() == false;
 
 
    return false;
    return false;
 }
 }
@@ -756,27 +742,12 @@ bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const
    if (Prv.OwnerPkg()->Group == Pkg->Group)
    if (Prv.OwnerPkg()->Group == Pkg->Group)
       return true;
       return true;
    // Implicit group-conflicts should not be applied on providers of other groups
    // Implicit group-conflicts should not be applied on providers of other groups
-   if (Pkg->Group == TargetPkg()->Group && Prv.OwnerPkg()->Group != Pkg->Group)
+   if (IsMultiArchImplicit() && Prv.OwnerPkg()->Group != Pkg->Group)
       return true;
       return true;
 
 
    return false;
    return false;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// DepIterator::IsMultiArchImplicit - added by the cache generation	/*{{{*/
-// ---------------------------------------------------------------------
-/* MultiArch can be translated to SingleArch for an resolver and we did so,
-   by adding dependencies to help the resolver understand the problem, but
-   sometimes it is needed to identify these to ignore them… */
-bool pkgCache::DepIterator::IsMultiArchImplicit() const
-{
-   if (ParentPkg()->Arch != TargetPkg()->Arch &&
-       (S2->Type == pkgCache::Dep::Replaces ||
-	S2->Type == pkgCache::Dep::DpkgBreaks ||
-	S2->Type == pkgCache::Dep::Conflicts))
-      return true;
-   return false;
-}
-									/*}}}*/
 // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
 // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
 bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const
 bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const
 {
 {
@@ -787,6 +758,20 @@ bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const
    return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer());
    return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer());
 }
 }
 									/*}}}*/
 									/*}}}*/
+// DepIterator::IsImplicit - added by the cache generation		/*{{{*/
+bool pkgCache::DepIterator::IsImplicit() const
+{
+   if (IsMultiArchImplicit() == true)
+      return true;
+   if (IsNegative() || S2->Type == pkgCache::Dep::Replaces)
+   {
+      if ((S2->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific &&
+	    strcmp(ParentPkg().Arch(), TargetPkg().Arch()) != 0)
+	 return true;
+   }
+   return false;
+}
+									/*}}}*/
 // ostream operator to handle string representation of a dependecy	/*{{{*/
 // ostream operator to handle string representation of a dependecy	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
@@ -1067,19 +1052,5 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
 }
 }
 
 
 									/*}}}*/
 									/*}}}*/
-// PrvIterator::IsMultiArchImplicit - added by the cache generation	/*{{{*/
-// ---------------------------------------------------------------------
-/* MultiArch can be translated to SingleArch for an resolver and we did so,
-   by adding provides to help the resolver understand the problem, but
-   sometimes it is needed to identify these to ignore them… */
-bool pkgCache::PrvIterator::IsMultiArchImplicit() const
-{
-   pkgCache::PkgIterator const Owner = OwnerPkg();
-   pkgCache::PkgIterator const Parent = ParentPkg();
-   if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner.Group()->Name == Parent.Group()->Name)
-      return true;
-   return false;
-}
-									/*}}}*/
 
 
 pkgCache::~pkgCache() {}
 pkgCache::~pkgCache() {}

+ 12 - 4
apt-pkg/pkgcache.h

@@ -149,8 +149,12 @@ class pkgCache								/*{{{*/
           The lower 4 bits are used to indicate what operator is being specified and
           The lower 4 bits are used to indicate what operator is being specified and
           the upper 4 bits are flags. OR indicates that the next package is
           the upper 4 bits are flags. OR indicates that the next package is
           or'd with the current package. */
           or'd with the current package. */
-      enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
-	 Greater=0x4,Equals=0x5,NotEquals=0x6};
+      enum DepCompareOp {NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
+	 Greater=0x4,Equals=0x5,NotEquals=0x6,
+	 Or=0x10, /*!< or'ed with the next dependency */
+	 MultiArchImplicit=0x20, /*!< generated internally, not spelled out in the index */
+	 ArchSpecific=0x40 /*!< was decorated with an explicit architecture in index */
+      };
    };
    };
    
    
    struct State
    struct State
@@ -178,6 +182,10 @@ class pkgCache								/*{{{*/
 	 NotAutomatic=(1<<0), /*!< archive has a default pin of 1 */
 	 NotAutomatic=(1<<0), /*!< archive has a default pin of 1 */
 	 ButAutomaticUpgrades=(1<<1), /*!< (together with the previous) archive has a default pin of 100 */
 	 ButAutomaticUpgrades=(1<<1), /*!< (together with the previous) archive has a default pin of 100 */
       };
       };
+      enum ProvidesFlags {
+	 MultiArchImplicit=pkgCache::Dep::MultiArchImplicit, /*!< generated internally, not spelled out in the index */
+	 ArchSpecific=pkgCache::Dep::ArchSpecific /*!< was decorated with an explicit architecture in index */
+      };
    };
    };
    
    
    protected:
    protected:
@@ -725,9 +733,9 @@ struct pkgCache::Provides
    /** \brief version in the provides line (if any)
    /** \brief version in the provides line (if any)
 
 
        This version allows dependencies to depend on specific versions of a
        This version allows dependencies to depend on specific versions of a
-       Provides, as well as allowing Provides to override existing packages.
-       This is experimental. Note that Debian doesn't allow versioned provides */
+       Provides, as well as allowing Provides to override existing packages. */
    map_stringitem_t ProvideVersion;
    map_stringitem_t ProvideVersion;
+   map_flags_t Flags;
    /** \brief next provides (based of package) */
    /** \brief next provides (based of package) */
    map_pointer_t NextProvides;     // Provides
    map_pointer_t NextProvides;     // Provides
    /** \brief next provides (based of version) */
    /** \brief next provides (based of version) */

+ 16 - 16
apt-pkg/pkgcachegen.cc

@@ -709,16 +709,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G,
       {
       {
 	 // Replaces: ${self}:other ( << ${binary:Version})
 	 // Replaces: ${self}:other ( << ${binary:Version})
 	 NewDepends(D, V, VerStrIdx,
 	 NewDepends(D, V, VerStrIdx,
-		    pkgCache::Dep::Less, pkgCache::Dep::Replaces,
+		    pkgCache::Dep::Less | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Replaces,
 		    OldDepLast);
 		    OldDepLast);
 	 // Breaks: ${self}:other (!= ${binary:Version})
 	 // Breaks: ${self}:other (!= ${binary:Version})
 	 NewDepends(D, V, VerStrIdx,
 	 NewDepends(D, V, VerStrIdx,
-		    pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
+		    pkgCache::Dep::NotEquals | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::DpkgBreaks,
 		    OldDepLast);
 		    OldDepLast);
       } else {
       } else {
 	 // Conflicts: ${self}:other
 	 // Conflicts: ${self}:other
 	 NewDepends(D, V, 0,
 	 NewDepends(D, V, 0,
-		    pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
+		    pkgCache::Dep::NoOp | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Conflicts,
 		    OldDepLast);
 		    OldDepLast);
       }
       }
    }
    }
@@ -737,16 +737,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V,
       map_stringitem_t const VerStrIdx = V->VerStr;
       map_stringitem_t const VerStrIdx = V->VerStr;
       // Replaces: ${self}:other ( << ${binary:Version})
       // Replaces: ${self}:other ( << ${binary:Version})
       NewDepends(D, V, VerStrIdx,
       NewDepends(D, V, VerStrIdx,
-		 pkgCache::Dep::Less, pkgCache::Dep::Replaces,
+		 pkgCache::Dep::Less | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Replaces,
 		 OldDepLast);
 		 OldDepLast);
       // Breaks: ${self}:other (!= ${binary:Version})
       // Breaks: ${self}:other (!= ${binary:Version})
       NewDepends(D, V, VerStrIdx,
       NewDepends(D, V, VerStrIdx,
-		 pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
+		 pkgCache::Dep::NotEquals | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::DpkgBreaks,
 		 OldDepLast);
 		 OldDepLast);
    } else {
    } else {
       // Conflicts: ${self}:other
       // Conflicts: ${self}:other
       NewDepends(D, V, 0,
       NewDepends(D, V, 0,
-		 pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
+		 pkgCache::Dep::NoOp | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Conflicts,
 		 OldDepLast);
 		 OldDepLast);
    }
    }
    return true;
    return true;
@@ -913,8 +913,8 @@ map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 				   pkgCache::VerIterator &Ver,
 				   pkgCache::VerIterator &Ver,
 				   string const &Version,
 				   string const &Version,
-				   unsigned int const &Op,
-				   unsigned int const &Type,
+				   uint8_t const Op,
+				   uint8_t const Type,
 				   map_stringitem_t* &OldDepLast)
 				   map_stringitem_t* &OldDepLast)
 {
 {
    map_stringitem_t index = 0;
    map_stringitem_t index = 0;
@@ -940,8 +940,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 				   pkgCache::VerIterator &Ver,
 				   pkgCache::VerIterator &Ver,
 				   map_pointer_t const Version,
 				   map_pointer_t const Version,
-				   unsigned int const &Op,
-				   unsigned int const &Type,
+				   uint8_t const Op,
+				   uint8_t const Type,
 				   map_pointer_t* &OldDepLast)
 				   map_pointer_t* &OldDepLast)
 {
 {
    void const * const oldMap = Map.Data();
    void const * const oldMap = Map.Data();
@@ -1040,8 +1040,8 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 					       const string &PackageName,
 					       const string &PackageName,
 					       const string &Arch,
 					       const string &Arch,
 					       const string &Version,
 					       const string &Version,
-					       unsigned int Op,
-					       unsigned int Type)
+					       uint8_t const Op,
+					       uint8_t const Type)
 {
 {
    pkgCache::GrpIterator Grp;
    pkgCache::GrpIterator Grp;
    Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
    Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
@@ -1073,12 +1073,11 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ListParser::NewProvides - Create a Provides element			/*{{{*/
 // ListParser::NewProvides - Create a Provides element			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
-					        const string &PkgName,
+						const string &PkgName,
 						const string &PkgArch,
 						const string &PkgArch,
-						const string &Version)
+						const string &Version,
+						uint8_t const Flags)
 {
 {
    pkgCache &Cache = Owner->Cache;
    pkgCache &Cache = Owner->Cache;
 
 
@@ -1097,6 +1096,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
    pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
    pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
    Dynamic<pkgCache::PrvIterator> DynPrv(Prv);
    Dynamic<pkgCache::PrvIterator> DynPrv(Prv);
    Prv->Version = Ver.Index();
    Prv->Version = Ver.Index();
+   Prv->Flags = Flags;
    Prv->NextPkgProv = Ver->ProvidesList;
    Prv->NextPkgProv = Ver->ProvidesList;
    Ver->ProvidesList = Prv.Index();
    Ver->ProvidesList = Prv.Index();
    if (Version.empty() == false) {
    if (Version.empty() == false) {

+ 8 - 7
apt-pkg/pkgcachegen.h

@@ -82,11 +82,11 @@ class APT_HIDDEN pkgCacheGenerator					/*{{{*/
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
-		   std::string const &Version, unsigned int const &Op,
-		   unsigned int const &Type, map_pointer_t* &OldDepLast);
+		   std::string const &Version, uint8_t const Op,
+		   uint8_t const Type, map_pointer_t* &OldDepLast);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
-		   map_pointer_t const Version, unsigned int const &Op,
-		   unsigned int const &Type, map_pointer_t* &OldDepLast);
+		   map_pointer_t const Version, uint8_t const Op,
+		   uint8_t const Type, map_pointer_t* &OldDepLast);
    map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,map_pointer_t const Next) APT_DEPRECATED
    map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,map_pointer_t const Next) APT_DEPRECATED
    { return NewVersion(Ver, VerStr, 0, 0, Next); }
    { return NewVersion(Ver, VerStr, 0, 0, Next); }
    map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,
    map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,
@@ -162,10 +162,11 @@ class APT_HIDDEN pkgCacheGenerator::ListParser
    inline map_stringitem_t WriteString(const std::string &S) {return Owner->WriteStringInMap(S);};
    inline map_stringitem_t WriteString(const std::string &S) {return Owner->WriteStringInMap(S);};
    inline map_stringitem_t WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);};
    inline map_stringitem_t WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);};
    bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch,
    bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch,
-		   const std::string &Version,unsigned int Op,
-		   unsigned int Type);
+		   const std::string &Version,uint8_t const Op,
+		   uint8_t const Type);
    bool NewProvides(pkgCache::VerIterator &Ver,const std::string &PkgName,
    bool NewProvides(pkgCache::VerIterator &Ver,const std::string &PkgName,
-		    const std::string &PkgArch, const std::string &Version);
+		    const std::string &PkgArch, const std::string &Version,
+		    uint8_t const Flags);
    
    
    public:
    public:
    
    

+ 1 - 0
apt-private/private-cmndline.cc

@@ -51,6 +51,7 @@ static bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char cons
       addArg(0, "conflicts", "APT::Cache::ShowConflicts", 0);
       addArg(0, "conflicts", "APT::Cache::ShowConflicts", 0);
       addArg(0, "enhances", "APT::Cache::ShowEnhances", 0);
       addArg(0, "enhances", "APT::Cache::ShowEnhances", 0);
       addArg(0, "recurse", "APT::Cache::RecurseDepends", 0);
       addArg(0, "recurse", "APT::Cache::RecurseDepends", 0);
+      addArg(0, "implicit", "APT::Cache::ShowImplicit", 0);
    }
    }
    else if (CmdMatches("search"))
    else if (CmdMatches("search"))
    {
    {

+ 8 - 3
cmdline/apt-cache.cc

@@ -689,6 +689,7 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
    bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
    bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
    bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
    bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
    bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
    bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
+   bool const ShowImplicit = _config->FindB("APT::Cache::ShowImplicit", false);
 
 
    while (verset.empty() != true)
    while (verset.empty() != true)
    {
    {
@@ -709,12 +710,16 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
 	    case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
 	    case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
 	    case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
 	    case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
 	    case pkgCache::Dep::Suggests: if (!ShowSuggests) 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::Replaces: if (!ShowReplaces) continue; break;
+	    case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
 	    case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
 	    case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
 	    case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
 	    case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
 	    }
 	    }
+	    if (ShowImplicit == false && D.IsImplicit())
+	       continue;
 
 
 	    pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
 	    pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
+	    bool const showNoArch = RevDepends || (D->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific;
 
 
 	    if((Installed && Trg->CurrentVer != 0) || !Installed)
 	    if((Installed && Trg->CurrentVer != 0) || !Installed)
 	      {
 	      {
@@ -728,9 +733,9 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
 		if (ShowDepType == true)
 		if (ShowDepType == true)
 		  cout << D.DepType() << ": ";
 		  cout << D.DepType() << ": ";
 		if (Trg->VersionList == 0)
 		if (Trg->VersionList == 0)
-		  cout << "<" << Trg.FullName(true) << ">";
+		  cout << "<" << Trg.FullName(showNoArch) << ">";
 		else
 		else
-		  cout << Trg.FullName(true);
+		  cout << Trg.FullName(showNoArch);
 		if (ShowVersion == true && D->Version != 0)
 		if (ShowVersion == true && D->Version != 0)
 		   cout << " (" << pkgCache::CompTypeDeb(D->CompareOp) << ' ' << D.TargetVer() << ')';
 		   cout << " (" << pkgCache::CompTypeDeb(D->CompareOp) << ' ' << D.TargetVer() << ')';
 		cout << std::endl;
 		cout << std::endl;

+ 13 - 2
doc/apt-cache.8.xml

@@ -281,12 +281,23 @@ Reverse Provides:
 		   <term><option>--no-breaks</option></term>
 		   <term><option>--no-breaks</option></term>
 		   <term><option>--no-replaces</option></term>
 		   <term><option>--no-replaces</option></term>
 		   <term><option>--no-enhances</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 tweaked with
+		   <listitem><para>Per default the <command>depends</command> and
+     <command>rdepends</command> print all dependencies. This can be tweaked with
      these flags which will omit the specified dependency type.
      these flags which will omit the specified dependency type.
      Configuration Item: <literal>APT::Cache::Show<replaceable>DependencyType</replaceable></literal>
      Configuration Item: <literal>APT::Cache::Show<replaceable>DependencyType</replaceable></literal>
      e.g. <literal>APT::Cache::ShowRecommends</literal>.</para></listitem>
      e.g. <literal>APT::Cache::ShowRecommends</literal>.</para></listitem>
      </varlistentry>
      </varlistentry>
+
+     <varlistentry><term><option>--implicit</option></term>
+	<listitem><para>Per default <command>depends</command> and <command>rdepends</command>
+	      print only dependencies explicitly expressed in the metadata. With this flag
+	      it will also show dependencies implicitely added based on the encountered data.
+	      A <literal>Conflicts: foo</literal> e.g. expresses implicitely that this package
+	      also conflicts with the package foo from any other architecture.
+	      Configuration Item: <literal>APT::Cache::ShowImplicit</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>

+ 71 - 7
test/integration/test-apt-cache

@@ -16,6 +16,9 @@ Recommends: cool (>= 2) | cooler (<< 5)' "$DESCR"
 insertpackage 'unstable' 'bar' 'all' '1' 'Depends: bar
 insertpackage 'unstable' 'bar' 'all' '1' 'Depends: bar
 Breaks: foo (<< 1)
 Breaks: foo (<< 1)
 Replaces: foo (<< 1)' "$DESCR"
 Replaces: foo (<< 1)' "$DESCR"
+insertpackage 'unstable' 'specific' 'all' '1' 'Depends: bar:i386, specific:amd64
+Breaks: foo:amd64 (<< 1)
+Replaces: foo:i386 (<< 1)' "$DESCR"
 
 
 setupaptarchive
 setupaptarchive
 
 
@@ -44,6 +47,7 @@ testsuccess test -s dump.output
 
 
 testsuccessequal 'dpkg
 testsuccessequal 'dpkg
 bar
 bar
+specific
 fancy
 fancy
 foo' aptcache pkgnames
 foo' aptcache pkgnames
 testsuccessequal 'bar' aptcache pkgnames bar
 testsuccessequal 'bar' aptcache pkgnames bar
@@ -57,29 +61,60 @@ testsuccessequal "       foo |          1 | file:$(readlink -f .)/aptarchive uns
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Depends: bar
   Conflicts: <foobar>
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>
  |Recommends: <cool>
  |Recommends: <cool>
   Recommends: <cooler>' aptcache depends foo
   Recommends: <cooler>' aptcache depends foo
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Depends: bar
   Conflicts: <foobar>
   Conflicts: <foobar>
   Conflicts: <foobar:i386>
   Conflicts: <foobar:i386>
+ |Recommends: <cool>
+  Recommends: <cooler>' aptcache depends foo --implicit
+testsuccessequal 'foo
+  Depends: bar
+  Conflicts: <foobar>
   Recommends: <cool>' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1
   Recommends: <cool>' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Depends: bar
   Conflicts: <foobar>
   Conflicts: <foobar>
   Conflicts: <foobar:i386>
   Conflicts: <foobar:i386>
+  Recommends: <cool>' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 --implicit
+testsuccessequal 'foo
+  Depends: bar
+  Conflicts: <foobar>
  |Recommends: <cool> (>= 2)
  |Recommends: <cool> (>= 2)
   Recommends: <cooler> (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1
   Recommends: <cooler> (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Depends: bar
   Conflicts: <foobar>
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>' aptcache depends foo --no-recommends
+  Conflicts: <foobar:i386>
+ |Recommends: <cool> (>= 2)
+  Recommends: <cooler> (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 --implicit
 testsuccessequal 'foo
 testsuccessequal 'foo
-  Depends: bar' aptcache depends foo --important
+  Depends: bar
+  Conflicts: <foobar>' aptcache depends foo --no-recommends
+testsuccessequal 'foo
+  Depends: bar
+  Conflicts: <foobar>
+  Conflicts: <foobar:i386>' aptcache depends foo --no-recommends --implicit
+testsuccessequal 'foo
+  Depends: bar' aptcache depends foo --important --implicit
 testsuccessequal 'foo
 testsuccessequal 'foo
+  Conflicts: <foobar>' aptcache depends foo --important --no-depends --conflicts
+testsuccessequal 'foo
+  Conflicts: <foobar>
+  Conflicts: <foobar:i386>' aptcache depends foo --important --no-depends --conflicts --implicit
+testsuccessequal 'foo
+  Depends: bar
   Conflicts: <foobar>
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>' aptcache depends foo --important --no-depends --conflicts
+ |Recommends: <cool>
+  Recommends: <cooler>
+bar
+  Depends: bar
+  Breaks: foo
+  Replaces: foo
+<foobar>
+<cool>
+<cooler>' aptcache depends foo --recurse
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Depends: bar
   Conflicts: <foobar>
   Conflicts: <foobar>
@@ -96,29 +131,58 @@ bar
 <foobar:i386>
 <foobar:i386>
 <cool>
 <cool>
 <cooler>
 <cooler>
-<foo:i386>' aptcache depends foo --recurse
+<foo:i386>' aptcache depends foo --recurse --implicit
+testsuccessequal 'foo
+  Depends: bar
+bar
+  Depends: bar
+  Replaces: foo' aptcache depends foo --recurse --important --replaces
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Depends: bar
 bar
 bar
   Depends: bar
   Depends: bar
   Replaces: foo
   Replaces: foo
   Replaces: <foo:i386>
   Replaces: <foo:i386>
-<foo:i386>' aptcache depends foo --recurse --important --replaces
+<foo:i386>' aptcache depends foo --recurse --important --replaces --implicit
+testsuccessequal 'bar
+  Depends: bar
+  Breaks: foo
+  Replaces: foo' aptcache depends bar
+testsuccessequal 'bar
+  Depends: bar
+  Breaks: foo
+  Breaks: <foo:i386>
+  Replaces: foo
+  Replaces: <foo:i386>' aptcache depends bar --implicit
+testsuccessequal 'specific
+  Depends: <bar:i386>
+  Depends: specific:amd64
+  Breaks: foo:amd64
+  Replaces: <foo:i386>' aptcache depends specific
+testsuccessequal 'specific
+  Depends: <bar:i386>
+  Depends: specific:amd64
+  Breaks: foo:amd64
+  Replaces: <foo:i386>' aptcache depends specific --implicit
 
 
 ## rdpends
 ## rdpends
 
 
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
   bar
   bar
+  specific
   bar' aptcache rdepends foo
   bar' aptcache rdepends foo
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
   Breaks: bar
   Breaks: bar
+  Breaks: specific
   Replaces: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1
   Replaces: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
   Breaks: bar (<< 1)
   Breaks: bar (<< 1)
+  Breaks: specific (<< 1)
   Replaces: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1
   Replaces: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
-  Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks
+  Breaks: bar (<< 1)
+  Breaks: specific (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks

+ 0 - 56
test/integration/test-ordering-ignore-not-matching-breaks

@@ -1,56 +0,0 @@
-#!/bin/sh
-set -e
-
-TESTDIR=$(readlink -f $(dirname $0))
-. $TESTDIR/framework
-setupenvironment
-configarchitecture 'amd64' 'i386'
-
-insertpackage 'unstable-mp' 'crda' 'i386,amd64' '1.1.1-1ubuntu4mp' 'Provides: wireless-crda
-Multi-Arch: foreign'
-insertpackage 'unstable-m' 'crda' 'i386,amd64' '1.1.1-1ubuntu4m' 'Multi-Arch: foreign'
-insertpackage 'unstable-p' 'crda' 'i386,amd64' '1.1.1-1ubuntu4p' 'Provides: wireless-crda'
-insertpackage 'unstable' 'wireless-crda' 'i386,amd64' '1.16'
-
-
-insertinstalledpackage 'wireless-crda' 'amd64' '1.14'
-
-setupaptarchive
-
-testsuccessequal 'Reading package lists...
-Building dependency tree...
-The following NEW packages will be installed:
-  crda
-0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
-Inst crda (1.1.1-1ubuntu4m unstable-m [amd64])
-Conf crda (1.1.1-1ubuntu4m unstable-m [amd64])' aptget install crda -s -t unstable-m
-
-testsuccessequal 'Reading package lists...
-Building dependency tree...
-The following NEW packages will be installed:
-  crda
-0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
-Inst crda (1.1.1-1ubuntu4p unstable-p [amd64])
-Conf crda (1.1.1-1ubuntu4p unstable-p [amd64])' aptget install crda -s -t unstable-p
-
-testsuccessequal 'Reading package lists...
-Building dependency tree...
-The following NEW packages will be installed:
-  crda
-0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
-Inst crda (1.1.1-1ubuntu4mp unstable-mp [amd64])
-Conf crda (1.1.1-1ubuntu4mp unstable-mp [amd64])' aptget install crda -s -t unstable-mp
-
-rm rootdir/var/lib/dpkg/status
-insertinstalledpackage 'crda' 'amd64' '1.1.1-1ubuntu4mp' 'Provides: wireless-crda
-Conflicts: wireless-crda (<< 1.15)
-Replaces: wireless-crda ( << 1.15)
-Multi-arch: foreign'
-
-testsuccessequal 'Reading package lists...
-Building dependency tree...
-The following NEW packages will be installed:
-  wireless-crda
-0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
-Inst wireless-crda (1.16 unstable [amd64])
-Conf wireless-crda (1.16 unstable [amd64])' aptget install wireless-crda -s -t unstable