~thopiekar/zypper/libzypp-manual-import

« back to all changes in this revision

Viewing changes to zypp/solver/detail/SATResolver.cc

  • Committer: Thomas-Karl Pietrowski
  • Date: 2014-01-29 22:44:28 UTC
  • Revision ID: thopiekar@googlemail.com-20140129224428-gpcqnsdakby362n8
firstĀ import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
2
/* SATResolver.cc
 
3
 *
 
4
 * Copyright (C) 2000-2002 Ximian, Inc.
 
5
 * Copyright (C) 2005 SUSE Linux Products GmbH
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License,
 
9
 * version 2, as published by the Free Software Foundation.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
extern "C"
 
22
{
 
23
#include <solv/repo_solv.h>
 
24
#include <solv/poolarch.h>
 
25
#include <solv/evr.h>
 
26
#include <solv/poolvendor.h>
 
27
#include <solv/policy.h>
 
28
#include <solv/bitmap.h>
 
29
#include <solv/queue.h>
 
30
}
 
31
 
 
32
#include "zypp/solver/detail/Helper.h"
 
33
#include "zypp/base/String.h"
 
34
#include "zypp/Product.h"
 
35
#include "zypp/Capability.h"
 
36
#include "zypp/ResStatus.h"
 
37
#include "zypp/VendorAttr.h"
 
38
#include "zypp/base/LogTools.h"
 
39
#include "zypp/base/String.h"
 
40
#include "zypp/base/Gettext.h"
 
41
#include "zypp/base/Algorithm.h"
 
42
#include "zypp/ResPool.h"
 
43
#include "zypp/ResFilters.h"
 
44
#include "zypp/ZConfig.h"
 
45
#include "zypp/sat/Pool.h"
 
46
#include "zypp/sat/WhatProvides.h"
 
47
#include "zypp/sat/WhatObsoletes.h"
 
48
#include "zypp/solver/detail/SATResolver.h"
 
49
#include "zypp/solver/detail/ProblemSolutionCombi.h"
 
50
#include "zypp/solver/detail/ProblemSolutionIgnore.h"
 
51
#include "zypp/solver/detail/SolverQueueItemInstall.h"
 
52
#include "zypp/solver/detail/SolverQueueItemDelete.h"
 
53
#include "zypp/solver/detail/SystemCheck.h"
 
54
#include "zypp/sat/Transaction.h"
 
55
#include "zypp/sat/Queue.h"
 
56
 
 
57
/////////////////////////////////////////////////////////////////////////
 
58
namespace zypp
 
59
{ ///////////////////////////////////////////////////////////////////////
 
60
  ///////////////////////////////////////////////////////////////////////
 
61
  namespace solver
 
62
  { /////////////////////////////////////////////////////////////////////
 
63
    /////////////////////////////////////////////////////////////////////
 
64
    namespace detail
 
65
    { ///////////////////////////////////////////////////////////////////
 
66
 
 
67
using namespace std;
 
68
 
 
69
IMPL_PTR_TYPE(SATResolver);
 
70
 
 
71
#define MAYBE_CLEANDEPS (cleandepsOnRemove()?SOLVER_CLEANDEPS:0)
 
72
 
 
73
//---------------------------------------------------------------------------
 
74
// Callbacks for SAT policies
 
75
//---------------------------------------------------------------------------
 
76
 
 
77
int vendorCheck( Pool *pool, Solvable *solvable1, Solvable *solvable2 )
 
78
{
 
79
  return VendorAttr::instance().equivalent( IdString(solvable1->vendor),
 
80
                                            IdString(solvable2->vendor) ) ? 0 : 1;
 
81
}
 
82
 
 
83
 
 
84
inline std::string itemToString( const PoolItem & item )
 
85
{
 
86
  if ( !item )
 
87
    return std::string();
 
88
 
 
89
  sat::Solvable slv( item.satSolvable() );
 
90
  std::string ret( slv.asString() ); // n-v-r.a
 
91
  if ( ! slv.isSystem() )
 
92
  {
 
93
    ret += "[";
 
94
    ret += slv.repository().alias();
 
95
    ret += "]";
 
96
  }
 
97
  return ret;
 
98
}
 
99
 
 
100
inline PoolItem getPoolItem( Id id_r )
 
101
{
 
102
  PoolItem ret( (sat::Solvable( id_r )) );
 
103
  if ( !ret && id_r )
 
104
    INT << "id " << id_r << " not found in ZYPP pool." << endl;
 
105
  return ret;
 
106
}
 
107
 
 
108
//---------------------------------------------------------------------------
 
109
 
 
110
std::ostream &
 
111
SATResolver::dumpOn( std::ostream & os ) const
 
112
{
 
113
    os << "<resolver>" << endl;
 
114
    if (_solv) {
 
115
        // os << "  fixsystem = " << _solv->fixsystem << endl;
 
116
        // os << "  updatesystem = " << _solv->updatesystem << endl;
 
117
        os << "  allowdowngrade = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_DOWNGRADE) << endl;
 
118
        os << "  allowarchchange = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_ARCHCHANGE) << endl;
 
119
        os << "  allowvendorchange = " <<  solver_get_flag(_solv, SOLVER_FLAG_ALLOW_VENDORCHANGE) << endl;
 
120
        os << "  allowuninstall = " << solver_get_flag(_solv, SOLVER_FLAG_ALLOW_UNINSTALL) << endl;
 
121
        os << "  noupdateprovide = " << solver_get_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE) << endl;
 
122
        os << "  dosplitprovides = " << solver_get_flag(_solv, SOLVER_FLAG_SPLITPROVIDES) << endl;
 
123
        os << "  onlyRequires = " << solver_get_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED) << endl;
 
124
        os << "  ignorealreadyrecommended = " << !solver_get_flag(_solv, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED) << endl;
 
125
        os << "  distupgrade = " << _distupgrade << endl;
 
126
        os << "  distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl;
 
127
        os << "  solveSrcPackages = " << _solveSrcPackages << endl;
 
128
        os << "  cleandepsOnRemove = " << _cleandepsOnRemove << endl;
 
129
    } else {
 
130
        os << "<NULL>";
 
131
    }
 
132
    return os << "<resolver/>" << endl;
 
133
}
 
134
 
 
135
//---------------------------------------------------------------------------
 
136
 
 
137
SATResolver::SATResolver (const ResPool & pool, Pool *SATPool)
 
138
    : _pool (pool)
 
139
    , _SATPool (SATPool)
 
140
    , _solv(NULL)
 
141
    , _fixsystem(false)
 
142
    , _allowdowngrade(false)
 
143
    , _allowarchchange(false)
 
144
    , _allowvendorchange(ZConfig::instance().solver_allowVendorChange())
 
145
    , _allowuninstall(false)
 
146
    , _updatesystem(false)
 
147
    , _noupdateprovide(false)
 
148
    , _dosplitprovides(false)
 
149
    , _onlyRequires(ZConfig::instance().solver_onlyRequires())
 
150
    , _ignorealreadyrecommended(false)
 
151
    , _distupgrade(false)
 
152
    , _distupgrade_removeunsupported(false)
 
153
    , _solveSrcPackages(false)
 
154
    , _cleandepsOnRemove(ZConfig::instance().solver_cleandepsOnRemove())
 
155
{
 
156
}
 
157
 
 
158
 
 
159
SATResolver::~SATResolver()
 
160
{
 
161
  solverEnd();
 
162
}
 
163
 
 
164
//---------------------------------------------------------------------------
 
165
 
 
166
ResPool
 
167
SATResolver::pool (void) const
 
168
{
 
169
    return _pool;
 
170
}
 
171
 
 
172
void
 
173
SATResolver::resetItemTransaction (PoolItem item)
 
174
{
 
175
    bool found = false;
 
176
    for (PoolItemList::const_iterator iter = _items_to_remove.begin();
 
177
         iter != _items_to_remove.end(); ++iter) {
 
178
        if (*iter == item) {
 
179
            _items_to_remove.remove(*iter);
 
180
            found = true;
 
181
            break;
 
182
        }
 
183
    }
 
184
    if (!found) {
 
185
        for (PoolItemList::const_iterator iter = _items_to_install.begin();
 
186
             iter != _items_to_install.end(); ++iter) {
 
187
            if (*iter == item) {
 
188
                _items_to_install.remove(*iter);
 
189
                found = true;
 
190
                break;
 
191
            }
 
192
        }
 
193
    }
 
194
    if (!found) {
 
195
        for (PoolItemList::const_iterator iter = _items_to_keep.begin();
 
196
             iter != _items_to_keep.end(); ++iter) {
 
197
            if (*iter == item) {
 
198
                _items_to_keep.remove(*iter);
 
199
                found = true;
 
200
                break;
 
201
            }
 
202
        }
 
203
    }
 
204
    if (!found) {
 
205
        for (PoolItemList::const_iterator iter = _items_to_lock.begin();
 
206
             iter != _items_to_lock.end(); ++iter) {
 
207
            if (*iter == item) {
 
208
                _items_to_lock.remove(*iter);
 
209
                found = true;
 
210
                break;
 
211
            }
 
212
        }
 
213
    }
 
214
}
 
215
 
 
216
 
 
217
void
 
218
SATResolver::addPoolItemToInstall (PoolItem item)
 
219
{
 
220
    resetItemTransaction (item);
 
221
    _items_to_install.push_back (item);
 
222
    _items_to_install.unique ();
 
223
}
 
224
 
 
225
 
 
226
void
 
227
SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
 
228
{
 
229
    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
 
230
        addPoolItemToInstall (*iter);
 
231
    }
 
232
}
 
233
 
 
234
 
 
235
void
 
236
SATResolver::addPoolItemToRemove (PoolItem item)
 
237
{
 
238
    resetItemTransaction (item);
 
239
    _items_to_remove.push_back (item);
 
240
    _items_to_remove.unique ();
 
241
}
 
242
 
 
243
 
 
244
void
 
245
SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
 
246
{
 
247
    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
 
248
        addPoolItemToRemove (*iter);
 
249
    }
 
250
}
 
251
 
 
252
void
 
253
SATResolver::addPoolItemToLock (PoolItem item)
 
254
{
 
255
    resetItemTransaction (item);
 
256
    _items_to_lock.push_back (item);
 
257
    _items_to_lock.unique ();
 
258
}
 
259
 
 
260
void
 
261
SATResolver::addPoolItemToKeep (PoolItem item)
 
262
{
 
263
    resetItemTransaction (item);
 
264
    _items_to_keep.push_back (item);
 
265
    _items_to_keep.unique ();
 
266
}
 
267
 
 
268
//---------------------------------------------------------------------------
 
269
 
 
270
// copy marked item from solution back to pool
 
271
// if data != NULL, set as APPL_LOW (from establishPool())
 
272
 
 
273
static void
 
274
SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
 
275
{
 
276
    // resetting
 
277
    item.status().resetTransact (causer);
 
278
    item.status().resetWeak ();
 
279
 
 
280
    bool r;
 
281
 
 
282
    // installation/deletion
 
283
    if (status.isToBeInstalled()) {
 
284
        r = item.status().setToBeInstalled (causer);
 
285
        _XDEBUG("SATSolutionToPool install returns " << item << ", " << r);
 
286
    }
 
287
    else if (status.isToBeUninstalledDueToUpgrade()) {
 
288
        r = item.status().setToBeUninstalledDueToUpgrade (causer);
 
289
        _XDEBUG("SATSolutionToPool upgrade returns " << item << ", " <<  r);
 
290
    }
 
291
    else if (status.isToBeUninstalled()) {
 
292
        r = item.status().setToBeUninstalled (causer);
 
293
        _XDEBUG("SATSolutionToPool remove returns " << item << ", " <<  r);
 
294
    }
 
295
 
 
296
    return;
 
297
}
 
298
 
 
299
//----------------------------------------------------------------------------
 
300
//----------------------------------------------------------------------------
 
301
// resolvePool
 
302
//----------------------------------------------------------------------------
 
303
//----------------------------------------------------------------------------
 
304
 
 
305
//----------------------------------------------------------------------------
 
306
// Helper functions for the ZYPP-Pool
 
307
//----------------------------------------------------------------------------
 
308
 
 
309
 
 
310
//------------------------------------------------------------------------------------------------------------
 
311
//  This function loops over the pool and grabs all items
 
312
//  It clears all previous bySolver() states also
 
313
//
 
314
//  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
 
315
//  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
 
316
//
 
317
//  Solver results must be written back to the pool.
 
318
//------------------------------------------------------------------------------------------------------------
 
319
 
 
320
 
 
321
struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
 
322
{
 
323
    SATResolver & resolver;
 
324
 
 
325
    SATCollectTransact (SATResolver & r)
 
326
        : resolver (r)
 
327
    { }
 
328
 
 
329
    bool operator()( PoolItem item )            // only transacts() items go here
 
330
    {
 
331
        ResStatus status = item.status();
 
332
        bool by_solver = (status.isBySolver() || status.isByApplLow());
 
333
 
 
334
        if (by_solver) {
 
335
            item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
 
336
            return true;                                // back out here, dont re-queue former solver result
 
337
        }
 
338
 
 
339
        if ( item.satSolvable().isKind<SrcPackage>() && ! resolver.solveSrcPackages() )
 
340
        {
 
341
          // Later we may continue on a per source package base.
 
342
          return true; // dont process this source package.
 
343
        }
 
344
 
 
345
        if (status.isToBeInstalled()) {
 
346
            resolver.addPoolItemToInstall(item);        // -> install!
 
347
        }
 
348
        else if (status.isToBeUninstalled()) {
 
349
            resolver.addPoolItemToRemove(item);         // -> remove !
 
350
        }
 
351
        else if (status.isLocked()
 
352
                 && !by_solver) {
 
353
            resolver.addPoolItemToLock (item);
 
354
        }
 
355
        else if (status.isKept()
 
356
                 && !by_solver) {
 
357
            resolver.addPoolItemToKeep (item);
 
358
        }
 
359
 
 
360
        return true;
 
361
    }
 
362
};
 
363
 
 
364
 
 
365
//----------------------------------------------------------------------------
 
366
//----------------------------------------------------------------------------
 
367
// solving.....
 
368
//----------------------------------------------------------------------------
 
369
//----------------------------------------------------------------------------
 
370
 
 
371
 
 
372
class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
 
373
{
 
374
  public:
 
375
    bool is_updated;
 
376
    bool multiversion;
 
377
    sat::Solvable _installed;
 
378
 
 
379
    CheckIfUpdate( sat::Solvable installed_r )
 
380
        : is_updated( false )
 
381
        , multiversion( installed_r.multiversionInstall() )
 
382
        , _installed( installed_r )
 
383
    {}
 
384
 
 
385
    // check this item will be updated
 
386
 
 
387
    bool operator()( PoolItem item )
 
388
    {
 
389
        if ( item.status().isToBeInstalled() )
 
390
        {
 
391
          if ( ! multiversion || sameNVRA( _installed, item ) )
 
392
          {
 
393
            is_updated = true;
 
394
            return false;
 
395
          }
 
396
        }
 
397
        return true;
 
398
    }
 
399
};
 
400
 
 
401
 
 
402
class CollectPseudoInstalled : public resfilter::PoolItemFilterFunctor
 
403
{
 
404
  public:
 
405
    Queue *solvableQueue;
 
406
 
 
407
    CollectPseudoInstalled( Queue *queue )
 
408
        :solvableQueue (queue)
 
409
    {}
 
410
 
 
411
    // collecting PseudoInstalled items
 
412
    bool operator()( PoolItem item )
 
413
    {
 
414
      if ( traits::isPseudoInstalled( item.satSolvable().kind() ) )
 
415
        queue_push( solvableQueue, item.satSolvable().id() );
 
416
      return true;
 
417
    }
 
418
};
 
419
 
 
420
bool
 
421
SATResolver::solving(const CapabilitySet & requires_caps,
 
422
                     const CapabilitySet & conflict_caps)
 
423
{
 
424
    _solv = solver_create( _SATPool );
 
425
    ::pool_set_custom_vendorcheck( _SATPool, &vendorCheck );
 
426
    if (_fixsystem) {
 
427
        queue_push( &(_jobQueue), SOLVER_VERIFY|SOLVER_SOLVABLE_ALL);
 
428
        queue_push( &(_jobQueue), 0 );
 
429
    }
 
430
    if (_updatesystem) {
 
431
        queue_push( &(_jobQueue), SOLVER_UPDATE|SOLVER_SOLVABLE_ALL);
 
432
        queue_push( &(_jobQueue), 0 );
 
433
    }
 
434
    if (_distupgrade) {
 
435
        queue_push( &(_jobQueue), SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_ALL);
 
436
        queue_push( &(_jobQueue), 0 );
 
437
    }
 
438
    if (_distupgrade_removeunsupported) {
 
439
        queue_push( &(_jobQueue), SOLVER_DROP_ORPHANED|SOLVER_SOLVABLE_ALL);
 
440
        queue_push( &(_jobQueue), 0 );
 
441
    }
 
442
    solver_set_flag(_solv, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED, !_ignorealreadyrecommended);
 
443
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_DOWNGRADE, _allowdowngrade);
 
444
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_UNINSTALL, _allowuninstall);
 
445
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_ARCHCHANGE, _allowarchchange);
 
446
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, _allowvendorchange);
 
447
    solver_set_flag(_solv, SOLVER_FLAG_SPLITPROVIDES, _dosplitprovides);
 
448
    solver_set_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide);
 
449
    solver_set_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED, _onlyRequires);
 
450
 
 
451
    sat::Pool::instance().prepareForSolving();
 
452
 
 
453
    // Solve !
 
454
    MIL << "Starting solving...." << endl;
 
455
    MIL << *this;
 
456
    solver_solve( _solv, &(_jobQueue) );
 
457
    MIL << "....Solver end" << endl;
 
458
 
 
459
    // copying solution back to zypp pool
 
460
    //-----------------------------------------
 
461
    _result_items_to_install.clear();
 
462
    _result_items_to_remove.clear();
 
463
 
 
464
    /*  solvables to be installed */
 
