Bugfixes concerning vendor handling:
authorStefan Schubert <schubi@suse.de>
Wed, 22 Aug 2007 14:51:35 +0000 (14:51 +0000)
committerStefan Schubert <schubi@suse.de>
Wed, 22 Aug 2007 14:51:35 +0000 (14:51 +0000)
- first bug:
 Installed A-1.0(vendor SuSE)
 Available A-2.0(other vendor)
 A will not be regarded as "unmaintained". So it will not be deleted.
- second bug:
 A need B-2.0. B-1.0 is installed but has another vendor. Report a
proper errmessage.
Testcase : solution-tests/vendor-test.xml

14 files changed:
zypp/solver/detail/ProblemSolutionIgnore.cc
zypp/solver/detail/ProblemSolutionIgnore.h
zypp/solver/detail/QueueItemRequire.cc
zypp/solver/detail/Resolver.cc
zypp/solver/detail/Resolver.h
zypp/solver/detail/ResolverContext.cc
zypp/solver/detail/ResolverContext.h
zypp/solver/detail/ResolverInfo.cc
zypp/solver/detail/ResolverInfo.h
zypp/solver/detail/ResolverInfoMisc.cc
zypp/solver/detail/ResolverUpgrade.cc
zypp/solver/detail/Resolver_problems.cc
zypp/solver/detail/SolutionAction.cc
zypp/solver/detail/SolutionAction.h

index 1c5984e..f723aee 100644 (file)
@@ -42,6 +42,7 @@ namespace zypp
 IMPL_PTR_TYPE(ProblemSolutionIgnoreConflicts);
 IMPL_PTR_TYPE(ProblemSolutionIgnoreRequires);
 IMPL_PTR_TYPE(ProblemSolutionIgnoreArchitecture);
+IMPL_PTR_TYPE(ProblemSolutionIgnoreVendor);    
 IMPL_PTR_TYPE(ProblemSolutionIgnoreInstalled); 
 
 //---------------------------------------------------------------------------
@@ -79,6 +80,19 @@ ProblemSolutionIgnoreArchitecture::ProblemSolutionIgnoreArchitecture( ResolverPr
                            ResolverInfo::toString (item).c_str());
        addAction ( new InjectSolutionAction (item, ARCHITECTURE));
 }
+
+ProblemSolutionIgnoreVendor::ProblemSolutionIgnoreVendor( ResolverProblem_Ptr parent,
+                                                         PoolItem_Ref item)
+    : ProblemSolution (parent, "", "")
+{
+        // TranslatorExplanation %s = name of package, patch, selection ...
+       _description = str::form(_("Install %s although it would change the vendor"),
+                                item->name().c_str());
+       // TranslatorExplanation %s = name of package, patch, selection ...     
+       _details = str::form(_("%s provides this dependency, but would change the vendor of the installed item"),
+                           ResolverInfo::toString (item).c_str());
+       addAction ( new InjectSolutionAction (item, VENDOR));
+}
        
 ProblemSolutionIgnoreConflicts::ProblemSolutionIgnoreConflicts( ResolverProblem_Ptr parent,
                                                                PoolItem_Ref item,
index 4192794..75837f4 100644 (file)
@@ -81,7 +81,18 @@ namespace zypp
             **/
            ProblemSolutionIgnoreArchitecture( ResolverProblem_Ptr parent,
                                               PoolItem_Ref item);
-       };      
+       };
+
+       class ProblemSolutionIgnoreVendor : public ProblemSolution
+       {
+       public:
+
+           /**
+            * Constructor.
+            **/
+           ProblemSolutionIgnoreVendor( ResolverProblem_Ptr parent,
+                                        PoolItem_Ref item);
+       };              
 
        class ProblemSolutionIgnoreObsoletes : public ProblemSolution
        {
index c37690d..ee51876 100644 (file)
@@ -216,11 +216,31 @@ struct RequireProcess
            }
        }
 
