1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/ui/SelectableImpl.cc
13 //#include "zypp/base/Logger.h"
15 #include "zypp/ui/SelectableImpl.h"
19 ///////////////////////////////////////////////////////////////////
21 { /////////////////////////////////////////////////////////////////
22 ///////////////////////////////////////////////////////////////////
24 { /////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////
28 // CLASS NAME : StatusHelper
34 StatusHelper( const Selectable::Impl & impl, ResStatus::TransactByValue causer_r )
36 , inst( impl.installedObj() )
37 , cand( impl.candidateObj() )
41 typedef Selectable::Impl::available_const_iterator available_const_iterator;
46 bool hasInstalled() const
49 bool hasCandidate() const
52 bool hasInstalledOnly() const
53 { return inst && !cand; }
55 bool hasCandidateOnly() const
56 { return cand && !inst; }
59 { return inst && cand; }
61 /** \name Topevel methods must restore status on failure. */
68 ResStatus & inststatus( backup( inst.status() ) );
69 if ( ! inststatus.setTransact( false, causer ) ) return restore();
70 if ( ! inststatus.setLock ( false, causer ) ) return restore();
71 if ( ! cand->installOnly() )
73 // This is what the solver most probabely will do.
74 // If we are wrong the solver will correct it. But
75 // this way we will get a better disk usage result,
76 // even if no autosolving is on.
77 inststatus.setTransact( true, ResStatus::SOLVER );
80 if ( ! unlockCandidates() ) return restore();
81 ResStatus & candstatus( backup( cand.status() ) );
82 if ( ! candstatus.setTransact( true, causer ) ) return restore();
92 if ( ! resetTransactingCandidates() ) return restore();
93 ResStatus & inststatus( backup( inst.status() ) );
94 if ( ! inststatus.setLock( false, causer ) ) return restore();
95 if ( ! inststatus.setTransact( true, causer ) ) return restore();
105 ResStatus & inststatus( backup( inst.status() ) );
106 if ( ! inststatus.setTransact( false, causer ) ) return restore();
107 if ( ! inststatus.setLock( false, causer ) ) return restore();
109 if ( ! unlockCandidates() ) return restore();
115 if ( causer != ResStatus::USER ) // by user only
119 resetTransactingCandidates();
120 inst.status().setTransact( false, causer );
121 return inst.status().setLock( true, causer );
128 if ( causer != ResStatus::USER ) // by user only
140 /** \name Helper methods backup status but do not replay. */
142 bool resetTransactingCandidates()
144 for_( it, _impl.availableBegin(), _impl.availableEnd() )
146 ResStatus & status( backup( (*it).status() ) );
147 if ( ! status.setTransact( false, causer ) ) return false;
151 bool unlockCandidates()
153 for_( it, _impl.availableBegin(), _impl.availableEnd() )
155 ResStatus & status( backup( (*it).status() ) );
156 if ( ! status.setTransact( false, causer ) ) return false;
157 if ( ! status.setLock( false, causer ) ) return false;
161 bool lockCandidates()
163 for_( it, _impl.availableBegin(), _impl.availableEnd() )
165 ResStatus & status( backup( (*it).status() ) );
166 if ( ! status.setTransact( false, causer ) ) return false;
167 if ( ! status.setLock( true, causer ) ) return false;
174 const Selectable::Impl & _impl;
177 ResStatus::TransactByValue causer;
180 // No backup replay needed if causer is user,
181 // because actions should always succeed.
183 ResStatus & backup( ResStatus & status_r )
185 if ( causer != ResStatus::USER )
186 _backup.push_back( status_r );
192 if ( causer != ResStatus::USER )
194 for_( rit, _backup.rbegin(), _backup.rend() )
199 return false; // restore is done on error - return restore();
202 std::vector<resstatus::StatusBackup> _backup;
204 ///////////////////////////////////////////////////////////////////
206 ///////////////////////////////////////////////////////////////////
208 // CLASS NAME : Selectable::Impl
210 ///////////////////////////////////////////////////////////////////
212 Status Selectable::Impl::status() const
214 PoolItem cand( candidateObj() );
215 if ( cand && cand.status().transacts() )
217 if ( cand.status().isByUser() )
218 return( installedObj() ? S_Update : S_Install );
220 return( installedObj() ? S_AutoUpdate : S_AutoInstall );
223 if ( installedObj() && installedObj().status().transacts() )
225 return( installedObj().status().isByUser() ? S_Del : S_AutoDel );
228 if ( installedObj() && installedObj().status().isLocked() )
231 if ( !installedObj() && allCandidatesLocked() )
235 if ( installedObj() )
236 return S_KeepInstalled;
237 // Report pseudo installed items as installed, if they are satisfied.
238 if ( traits::isPseudoInstalled( kind() )
239 && cand.status().isSatisfied() ) // no installed, so we must have candidate
240 return S_KeepInstalled;
245 bool Selectable::Impl::setStatus( const Status state_r, ResStatus::TransactByValue causer_r )
247 StatusHelper self( *this, causer_r );
252 return self.setProtected();
254 return self.setTaboo();
258 // Auto level is SOLVER level. UI may query, but not
259 // set at this level.
263 return self.setDelete();
267 return self.hasCandidateOnly() && self.setInstall();
271 return self.hasBoth() && self.setInstall();
274 case S_KeepInstalled:
275 return self.hasInstalled() && self.unset();
279 return !self.hasInstalled() && self.unset();
286 PoolItem Selectable::Impl::setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r )
288 PoolItem newCandidate;
290 if ( newCandidate_r ) // must be in available list
292 for_( it, availableBegin(), availableEnd() )
294 if ( *it == newCandidate_r )
304 PoolItem trans( transactingCandidate() );
305 if ( trans && trans != newCandidate )
307 // adjust transact to the new cancidate
308 if ( trans.status().maySetTransact( false, causer_r )
309 && newCandidate.status().maySetTransact( true, causer_r ) )
311 trans.status().setTransact( false, causer_r );
312 newCandidate.status().setTransact( true, causer_r );
316 // No permission to change a transacting candidate.
317 // Leave _candidate untouched and return NULL.
323 return _candidate = newCandidate;
326 ///////////////////////////////////////////////////////////////////
328 bool Selectable::Impl::setPickStatus( const PoolItem & pi_r, const Status state_r, ResStatus::TransactByValue causer_r )
333 Status Selectable::Impl::pickStatus( const PoolItem & pi_r ) const
335 if ( pi_r.satSolvable().ident() == ident() )
337 if ( pi_r.satSolvable().isSystem() )
340 if ( pi_r.status().isLocked() )
343 // at least one identical available transacing?
344 for_( it, _availableItems.begin(), _availableItems.end() )
346 if ( identical( *it, pi_r ) )
348 if ( (*it).status().transacts() )
349 return( (*it).status().isByUser() ? S_Update : S_AutoUpdate );
353 // no update, so maybe delete?
354 if ( pi_r.status().transacts() )
355 return ( pi_r.status().isByUser() ? S_Del : S_AutoDel );
358 return S_KeepInstalled;
363 if ( pi_r.status().isLocked() )
366 // have identical installed? (maybe transacting):
368 for_( it, _installedItems.begin(), _installedItems.end() )
370 if ( identical( *it, pi_r ) )
372 if ( (*it).status().transacts() )
382 // check for inst/update
383 if ( pi_r.status().transacts() )
386 return( pi_r.status().isByUser() ? S_Update : S_AutoUpdate );
388 return( pi_r.status().isByUser() ? S_Install : S_AutoInstall );
391 // no inst/update, so maybe delete?
395 if ( inst.status().transacts() )
396 return( inst.status().isByUser() ? S_Del : S_AutoDel );
398 return S_KeepInstalled;
401 return Status(-1); // not my PoolItem
404 ///////////////////////////////////////////////////////////////////
406 ResStatus::TransactByValue Selectable::Impl::modifiedBy() const
408 PoolItem cand( candidateObj() );
409 if ( cand && cand.status().transacts() )
410 return cand.status().getTransactByValue();
412 if ( installedObj() && installedObj().status().transacts() )
413 return installedObj().status().getTransactByValue();
416 return cand.status().getTransactByValue();
418 if ( installedObj() )
419 return installedObj().status().getTransactByValue();
421 return ResStatus::SOLVER;
424 /////////////////////////////////////////////////////////////////
426 ///////////////////////////////////////////////////////////////////
427 /////////////////////////////////////////////////////////////////
429 ///////////////////////////////////////////////////////////////////