465
    Queue decisionq;
 
466
    queue_init(&decisionq);
 
467
    solver_get_decisionqueue(_solv, &decisionq);
 
468
    for ( int i = 0; i < decisionq.count; ++i )
 
469
    {
 
470
      sat::Solvable slv( decisionq.elements[i] );
 
471
      if ( !slv || slv.isSystem() )
 
472
        continue;
 
473
 
 
474
      PoolItem poolItem( slv );
 
475
      SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
 
476
      _result_items_to_install.push_back (poolItem);
 
477
    }
 
478
    queue_free(&decisionq);
 
479
 
 
480
    /* solvables to be erased */
 
481
    Repository systemRepo( sat::Pool::instance().findSystemRepo() ); // don't create if it does not exist
 
482
    if ( systemRepo && ! systemRepo.solvablesEmpty() )
 
483
    {
 
484
      bool mustCheckObsoletes = false;
 
485
      for_( it, systemRepo.solvablesBegin(), systemRepo.solvablesEnd() )
 
486
      {
 
487
        if (solver_get_decisionlevel(_solv, it->id()) > 0)
 
488
          continue;
 
489
 
 
490
        // Check if this is an update
 
491
        CheckIfUpdate info( *it );
 
492
        PoolItem poolItem( *it );
 
493
        invokeOnEach( _pool.byIdentBegin( poolItem ),
 
494
                      _pool.byIdentEnd( poolItem ),
 
495
                      resfilter::ByUninstalled(),                       // ByUninstalled
 
496
                      functor::functorRef<bool,PoolItem> (info) );
 
497
 
 
498
        if (info.is_updated) {
 
499
          SATSolutionToPool( poolItem, ResStatus::toBeUninstalledDueToUpgrade, ResStatus::SOLVER );
 
500
        } else {
 
501
          SATSolutionToPool( poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER );
 
502
          if ( ! mustCheckObsoletes )
 
503
            mustCheckObsoletes = true; // lazy check for UninstalledDueToObsolete
 
504
        }
 
505
        _result_items_to_remove.push_back (poolItem);
 
506
      }
 
507
      if ( mustCheckObsoletes )
 
508
      {
 
509
        sat::WhatObsoletes obsoleted( _result_items_to_install.begin(), _result_items_to_install.end() );
 
510
        for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() )
 
511
        {
 
512
          ResStatus & status( it->status() );
 
513
          // WhatObsoletes contains installed items only!
 
514
          if ( status.transacts() && ! status.isToBeUninstalledDueToUpgrade() )
 
515
            status.setToBeUninstalledDueToObsolete();
 
516
        }
 
517
      }
 