+       // checking vendor
+       bool vendorFit = true;
+       if ( provider
+            && upgrades
+            && provider->vendor() != upgrades->vendor()) {
+           // checking if there is already an ignore
+           MIL << "provider " << provider << " has ANOTHER vendor '" << provider->vendor() << "' than the updated item "
+               << upgrades << endl;
+           PoolItemList ignore = _context->getIgnoreVendorItem();
+           PoolItemList::iterator it;
+           for (it = ignore.begin(); it != ignore.end(); ++it) {
+               if (provider == *it) break;
+           }
+           if (it != ignore.end()) {
+               MIL << " ---> will be ignored " << endl;
+           } else {
+               vendorFit = false;
+           }
+       }
+
        if (! (status.isToBeUninstalled() || status.isImpossible())
            && ! _context->isParallelInstall( provider )
            && _context->itemIsPossible( provider )
            && ! provider.status().isLocked()
-            && ( (!provider || !upgrades) || (provider->vendor() == upgrades->vendor()) )
+            && vendorFit
            && ! (provider.status().isKept()
                  &&provider.status().isByUser())
            ) {
@@ -317,12 +337,17 @@ struct NoInstallableProviders
        } else if (provider.status().isKept() && provider.status().isByUser()) {
            misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_KEEP_PROVIDER, requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
            misc_info->setOtherPoolItem (provider);         
-       } else  if (provider->arch().compatibleWith( context->architecture() )) {
-           misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_OTHER_ARCH_PROVIDER,
+       } else  if (provider->vendor() != requirer->vendor()) {
+           misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_OTHER_VENDOR_PROVIDER,
                                                                   requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
            misc_info->setOtherPoolItem (provider);
        }
-
+       else if (provider->arch().compatibleWith( context->architecture() )) {
+           misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_OTHER_ARCH_PROVIDER,
+                                                                  requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
+           misc_info->setOtherPoolItem (provider);
+       } 
+       
        if (misc_info != NULL) {
            context->addInfo (misc_info);
        }
index 1d08477..0c5f0a2 100644 (file)
@@ -463,6 +463,11 @@ Resolver::addIgnoreArchitectureItem (const PoolItem_Ref item)
     _ignoreArchitectureItem.push_back (item);
 }
 
+void
+Resolver::addIgnoreVendorItem (const PoolItem_Ref item)
+{
+    _ignoreVendorItem.push_back (item);
+}
 
 //---------------------------------------------------------------------------
 
@@ -650,7 +655,8 @@ Resolver::establishState( ResolverContext_Ptr context )
                                    _ignoreRequires,
                                    _ignoreObsoletes,
                                    _ignoreInstalledItem,
-                                   _ignoreArchitectureItem);
+                                   _ignoreArchitectureItem,
+                                   _ignoreVendorItem);
     context->setForceResolve( _forceResolve );
     context->setEstablishContext( _establish_context );
     context->setPreferHighestVersion ( _preferHighestVersion );
@@ -775,7 +781,8 @@ Resolver::freshenState( ResolverContext_Ptr context,
                                    _ignoreRequires,
                                    _ignoreObsoletes,
                                    _ignoreInstalledItem,
-                                   _ignoreArchitectureItem );
+                                   _ignoreArchitectureItem,
+                                   _ignoreVendorItem);
     context->setForceResolve( _forceResolve );
     context->setEstablishContext( _establish_context );
     context->setPreferHighestVersion( _preferHighestVersion );
@@ -900,7 +907,8 @@ Resolver::resolveDependencies (const ResolverContext_Ptr context)
                                                     ignoreRequires,
                                                     _ignoreObsoletes,
                                                     _ignoreInstalledItem,
-                                                    _ignoreArchitectureItem);
+                                                    _ignoreArchitectureItem,
+                                                    _ignoreVendorItem);
     initial_queue->context()->setForceResolve( _forceResolve );
     initial_queue->context()->setEstablishContext( _establish_context );
     initial_queue->context()->setPreferHighestVersion( _preferHighestVersion );
@@ -1124,6 +1132,8 @@ Resolver::undo(void)
     _ignoreInstalledItem.clear();
     // Ignore the architecture of the item
     _ignoreArchitectureItem.clear();
+    // Ignore the vendor of the item
+    _ignoreVendorItem.clear();
 
 
     return;
