From: Michael Andres Date: Tue, 31 May 2011 15:25:08 +0000 (+0200) Subject: Do commit based on sat::Transaction. X-Git-Tag: 9.5.0~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=686a8339e71d146b08116c53b917db6acd595d36;p=platform%2Fupstream%2Flibzypp.git Do commit based on sat::Transaction. --- diff --git a/zypp/ZYppCommitResult.cc b/zypp/ZYppCommitResult.cc index 8431424..33a79ed 100644 --- a/zypp/ZYppCommitResult.cc +++ b/zypp/ZYppCommitResult.cc @@ -11,6 +11,7 @@ */ #include +#include "zypp/base/LogTools.h" #include "zypp/ZYppCommitResult.h" @@ -32,6 +33,8 @@ namespace zypp public: Pathname _root; + sat::Transaction _transaction; + TransactionStepList _transactionStepList; UpdateNotifications _updateMessages; private: @@ -57,22 +60,86 @@ namespace zypp const Pathname & ZYppCommitResult::root() const { return _pimpl->_root; } + const sat::Transaction & ZYppCommitResult::transaction() const + { return _pimpl->_transaction; } + + sat::Transaction & ZYppCommitResult::rTransaction() + { return _pimpl->_transaction; } + + const ZYppCommitResult::TransactionStepList & ZYppCommitResult::transactionStepList() const + { return _pimpl->_transactionStepList; } + + ZYppCommitResult::TransactionStepList & ZYppCommitResult::rTransactionStepList() + { return _pimpl->_transactionStepList; } + const UpdateNotifications & ZYppCommitResult::updateMessages() const { return _pimpl->_updateMessages; } - UpdateNotifications & ZYppCommitResult::setUpdateMessages() + UpdateNotifications & ZYppCommitResult::rUpdateMessages() { return _pimpl->_updateMessages; } + ZYppCommitResult::InsDelCnt ZYppCommitResult::totalCount() const + { + InsDelCnt ret; + for_( it, _pimpl->_transaction.actionBegin(), _pimpl->_transaction.actionEnd() ) + { + ++( it->stepType() == sat::Transaction::TRANSACTION_ERASE ? ret.second : ret.first ); + } + + return ret; + } + + ZYppCommitResult::InsDelCnt ZYppCommitResult::stepStageCount( sat::Transaction::StepStage stage_r ) const + { + InsDelCnt ret; + for_( it, _pimpl->_transaction.actionBegin(), _pimpl->_transaction.actionEnd() ) + { + if ( it->stepStage() != stage_r ) + continue; + ++( it->stepType() == sat::Transaction::TRANSACTION_ERASE ? ret.second : ret.first ); + } + return ret; + } + + void ZYppCommitResult::resultCount( InsDelCnt & total_r, InsDelCnt & done_r, InsDelCnt & error_r, InsDelCnt & skipped_r ) const + { + total_r = done_r = error_r = skipped_r = InsDelCnt(); + for_( it, _pimpl->_transaction.actionBegin(), _pimpl->_transaction.actionEnd() ) + { + ++( it->stepType() == sat::Transaction::TRANSACTION_ERASE ? total_r.second : total_r.first ); + switch ( it->stepStage() ) + { + case sat::Transaction::STEP_DONE: + ++( it->stepType() == sat::Transaction::TRANSACTION_ERASE ? done_r.second : done_r.first ); + break; + case sat::Transaction::STEP_ERROR: + ++( it->stepType() == sat::Transaction::TRANSACTION_ERASE ? error_r.second : error_r.first ); + break; + case sat::Transaction::STEP_TODO: + ++( it->stepType() == sat::Transaction::TRANSACTION_ERASE ? skipped_r.second : skipped_r.first ); + break; + } + } + } + /////////////////////////////////////////////////////////////////// + std::ostream & operator<<( std::ostream & str, const ZYppCommitResult::InsDelCnt & obj ) + { return str << obj.first << '/' << obj.second; } + std::ostream & operator<<( std::ostream & str, const ZYppCommitResult & obj ) { - str << "CommitResult " << obj._result - << " (errors " << obj._errors.size() - << ", remaining " << obj._remaining.size() - << ", srcremaining " << obj._srcremaining.size() + ZYppCommitResult::InsDelCnt result[4]; + obj.resultCount( result[0], result[1], result[2], result[3] ); + + str << "CommitResult " + << " (ins/del total " << result[0] + << ", done " << result[1] + << ", error " << result[2] + << ", skipped " << result[3] << ", updateMessages " << obj.updateMessages().size() - << ")"; + << ")" + << std::endl << obj.transaction(); return str; } diff --git a/zypp/ZYppCommitResult.h b/zypp/ZYppCommitResult.h index 81f6559..23ec5c2 100644 --- a/zypp/ZYppCommitResult.h +++ b/zypp/ZYppCommitResult.h @@ -13,14 +13,22 @@ #define ZYPP_ZYPPCOMMITRESULT_H #include +#include #include #include "zypp/PoolItem.h" +#include "zypp/sat/Transaction.h" +#include "zypp/base/DefaultIntegral.h" /////////////////////////////////////////////////////////////////// namespace zypp { ///////////////////////////////////////////////////////////////// + namespace sat + { + class Transaction; + } + /** Pair of \ref sat::Solvable and \ref Pathname. */ class UpdateNotificationFile { @@ -44,12 +52,19 @@ namespace zypp // /** Result returned from ZYpp::commit. * + * \note Transaction data are provided and maintained during commit. + * Though the interface does not inhibit manipulation of transaction + * data outside commit (those methods could have been made \c private:), + * this is not recommended as you may easily mess up things. + * * \see \ref ZYpp::commit - * \todo document fields. */ class ZYppCommitResult { public: + typedef std::vector TransactionStepList; + + public: ZYppCommitResult(); ZYppCommitResult( const Pathname & root_r ); @@ -60,6 +75,26 @@ namespace zypp */ const Pathname & root() const; + /** The full transaction list. + * The complete list including transaction steps that do not require + * any action (like obsoletes or non-package actions). Depending on + * \ref ZYppCommitPolicy::restrictToMedia only a subset of this + * transaction might have been executed. + * \see \ref transactionStepList. + */ + const sat::Transaction & transaction() const; + + /** Manipulate \ref transaction */ + sat::Transaction & rTransaction(); + + /** List of \ref sat::Transaction::Step to be executed by commit. + * The list of transaction step commit actually tried to execute. + */ + const TransactionStepList & transactionStepList() const; + + /** Manipulate \ref transactionStepList. */ + TransactionStepList & rTransactionStepList(); + /** List of update messages installed during this commit. * \Note Pathnames are relative to the targets root directory. * \code @@ -89,32 +124,65 @@ namespace zypp */ const UpdateNotifications & updateMessages() const; - /** Change list of update messages installed during this commit. + /** Manipulate \ref updateMessages * \Note Pathnames are relative to the targets root directory. */ - UpdateNotifications & setUpdateMessages(); + UpdateNotifications & rUpdateMessages(); + + public: + + /** \name Some statistics based on \ref transaction + */ + //@{ + /** Basically std::pair, but default ctor sets <0,0>. */ + typedef std::pair, DefaultIntegral > InsDelCnt; + + /** Total number of install/delete actions to be performed. */ + InsDelCnt totalCount() const; + + /** Number of install/delete actions with result \a stage_r. */ + InsDelCnt stepStageCount( sat::Transaction::StepStage stage_r ) const; + + /** Number of install/delete actions done. */ + InsDelCnt doneCount() const + { return stepStageCount( sat::Transaction::STEP_DONE ); } + + /** Number of install/delete actions that failed with error. */ + InsDelCnt errorCount() const + { return stepStageCount( sat::Transaction::STEP_ERROR ); } + + /** Number of install/delete actions that were skipped (e.g. due to unwanted media). */ + InsDelCnt skippedCount() const + { return stepStageCount( sat::Transaction::STEP_TODO ); } + + /** All in one go. */ + void resultCount( InsDelCnt & total_r, InsDelCnt & done_r, InsDelCnt & error_r, InsDelCnt & skipped_r ) const; + //@} public: /** \name Oldstlye interface to be removed asap. + * \deprecated PoolItem is not suitable for reporting errors about + * packages to be deteled, as reloading the rpm database after commit + * invalidates them. */ //@{ typedef std::list PoolItemList; /** * number of committed resolvables **/ - int _result; + int _result ZYPP_DEPRECATED; /** * list of resolvables with error **/ - PoolItemList _errors; + PoolItemList _errors ZYPP_DEPRECATED; /** * list of resolvables remaining (due to wrong media) **/ - PoolItemList _remaining; + PoolItemList _remaining ZYPP_DEPRECATED; /** * list of kind:source resolvables remaining (due to wrong media) **/ - PoolItemList _srcremaining; + PoolItemList _srcremaining ZYPP_DEPRECATED; //@} public: diff --git a/zypp/sat/Transaction.cc b/zypp/sat/Transaction.cc index 99ece4d..a4c19c8 100644 --- a/zypp/sat/Transaction.cc +++ b/zypp/sat/Transaction.cc @@ -35,15 +35,36 @@ namespace zypp { ///////////////////////////////////////////////////////////////// /** Transaction implementation. - * \todo check whether the pool serial number changed! + * + * \NOTE After commit the @System repo is reloaded. This invalidates + * the ids off all installed items in the transaction, including their + * stepType. Thats why some information (stepType, NVRA) is be stored + * for post mortem access (i.e. tell after commit which NVRA were deleted). + * */ struct Transaction::Impl : protected detail::PoolMember { friend std::ostream & operator<<( std::ostream & str, const Impl & obj ); public: - typedef std::tr1::unordered_set set_type; - typedef std::tr1::unordered_map map_type; + typedef std::tr1::unordered_set set_type; + typedef std::tr1::unordered_map map_type; + + struct PostMortem + { + PostMortem() + {} + PostMortem( const sat::Solvable & solv_r ) + : _ident( solv_r.ident() ) + , _edition( solv_r.edition() ) + , _arch( solv_r.arch() ) + {} + + IdString _ident; + Edition _edition; + Arch _arch; + }; + typedef std::tr1::unordered_map pmmap_type; public: Impl() @@ -60,6 +81,7 @@ namespace zypp for_( it, _trans.steps.elements, _trans.steps.elements + _trans.steps.count ) { sat::Solvable solv( *it ); + // buddy list: if ( ! solv.isKind() ) { PoolItem pi( solv ); @@ -68,6 +90,16 @@ namespace zypp _linkMap[*it] = pi.buddy().id(); } } + if ( solv.isSystem() ) + { + // to delete list: + if ( stepType( solv ) == TRANSACTION_ERASE ) + { + _systemErase.insert( *it ); + } + // post mortem data + _pmMap[*it] = solv; + } } } @@ -145,23 +177,15 @@ namespace zypp iterator find(const RW_pointer & self_r, const sat::Solvable & solv_r ) { detail::IdType * it( _find( solv_r ) ); return it ? iterator( self_r, it ) : end( self_r ); } - private: - detail::IdType * _find( const sat::Solvable & solv_r ) const + public: + StepType stepType( Solvable solv_r ) const { - if ( solv_r && _trans.steps.elements ) + if ( ! solv_r ) { - for_( it, _trans.steps.elements, _trans.steps.elements + _trans.steps.count ) - { - if ( *it == detail::IdType(solv_r.id()) ) - return it; - } + // post mortem @System solvable + return isIn( _systemErase, solv_r.id() ) ? TRANSACTION_ERASE : TRANSACTION_IGNORE; } - return 0; - } - public: - StepType stepType( Solvable solv_r ) const - { switch( ::transaction_type( &_trans, solv_r.id(), SOLVER_TRANSACTION_RPM_ONLY ) ) { case SOLVER_TRANSACTION_ERASE: return TRANSACTION_ERASE; break; @@ -177,8 +201,14 @@ namespace zypp void stepStage( Solvable solv_r, StepStage newval_r ) { stepStage( resolve( solv_r ), newval_r ); } - private: + const PostMortem & pmdata( Solvable solv_r ) const + { + static PostMortem _none; + pmmap_type::const_iterator it( _pmMap.find( solv_r.id() ) ); + return( it == _pmMap.end() ? _none : it->second ); + } + private: detail::IdType resolve( const Solvable & solv_r ) const { map_type::const_iterator res( _linkMap.find( solv_r.id() ) ); @@ -213,14 +243,31 @@ namespace zypp } } } + + private: + detail::IdType * _find( const sat::Solvable & solv_r ) const + { + if ( solv_r && _trans.steps.elements ) + { + for_( it, _trans.steps.elements, _trans.steps.elements + _trans.steps.count ) + { + if ( *it == detail::IdType(solv_r.id()) ) + return it; + } + } + return 0; + } + private: SerialNumberWatcher _watcher; mutable ::Transaction _trans; DefaultIntegral _ordered; // - set_type _doneSet; - set_type _errSet; - map_type _linkMap; + set_type _doneSet; + set_type _errSet; + map_type _linkMap; // buddy map to adopt buddies StepResult + set_type _systemErase; // @System packages to be eased (otherse are TRANSACTION_IGNORE) + pmmap_type _pmMap; // Post mortem data of deleted @System solvables public: /** Offer default Impl. */ @@ -317,8 +364,24 @@ namespace zypp void Transaction::Step::stepStage( StepStage val_r ) { _pimpl->stepStage( _solv, val_r ); } + IdString Transaction::Step::ident() const + { return _solv ? _solv.ident() : _pimpl->pmdata(_solv )._ident; } + + Edition Transaction::Step::edition() const + { return _solv ? _solv.edition() : _pimpl->pmdata(_solv )._edition; } + + Arch Transaction::Step::arch() const + { return _solv ? _solv.arch() : _pimpl->pmdata(_solv )._arch; } + std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj ) - { return str << obj.stepType() << obj.stepStage() << " " << PoolItem( obj.satSolvable() ); } + { + str << obj.stepType() << obj.stepStage() << " "; + if ( obj.satSolvable() ) + str << PoolItem( obj.satSolvable() ); + else + str << '[' << obj.ident() << '-' << obj.edition() << '.' << obj.arch() << ']'; + return str; + } std::ostream & operator<<( std::ostream & str, Transaction::StepType obj ) { @@ -331,6 +394,7 @@ namespace zypp OUTS( TRANSACTION_MULTIINSTALL, [M] ); #undef OUTS } + return str << "[?]"; } std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj ) @@ -343,6 +407,7 @@ namespace zypp OUTS( STEP_ERROR, [**] ); #undef OUTS } + return str << "[??]"; } /////////////////////////////////////////////////////////////////// namespace detail diff --git a/zypp/sat/Transaction.h b/zypp/sat/Transaction.h index e622023..31f1d22 100644 --- a/zypp/sat/Transaction.h +++ b/zypp/sat/Transaction.h @@ -168,6 +168,13 @@ namespace zypp /** A single step within a \ref Transaction. + * + * \note After commit, when the @System repo (rpm database) is reread, all + * @System solvables within the transaction are invalidated (they got deleted). + * Thats why we internally store the NVRA, so you can access \ref ident + * (\see \ref sat::Solvable::ident), \ref edition, \ref arch of a deleted package, + * even if the \ref satSolvable itself is meanwhile invalid. + * * \see \ref Transaction. */ class Transaction::Step @@ -191,10 +198,32 @@ namespace zypp /** Set step action result. */ void stepStage( StepStage val_r ); - /** Return the corresponding \ref Solvable. */ + /** Return the corresponding \ref Solvable (or. + * + */ Solvable satSolvable() const { return _solv; } + /** \name Post mortem acccess to @System solvables + * \code + * Transaction::Step step; + * if ( step.satSolvable() ) + * std::cout << step.satSolvable() << endl; + * else + * std::cout << step.ident() << endl; // deleted @System solvable + * \endcode + */ + //@{ + /** \see \ref sat::Solvable::ident. */ + IdString ident() const; + + /** \see \ref sat::Solvable::edition. */ + Edition edition() const; + + /** \see \ref sat::Solvable::arch. */ + Arch arch() const; + //@} + /** Implicit conversion to \ref Solvable */ operator const Solvable &() const { return _solv; } /** \overload nonconst */ diff --git a/zypp/target/TargetImpl.cc b/zypp/target/TargetImpl.cc index c05353d..b6a5a91 100644 --- a/zypp/target/TargetImpl.cc +++ b/zypp/target/TargetImpl.cc @@ -9,6 +9,14 @@ /** \file zypp/target/TargetImpl.cc * */ +#ifdef _RPM_4_4 +#warning _RPM_4_4 +#else +#ifdef _RPM_4_X +#warning _RPM_4_X +#endif +#endif + #include #include #include @@ -55,12 +63,12 @@ #include "zypp/repo/SrcPackageProvider.h" #include "zypp/sat/Pool.h" +#include "zypp/sat/Transaction.h" #include "zypp/PluginScript.h" using namespace std; - /////////////////////////////////////////////////////////////////// namespace zypp { ///////////////////////////////////////////////////////////////// @@ -449,7 +457,7 @@ namespace zypp MIL << "Found update message " << *sit << endl; Pathname localPath( messagesPath_r/(*sit) ); // without root prefix - result_r.setUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) ); + result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) ); historylog.comment( str::Str() << _("New update message") << " " << localPath, /*timestamp*/true ); } } @@ -1001,65 +1009,29 @@ namespace zypp /////////////////////////////////////////////////////////////////// // Compute transaction: /////////////////////////////////////////////////////////////////// - ZYppCommitResult result( root() ); - TargetImpl::PoolItemList to_uninstall; - TargetImpl::PoolItemList to_install; - TargetImpl::PoolItemList to_srcinstall; - - { - pool::GetResolvablesToInsDel - collect( pool_r, policy_r.restrictToMedia() ? pool::GetResolvablesToInsDel::ORDER_BY_MEDIANR - : pool::GetResolvablesToInsDel::ORDER_BY_SOURCE ); - MIL << "GetResolvablesToInsDel: " << endl << collect << endl; - to_uninstall.swap ( collect._toDelete ); - to_install.swap ( collect._toInstall ); - to_srcinstall.swap( collect._toSrcinstall ); - } - + result.rTransaction() = pool_r.resolver().getTransaction(); + result.rTransaction().order(); + // steps: this is our todo-list + ZYppCommitResult::TransactionStepList & steps( result.rTransactionStepList() ); if ( policy_r.restrictToMedia() ) { - MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl; - - TargetImpl::PoolItemList current_install; - TargetImpl::PoolItemList current_srcinstall; - - // Collect until the 1st package from an unwanted media occurs. + // Collect until the 1st package from an unwanted media occurs. // Further collection could violate install order. - bool hitUnwantedMedia = false; - for ( TargetImpl::PoolItemList::iterator it = to_install.begin(); it != to_install.end(); ++it ) - { - ResObject::constPtr res( it->resolvable() ); - - if ( hitUnwantedMedia - || ( res->mediaNr() && res->mediaNr() != policy_r.restrictToMedia() ) ) - { - hitUnwantedMedia = true; - result._remaining.push_back( *it ); - } - else - { - current_install.push_back( *it ); - } - } - - for (TargetImpl::PoolItemList::iterator it = to_srcinstall.begin(); it != to_srcinstall.end(); ++it) - { - Resolvable::constPtr res( it->resolvable() ); - Package::constPtr pkg( asKind(res) ); - if ( pkg && policy_r.restrictToMedia() != pkg->mediaNr() ) // check medianr for packages only - { - result._srcremaining.push_back( *it ); - } - else - { - current_srcinstall.push_back( *it ); - } - } - - to_install.swap ( current_install ); - to_srcinstall.swap( current_srcinstall ); + MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl; +#warning Also need to be able to compute ORDER_BY_MEDIANR + for_( it, result.transaction().begin(), result.transaction().end() ) + { + if ( makeResObject( *it )->mediaNr() > 1 ) + break; + steps.push_back( *it ); + } } + else + { + result.rTransactionStepList().insert( steps.end(), result.transaction().begin(), result.transaction().end() ); + } + MIL << "Todo: " << result << endl; /////////////////////////////////////////////////////////////////// // First collect and display all messages @@ -1067,23 +1039,25 @@ namespace zypp /////////////////////////////////////////////////////////////////// if ( ! policy_r.dryRun() ) { - for_( it, to_install.begin(), to_install.end() ) + for_( it, steps.begin(), steps.end() ) { - if ( ! isKind(it->resolvable()) ) - continue; - if ( ! it->status().isToBeInstalled() ) + if ( ! it->satSolvable().isKind() ) + continue; + + PoolItem pi( *it ); + if ( ! pi.status().isToBeInstalled() ) continue; - Patch::constPtr patch( asKind(it->resolvable()) ); - if ( ! patch->message().empty() ) - { - MIL << "Show message for " << patch << endl; - callback::SendReport report; - if ( ! report->show( patch ) ) - { - WAR << "commit aborted by the user" << endl; - ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) ); - } + Patch::constPtr patch( asKind(pi.resolvable()) ); + if ( ! patch ||patch->message().empty() ) + continue; + + MIL << "Show message for " << patch << endl; + callback::SendReport report; + if ( ! report->show( patch ) ) + { + WAR << "commit aborted by the user" << endl; + ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) ); } } } @@ -1095,24 +1069,14 @@ namespace zypp /////////////////////////////////////////////////////////////////// // Remove/install packages. /////////////////////////////////////////////////////////////////// - DBG << "commit log file is set to: " << HistoryLog::fname() << endl; if ( ! policy_r.dryRun() || policy_r.downloadMode() == DownloadOnly ) { - // somewhat uggly constraint: The iterator passed to the CommitPackageCache - // must match begin and end of the install PoolItemList passed to commit. - // For the download policies it's the easiest, if we have just a single - // toInstall list. So we unify to_install and to_srcinstall. In case - // of errors we have to split it up again. This will be cleaned up when - // we introduce the new install order. - TargetImpl::PoolItemList items( to_install ); - items.insert( items.end(), to_srcinstall.begin(), to_srcinstall.end() ); - - // prepare the package cache according to the download options: + // Prepare the package cache. Pass all items requiring download. repo::RepoMediaAccess access; RepoProvidePackage repoProvidePackage( access, pool_r ); - CommitPackageCache packageCache( items.begin(), items.end(), - root() / "tmp", repoProvidePackage ); + CommitPackageCache packageCache( root() / "tmp", repoProvidePackage ); + packageCache.setCommitList( steps.begin(), steps.end() ); bool miss = false; if ( policy_r.downloadMode() != DownloadAsNeeded ) @@ -1120,26 +1084,28 @@ namespace zypp // Preload the cache. Until now this means pre-loading all packages. // Once DownloadInHeaps is fully implemented, this will change and // we may actually have more than one heap. - for_( it, items.begin(), items.end() ) + for_( it, steps.begin(), steps.end() ) { - if ( (*it)->isKind() || (*it)->isKind() ) + PoolItem pi( *it ); + if ( pi->isKind() || pi->isKind() ) { ManagedFile localfile; try { - if ( (*it)->isKind() ) + // TODO: unify packageCache.get for Package and SrcPackage + if ( pi->isKind() ) { - localfile = packageCache.get( it ); + localfile = packageCache.get( pi ); } - else if ( (*it)->isKind() ) + else if ( pi->isKind() ) { repo::RepoMediaAccess access; repo::SrcPackageProvider prov( access ); - localfile = prov.provideSrcPackage( (*it)->asKind() ); + localfile = prov.provideSrcPackage( pi->asKind() ); } else { - INT << "Don't know howto cache: Neither Package nor SrcPackage: " << *it << endl; + INT << "Don't know howto cache: Neither Package nor SrcPackage: " << pi << endl; continue; } localfile.resetDispose(); // keep the package file in the cache @@ -1147,7 +1113,6 @@ namespace zypp catch ( const AbortRequestException & exp ) { miss = true; - result._errors.push_back( *it ); WAR << "commit cache preload aborted by the user" << endl; ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) ); break; @@ -1156,8 +1121,7 @@ namespace zypp { ZYPP_CAUGHT( exp ); miss = true; - result._errors.push_back( *it ); - WAR << "Skipping cache preload package " << (*it)->asKind() << " in commit" << endl; + WAR << "Skipping cache preload package " << pi->asKind() << " in commit" << endl; continue; } catch ( const Exception & exp ) @@ -1166,8 +1130,7 @@ namespace zypp // TODO see if packageCache fails to handle errors correctly. ZYPP_CAUGHT( exp ); miss = true; - result._errors.push_back( *it ); - INT << "Unexpected Error: Skipping cache preload package " << (*it)->asKind() << " in commit" << endl; + INT << "Unexpected Error: Skipping cache preload package " << pi->asKind() << " in commit" << endl; continue; } } @@ -1177,23 +1140,10 @@ namespace zypp if ( miss ) { ERR << "Some packages could not be provided. Aborting commit."<< endl; - result._remaining.insert( result._remaining.end(), to_install.begin(), to_install.end() ); - result._srcremaining.insert( result._srcremaining.end(), to_srcinstall.begin(), to_srcinstall.end() ); } else if ( ! policy_r.dryRun() ) { - commit ( to_uninstall, policy_r, result, packageCache ); - TargetImpl::PoolItemList bad = commit( items, policy_r, result, packageCache ); - if ( ! bad.empty() ) - { - for_( it, bad.begin(), bad.end() ) - { - if ( isKind(it->resolvable()) ) - result._srcremaining.push_back( *it ); - else - result._remaining.push_back( *it ); - } - } + commit( policy_r, packageCache, result ); } else { @@ -1213,55 +1163,105 @@ namespace zypp buildCache(); } - result._result = (to_install.size() - result._remaining.size()); + // for DEPRECATED old ZyppCommitResult results: + /////////////////////////////////////////////////////////////////// + // build return statistics + /////////////////////////////////////////////////////////////////// + result._errors.clear(); + result._remaining.clear(); + result._srcremaining.clear(); + unsigned toInstall = 0; + for_( step, steps.begin(), steps.end() ) + { + if ( step->stepType() == sat::Transaction::TRANSACTION_IGNORE ) + { + // For non-packages only products might have beed installed. + // All the rest is ignored. + if ( step->satSolvable().isSystem() || ! step->satSolvable().isKind() ) + continue; + } + else if ( step->stepType() == sat::Transaction::TRANSACTION_ERASE ) + { + continue; + } + // to be installed: + ++toInstall; + switch ( step->stepStage() ) + { + case sat::Transaction::STEP_TODO: + if ( step->satSolvable().isKind() ) + result._remaining.push_back( PoolItem( *step ) ); + else if ( step->satSolvable().isKind() ) + result._srcremaining.push_back( PoolItem( *step ) ); + break; + case sat::Transaction::STEP_DONE: + // NOOP + break; + case sat::Transaction::STEP_ERROR: + result._errors.push_back( PoolItem( *step ) ); + break; + } + } + result._result = (toInstall - result._remaining.size()); + /////////////////////////////////////////////////////////////////// + MIL << "TargetImpl::commit(, " << policy_r << ") returns: " << result << endl; return result; } - /////////////////////////////////////////////////////////////////// // // COMMIT internal // /////////////////////////////////////////////////////////////////// - TargetImpl::PoolItemList - TargetImpl::commit( const TargetImpl::PoolItemList & items_r, - const ZYppCommitPolicy & policy_r, - ZYppCommitResult & result_r, - CommitPackageCache & packageCache_r ) + void TargetImpl::commit( const ZYppCommitPolicy & policy_r, + CommitPackageCache & packageCache_r, + ZYppCommitResult & result_r ) { - MIL << "TargetImpl::commit(" << policy_r << ")" << items_r.size() << endl; + // steps: this is our todo-list + ZYppCommitResult::TransactionStepList & steps( result_r.rTransactionStepList() ); + MIL << "TargetImpl::commit(" << policy_r << ")" << steps.size() << endl; bool abort = false; std::vector successfullyInstalledPackages; TargetImpl::PoolItemList remaining; - for ( TargetImpl::PoolItemList::const_iterator it = items_r.begin(); it != items_r.end(); it++ ) + for_( step, steps.begin(), steps.end() ) { - if ( (*it)->isKind() ) + PoolItem citem( *step ); + if ( step->stepType() == sat::Transaction::TRANSACTION_IGNORE ) + { + if ( citem->isKind() ) + { + // for packages this means being obsoleted (by rpm) + // thius no additional action is needed. + step->stepStage( sat::Transaction::STEP_DONE ); + continue; + } + } + + if ( citem->isKind() ) { - Package::constPtr p = (*it)->asKind(); - if (it->status().isToBeInstalled()) + Package::constPtr p = citem->asKind(); + if ( citem.status().isToBeInstalled() ) { ManagedFile localfile; try { - localfile = packageCache_r.get( it ); + localfile = packageCache_r.get( citem ); } catch ( const AbortRequestException &e ) { WAR << "commit aborted by the user" << endl; abort = true; - result_r._errors.push_back( *it ); - remaining.insert( remaining.end(), it, items_r.end() ); + step->stepStage( sat::Transaction::STEP_ERROR ); break; } catch ( const SkipRequestException &e ) { ZYPP_CAUGHT( e ); WAR << "Skipping package " << p << " in commit" << endl; - result_r._errors.push_back( *it ); - remaining.push_back( *it ); + step->stepStage( sat::Transaction::STEP_ERROR ); continue; } catch ( const Exception &e ) @@ -1270,14 +1270,13 @@ namespace zypp // TODO see if packageCache fails to handle errors correctly. ZYPP_CAUGHT( e ); INT << "Unexpected Error: Skipping package " << p << " in commit" << endl; - result_r._errors.push_back( *it ); - remaining.push_back( *it ); + step->stepStage( sat::Transaction::STEP_ERROR ); continue; } #warning Exception handling // create a installation progress report proxy - RpmInstallPackageReceiver progress( it->resolvable() ); + RpmInstallPackageReceiver progress( citem.resolvable() ); progress.connect(); // disconnected on destruction. bool success = false; @@ -1300,21 +1299,21 @@ namespace zypp try { progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE ); - rpm().installPackage( localfile, flags ); - HistoryLog().install(*it); + rpm().installPackage( localfile, flags ); + HistoryLog().install(citem); if ( progress.aborted() ) { WAR << "commit aborted by the user" << endl; localfile.resetDispose(); // keep the package file in the cache abort = true; - result_r._errors.push_back( *it ); - remaining.insert( remaining.end(), it, items_r.end() ); + step->stepStage( sat::Transaction::STEP_ERROR ); break; } else { success = true; + step->stepStage( sat::Transaction::STEP_DONE ); } } catch ( Exception & excpt_r ) @@ -1325,8 +1324,7 @@ namespace zypp if ( policy_r.dryRun() ) { WAR << "dry run failed" << endl; - result_r._errors.push_back( *it ); - remaining.insert( remaining.end(), it, items_r.end() ); + step->stepStage( sat::Transaction::STEP_ERROR ); break; } // else @@ -1339,21 +1337,20 @@ namespace zypp { WAR << "Install failed" << endl; } - result_r._errors.push_back( *it ); - remaining.insert( remaining.end(), it, items_r.end() ); + step->stepStage( sat::Transaction::STEP_ERROR ); break; // stop } if ( success && !policy_r.dryRun() ) { - it->status().resetTransact( ResStatus::USER ); - // Remember to check this package for presence of patch scripts. - successfullyInstalledPackages.push_back( it->satSolvable() ); + citem.status().resetTransact( ResStatus::USER ); + successfullyInstalledPackages.push_back( citem.satSolvable() ); + step->stepStage( sat::Transaction::STEP_DONE ); } } else { - RpmRemovePackageReceiver progress( it->resolvable() ); + RpmRemovePackageReceiver progress( citem.resolvable() ); progress.connect(); // disconnected on destruction. bool success = false; @@ -1362,19 +1359,20 @@ namespace zypp if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST; try { - rpm().removePackage( p, flags ); - HistoryLog().remove(*it); + rpm().removePackage( p, flags ); + HistoryLog().remove(citem); if ( progress.aborted() ) { WAR << "commit aborted by the user" << endl; abort = true; - result_r._errors.push_back( *it ); + step->stepStage( sat::Transaction::STEP_ERROR ); break; } else { success = true; + step->stepStage( sat::Transaction::STEP_DONE ); } } catch (Exception & excpt_r) @@ -1384,16 +1382,17 @@ namespace zypp { WAR << "commit aborted by the user" << endl; abort = true; - result_r._errors.push_back( *it ); + step->stepStage( sat::Transaction::STEP_ERROR ); break; } // else WAR << "removal of " << p << " failed"; - result_r._errors.push_back( *it ); + step->stepStage( sat::Transaction::STEP_ERROR ); } if ( success && !policy_r.dryRun() ) { - it->status().resetTransact( ResStatus::USER ); + citem.status().resetTransact( ResStatus::USER ); + step->stepStage( sat::Transaction::STEP_DONE ); } } } @@ -1401,14 +1400,14 @@ namespace zypp { // Status is changed as the buddy package buddy // gets installed/deleted. Handle non-buddies only. - if ( ! it->buddy() ) + if ( ! citem.buddy() ) { - if ( (*it)->isKind() ) + if ( citem->isKind() ) { - Product::constPtr p = (*it)->asKind(); - if ( it->status().isToBeInstalled() ) + Product::constPtr p = citem->asKind(); + if ( citem.status().isToBeInstalled() ) { - ERR << "Can't install orphan product without release-package! " << (*it) << endl; + ERR << "Can't install orphan product without release-package! " << citem << endl; } else { @@ -1417,7 +1416,7 @@ namespace zypp std::string referenceFilename( p->referenceFilename() ); if ( referenceFilename.empty() ) { - ERR << "Can't remove orphan product without 'referenceFilename'! " << (*it) << endl; + ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl; } else { @@ -1429,15 +1428,17 @@ namespace zypp } } } - else if ( (*it)->isKind() && it->status().isToBeInstalled() ) + else if ( citem->isKind() && citem.status().isToBeInstalled() ) { // SrcPackage is install-only - SrcPackage::constPtr p = (*it)->asKind(); + SrcPackage::constPtr p = citem->asKind(); installSrcPackage( p ); } - it->status().resetTransact( ResStatus::USER ); + citem.status().resetTransact( ResStatus::USER ); + step->stepStage( sat::Transaction::STEP_DONE ); } + } // other resolvables } // for @@ -1455,18 +1456,18 @@ namespace zypp // send messages after scripts in case some script generates output, // that should be kept in t %ghost message file. RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(), - successfullyInstalledPackages, - result_r ); + successfullyInstalledPackages, + result_r ); } if ( abort ) { ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) ); } - - return remaining; } + /////////////////////////////////////////////////////////////////// + rpm::RpmDb & TargetImpl::rpm() { return _rpm; diff --git a/zypp/target/TargetImpl.h b/zypp/target/TargetImpl.h index 3de2af9..189b9fc 100644 --- a/zypp/target/TargetImpl.h +++ b/zypp/target/TargetImpl.h @@ -13,7 +13,6 @@ #define ZYPP_TARGET_TARGETIMPL_H #include -#include #include #include "zypp/base/ReferenceCounted.h" @@ -184,10 +183,9 @@ namespace zypp private: /** Commit ordered changes (internal helper) */ - PoolItemList commit( const PoolItemList & items_r, - const ZYppCommitPolicy & policy_r, - ZYppCommitResult & result_r, - CommitPackageCache & packageCache_r ); + void commit( const ZYppCommitPolicy & policy_r, + CommitPackageCache & packageCache_r, + ZYppCommitResult & result_r ); protected: /** Path to the target */