518
    }
 
519
 
 
520
    Queue recommendations;
 
521
    Queue suggestions;
 
522
    Queue orphaned;
 
523
    Queue unneeded;
 
524
    queue_init(&recommendations);
 
525
    queue_init(&suggestions);
 
526
    queue_init(&orphaned);
 
527
    queue_init(&unneeded);
 
528
    solver_get_recommendations(_solv, &recommendations, &suggestions, 0);
 
529
    solver_get_orphaned(_solv, &orphaned);
 
530
    solver_get_unneeded(_solv, &unneeded, 1);
 
531
    /*  solvables which are recommended */
 
532
    for ( int i = 0; i < recommendations.count; ++i )
 
533
    {
 
534
      PoolItem poolItem( getPoolItem( recommendations.elements[i] ) );
 
535
      poolItem.status().setRecommended( true );
 
536
    }
 
537
 
 
538
    /*  solvables which are suggested */
 
539
    for ( int i = 0; i < suggestions.count; ++i )
 
540
    {
 
541
      PoolItem poolItem( getPoolItem( suggestions.elements[i] ) );
 
542
      poolItem.status().setSuggested( true );
 
543
    }
 
544
 
 
545
    _problem_items.clear();
 
546
    /*  solvables which are orphaned */
 
547
    for ( int i = 0; i < orphaned.count; ++i )
 
548
    {
 
549
      PoolItem poolItem( getPoolItem( orphaned.elements[i] ) );
 
550
      poolItem.status().setOrphaned( true );
 
551
      _problem_items.push_back( poolItem );
 
552
    }
 
553
 
 
554
    /*  solvables which are unneeded */
 
555
    for ( int i = 0; i < unneeded.count; ++i )
 
556
    {
 
557
      PoolItem poolItem( getPoolItem( unneeded.elements[i] ) );
 
558
      poolItem.status().setUnneeded( true );
 
559
    }
 
560
 
 
561
    queue_free(&recommendations);
 
562
    queue_free(&suggestions);
 
563
    queue_free(&orphaned);
 
564
    queue_free(&unneeded);
 
565
 
 
566
    /* Write validation state back to pool */
 
567
    Queue flags, solvableQueue;
 
568
 
 
569
    queue_init(&flags);
 
570
    queue_init(&solvableQueue);
 
571
 
 
572
    CollectPseudoInstalled collectPseudoInstalled(&solvableQueue);
 
573
    invokeOnEach( _pool.begin(),
 
574
                  _pool.end(),
 
575
                  functor::functorRef<bool,PoolItem> (collectPseudoInstalled) );
 
576
    solver_trivial_installable(_solv, &solvableQueue, &flags );
 
577
    for (int i = 0; i < solvableQueue.count; i++) {
 
578
        PoolItem item = _pool.find (sat::Solvable(solvableQueue.elements[i]));
 
579
        item.status().setUndetermined();
 
580
 
 
581
        if (flags.elements[i] == -1) {
 
582
            item.status().setNonRelevant();
 
583
            _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
 
584
        } else if (flags.elements[i] == 1) {
 
585
            item.status().setSatisfied();
 
586
            _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
 
587
        } else if (flags.elements[i] == 0) {
 
588
            item.status().setBroken();
 
589
            _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
 
590
        }
 
591
    }
 
592
    queue_free(&(solvableQueue));
 
593
    queue_free(&flags);
 
594
 
 
595
 
 
596
    // Solvables which were selected due requirements which have been made by the user will
 
597
    // be selected by APPL_LOW. We can't use any higher level, because this setting must
 
598
    // not serve as a request for the next solver run. APPL_LOW is reset before solving.
 
599
    for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
 
600
        sat::WhatProvides rpmProviders(*iter);
 
601
        for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
 