index 9ef2e9a..6807ff1 100644 (file)
@@ -137,7 +137,8 @@ class Resolver : public base::ReferenceCounted, private base::NonCopyable {
     PoolItemList _ignoreInstalledItem;
     // Ignore the architecture of the item
     PoolItemList _ignoreArchitectureItem;
-
+    // Ignore the vendor of the item
+    PoolItemList _ignoreVendorItem;
 
     ResolverQueueList _pending_queues;
     ResolverQueueList _pruned_queues;
@@ -237,6 +238,7 @@ class Resolver : public base::ReferenceCounted, private base::NonCopyable {
                             const Capability & capability);
     void addIgnoreInstalledItem (const PoolItem_Ref item);
     void addIgnoreArchitectureItem (const PoolItem_Ref item);
+    void addIgnoreVendorItem (const PoolItem_Ref item);    
 
     void setForceResolve (const bool force) { _forceResolve = force; }
     const bool forceResolve() { return _forceResolve; }
index 36998f1..94629fb 100644 (file)
@@ -121,7 +121,8 @@ _XDEBUG( "new ResolverContext()" );
        _ignoreRequires      = parent->_ignoreRequires;
        _ignoreObsoletes     = parent->_ignoreObsoletes;
        _ignoreInstalledItem = parent->_ignoreInstalledItem;
-       _ignoreArchitectureItem = parent->_ignoreArchitectureItem;      
+       _ignoreArchitectureItem = parent->_ignoreArchitectureItem;
+       _ignoreVendorItem    = parent->_ignoreVendorItem;
        _forceResolve        = parent->_forceResolve;
        _upgradeMode         = parent->_upgradeMode;
        _preferHighestVersion = parent->_preferHighestVersion;
index 7e56077..3d6e5a9 100644 (file)
@@ -99,6 +99,8 @@ class ResolverContext : public base::ReferenceCounted, private base::NonCopyable
     PoolItemList _ignoreInstalledItem;
     // Ignore the architecture of the item
     PoolItemList _ignoreArchitectureItem;
+    // Ignore the vendor of the item
+    PoolItemList _ignoreVendorItem;    
 
     // Items which has been selected NOT by the solver
     // This will be stored while a solver run in order to save time
@@ -166,19 +168,22 @@ class ResolverContext : public base::ReferenceCounted, private base::NonCopyable
                               const IgnoreMap ignoreRequires,
                               const IgnoreMap ignoreObsoletes,
                               const PoolItemList ignoreInstalledItem,
-                              const PoolItemList ignoreArchitectureItem)
+                              const PoolItemList ignoreArchitectureItem,
+                              const PoolItemList ignoreVendorItem)
        {_ignoreConflicts = ignoreConflicts;
        _ignoreRequires = ignoreRequires;
        _ignoreObsoletes = ignoreObsoletes;
        _ignoreInstalledItem = ignoreInstalledItem;
-       _ignoreArchitectureItem = ignoreArchitectureItem;}
+       _ignoreArchitectureItem = ignoreArchitectureItem;
+       _ignoreVendorItem = ignoreVendorItem;
+       }
 
     const IgnoreMap getIgnoreConflicts() const { return _ignoreConflicts; }
     const IgnoreMap getIgnoreRequires() const { return _ignoreRequires; }
     const IgnoreMap getIgnoreObsoletes() const { return _ignoreObsoletes; }    
     const PoolItemList getIgnoreInstalledItem() const { return _ignoreInstalledItem; }
     const PoolItemList getIgnoreArchitectureItem() const { return _ignoreArchitectureItem; }
-
+    const PoolItemList getIgnoreVendorItem() const { return _ignoreVendorItem; }
     
     void setForceResolve (const bool force) { _forceResolve = force; }
     const bool forceResolve() { return _forceResolve; }
index 4348bf8..dfe0068 100644 (file)
@@ -81,6 +81,7 @@ static struct {
     { RIT(NOT_INSTALLABLE_PROVIDER),   "p provides c but is uninstallable" },
     { RIT(LOCKED_PROVIDER),            "p provides c but is locked" },
     { RIT(OTHER_ARCH_PROVIDER),                "p provides c but has other architecture" },
+    { RIT(OTHER_VENDOR_PROVIDER),      "p provides c but has other vendor" },    
     { RIT(CANT_SATISFY),               "Can't satisfy requirement c" },
        // from QueueItemUninstall
     { RIT(UNINSTALL_TO_BE_INSTALLED),  "p is to-be-installed, so it won't be unlinked." },
index c42772a..d13cc51 100644 (file)
@@ -66,6 +66,7 @@ typedef enum {
     RESOLVER_INFO_TYPE_NOT_INSTALLABLE_PROVIDER,       // p provides c but is uninstallable
     RESOLVER_INFO_TYPE_LOCKED_PROVIDER,                        // p provides c but is locked
     RESOLVER_INFO_TYPE_OTHER_ARCH_PROVIDER,            // p provides c but has other architecture
+    RESOLVER_INFO_TYPE_OTHER_VENDOR_PROVIDER,          // p provides c but has other vendor    
     RESOLVER_INFO_TYPE_CANT_SATISFY,                   // Can't satisfy requirement c
        // from QueueItemUninstall
     RESOLVER_INFO_TYPE_UNINSTALL_TO_BE_INSTALLED,      // p is to-be-installed, so it won't be unlinked.
index aa77368..0b96a0a 100644 (file)
@@ -453,7 +453,25 @@ ResolverInfoMisc::message (void) const
                             cap_str.c_str());
        }
        break;
