74aeaa684800393e3525f4211ac788310116e0fd
[platform/upstream/libzypp.git] / zypp / target / TargetImpl.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/target/TargetImpl.cc
10  *
11 */
12 #include <iostream>
13 #include <string>
14 #include <list>
15 #include <set>
16
17 #include "zypp/base/Logger.h"
18 #include "zypp/base/Exception.h"
19 #include "zypp/base/Gettext.h"
20 #include "zypp/PoolItem.h"
21 #include "zypp/Resolvable.h"
22 #include "zypp/ResObject.h"
23 #include "zypp/Package.h"
24 #include "zypp/Script.h"
25 #include "zypp/Message.h"
26 #include "zypp/Source.h"
27 #include "zypp/Url.h"
28
29 #include "zypp/target/TargetImpl.h"
30 #include "zypp/target/TargetCallbackReceiver.h"
31
32 #include "zypp/solver/detail/InstallOrder.h"
33
34 using namespace std;
35 using zypp::solver::detail::InstallOrder;
36
37 ///////////////////////////////////////////////////////////////////
38 namespace zypp
39 { /////////////////////////////////////////////////////////////////
40   ///////////////////////////////////////////////////////////////////
41   namespace target
42   { /////////////////////////////////////////////////////////////////
43
44     ///////////////////////////////////////////////////////////////////
45     namespace 
46     { /////////////////////////////////////////////////////////////////
47     
48       struct PubKeyHelper
49       {
50       };
51       
52       /////////////////////////////////////////////////////////////////
53     } // namespace 
54     ///////////////////////////////////////////////////////////////////
55     
56     IMPL_PTR_TYPE(TargetImpl);
57
58     TargetImpl_Ptr TargetImpl::_nullimpl;
59
60     /** Null implementation */
61     TargetImpl_Ptr TargetImpl::nullimpl()
62     {
63       if (_nullimpl == 0)
64         _nullimpl = new TargetImpl;
65       return _nullimpl;
66     }
67
68
69     ///////////////////////////////////////////////////////////////////
70     //
71     //  METHOD NAME : TargetImpl::TargetImpl
72     //  METHOD TYPE : Ctor
73     //
74     TargetImpl::TargetImpl(const Pathname & root_r)
75     : _root(root_r)
76     {
77       _rpm.initDatabase(_root);
78       _storage_enabled = false;
79       MIL << "Initialized target on " << _root << endl;
80     }
81
82     ///////////////////////////////////////////////////////////////////
83     //
84     //  METHOD NAME : TargetImpl::~TargetImpl
85     //  METHOD TYPE : Dtor
86     //
87     TargetImpl::~TargetImpl()
88     {
89       _rpm.closeDatabase();
90       MIL << "Targets closed" << endl;
91     }
92
93     bool TargetImpl::isStorageEnabled() const
94     {
95       return _storage_enabled;
96     }
97
98     
99     void TargetImpl::enableStorage(const Pathname &root_r)
100     {
101       _storage.init(root_r);
102       _storage_enabled = true;
103     }
104
105     Pathname TargetImpl::root() const
106     {
107       return _root;
108     }
109   
110     const ResStore & TargetImpl::resolvables()
111     {
112       _store.clear();
113       // RPM objects
114       std::list<Package::Ptr> packages = _rpm.getPackages();
115       for (std::list<Package::Ptr>::const_iterator it = packages.begin();
116            it != packages.end();
117            it++)
118       {
119         _store.insert(*it);
120       }
121
122       if ( isStorageEnabled() )
123       {
124         // resolvables stored in the zypp storage database
125         std::list<ResObject::Ptr> resolvables = _storage.storedObjects();
126         for (std::list<ResObject::Ptr>::iterator it = resolvables.begin();
127             it != resolvables.end();
128             it++)
129         {
130           _store.insert(*it);
131         }
132       }
133       else
134       {
135         WAR << "storage target not enabled" << std::endl;
136       }
137
138       return _store;
139     }
140
141     
142     Pathname TargetImpl::getRpmFile(Package::constPtr package)
143     {
144         callback::SendReport<source::DownloadResolvableReport> report;
145
146 #warning FIXME: error handling
147 #warning FIXME: Url
148         report->start( package, package->source().url() );
149
150         Pathname file = package->getPlainRpm();
151
152         report->finish( package, source::DownloadResolvableReport::NO_ERROR, "" );
153         
154         return file;
155     }
156
157
158     int TargetImpl::commit(ResPool pool_r, unsigned int medianr, TargetImpl::PoolItemList & errors_r, TargetImpl::PoolItemList & remaining_r, TargetImpl::PoolItemList & srcremaining_r)
159     {
160       MIL << "TargetImpl::commit(<pool>, " << medianr << ")" << endl;
161
162       errors_r.clear();
163       remaining_r.clear();
164       srcremaining_r.clear();
165
166       TargetImpl::PoolItemList to_uninstall;
167       TargetImpl::PoolItemList to_install;
168       TargetImpl::PoolItemList to_srcinstall;
169       getResolvablesToInsDel( pool_r, to_uninstall, to_install, to_srcinstall );
170
171       if ( medianr ) {
172         MIL << "Restrict to media number " << medianr << endl;
173       }
174
175       commit (to_uninstall);
176
177       if (medianr == 0) {                       // commit all
178         remaining_r = commit( to_install );
179         srcremaining_r = commit( to_srcinstall );
180       }
181       else
182       {
183         TargetImpl::PoolItemList current_install;
184         TargetImpl::PoolItemList current_srcinstall;
185
186         for (TargetImpl::PoolItemList::iterator it = to_install.begin(); it != to_install.end(); ++it)
187         {
188           Resolvable::constPtr res( it->resolvable() );
189           Package::constPtr pkg( asKind<Package>(res) );
190           if (pkg && medianr != pkg->mediaId())                                                         // check medianr for packages only
191           {
192             XXX << "Package " << *pkg << ", wrong media " << pkg->mediaId() << endl;
193             remaining_r.push_back( *it );
194           }
195           else
196           {
197             current_install.push_back( *it );
198           }
199         }
200         TargetImpl::PoolItemList bad = commit (current_install);
201         remaining_r.insert(remaining_r.end(), bad.begin(), bad.end());
202
203         for (TargetImpl::PoolItemList::iterator it = to_srcinstall.begin(); it != to_srcinstall.end(); ++it)
204         {
205           Resolvable::constPtr res( it->resolvable() );
206           Package::constPtr pkg( asKind<Package>(res) );
207           if (pkg && medianr != pkg->mediaId()) // check medianr for packages only
208           {
209             XXX << "Package " << *pkg << ", wrong media " << pkg->mediaId() << endl;
210             srcremaining_r.push_back( *it );
211           }
212           else {
213             current_srcinstall.push_back( *it );
214           }
215         }
216         bad = commit (current_srcinstall);
217         srcremaining_r.insert(srcremaining_r.end(), bad.begin(), bad.end());
218       }
219       return to_install.size() - remaining_r.size();
220     }
221
222
223     TargetImpl::PoolItemList
224     TargetImpl::commit( const TargetImpl::PoolItemList & items_r)
225     {
226       TargetImpl::PoolItemList remaining;
227
228       MIL << "TargetImpl::commit(<list>)" << endl;
229       
230       bool abort = false;
231
232       // remember the last used source (if any)
233       Source_Ref lastUsedSource;
234
235       for (TargetImpl::PoolItemList::const_iterator it = items_r.begin(); it != items_r.end(); it++)
236       {
237         if (isKind<Package>(it->resolvable()))
238         {
239           Package::constPtr p = dynamic_pointer_cast<const Package>(it->resolvable());
240           if (it->status().isToBeInstalled())
241           {
242             Pathname localfile = getRpmFile( p );
243             lastUsedSource = p->source();                       // remember the package source
244
245 #warning Exception handling
246             // create a installation progress report proxy
247             RpmInstallPackageReceiver progress( it->resolvable() );
248             progress.connect();
249             bool success = true;
250
251             try {
252               progress.tryLevel( target::rpm::InstallResolvableReport::RPM );
253                 
254               rpm().installPackage(localfile,
255                   p->installOnly() ? rpm::RpmDb::RPMINST_NOUPGRADE : 0);
256
257               if( progress.aborted() )
258               {
259                 WAR << "commit aborted by the user" << endl;
260                 progress.disconnect(); 
261                 abort = true;
262                 break;
263               }
264
265             }
266             catch (Exception & excpt_r) {
267               ZYPP_CAUGHT(excpt_r);
268               WAR << "Install failed, retrying with --nodeps" << endl;
269               try {
270                 progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS );
271                 rpm().installPackage(localfile,
272                 p->installOnly() ? rpm::RpmDb::RPMINST_NOUPGRADE : rpm::RpmDb::RPMINST_NODEPS);
273
274                 if( progress.aborted() )
275                 {
276                   WAR << "commit aborted by the user" << endl;
277                   abort = true;
278                   progress.disconnect(); 
279                   break;
280                 }
281               }
282               catch (Exception & excpt_r) 
283               {
284                 ZYPP_CAUGHT(excpt_r);
285                 WAR << "Install failed again, retrying with --force --nodeps" << endl;
286     
287                 try {
288                   progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE );
289                   rpm().installPackage(localfile,
290                       p->installOnly() ? rpm::RpmDb::RPMINST_NOUPGRADE : (rpm::RpmDb::RPMINST_NODEPS|rpm::RpmDb::RPMINST_FORCE));
291                 }
292                 catch (Exception & excpt_r) {
293                   remaining.push_back( *it );
294                   success = false;
295                   ZYPP_CAUGHT(excpt_r);
296                 }
297                 
298                 if( progress.aborted() )
299                 {
300                     WAR << "commit aborted by the user" << endl;
301                     abort = true;
302                     progress.disconnect(); 
303                     break;
304                 }
305               }
306             }
307             if (success) {
308               it->status().setTransact( false, ResStatus::USER );
309             }
310             progress.disconnect();
311             p->source().releaseFile(p->plainRpm(), p->mediaId());
312           }
313           else
314           {
315             bool success = true;
316
317             RpmRemovePackageReceiver progress(it->resolvable());
318             progress.connect();
319             try {
320               rpm().removePackage( p, rpm::RpmDb::RPMINST_NODEPS );
321             }
322             catch (Exception & excpt_r) {
323               WAR << "removal of " << p << " failed";
324               success = false;
325               ZYPP_CAUGHT( excpt_r );
326             }
327             if (success) {
328               it->status().setTransact( false, ResStatus::USER );
329             }
330             progress.disconnect();
331           }
332         }
333         else // other resolvables
334         {
335           if ( isStorageEnabled() )
336           {
337             if (it->status().isToBeInstalled())
338             { 
339               bool success = false;
340               try
341               {
342                 if (isKind<Message>(it->resolvable()))
343                 {
344                   Message::constPtr m = dynamic_pointer_cast<const Message>(it->resolvable());
345                   std::string text = m->text().asString();
346                   
347                   callback::SendReport<target::MessageResolvableReport> report;
348                   
349                   report->show( m );
350                   
351                   MIL << "Displaying the text " << text << endl;
352                 }
353                 else if (isKind<Script>(it->resolvable()))
354                 {
355                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
356                   Pathname p = s->do_script();
357                   if (p != "" && p != "/")
358                   {
359                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
360                     if (! prog)
361                       ZYPP_THROW(Exception("Cannot run the script"));
362                     int retval = prog->close();
363                     delete prog;
364                     if (retval != 0)
365                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
366                   }
367                   else
368                   {
369                     ERR << "Do script not defined" << endl;
370                   }
371                 }
372                 else
373                 {
374                   _storage.storeObject(it->resolvable());
375                 }
376                 success = true;
377               }
378               catch (Exception & excpt_r)
379               {
380                 ZYPP_CAUGHT(excpt_r);
381                 WAR << "Install of Resolvable from storage failed" << endl;
382               }
383               if (success)
384                 it->status().setTransact( false, ResStatus::USER );
385             }
386             else
387             {
388               bool success = false;
389               try
390               {
391                 if (isKind<Message>(it->resolvable()))
392                 {
393                   DBG << "Uninstalling message - no-op" << endl;
394                 }
395                 else if (isKind<Script>(it->resolvable()))
396                 {
397                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
398                   Pathname p = s->undo_script();
399                   if (! s->undo_available())
400                   {
401                     DBG << "Undo script not available" << endl;
402                   }
403                   if (p != "" && p != "/")
404                   {
405                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
406                     if (! prog)
407                       ZYPP_THROW(Exception("Cannot run the script"));
408                     int retval = prog->close();
409                     delete prog;
410                     if (retval != 0)
411                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
412                   }
413                   else
414                   {
415                     ERR << "Undo script not defined" << endl;
416                   }
417                 }
418                 else
419                 {
420                   _storage.deleteObject(it->resolvable());
421                 }
422                 success = true;
423               }
424               catch (Exception & excpt_r)
425               {
426                 ZYPP_CAUGHT(excpt_r);
427                 WAR << "Uninstall of Resolvable from storage failed" << endl;
428               }
429               if (success)
430                 it->status().setTransact( false, ResStatus::USER );
431             }
432           }
433           else
434           {
435             WAR << "storage target disabled" << std::endl;
436           }
437
438         }  // other resolvables
439
440       } // for
441
442       // we're done with the commit, release the source media
443       //   In the case of a single media, end of commit means we don't need _this_
444       //   media any more.
445       //   In the case of 'commit any media', end of commit means we're completely
446       //   done and don't need the source's media anyways.
447
448       if (lastUsedSource) {             // if a source was used
449         lastUsedSource.release();       //  release their medias
450       }
451
452       if( abort ) 
453         ZYPP_THROW( TargetAbortedException( N_("Target commit aborted by user.") ) );
454
455       return remaining;
456     }
457
458     rpm::RpmDb & TargetImpl::rpm()
459     { return _rpm; }
460
461     bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
462     { return _rpm.hasFile(path_str, name_str); }
463
464       /** Return the resolvable which provides path_str (rpm -qf)
465           return NULL if no resolvable provides this file  */
466     ResObject::constPtr TargetImpl::whoOwnsFile (const std::string & path_str) const
467     {
468         string name = _rpm.whoOwnsFile (path_str);
469         if (name.empty())
470             return NULL;
471
472         for (ResStore::const_iterator it = _store.begin(); it != _store.end(); ++it) {
473             if ((*it)->name() == name) {
474                 return *it;
475             }
476         }
477         return NULL;
478     }
479
480     /** Set the log file for target */
481     bool TargetImpl::setInstallationLogfile(const Pathname & path_r)
482     {
483       return rpm::RpmDb::setInstallationLogfile(path_r);
484     }
485
486 //-----------------------------------------------------------------------------
487 /******************************************************************
488 **
489 **
490 **      FUNCTION NAME : strip_obsoleted_to_delete
491 **      FUNCTION TYPE : void
492 **
493 ** strip packages to_delete which get obsoleted by
494 ** to_install (i.e. delay deletion in case the
495 ** obsoleting package likes to save whatever...
496 */
497
498 static void
499 strip_obsoleted_to_delete( TargetImpl::PoolItemList & deleteList_r,
500                                 const TargetImpl::PoolItemList & instlist_r )
501 {
502   if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
503     return; // ---> nothing to do
504
505   // build obsoletes from instlist_r
506   CapSet obsoletes;
507   for ( TargetImpl::PoolItemList::const_iterator it = instlist_r.begin();
508         it != instlist_r.end(); ++it )
509   {
510     PoolItem_Ref item( *it );
511     obsoletes.insert( item->dep(Dep::OBSOLETES).begin(), item->dep(Dep::OBSOLETES).end() );
512   }
513   if ( obsoletes.size() == 0 )
514     return; // ---> nothing to do
515
516   // match them... ;(
517   TargetImpl::PoolItemList undelayed;
518   // forall applDelete Packages...
519   for ( TargetImpl::PoolItemList::iterator it = deleteList_r.begin();
520         it != deleteList_r.end(); ++it )
521   {
522     PoolItem_Ref ipkg( *it );
523     bool delayPkg = false;
524     // ...check whether an obsoletes....
525     for ( CapSet::iterator obs = obsoletes.begin();
526           ! delayPkg && obs != obsoletes.end(); ++obs )
527     {
528       // ...matches anything provided by the package?
529       for ( CapSet::const_iterator prov = ipkg->dep(Dep::PROVIDES).begin();
530             prov != ipkg->dep(Dep::PROVIDES).end(); ++prov )
531       {
532         if ( obs->matches( *prov ) == CapMatch::yes )
533         {
534           // if so, delay package deletion
535           DBG << "Ignore appl_delete (should be obsoleted): " << ipkg << endl;
536           delayPkg = true;
537           ipkg.status().setTransact( false, ResStatus::USER );
538           break;
539         }
540       }
541     }
542     if ( ! delayPkg ) {
543       DBG << "undelayed " << ipkg << endl;
544       undelayed.push_back( ipkg );
545     }
546   }
547   // Puhh...
548   deleteList_r.swap( undelayed );
549 }
550
551
552
553
554 void
555 TargetImpl::getResolvablesToInsDel ( const ResPool pool_r,
556                                     TargetImpl::PoolItemList & dellist_r,
557                                     TargetImpl::PoolItemList & instlist_r,
558                                     TargetImpl::PoolItemList & srclist_r ) const
559 {
560     dellist_r.clear();
561     instlist_r.clear();
562     srclist_r.clear();
563     TargetImpl::PoolItemList nonpkglist;
564
565     for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
566     {
567         if (it->status().isToBeInstalled())
568         {
569             if ((*it)->kind() == ResTraits<SrcPackage>::kind) {
570                 srclist_r.push_back( *it );
571             }
572             else if ((*it)->kind() != ResTraits<Package>::kind) {
573                 nonpkglist.push_back( *it );
574             }
575             else
576                 instlist_r.push_back( *it );
577         }
578         else if (it->status().isToBeUninstalled())
579         {
580             if ( it->status().isToBeUninstalledDueToObsolete() )
581             {
582                 DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
583             }
584             else if ( it->status().isToBeUninstalledDueToUpgrade() )
585             {
586                 DBG << "Ignore auto_delete (should be upgraded): " << *it << endl;
587             }
588             else {
589                 dellist_r.push_back( *it );
590             }
591         }
592     }
593
594     MIL << "ResolvablesToInsDel: delete " << dellist_r.size()
595       << ", install " << instlist_r.size()
596         << ", srcinstall " << srclist_r.size()
597           << ", nonpkg " << nonpkglist.size() << endl;
598
599     ///////////////////////////////////////////////////////////////////
600     //
601     // strip packages to_delete which get obsoleted by
602     // to_install (i.e. delay deletion in case the
603     // obsoleting package likes to save whatever...
604     //
605     ///////////////////////////////////////////////////////////////////
606     strip_obsoleted_to_delete( dellist_r, instlist_r );
607
608     if ( dellist_r.size() ) {
609       ///////////////////////////////////////////////////////////////////
610       //
611       // sort delete list...
612       //
613       ///////////////////////////////////////////////////////////////////
614       TargetImpl::PoolItemSet delset;  // for delete order
615       TargetImpl::PoolItemSet dummy; // dummy, empty, should contain already installed
616       for ( TargetImpl::PoolItemList::iterator pkgIt = dellist_r.begin();
617             pkgIt != dellist_r.end(); ++pkgIt )
618       {
619         delset.insert( *pkgIt );
620       }
621
622       InstallOrder order( pool_r, delset, dummy ); // sort according top prereq
623       order.init();
624       const TargetImpl::PoolItemList dsorted( order.getTopSorted() );
625
626       dellist_r.clear();
627       for ( TargetImpl::PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
628             cit != dsorted.rend(); ++cit )
629       {
630         dellist_r.push_back( *cit );
631       }
632     }
633
634     ///////////////////////////////////////////////////////////////////
635     //
636     // sort installed list...
637     //
638     ///////////////////////////////////////////////////////////////////
639     if ( instlist_r.empty() ) {
640       instlist_r.splice( instlist_r.end(), nonpkglist );
641
642       return;
643     }
644 #warning Source Rank Priority ?
645 #if 0
646     ///////////////////////////////////////////////////////////////////
647     // Get desired order of InstSrc'es to install from.
648     ///////////////////////////////////////////////////////////////////
649     typedef map<unsigned,unsigned> RankPriority;
650
651     RankPriority rankPriority;
652     {
653       InstSrcManager::ISrcIdList sourcerank( Y2PM::instSrcManager().instOrderSources() );
654       // map InstSrc rank to install priority
655       unsigned prio = 0;
656       for ( InstSrcManager::ISrcIdList::const_iterator it = sourcerank.begin();
657             it != sourcerank.end(); ++it, ++prio ) {
658         rankPriority[(*it)->descr()->default_rank()] = prio;
659       }
660     }
661 #endif
662
663     ///////////////////////////////////////////////////////////////////
664     // Compute install order according to packages prereq.
665     // Try to group packages with respect to the desired install order
666     ///////////////////////////////////////////////////////////////////
667     // backup list for debug purpose.
668     // You can as well build the set, clear the list and rebuild it in install order.
669     TargetImpl::PoolItemList instbackup_r;
670     instbackup_r.swap( instlist_r );
671
672     TargetImpl::PoolItemSet insset; // for install order
673     TargetImpl::PoolItemSet installed; // dummy, empty, should contain already installed
674     for ( TargetImpl::PoolItemList::iterator resIt = instbackup_r.begin(); resIt != instbackup_r.end(); ++resIt ) {
675       insset.insert( *resIt );
676     }
677     InstallOrder order( pool_r, insset, installed );
678     // start recursive depth-first-search
679     order.init();
680 MIL << "order.init() done" << endl;
681     order.printAdj( XXX, false );
682     ///////////////////////////////////////////////////////////////////
683     // build install list in install order
684     ///////////////////////////////////////////////////////////////////
685     TargetImpl::PoolItemList best_list;
686 //    unsigned best_prio     = 0;
687     unsigned best_medianum = 0;
688
689     TargetImpl::PoolItemList last_list;
690 //    unsigned last_prio     = 0;
691     unsigned last_medianum = 0;
692
693     TargetImpl::PoolItemList other_list;
694
695     for ( TargetImpl::PoolItemList items = order.computeNextSet(); ! items.empty(); items = order.computeNextSet() )
696     {
697 MIL << "order.computeNextSet: " << items.size() << " resolvables" << endl;
698       ///////////////////////////////////////////////////////////////////
699       // items contains all packages we could install now. Pick all packages
700       // from current media, or best media if none for current.
701       ///////////////////////////////////////////////////////////////////
702
703       best_list.clear();
704       last_list.clear();
705       other_list.clear();
706
707       for ( TargetImpl::PoolItemList::iterator cit = items.begin(); cit != items.end(); ++cit )
708       {
709         Resolvable::constPtr res( cit->resolvable() );
710         if (!res) continue;
711         Package::constPtr cpkg( asKind<Package>(res) );
712         if (!cpkg) {
713             XXX << "Not a package " << *cit << endl;
714             order.setInstalled( *cit );
715             other_list.push_back( *cit );
716             continue;
717         }
718         XXX << "Package " << *cpkg << ", media " << cpkg->mediaId() << " last_medianum " << last_medianum << " best_medianum " << best_medianum << endl;
719         if (                                                                    //  rankPriority[cpkg->instSrcRank()] == last_prio &&
720              cpkg->mediaId() == last_medianum ) {
721           // prefer packages on current media.
722           last_list.push_back( *cit );
723           continue;
724         }
725
726         if ( last_list.empty() ) {
727           // check for best media as long as there are no packages for current media.
728
729           if ( ! best_list.empty() ) {
730
731 #if 0
732             if ( rankPriority[cpkg->instSrcRank()] < best_prio ) {
733               best_list.clear(); // new best
734             } else if ( rankPriority[cpkg->instSrcRank()] == best_prio ) {
735 #endif
736
737               if ( cpkg->mediaId() < best_medianum ) {
738                 best_list.clear(); // new best
739               } else if ( cpkg->mediaId() == best_medianum ) {
740                 best_list.push_back( *cit ); // same as best -> add
741                 continue;
742               } else {
743                 continue; // worse
744               }
745 #if 0
746             } else {
747               continue; // worse
748             }
749 #endif
750           }
751
752           if ( best_list.empty() )
753           {
754             // first package or new best
755             best_list.push_back( *cit );
756 //          best_prio     = rankPriority[cpkg->instSrcRank()];
757             best_medianum = cpkg->mediaId();
758             continue;
759           }
760         }
761
762       } // for all packages in current set
763
764       ///////////////////////////////////////////////////////////////////
765       // remove packages picked from install order and append them to
766       // install list.
767       ///////////////////////////////////////////////////////////////////
768       TargetImpl::PoolItemList & take_list( last_list.empty() ? best_list : last_list );
769       if ( last_list.empty() )
770       {
771         MIL << "SET NEW media " << best_medianum << endl;
772 //      last_prio     = best_prio;
773         last_medianum = best_medianum;
774       }
775       else
776       {
777         MIL << "SET CONTINUE" << endl;
778       }
779
780       for ( TargetImpl::PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
781       {
782         order.setInstalled( *it );
783         XXX << "SET isrc " << (*it)->name() << endl;
784       }
785       // move everthing from take_list to the end of instlist_r, clean take_list
786       instlist_r.splice( instlist_r.end(), take_list );
787       // same for other_list
788       instlist_r.splice( instlist_r.end(), other_list );
789
790     } // for all sets computed
791
792
793     if ( instbackup_r.size() != instlist_r.size() )
794     {
795         ERR << "***************** Lost packages in InstallOrder sort." << endl;
796     }
797     instlist_r.splice( instlist_r.end(), nonpkglist );
798 }
799
800
801     /////////////////////////////////////////////////////////////////
802   } // namespace target
803   ///////////////////////////////////////////////////////////////////
804   /////////////////////////////////////////////////////////////////
805 } // namespace zypp
806 ///////////////////////////////////////////////////////////////////