602
            PoolItem poolItem(*iter2);
 
603
            if (poolItem.status().isToBeInstalled()) {
 
604
                MIL << "User requirement " << *iter << " sets " << poolItem << endl;
 
605
                poolItem.status().setTransactByValue (ResStatus::APPL_LOW);
 
606
            }
 
607
        }
 
608
    }
 
609
    for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
 
610
        sat::WhatProvides rpmProviders(*iter);
 
611
        for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
 
612
            PoolItem poolItem(*iter2);
 
613
            if (poolItem.status().isToBeUninstalled()) {
 
614
                MIL << "User conflict " << *iter << " sets " << poolItem << endl;
 
615
                poolItem.status().setTransactByValue (ResStatus::APPL_LOW);
 
616
            }
 
617
        }
 
618
    }
 
619
 
 
620
    if (solver_problem_count(_solv) > 0 )
 
621
    {
 
622
        ERR << "Solverrun finished with an ERROR" << endl;
 
623
        return false;
 
624
    }
 
625
 
 
626
    return true;
 
627
}
 
628
 
 
629
 
 
630
void
 
631
SATResolver::solverInit(const PoolItemList & weakItems)
 
632
{
 
633
    SATCollectTransact info (*this);
 
634
 
 
635
    MIL << "SATResolver::solverInit()" << endl;
 
636
 
 
637
    // remove old stuff
 
638
    solverEnd();
 
639
 
 
640
    queue_init( &_jobQueue );
 
641
    _items_to_install.clear();
 
642
    _items_to_remove.clear();
 
643
    _items_to_lock.clear();
 
644
    _items_to_keep.clear();
 
645
 
 
646
    invokeOnEach ( _pool.begin(), _pool.end(),
 
647
                   functor::functorRef<bool,PoolItem>(info) );
 
648
 
 
649
    for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) {
 
650
        Id id = (*iter)->satSolvable().id();
 
651
        if (id == ID_NULL) {
 
652
            ERR << "Weaken: " << *iter << " not found" << endl;
 
653
        }
 
654
        MIL << "Weaken dependencies of " << *iter << endl;
 
655
        queue_push( &(_jobQueue), SOLVER_WEAKENDEPS | SOLVER_SOLVABLE );
 
656
        queue_push( &(_jobQueue), id );
 
657
    }
 
658
 
 
659
    // Add rules for parallel installable resolvables with different versions
 
660
    for_( it, sat::Pool::instance().multiversionBegin(), sat::Pool::instance().multiversionEnd() )
 
661
    {
 
662
      queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE_NAME );
 
663
      queue_push( &(_jobQueue), it->id() );
 
664
    }
 
665
 
 
666
    if ( cleandepsOnRemove() )
 
667
    {
 
668
      // Add all items known to be installed by user request (not solver selected).
 
669
      for_( it, sat::Pool::instance().onSystemByUserBegin(), sat::Pool::instance().onSystemByUserEnd() )
 
670
      {
 
671
        queue_push( &(_jobQueue), SOLVER_USERINSTALLED | SOLVER_SOLVABLE_NAME );
 
672
        queue_push( &(_jobQueue), it->id() );
 
673
      }
 
674
    }
 
675
 
 
676
    if ( _distupgrade )
 
677
    {
 
678
      if ( ZConfig::instance().solverUpgradeRemoveDroppedPackages() )
 
679
      {
 
680
        MIL << "Checking droplists ..." << endl;
 
681
        // Dropped packages: look for 'weakremover()' provides
 
682
        // in dup candidates of installed products.
 
683
        ResPoolProxy proxy( ResPool::instance().proxy() );
 
684
        for_( it, proxy.byKindBegin<Product>(), proxy.byKindEnd<Product>() )
 
685
        {
 
686
          if ( (*it)->onSystem() ) // (to install) or (not to delete)
 
687
          {
 
688
            Product::constPtr prodCand( (*it)->candidateAsKind<Product>() );
 
689
            if ( ! prodCand )
 
690
              continue; // product no longer available
 
691
 
 
692
            CapabilitySet droplist( prodCand->droplist() );
 
693
            dumpRangeLine( MIL << "Droplist for " << (*it)->candidateObj() << ": " << droplist.size() << " ", droplist.begin(), droplist.end() ) << endl;
 
694
            for_( cap, droplist.begin(), droplist.end() )
 
695
            {
 
696
              queue_push( &_jobQueue, SOLVER_DROP_ORPHANED | SOLVER_SOLVABLE_NAME );
 
697
              queue_push( &_jobQueue, cap->id() );
 
698
            }
 
699
          }
 
700
        }
 
701
      }
 
702
      else
 
703
      {
 
704
        MIL << "Droplist processing is disabled." << endl;
 
705
      }
 
706
    }
 
707
}
 
708
 
 
709
void
 
710
SATResolver::solverEnd()
 
711
{
 
712
  // cleanup
 
713
  if ( _solv )
 
714
  {
 
715
    solver_free(_solv);
 
716
    _solv = NULL;
 
717
    queue_free( &(_jobQueue) );
 
718
  }
 
719
}
 
720
 
 
721
 
 
722
bool
 
723
SATResolver::resolvePool(const CapabilitySet & requires_caps,
 
724
                         const CapabilitySet & conflict_caps,
 
725
                         const PoolItemList & weakItems,
 
726
                         const std::set<Repository> & upgradeRepos)
 
727
{
 
728
    MIL << "SATResolver::resolvePool()" << endl;
 
729
 
 
730
    // initialize
 
731
    solverInit(weakItems);
 
732
 
 
733
    for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
 
734
        Id id = (*iter)->satSolvable().id();
 
735
        if (id == ID_NULL) {
 
736
            ERR << "Install: " << *iter << " not found" << endl;
 
737
        } else {
 
738
            MIL << "Install " << *iter << endl;
 
739
            queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE );
 
740
            queue_push( &(_jobQueue), id );
 
741
        }
 
742
    }
 
743
 
 
744
    for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
 
745
        Id id = (*iter)->satSolvable().id();
 
746
        if (id == ID_NULL) {
 
747
            ERR << "Delete: " << *iter << " not found" << endl;
 
748
        } else {
 
749
            MIL << "Delete " << *iter << endl;
 
750
            queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE | MAYBE_CLEANDEPS );
 
751
            queue_push( &(_jobQueue), id);
 
752
        }
 
753
    }
 
754
 
 
755
    for_( iter, upgradeRepos.begin(), upgradeRepos.end() )
 
756
    {
 
757
        queue_push( &(_jobQueue), SOLVER_DISTUPGRADE | SOLVER_SOLVABLE_REPO );
 
758
        queue_push( &(_jobQueue), iter->get()->repoid );
 
759
        MIL << "Upgrade repo " << *iter << endl;
 
760
    }
 
761
 
 
762
    for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
 
763
        queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES );
 
764
        queue_push( &(_jobQueue), iter->id() );
 
765
        MIL << "Requires " << *iter << endl;
 
766
    }
 
767
 
 
768
    for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
 
769
        queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS );
 
770
        queue_push( &(_jobQueue), iter->id() );
 
771
        MIL << "Conflicts " << *iter << endl;
 
772
    }
 
773
 
 
774
    // set requirements for a running system
 
775
    setSystemRequirements();
 
776
 
 
777
    // set locks for the solver
 
778
    setLocks();
 
779
 
 
780
    // solving
 
781
    bool ret = solving(requires_caps, conflict_caps);
 
782
 
 
783
    (ret?MIL:WAR) << "SATResolver::resolvePool() done. Ret:" << ret <<  endl;
 
784
    return ret;
 
785
}
 
786
 
 
787
 
 
788
bool
 
789
SATResolver::resolveQueue(const SolverQueueItemList &requestQueue,
 
790
                          const PoolItemList & weakItems)
 
791
{
 
792
    MIL << "SATResolver::resolvQueue()" << endl;
 
793
 
 
794
    // initialize
 
795
    solverInit(weakItems);
 
796
 
 
797
    // generate solver queue
 
798
    for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) {
 
799
        (*iter)->addRule(_jobQueue);
 
800
    }
 
801
 
 
802
    // Add addition item status to the resolve-queue cause these can be set by problem resolutions
 