-       
+
+       //-------------------
+       // p provides c but has other vendor
+
+       case RESOLVER_INFO_TYPE_OTHER_VENDOR_PROVIDER: {
+           // affected() = requirer of capability
+           // _capability = provided by other()
+           // other() = provider of capability
+           // other_capability() = - empty -
+
+           string other_str = ResolverInfo::toString(other());
+           string cap_str = ResolverInfo::toString (_capability);
+           // Translator: 1.%s = name of package,patch,...; 2.%s = dependency; 3.%s = vendor ID
+           msg = str::form (_("%s provides %s, but has another vendor (%s)."),
+                            other_str.c_str(),
+                            cap_str.c_str(),
+                            (other()->vendor()).c_str());
+       }
+       break;
 
        //-------------------
        // Can't satisfy requirement
index a88c1f5..f52ebe6 100644 (file)
@@ -203,14 +203,23 @@ typedef map<string, PoolItem_Ref> FindMap;
 struct FindProviders
 {
     FindMap providers;         // the best providers which matched
-
-    FindProviders ()
+    PoolItem forItem;
+    bool otherVendorFound;
+    FindProviders (PoolItem item)
+       :forItem(item),
+        otherVendorFound(false)
     { }
 
     bool operator()( const CapAndItem & cai )
     {
        PoolItem provider( cai.item );
-       if ( provider.status().isToBeUninstalled() ) {
+       if ( provider->vendor() != forItem->vendor() )
+       {
+           MIL << "Discarding '" << provider << "' from vendor '"
+               << provider->vendor() << "' different to uninstalled '"
+               << forItem->vendor() << "' vendor." << endl;
+           otherVendorFound = true;
+       } else if ( provider.status().isToBeUninstalled() ) {
            MIL << "  IGNORE relation match (package is tagged to delete): " << cai.cap << " ==> " << provider << endl;
        }
        else {
@@ -365,8 +374,8 @@ Resolver::doUpgrade( UpgradeStatistics & opt_stats_r )
        if (cand_it == candidatemap.end()                                               // not in map yet
            || (cand_it->second->arch().compare( candidate->arch() ) < 0)               // or the new has better architecture
            || ((cand_it->second->arch().compare( candidate->arch() ) == 0)             // or the new has the same architecture
-               && (cand_it->second->edition().compare( candidate->edition() ) < 0)     //   and a better edition (-> 157501)
-                && (cand_it->second->vendor() == candidate->vendor() ) ) )//   and same vendor
+               && (cand_it->second->edition().compare( candidate->edition() ) < 0))    //   and a better edition (-> 157501)
+           )
        {
            candidatemap[installed] = candidate;                                // put it in !
        }
@@ -533,7 +542,7 @@ Resolver::doUpgrade( UpgradeStatistics & opt_stats_r )
       CapFactory factory;
       Capability installedCap = factory.parse( installed->kind(), installed->name(), Rel::GE, installed->edition() );
 
-      FindProviders info;
+      FindProviders info(installed);
 
       invokeOnEach( _pool.byCapabilityIndexBegin( installed->name(), dep ),
                    _pool.byCapabilityIndexEnd( installed->name(), dep ),
@@ -553,11 +562,15 @@ Resolver::doUpgrade( UpgradeStatistics & opt_stats_r )
 
       switch ( info.providers.size() ) {
       case 0:
-       MIL << " ==> (dropped)" << endl;
-       // wait untill splits are processed. Might be a split obsoletes
-       // this one (i.e. package replaced but not provided by new one).
-       // otherwise it's finaly dropped.
-       probably_dropped = true;
+         if (info.otherVendorFound) {
+             MIL << " only resolvable with other vendor found ==> do nothing" << endl;
+         } else {
+             MIL << " ==> (dropped)" << endl;
+             // wait untill splits are processed. Might be a split obsoletes
+             // this one (i.e. package replaced but not provided by new one).
+             // otherwise it's finaly dropped.
+             probably_dropped = true;
+         }
        break;
       case 1:
         addProvided[installed] = providers;
index 833540c..bcb0215 100644 (file)
@@ -119,6 +119,8 @@ typedef struct {
     ItemCapabilityMap provideAndLockMap;
     // A map of PoolItems which provides a capability but have another architecture
     ItemCapabilityMap provideAndOtherArchMap;
+    // A map of PoolItems which provides a capability but have another vendor
+    ItemCapabilityMap provideAndOtherVendorMap;
     // A map of conflicting Items
     ConflictMap conflictMap;
 } ResItemCollector;
@@ -195,8 +197,21 @@ collector_cb (ResolverInfo_Ptr info, void *data)
            collector->provideAndOtherArchMap.insert (make_pair( misc_info->other(), misc_info->capability()));
        }
     }
-    
-
+    // Collecting items which are providing requirements but they
+    // have another vendor
+    if (info->type() == RESOLVER_INFO_TYPE_OTHER_VENDOR_PROVIDER) {
+       ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
+       // does entry already exists ?
+       ItemCapabilityMap::iterator pos = find_if (collector->provideAndOtherVendorMap.begin(),
+                                                  collector->provideAndOtherVendorMap.end(),
+                                                  cap_equals<PoolItem_Ref, Capability>(misc_info->capability()));
+       
+       if (pos == collector->provideAndOtherVendorMap.end()) {
+           _XDEBUG ("Inserting " << misc_info->capability() << "/" <<  misc_info->other()
+                    << " into provideAndOtherVendorMap map");
+           collector->provideAndOtherVendorMap.insert (make_pair( misc_info->other(), misc_info->capability()));
+       }
+    }    
     // Collecting all conflicting Items
     if (info->type() == RESOLVER_INFO_TYPE_CONFLICT_UNINSTALLABLE
        || info->type() == RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL) {
@@ -662,6 +677,14 @@ Resolver::problems (const bool ignoreValidSolution) const
                            problem->addSolution (new ProblemSolutionIgnoreArchitecture (problem, it->first));
                        }
                    }
+                   // Searching for another item which provides this requires BUT has another vendor
+                   for (ItemCapabilityMap::const_iterator it = collector.provideAndOtherVendorMap.begin();
+                        it != collector.provideAndOtherVendorMap.end(); ++it) {
+                       if (it->second.matches (misc_info->capability()) == CapMatch::yes) {
+                           // ignoring vendor
+                           problem->addSolution (new ProblemSolutionIgnoreVendor (problem, it->first));
+                       }
+                   }               
                    // Searching for another item which provides this requires BUT has been set to be kept
                    for (ItemCapabilityMap::const_iterator it = collector.provideAndKeptMap.begin();
                         it != collector.provideAndKeptMap.end(); ++it) {
index 7436ad6..2670060 100644 (file)
@@ -110,7 +110,8 @@ InjectSolutionAction::dumpOn( ostream& os ) const
        case CONFLICTS: os << "Conflicts"; break;
        case OBSOLETES: os << "Obsoletes"; break;
        case INSTALLED: os << "Installed"; break;
-       case ARCHITECTURE: os << "Architecture"; break;     
+       case ARCHITECTURE: os << "Architecture"; break;
+       case VENDOR: os << "Vendor"; break;                 
        default: os << "Wrong kind"; break;
     }
     os << " ";
@@ -217,7 +218,11 @@ InjectSolutionAction::execute(Resolver & resolver) const
         case ARCHITECTURE:
            // This item is for ALL architectures available
            resolver.addIgnoreArchitectureItem (_item);
-           break;          
+           break;
+        case VENDOR:
+           // This item is for ALL vendor available
+           resolver.addIgnoreVendorItem (_item);
+           break;                  
         case OBSOLETES:
            // removing the obsoletes dependency from the item
            resolver.addIgnoreObsoletes (_otherItem, _capability);
index a0af526..4646817 100644 (file)
@@ -105,7 +105,7 @@ namespace zypp
 
 
        /**
-        * Type of ignoring dependencies and architectures
+        * Type of ignoring dependencies, architectures and vendor
         **/
 
        typedef enum
@@ -114,7 +114,8 @@ namespace zypp
            CONFLICTS,
            OBSOLETES,
            INSTALLED,
-           ARCHITECTURE
+           ARCHITECTURE,
+           VENDOR
        } InjectSolutionKind;