803
    for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
 
804
        Id id = (*iter)->satSolvable().id();
 
805
        if (id == ID_NULL) {
 
806
            ERR << "Install: " << *iter << " not found" << endl;
 
807
        } else {
 
808
            MIL << "Install " << *iter << endl;
 
809
            queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE );
 
810
            queue_push( &(_jobQueue), id );
 
811
        }
 
812
    }
 
813
    for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
 
814
        sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
 
815
        MIL << "Delete " << *iter << ident << endl;
 
816
        queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | MAYBE_CLEANDEPS );
 
817
        queue_push( &(_jobQueue), ident);
 
818
    }
 
819
 
 
820
    // set requirements for a running system
 
821
    setSystemRequirements();
 
822
 
 
823
    // set locks for the solver
 
824
    setLocks();
 
825
 
 
826
    // solving
 
827
    bool ret = solving();
 
828
 
 
829
    MIL << "SATResolver::resolveQueue() done. Ret:" << ret <<  endl;
 
830
    return ret;
 
831
}
 
832
 
 
833
/** \todo duplicate code to be joined with \ref solving. */
 
834
void SATResolver::doUpdate()
 
835
{
 
836
    MIL << "SATResolver::doUpdate()" << endl;
 
837
 
 
838
    // initialize
 
839
    solverInit(PoolItemList());
 
840
 
 
841
    // set requirements for a running system
 
842
    setSystemRequirements();
 
843
 
 
844
    // set locks for the solver
 
845
    setLocks();
 
846
 
 
847
    _solv = solver_create( _SATPool );
 
848
    ::pool_set_custom_vendorcheck( _SATPool, &vendorCheck );
 
849
    if (_fixsystem) {
 
850
        queue_push( &(_jobQueue), SOLVER_VERIFY|SOLVER_SOLVABLE_ALL);
 
851
        queue_push( &(_jobQueue), 0 );
 
852
    }
 
853
    if (1) {
 
854
        queue_push( &(_jobQueue), SOLVER_UPDATE|SOLVER_SOLVABLE_ALL);
 
855
        queue_push( &(_jobQueue), 0 );
 
856
    }
 
857
    if (_distupgrade) {
 
858
        queue_push( &(_jobQueue), SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_ALL);
 
859
        queue_push( &(_jobQueue), 0 );
 
860
    }
 
861
    if (_distupgrade_removeunsupported) {
 
862
        queue_push( &(_jobQueue), SOLVER_DROP_ORPHANED|SOLVER_SOLVABLE_ALL);
 
863
        queue_push( &(_jobQueue), 0 );
 
864
    }
 
865
    solver_set_flag(_solv, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED, !_ignorealreadyrecommended);
 
866
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_DOWNGRADE, _allowdowngrade);
 
867
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_UNINSTALL, _allowuninstall);
 
868
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_ARCHCHANGE, _allowarchchange);
 
869
    solver_set_flag(_solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, _allowvendorchange);
 
870
    solver_set_flag(_solv, SOLVER_FLAG_SPLITPROVIDES, _dosplitprovides);
 
871
    solver_set_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide);
 
872
    solver_set_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED, _onlyRequires);
 
873
 
 
874
    sat::Pool::instance().prepareForSolving();
 
875
 
 
876
    // Solve !
 
877
    MIL << "Starting solving for update...." << endl;
 
878
    MIL << *this;
 
879
    solver_solve( _solv, &(_jobQueue) );
 
880
    MIL << "....Solver end" << endl;
 
881
 
 
882
    // copying solution back to zypp pool
 
883
    //-----------------------------------------
 
884
 
 
885
    /*  solvables to be installed */
 
886
    Queue decisionq;
 
887
    queue_init(&decisionq);
 
888
    solver_get_decisionqueue(_solv, &decisionq);
 
889
    for (int i = 0; i < decisionq.count; i++)
 
890
    {
 
891
      Id p;
 
892
      p = decisionq.elements[i];
 
893
      if (p < 0 || !sat::Solvable(p))
 
894
        continue;
 
895
      if (sat::Solvable(p).repository().get() == _solv->pool->installed)
 
896
        continue;
 
897
 
 
898
      PoolItem poolItem = _pool.find (sat::Solvable(p));
 
899
      if (poolItem) {
 
900
          SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
 
901
      } else {
 
902
          ERR << "id " << p << " not found in ZYPP pool." << endl;
 
903
      }
 
904
    }
 
905
    queue_free(&decisionq);
 
906
 
 
907
    /* solvables to be erased */
 
908
    for (int i = _solv->pool->installed->start; i < _solv->pool->installed->start + _solv->pool->installed->nsolvables; i++)
 
909
    {
 
910
      if (solver_get_decisionlevel(_solv, i) > 0)
 
911
          continue;
 
912
 
 
913
      PoolItem poolItem( _pool.find( sat::Solvable(i) ) );
 
914
      if (poolItem) {
 
915
          // Check if this is an update
 
916
          CheckIfUpdate info( (sat::Solvable(i)) );
 
917
          invokeOnEach( _pool.byIdentBegin( poolItem ),
 
918
                        _pool.byIdentEnd( poolItem ),
 
919
                        resfilter::ByUninstalled(),                     // ByUninstalled
 
920
                        functor::functorRef<bool,PoolItem> (info) );
 
921
 
 
922
          if (info.is_updated) {
 
923
              SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
 
924
          } else {
 
925
              SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
 
926
          }
 
927
      } else {
 
928
          ERR << "id " << i << " not found in ZYPP pool." << endl;
 
929
      }
 
930
    }
 
931
    MIL << "SATResolver::doUpdate() done" << endl;
 
932
}
 
933
 
 
934
 
 
935
 
 
936
//----------------------------------------------------------------------------
 
937
//----------------------------------------------------------------------------
 
938
// error handling
 
939
//----------------------------------------------------------------------------
 
940
//----------------------------------------------------------------------------
 
941
 
 
942
//----------------------------------------------------------------------------
 
943
// helper function
 
944
//----------------------------------------------------------------------------
 
945
 
 
946
struct FindPackage : public resfilter::ResObjectFilterFunctor
 
947
{
 
948
    ProblemSolutionCombi *problemSolution;
 
949
    TransactionKind action;
 
950
    FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
 
951
       : problemSolution (p)
 
952
       , action (act)
 
953
        {
 
954
        }
 
955
 
 
956
    bool operator()( PoolItem p)
 
957
   {
 
958
       problemSolution->addSingleAction (p, action);
 
959
       return true;
 
960
   }
 
961
};
 
962
 
 
963
 
 
964
//----------------------------------------------------------------------------
 
965
// Checking if this solvable/item has a buddy which reflect the real
 
966
// user visible description of an item
 
967
// e.g. The release package has a buddy to the concerning product item.
 
968
// This user want's the message "Product foo conflicts with product bar" and
 
969
// NOT "package release-foo conflicts with package release-bar"
 
970
// (ma: that's why we should map just packages to buddies, not vice versa)
 
971
//----------------------------------------------------------------------------
 
972
inline sat::Solvable mapBuddy( const PoolItem & item_r )
 
973
{
 
974
  if ( item_r.satSolvable().isKind<Package>() )
 
975
  {
 
976
    sat::Solvable buddy = item_r.buddy();
 
977
    if ( buddy )
 
978
      return buddy;
 
979
  }
 
980
  return item_r.satSolvable();
 
981
}
 
982
inline sat::Solvable mapBuddy( sat::Solvable item_r )
 
983
{ return mapBuddy( PoolItem( item_r ) ); }
 
984
 
 
985
PoolItem SATResolver::mapItem ( const PoolItem & item )
 
986
{ return PoolItem( mapBuddy( item ) ); }
 
987
 
 
988
sat::Solvable SATResolver::mapSolvable ( const Id & id )
 
989
{ return mapBuddy( sat::Solvable(id) ); }
 
990
 
 
991
string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreId)
 
992
{
 
993
  string ret;
 
994
  Pool *pool = _solv->pool;
 
995
  Id probr;
 
996
  Id dep, source, target;
 
997
  sat::Solvable s, s2;
 
998
 
 
999
  ignoreId = 0;
 
1000
  probr = solver_findproblemrule(_solv, problem);
 
1001
  switch (solver_ruleinfo(_solv, probr, &source, &target, &dep))
 
1002
  {
 
1003
      case SOLVER_RULE_DISTUPGRADE:
 
1004
          s = mapSolvable (source);
 
1005
          ret = str::form (_("%s does not belong to a distupgrade repository"), s.asString().c_str());
 
1006
          break;
 
1007
      case SOLVER_RULE_INFARCH:
 
1008
          s = mapSolvable (source);
 
1009
          ret = str::form (_("%s has inferior architecture"), s.asString().c_str());
 
1010
          break;
 
1011
      case SOLVER_RULE_UPDATE:
 
1012
          s = mapSolvable (source);
 
1013
          ret = str::form (_("problem with installed package %s"), s.asString().c_str());
 
1014
          break;
 
1015
      case SOLVER_RULE_JOB:
 
1016
          ret = _("conflicting requests");
 
1017
          break;
 
1018
      case SOLVER_RULE_RPM:
 
1019
          ret = _("some dependency problem");
 
1020
          break;
 
1021
      case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
 
1022
          ret = str::form (_("nothing provides requested %s"), pool_dep2str(pool, dep));
 
1023
          detail += _("Have you enabled all requested repositories?");
 
1024
          break;
 
1025
      case SOLVER_RULE_JOB_UNKNOWN_PACKAGE:
 
1026
          ret = str::form (_("package %s does not exist"), pool_dep2str(pool, dep));
 
1027
          detail += _("Have you enabled all requested repositories?");
 
1028
          break;
 
1029
      case SOLVER_RULE_JOB_UNSUPPORTED:
 
1030
          ret = _("unsupported request");
 
1031
          break;
 
1032
      case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
 
1033
          ret = str::form (_("%s is provided by the system and cannot be erased"), pool_dep2str(pool, dep));
 
1034
          break;
 
1035
      case SOLVER_RULE_RPM_NOT_INSTALLABLE:
 
1036
          s = mapSolvable (source);
 
1037
          ret = str::form (_("%s is not installable"), s.asString().c_str());
 
1038
          break;
 
1039
      case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
 
1040
          ignoreId = source; // for setting weak dependencies
 
1041
          s = mapSolvable (source);
 
1042
          ret = str::form (_("nothing provides %s needed by %s"), pool_dep2str(pool, dep), s.asString().c_str());
 
1043
          break;
 
1044
      case SOLVER_RULE_RPM_SAME_NAME:
 
1045
          s = mapSolvable (source);
 
1046
          s2 = mapSolvable (target);
 
1047
          ret = str::form (_("cannot install both %s and %s"), s.asString().c_str(), s2.asString().c_str());
 
1048
          break;
 
1049
      case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
 
1050
          s = mapSolvable (source);
 
1051
          s2 = mapSolvable (target);
 
1052
          ret = str::form (_("%s conflicts with %s provided by %s"), s.asString().c_str(), pool_dep2str(pool, dep), s2.asString().c_str());
 
1053
          break;
 
1054
      case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
 
1055
          s = mapSolvable (source);
 
1056
          s2 = mapSolvable (target);
 
1057
          ret = str::form (_("%s obsoletes %s provided by %s"), s.asString().c_str(), pool_dep2str(pool, dep), s2.asString().c_str());
 
1058
          break;
 
1059
      case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES:
 
1060
          s = mapSolvable (source);
 
1061
          s2 = mapSolvable (target);
 
1062
          ret = str::form (_("installed %s obsoletes %s provided by %s"), s.asString().c_str(), pool_dep2str(pool, dep), s2.asString().c_str());
 
1063
          break;
 
1064
      case SOLVER_RULE_RPM_SELF_CONFLICT:
 
1065
          s = mapSolvable (source);
 
1066
          ret = str::form (_("solvable %s conflicts with %s provided by itself"), s.asString().c_str(), pool_dep2str(pool, dep));
 
1067
          break;
 
1068
      case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
 
1069
          ignoreId = source; // for setting weak dependencies
 
1070
          s = mapSolvable (source);
 
1071
          Capability cap(dep);
 
1072
          sat::WhatProvides possibleProviders(cap);
 
1073
 
 
1074
          // check, if a provider will be deleted
 
1075
          typedef list<PoolItem> ProviderList;
 
1076
          ProviderList providerlistInstalled, providerlistUninstalled;
 
1077
          for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
 
1078
              PoolItem provider1 = ResPool::instance().find( *iter1 );
 
1079
              // find pair of an installed/uninstalled item with the same NVR
 
1080
              bool found = false;
 
1081
              for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
 
1082
                  PoolItem provider2 = ResPool::instance().find( *iter2 );
 
1083
                  if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
 
1084
                      && ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
 
1085
                          || (provider2.status().isInstalled() && provider1.status().isUninstalled()) ))  {
 
1086
                      found = true;
 
1087
                      break;
 
1088
                  }
 
1089
              }
 
1090
              if (!found) {
 
1091
                  if (provider1.status().isInstalled())
 
1092
                      providerlistInstalled.push_back(provider1);
 
1093
                  else
 
1094
                      providerlistUninstalled.push_back(provider1);
 
1095
              }
 
1096
          }
 
1097
 
 
1098
          ret = str::form (_("%s requires %s, but this requirement cannot be provided"), s.asString().c_str(), pool_dep2str(pool, dep));
 
1099
          if (providerlistInstalled.size() > 0) {
 
1100
              detail += _("deleted providers: ");
 
1101
              for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
 
1102
                  if (iter == providerlistInstalled.begin())
 
1103
                      detail += itemToString( *iter );
 
1104
                  else
 
1105
                      detail += "\n                   " + itemToString( mapItem(*iter) );
 
1106
              }
 
1107
          }
 
1108
          if (providerlistUninstalled.size() > 0) {
 
1109
              if (detail.size() > 0)
 
1110
                  detail += _("\nuninstallable providers: ");
 
1111
              else
 
1112
                  detail = _("uninstallable providers: ");
 
1113
              for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
 
1114
                  if (iter == providerlistUninstalled.begin())
 
1115
                      detail += itemToString( *iter );
 
1116
                  else
 
1117
                      detail += "\n                   " + itemToString( mapItem(*iter) );
 
1118
              }
 
1119
          }
 
1120
          break;
 
1121
  }
 
1122
 
 
1123
  return ret;
 
1124
}
 
1125
 
 
1126
ResolverProblemList
 
1127
SATResolver::problems ()
 
1128
{
 
1129
    ResolverProblemList resolverProblems;
 
1130
    if (_solv && solver_problem_count(_solv)) {
 
1131
        Pool *pool = _solv->pool;
 
1132
        int pcnt;
 
1133
        Id p, rp, what;
 
1134
        Id problem, solution, element;
 
1135
        sat::Solvable s, sd;
 
1136
 
 
1137
        CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
 
1138
        CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
 
1139
 
 
1140
        MIL << "Encountered problems! Here are the solutions:\n" << endl;
 
1141
        pcnt = 1;
 
1142
        problem = 0;
 
1143
        while ((problem = solver_next_problem(_solv, problem)) != 0) {
 
1144
            MIL << "Problem " <<  pcnt++ << ":" << endl;
 
1145
            MIL << "====================================" << endl;
 
1146
            string detail;
 
1147
            Id ignoreId;
 
1148
            string whatString = SATprobleminfoString (problem,detail,ignoreId);
 
1149
            MIL << whatString << endl;
 
1150
            MIL << "------------------------------------" << endl;
 
1151
            ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
 
1152
 
 
1153
            solution = 0;
 
1154
            while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
 
1155
                element = 0;
 
1156
                ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
 
1157
                while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
 
1158
                    if (p == SOLVER_SOLUTION_JOB) {
 
1159
                        /* job, rp is index into job queue */
 
1160
                        what = _jobQueue.elements[rp];
 
1161
                        switch (_jobQueue.elements[rp-1]&(SOLVER_SELECTMASK|SOLVER_JOBMASK))
 
1162
                        {
 
1163
                            case SOLVER_INSTALL | SOLVER_SOLVABLE: {
 
1164
                                s = mapSolvable (what);
 
1165
                                PoolItem poolItem = _pool.find (s);
 
1166
                                if (poolItem) {
 
1167
                                    if (pool->installed && s.get()->repo == pool->installed) {
 
1168
                                        problemSolution->addSingleAction (poolItem, REMOVE);
 
1169
                                        string description = str::form (_("do not keep %s installed"),  s.asString().c_str() );
 
1170
                                        MIL << description << endl;
 
1171
                                        problemSolution->addDescription (description);
 
1172
                                    } else {
 
1173
                                        problemSolution->addSingleAction (poolItem, KEEP);
 
1174
                                        string description = str::form (_("do not install %s"), s.asString().c_str());
 
1175
                                        MIL << description << endl;
 
1176
                                        problemSolution->addDescription (description);
 
1177
                                    }
 
1178
                                } else {
 
1179
                                    ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl;
 
1180
                                }
 
1181
                            }
 
1182
                                break;
 
1183
                            case SOLVER_ERASE | SOLVER_SOLVABLE: {
 
1184
                                s = mapSolvable (what);
 
1185
                                PoolItem poolItem = _pool.find (s);
 
1186
                                if (poolItem) {
 
1187
                                    if (pool->installed && s.get()->repo == pool->installed) {
 
1188
                                        problemSolution->addSingleAction (poolItem, KEEP);
 
1189
                                        string description = str::form (_("keep %s"), s.asString().c_str());
 
1190
                                        MIL << description << endl;
 
1191
                                        problemSolution->addDescription (description);
 
1192
                                    } else {
 
1193
                                        problemSolution->addSingleAction (poolItem, UNLOCK);
 
1194
                                        string description = str::form (_("do not forbid installation of %s"), itemToString( poolItem ).c_str());
 
1195
                                        MIL << description << endl;
 
1196
                                        problemSolution->addDescription (description);
 
1197
                                    }
 
1198
                                } else {
 
1199
                                    ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << s.asString() << endl;
 
1200
                                }
 
1201
                            }
 
1202
                                break;
 
1203
                            case SOLVER_INSTALL | SOLVER_SOLVABLE_NAME:
 
1204
                                {
 
1205
                                IdString ident( what );
 
1206
                                SolverQueueItemInstall_Ptr install =
 
1207
                                    new SolverQueueItemInstall(_pool, ident.asString(), false );
 
1208
                                problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM);
 
1209
 
 
1210
                                string description = str::form (_("do not install %s"), ident.c_str() );
 
1211
                                MIL << description << endl;
 
1212
                                problemSolution->addDescription (description);
 
1213
                                }
 
1214
                                break;
 
1215
                            case SOLVER_ERASE | SOLVER_SOLVABLE_NAME:
 
1216
                                {
 
1217
                                // As we do not know, if this request has come from resolvePool or
 
1218
                                // resolveQueue we will have to take care for both cases.
 
1219
                                IdString ident( what );
 
1220
                                FindPackage info (problemSolution, KEEP);
 
1221
                                invokeOnEach( _pool.byIdentBegin( ident ),
 
1222
                                              _pool.byIdentEnd( ident ),
 
1223
                                              functor::chain (resfilter::ByInstalled (),                        // ByInstalled
 
1224
                                                              resfilter::ByTransact ()),                        // will be deinstalled
 
1225
                                              functor::functorRef<bool,PoolItem> (info) );
 
1226
 
 
1227
                                SolverQueueItemDelete_Ptr del =
 
1228
                                    new SolverQueueItemDelete(_pool, ident.asString(), false );
 
1229
                                problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM);
 
1230
 
 
1231
                                string description = str::form (_("keep %s"), ident.c_str());
 
1232
                                MIL << description << endl;
 
1233
                                problemSolution->addDescription (description);
 
1234
                                }
 
1235
                                break;
 
1236
                            case SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES:
 
1237
                                {
 
1238
                                problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_REQUIRE);
 
1239
                                string description = "";
 
1240
 
 
1241
                                // Checking if this problem solution would break your system
 
1242
                                if (system_requires.find(Capability(what)) != system_requires.end()) {
 
1243
                                    // Show a better warning
 
1244
                                    resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() );
 
1245
                                    resolverProblem->setDescription(_("This request will break your system!"));
 
1246
                                    description = _("ignore the warning of a broken system");
 
1247
                                    description += string(" (requires:")+pool_dep2str(pool, what)+")";
 
1248
                                    MIL << description << endl;
 
1249
                                    problemSolution->addFrontDescription (description);
 
1250
                                } else {
 
1251
                                    description = str::form (_("do not ask to install a solvable providing %s"), pool_dep2str(pool, what));
 
1252
                                    MIL << description << endl;
 
1253
                                    problemSolution->addDescription (description);
 
1254
                                }
 
1255
                                }
 
1256
                                break;
 
1257
                            case SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES:
 
1258
                                {
 
1259
                                problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_CONFLICT);
 
1260
                                string description = "";
 
1261
 
 
1262
                                // Checking if this problem solution would break your system
 
1263
                                if (system_conflicts.find(Capability(what)) != system_conflicts.end()) {
 
1264
                                    // Show a better warning
 
1265
                                    resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() );
 
1266
                                    resolverProblem->setDescription(_("This request will break your system!"));
 
1267
                                    description = _("ignore the warning of a broken system");
 
1268
                                    description += string(" (conflicts:")+pool_dep2str(pool, what)+")";
 
1269
                                    MIL << description << endl;
 
1270
                                    problemSolution->addFrontDescription (description);
 
1271
 
 
1272
                                } else {
 
1273
                                    description = str::form (_("do not ask to delete all solvables providing %s"), pool_dep2str(pool, what));
 
1274
                                    MIL << description << endl;
 
1275
                                    problemSolution->addDescription (description);
 
1276
                                }
 
1277
                                }
 
1278
                                break;
 
1279
                            case SOLVER_UPDATE | SOLVER_SOLVABLE:
 
1280
                                {
 
1281
                                s = mapSolvable (what);
 
1282
                                PoolItem poolItem = _pool.find (s);
 
1283
                                if (poolItem) {
 
1284
                                    if (pool->installed && s.get()->repo == pool->installed) {
 
1285
                                        problemSolution->addSingleAction (poolItem, KEEP);
 
1286
                                        string description = str::form (_("do not install most recent version of %s"), s.asString().c_str());
 
1287
                                        MIL << description << endl;
 
1288
                                        problemSolution->addDescription (description);
 
1289
                                    } else {
 
1290
                                        ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
 
1291
                                    }
 
1292
                                } else {
 
1293
                                    ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << s.asString() << endl;
 
1294
                                }
 
1295
                                }
 
1296
                                break;
 
1297
                            default:
 
1298
                                MIL << "- do something different" << endl;
 
1299
                                ERR << "No valid solution available" << endl;
 
1300
                                break;
 
1301
                        }
 
1302
                    } else if (p == SOLVER_SOLUTION_INFARCH) {
 
1303
                        s = mapSolvable (rp);
 
1304
                        PoolItem poolItem = _pool.find (s);
 
1305
                        if (pool->installed && s.get()->repo == pool->installed) {
 
1306
                            problemSolution->addSingleAction (poolItem, LOCK);
 
1307
                            string description = str::form (_("keep %s despite the inferior architecture"), s.asString().c_str());
 
1308
                            MIL << description << endl;
 
1309
                            problemSolution->addDescription (description);
 
1310
                        } else {
 
1311
                            problemSolution->addSingleAction (poolItem, INSTALL);
 
1312
                            string description = str::form (_("install %s despite the inferior architecture"), s.asString().c_str());
 
1313
                            MIL << description << endl;
 
1314
                            problemSolution->addDescription (description);
 
1315
                        }
 
1316
                    } else if (p == SOLVER_SOLUTION_DISTUPGRADE) {
 
1317
                        s = mapSolvable (rp);
 
1318
                        PoolItem poolItem = _pool.find (s);
 
1319
                        if (pool->installed && s.get()->repo == pool->installed) {
 
1320
                            problemSolution->addSingleAction (poolItem, LOCK);
 
1321
                            string description = str::form (_("keep obsolete %s"), s.asString().c_str());
 
1322
                            MIL << description << endl;
 
1323
                            problemSolution->addDescription (description);
 
1324
                        } else {
 
1325
                            problemSolution->addSingleAction (poolItem, INSTALL);
 
1326
                            string description = str::form (_("install %s from excluded repository"), s.asString().c_str());
 
1327
                            MIL << description << endl;
 
1328
                            problemSolution->addDescription (description);
 
1329
                        }
 
1330
                    } else {
 
1331
                        /* policy, replace p with rp */
 
1332
                        s = mapSolvable (p);
 
1333
                        PoolItem itemFrom = _pool.find (s);
 
1334
                        if (rp)
 
1335
                        {
 
1336
                            int gotone = 0;
 
1337
 
 
1338
                            sd = mapSolvable (rp);
 
1339
                            PoolItem itemTo = _pool.find (sd);
 
1340
                            if (itemFrom && itemTo) {
 
1341
                                problemSolution->addSingleAction (itemTo, INSTALL);
 
1342
                                int illegal = policy_is_illegal(_solv, s.get(), sd.get(), 0);
 
1343
 
 
1344
                                if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0)
 
1345
                                {
 
1346
                                    string description = str::form (_("downgrade of %s to %s"), s.asString().c_str(), sd.asString().c_str());
 
1347
                                    MIL << description << endl;
 
1348
                                    problemSolution->addDescription (description);
 
1349
                                    gotone = 1;
 
1350
                                }
 
1351
                                if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0)
 
1352
                                {
 
1353
                                    string description = str::form (_("architecture change of %s to %s"), s.asString().c_str(), sd.asString().c_str());
 
1354
                                    MIL << description << endl;
 
1355
                                    problemSolution->addDescription (description);
 
1356
                                    gotone = 1;
 
1357
                                }
 
1358
                                if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0)
 
1359
                                {
 
1360
                                    IdString s_vendor( s.vendor() );
 
1361
                                    IdString sd_vendor( sd.vendor() );
 
1362
                                    string description = str::form (_("install %s (with vendor change)\n  %s  -->  %s") ,
 
1363
                                                                    sd.asString().c_str(),
 
1364
                                                                    ( s_vendor ? s_vendor.c_str() : " (no vendor) " ),
 
1365
                                                                    ( sd_vendor ? sd_vendor.c_str() : " (no vendor) " ) );
 
1366
                                    MIL << description << endl;
 
1367
                                    problemSolution->addDescription (description);
 
1368
                                    gotone = 1;
 
1369
                                }
 
1370
                                if (!gotone) {
 
1371
                                    string description = str::form (_("replacement of %s with %s"), s.asString().c_str(), sd.asString().c_str());
 
1372
                                    MIL << description << endl;
 
1373
                                    problemSolution->addDescription (description);
 
1374
                                }
 
1375
                            } else {
 
1376
                                ERR << s.asString() << " or "  << sd.asString() << " not found" << endl;
 
1377
                            }
 
1378
                        }
 
1379
                        else
 
1380
                        {
 
1381
                            if (itemFrom) {
 
1382
                                string description = str::form (_("deinstallation of %s"), s.asString().c_str());
 
1383
                                MIL << description << endl;
 
1384
                                problemSolution->addDescription (description);
 
1385
                                problemSolution->addSingleAction (itemFrom, REMOVE);
 
1386
                            }
 
1387
                        }
 
1388
                    }
 
1389
                }
 
1390
                resolverProblem->addSolution (problemSolution,
 
1391
                                              problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
 
1392
                MIL << "------------------------------------" << endl;
 
1393
            }
 
1394
 
 
1395
            if (ignoreId > 0) {
 
1396
                // There is a possibility to ignore this error by setting weak dependencies
 
1397
                PoolItem item = _pool.find (sat::Solvable(ignoreId));
 
1398
                ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item);
 
1399
                resolverProblem->addSolution (problemSolution,
 
1400
                                              false); // Solutions will be shown at the end
 
1401
                MIL << "ignore some dependencies of " << item << endl;
 
1402
                MIL << "------------------------------------" << endl;
 
1403
            }
 
1404
 
 
1405
            // save problem
 
1406
            resolverProblems.push_back (resolverProblem);
 
1407
        }
 
1408
    }
 
1409
    return resolverProblems;
 
1410
}
 
1411
 
 
1412
void
 
1413
SATResolver::applySolutions (const ProblemSolutionList & solutions)
 
1414
{
 
1415
    for (ProblemSolutionList::const_iterator iter = solutions.begin();
 
1416
         iter != solutions.end(); ++iter) {
 
1417
        ProblemSolution_Ptr solution = *iter;
 
1418
        Resolver dummyResolver(_pool);
 
1419
        if (!solution->apply (dummyResolver))
 
1420
            break;
 
1421
    }
 
1422
}
 
1423
 
 
1424
void SATResolver::setLocks()
 
1425
{
 
1426
    for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); ++iter) {
 
1427
        sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
 
1428
        if (iter->status().isInstalled()) {
 
1429
            MIL << "Lock installed item " << *iter << endl;
 
1430
            queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE );
 
1431
            queue_push( &(_jobQueue), ident );
 
1432
        } else {
 
1433
            MIL << "Lock NOT installed item " << *iter << endl;
 
1434
            queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE | MAYBE_CLEANDEPS );
 
1435
            queue_push( &(_jobQueue), ident );
 
1436
        }
 
1437
    }
 
1438
 
 
1439
    ///////////////////////////////////////////////////////////////////
 
1440
    // Weak locks: Ignore if an item with this name is already installed.
 
1441
    // If it's not installed try to keep it this way using a weak delete
 
1442
    ///////////////////////////////////////////////////////////////////
 
1443
    std::set<IdString> unifiedByName;
 
1444
    for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); ++iter) {
 
1445
      IdString ident( (*iter)->satSolvable().ident() );
 
1446
      if ( unifiedByName.insert( ident ).second )
 
1447
      {
 
1448
        if ( ! ui::Selectable::get( *iter )->hasInstalledObj() )
 
1449
        {
 
1450
          MIL << "Keep NOT installed name " << ident << " (" << *iter << ")" << endl;
 
1451
          queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS );
 
1452
          queue_push( &(_jobQueue), ident.id() );
 
1453
        }
 
1454
      }
 
1455
    }
 
1456
}
 
1457
 
 
1458
void SATResolver::setSystemRequirements()
 
1459
{
 
1460
    CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
 
1461
    CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
 
1462
 
 
1463
    for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); ++iter) {
 
1464
        queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES );
 
1465
        queue_push( &(_jobQueue), iter->id() );
 
1466
        MIL << "SYSTEM Requires " << *iter << endl;
 
1467
    }
 
1468
 
 
1469
    for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); ++iter) {
 
1470
        queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS );
 
1471
        queue_push( &(_jobQueue), iter->id() );
 
1472
        MIL << "SYSTEM Conflicts " << *iter << endl;
 
1473
    }
 
1474
 
 
1475
    // Lock the architecture of the running systems rpm
 
1476
    // package on distupgrade.
 
1477
    if ( _distupgrade && ZConfig::instance().systemRoot() == "/" )
 
1478
    {
 
1479
      ResPool pool( ResPool::instance() );
 
1480
      IdString rpm( "rpm" );
 
1481
      for_( it, pool.byIdentBegin(rpm), pool.byIdentEnd(rpm) )
 
1482
      {
 
1483
        if ( (*it)->isSystem() )
 
1484
        {
 
1485
          Capability archrule( (*it)->arch(), rpm.c_str(), Capability::PARSED );
 
1486
          queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME | SOLVER_ESSENTIAL );
 
1487
          queue_push( &(_jobQueue), archrule.id() );
 
1488
 
 
1489
        }
 
1490
      }
 
1491
    }
 
1492
}
 
1493
 
 
1494
 
 
1495
///////////////////////////////////////////////////////////////////
 
1496
};// namespace detail
 
1497
    /////////////////////////////////////////////////////////////////////
 
1498
    /////////////////////////////////////////////////////////////////////
 
1499
  };// namespace solver
 
1500
  ///////////////////////////////////////////////////////////////////////
 
1501
  ///////////////////////////////////////////////////////////////////////
 
1502
};// namespace zypp
 
1503
/////////////////////////////////////////////////////////////////////////
 
1504