TargetImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 
00015 #include <iostream>
00016 #include <string>
00017 #include <list>
00018 #include <set>
00019 
00020 #include "zypp/base/Logger.h"
00021 #include "zypp/base/Exception.h"
00022 #include "zypp/base/Gettext.h"
00023 #include "zypp/PoolItem.h"
00024 #include "zypp/Resolvable.h"
00025 #include "zypp/ResObject.h"
00026 #include "zypp/Package.h"
00027 #include "zypp/Script.h"
00028 #include "zypp/Message.h"
00029 #include "zypp/Source.h"
00030 #include "zypp/Url.h"
00031 
00032 #include "zypp/target/TargetImpl.h"
00033 #include "zypp/target/TargetCallbackReceiver.h"
00034 
00035 #include "zypp/pool/GetResolvablesToInsDel.h"
00036 #include "zypp/solver/detail/Helper.h"
00037 
00038 using namespace std;
00039 using zypp::solver::detail::Helper;
00040 //using zypp::solver::detail::InstallOrder;
00041 
00043 namespace zypp
00044 { 
00045 
00046   namespace target
00047   { 
00048 
00050     namespace
00051     { 
00052 
00053       struct PubKeyHelper
00054       {
00055       };
00056 
00058     } // namespace
00060 
00061     IMPL_PTR_TYPE(TargetImpl);
00062 
00063     TargetImpl_Ptr TargetImpl::_nullimpl;
00064 
00066     TargetImpl_Ptr TargetImpl::nullimpl()
00067     {
00068       if (_nullimpl == 0)
00069         _nullimpl = new TargetImpl;
00070       return _nullimpl;
00071     }
00072 
00073 
00075     //
00076     //  METHOD NAME : TargetImpl::TargetImpl
00077     //  METHOD TYPE : Ctor
00078     //
00079     TargetImpl::TargetImpl(const Pathname & root_r)
00080     : _root(root_r)
00081     {
00082       _rpm.initDatabase(root_r);
00083       _storage_enabled = false;
00084       MIL << "Initialized target on " << _root << endl;
00085     }
00086 
00088     //
00089     //  METHOD NAME : TargetImpl::~TargetImpl
00090     //  METHOD TYPE : Dtor
00091     //
00092     TargetImpl::~TargetImpl()
00093     {
00094       _rpm.closeDatabase();
00095       MIL << "Targets closed" << endl;
00096     }
00097 
00098     bool TargetImpl::isStorageEnabled() const
00099     {
00100       return _storage_enabled;
00101     }
00102 
00103 
00104     void TargetImpl::enableStorage(const Pathname &root_r)
00105     {
00106       _storage.init(root_r);
00107       _storage_enabled = true;
00108     }
00109 
00110     Pathname TargetImpl::root() const
00111     {
00112       return _root;
00113     }
00114 
00115     const ResStore & TargetImpl::resolvables()
00116     {
00117       _store.clear();
00118       // RPM objects
00119       std::list<Package::Ptr> packages = _rpm.getPackages();
00120       for (std::list<Package::Ptr>::const_iterator it = packages.begin();
00121            it != packages.end();
00122            it++)
00123       {
00124         _store.insert(*it);
00125       }
00126 
00127       if ( isStorageEnabled() )
00128       {
00129         // resolvables stored in the zypp storage database
00130         std::list<ResObject::Ptr> resolvables = _storage.storedObjects();
00131         for (std::list<ResObject::Ptr>::iterator it = resolvables.begin();
00132             it != resolvables.end();
00133             it++)
00134         {
00135           _store.insert(*it);
00136         }
00137       }
00138       else
00139       {
00140         WAR << "storage target not enabled" << std::endl;
00141       }
00142 
00143       return _store;
00144     }
00145 
00146 
00147 
00148     ZYppCommitResult TargetImpl::commit( ResPool pool_r, const ZYppCommitPolicy & policy_rX )
00149     {
00150       // ----------------------------------------------------------------- //
00151       // Fake outstanding YCP fix: Honour restriction to media 1
00152       // at installation, but install all remaining packages if post-boot.
00153       ZYppCommitPolicy policy_r( policy_rX );
00154       if ( policy_r.restrictToMedia() > 1 )
00155         policy_r.allMedia();
00156       // ----------------------------------------------------------------- //
00157 
00158       MIL << "TargetImpl::commit(<pool>, " << policy_r << ")" << endl;
00159       ZYppCommitResult result;
00160 #warning Commit does not provide ZYppCommitResult::_errors
00161 
00162       TargetImpl::PoolItemList to_uninstall;
00163       TargetImpl::PoolItemList to_install;
00164       TargetImpl::PoolItemList to_srcinstall;
00165       {
00166 
00167         pool::GetResolvablesToInsDel
00168           collect( pool_r, policy_r.restrictToMedia() ? pool::GetResolvablesToInsDel::ORDER_BY_MEDIANR
00169                                                       : pool::GetResolvablesToInsDel::ORDER_BY_SOURCE );
00170         MIL << "GetResolvablesToInsDel: " << endl << collect << endl;
00171         to_uninstall.swap( collect._toDelete );
00172         to_install.swap( collect._toInstall );
00173         to_srcinstall.swap( collect._toSrcinstall );
00174       }
00175 
00176       if ( policy_r.restrictToMedia() ) {
00177         MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
00178       }
00179 
00180       commit (to_uninstall, policy_r, pool_r );
00181 
00182       if (policy_r.restrictToMedia() == 0) {                    // commit all
00183         result._remaining = commit( to_install, policy_r, pool_r );
00184         result._srcremaining = commit( to_srcinstall, policy_r, pool_r );
00185       }
00186       else
00187       {
00188         TargetImpl::PoolItemList current_install;
00189         TargetImpl::PoolItemList current_srcinstall;
00190 
00191         // Collect until the 1st package from an unwanted media occurs.
00192         // Further collection could violate install order.
00193         bool hitUnwantedMedia = false;
00194         for (TargetImpl::PoolItemList::iterator it = to_install.begin(); it != to_install.end(); ++it)
00195         {
00196           ResObject::constPtr res( it->resolvable() );
00197 
00198           if ( hitUnwantedMedia
00199                || ( res->sourceMediaNr() && res->sourceMediaNr() != policy_r.restrictToMedia() ) )
00200             {
00201               hitUnwantedMedia = true;
00202               result._remaining.push_back( *it );
00203             }
00204           else
00205             {
00206               current_install.push_back( *it );
00207             }
00208         }
00209 
00210         TargetImpl::PoolItemList bad = commit( current_install, policy_r, pool_r );
00211         result._remaining.insert(result._remaining.end(), bad.begin(), bad.end());
00212 
00213         for (TargetImpl::PoolItemList::iterator it = to_srcinstall.begin(); it != to_srcinstall.end(); ++it)
00214         {
00215           Resolvable::constPtr res( it->resolvable() );
00216           Package::constPtr pkg( asKind<Package>(res) );
00217           if (pkg && policy_r.restrictToMedia() != pkg->sourceMediaNr()) // check medianr for packages only
00218           {
00219             XXX << "Package " << *pkg << ", wrong media " << pkg->sourceMediaNr() << endl;
00220             result._srcremaining.push_back( *it );
00221           }
00222           else {
00223             current_srcinstall.push_back( *it );
00224           }
00225         }
00226         bad = commit( current_srcinstall, policy_r, pool_r );
00227         result._srcremaining.insert(result._srcremaining.end(), bad.begin(), bad.end());
00228       }
00229 
00230 
00231       result._result = (to_install.size() - result._remaining.size());
00232       return result;
00233     }
00234 
00235 
00236     TargetImpl::PoolItemList
00237     TargetImpl::commit( const TargetImpl::PoolItemList & items_r,
00238                         const ZYppCommitPolicy & policy_r,
00239                         const ResPool & pool_r )
00240     {
00241       TargetImpl::PoolItemList remaining;
00242 
00243       MIL << "TargetImpl::commit(<list>" << policy_r << ")" << endl;
00244 
00245       bool abort = false;
00246 
00247       // remember the last used source (if any)
00248       Source_Ref lastUsedSource;
00249 
00250       for (TargetImpl::PoolItemList::const_iterator it = items_r.begin(); it != items_r.end(); it++)
00251       {
00252         if (isKind<Package>(it->resolvable()))
00253         {
00254           Package::constPtr p = dynamic_pointer_cast<const Package>(it->resolvable());
00255           if (it->status().isToBeInstalled())
00256           {
00257             Pathname localfile;
00258             try {
00259                 localfile = p->source().providePackage(p);
00260             }
00261             catch( const source::SkipRequestedException & e )
00262             {
00263                 ZYPP_CAUGHT( e );
00264                 WAR << "Skipping package " << p << " in commit" << endl;
00265                 continue;
00266             }
00267 
00268             lastUsedSource = p->source();                       // remember the package source
00269 
00270 #warning Exception handling
00271             // create a installation progress report proxy
00272             RpmInstallPackageReceiver progress( it->resolvable() );
00273             progress.connect();
00274             bool success = true;
00275             unsigned flags = 0;
00276             if (p->installOnly()) flags |= rpm::RpmDb::RPMINST_NOUPGRADE;
00277             if (policy_r.dryRun()) flags |= rpm::RpmDb::RPMINST_TEST;
00278             if (policy_r.rpmNoSignature()) flags |= rpm::RpmDb::RPMINST_NOSIGNATURE;
00279 
00280             try {
00281               progress.tryLevel( target::rpm::InstallResolvableReport::RPM );
00282               rpm().installPackage( localfile, flags );
00283 
00284               if( progress.aborted() )
00285               {
00286                 WAR << "commit aborted by the user" << endl;
00287                 progress.disconnect();
00288                 abort = true;
00289                 break;
00290               }
00291 
00292             }
00293             catch (Exception & excpt_r) {
00294               ZYPP_CAUGHT(excpt_r);
00295               WAR << "Install failed, retrying with --nodeps" << endl;
00296               if (policy_r.dryRun()) {
00297                   WAR << "dry run failed" << endl;
00298                   progress.disconnect();
00299                   break;
00300               }
00301 
00302               try {
00303                 progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS );
00304                 flags |= rpm::RpmDb::RPMINST_NODEPS;
00305                 rpm().installPackage( localfile, flags );
00306 
00307                 if( progress.aborted() )
00308                 {
00309                   WAR << "commit aborted by the user" << endl;
00310                   abort = true;
00311                   progress.disconnect();
00312                   break;
00313                 }
00314               }
00315               catch (Exception & excpt_r)
00316               {
00317                 ZYPP_CAUGHT(excpt_r);
00318                 WAR << "Install failed again, retrying with --force --nodeps" << endl;
00319 
00320                 try {
00321                   progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE );
00322                   flags |= rpm::RpmDb::RPMINST_FORCE;
00323                   rpm().installPackage( localfile, flags );
00324                 }
00325                 catch (Exception & excpt_r) {
00326                   remaining.push_back( *it );
00327                   success = false;
00328                   ZYPP_CAUGHT(excpt_r);
00329                 }
00330 
00331                 if( progress.aborted() )
00332                 {
00333                     WAR << "commit aborted by the user" << endl;
00334                     abort = true;
00335                     progress.disconnect();
00336                     break;
00337                 }
00338               }
00339             }
00340             if (success
00341                 && !policy_r.dryRun())
00342             {
00343               it->status().resetTransact( ResStatus::USER );
00344             }
00345             progress.disconnect();
00346             p->source().releaseFile( p->location(), p->sourceMediaNr() );
00347           }
00348           else
00349           {
00350             bool success = true;
00351 
00352             RpmRemovePackageReceiver progress( it->resolvable() );
00353             progress.connect();
00354             unsigned flags = rpm::RpmDb::RPMINST_NODEPS;
00355             if (policy_r.dryRun()) flags |= rpm::RpmDb::RPMINST_TEST;
00356             try {
00357               rpm().removePackage( p, flags );
00358             }
00359             catch (Exception & excpt_r) {
00360               WAR << "removal of " << p << " failed";
00361               success = false;
00362               ZYPP_CAUGHT( excpt_r );
00363             }
00364             if (success
00365                 && !policy_r.dryRun())
00366             {
00367               it->status().resetTransact( ResStatus::USER );
00368             }
00369             progress.disconnect();
00370           }
00371         }
00372         else if (!policy_r.dryRun()) // other resolvables (non-Package)
00373         {
00374           if ( isStorageEnabled() )
00375           {
00376             if (it->status().isToBeInstalled())
00377             {
00378               bool success = false;
00379               try
00380               {
00381                 if (isKind<Message>(it->resolvable()))
00382                 {
00383                   Message::constPtr m = dynamic_pointer_cast<const Message>(it->resolvable());
00384                   std::string text = m->text().asString();
00385 
00386                   callback::SendReport<target::MessageResolvableReport> report;
00387 
00388                   report->show( m );
00389 
00390                   MIL << "Displaying the text '" << text << "'" << endl;
00391                 }
00392                 else if (isKind<Script>(it->resolvable()))
00393                 {
00394                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
00395                   Pathname p = s->do_script();
00396                   if (p != "" && p != "/")
00397                   {
00398                     chmod( p.asString().c_str(), S_IRUSR|S_IXUSR );     // "r-x------"
00399                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
00400                     if (! prog)
00401                       ZYPP_THROW(Exception("Cannot run the script"));
00402                     int retval = prog->close();
00403                     delete prog;
00404                     if (retval != 0)
00405                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
00406                   }
00407                   else
00408                   {
00409                     ERR << "Do script not defined" << endl;
00410                   }
00411                 }
00412                 else if (!isKind<Atom>(it->resolvable()))       // atoms are re-created from the patch data, no need to save them
00413                 {
00414                   // #160792 do not just add, also remove older versions
00415                   if (true) // !installOnly - only on Package?!
00416                   {
00417                     // this would delete the same item over and over
00418                     //for (PoolItem_Ref old = Helper::findInstalledItem (pool_r, *it); old; )
00419                     PoolItem_Ref old = Helper::findInstalledItem (pool_r, *it);
00420                     if (old)
00421                     {
00422                       _storage.deleteObject(old.resolvable());
00423                     }
00424                   }
00425                   _storage.storeObject(it->resolvable());
00426                 }
00427                 success = true;
00428               }
00429               catch (Exception & excpt_r)
00430               {
00431                 ZYPP_CAUGHT(excpt_r);
00432                 WAR << "Install of Resolvable from storage failed" << endl;
00433               }
00434               if (success)
00435                 it->status().resetTransact( ResStatus::USER );
00436             }
00437             else
00438             {                                   // isToBeUninstalled
00439               bool success = false;
00440               try
00441               {
00442                 if (isKind<Message>(it->resolvable()))
00443                 {
00444                   DBG << "Uninstalling message - no-op" << endl;
00445                 }
00446                 else if (isKind<Script>(it->resolvable()))
00447                 {
00448                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
00449                   Pathname p = s->undo_script();
00450                   if (! s->undo_available())
00451                   {
00452                     DBG << "Undo script not available" << endl;
00453                   }
00454                   if (p != "" && p != "/")
00455                   {
00456                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
00457                     if (! prog)
00458                       ZYPP_THROW(Exception("Cannot run the script"));
00459                     int retval = prog->close();
00460                     delete prog;
00461                     if (retval != 0)
00462                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
00463                   }
00464                   else
00465                   {
00466                     ERR << "Undo script not defined" << endl;
00467                   }
00468                 }
00469                 else
00470                 {
00471                   _storage.deleteObject(it->resolvable());
00472                 }
00473                 success = true;
00474               }
00475               catch (Exception & excpt_r)
00476               {
00477                 ZYPP_CAUGHT(excpt_r);
00478                 WAR << "Uninstall of Resolvable from storage failed" << endl;
00479               }
00480               if (success)
00481                 it->status().resetTransact( ResStatus::USER );
00482             }
00483           }
00484           else
00485           {
00486             WAR << "storage target disabled" << std::endl;
00487           }
00488 
00489         }  // other resolvables
00490 
00491       } // for
00492 
00493       // we're done with the commit, release the source media
00494       //   In the case of a single media, end of commit means we don't need _this_
00495       //   media any more.
00496       //   In the case of 'commit any media', end of commit means we're completely
00497       //   done and don't need the source's media anyways.
00498 
00499       if (lastUsedSource) {             // if a source was used
00500         lastUsedSource.release();       //  release their medias
00501       }
00502 
00503       if( abort )
00504         ZYPP_THROW( TargetAbortedException( N_("Target commit aborted by user.") ) );
00505 
00506       return remaining;
00507     }
00508 
00509     rpm::RpmDb & TargetImpl::rpm()
00510     { return _rpm; }
00511 
00512     bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
00513     { return _rpm.hasFile(path_str, name_str); }
00514 
00517     ResObject::constPtr TargetImpl::whoOwnsFile (const std::string & path_str) const
00518     {
00519         string name = _rpm.whoOwnsFile (path_str);
00520         if (name.empty())
00521             return NULL;
00522 
00523         for (ResStore::const_iterator it = _store.begin(); it != _store.end(); ++it) {
00524             if ((*it)->name() == name) {
00525                 return *it;
00526             }
00527         }
00528         return NULL;
00529     }
00530 
00532     bool TargetImpl::setInstallationLogfile(const Pathname & path_r)
00533     {
00534       return rpm::RpmDb::setInstallationLogfile(path_r);
00535     }
00536 
00537     void
00538     TargetImpl::getResolvablesToInsDel ( const ResPool pool_r,
00539                                          TargetImpl::PoolItemList & dellist_r,
00540                                          TargetImpl::PoolItemList & instlist_r,
00541                                          TargetImpl::PoolItemList & srclist_r ) const
00542     {
00543       pool::GetResolvablesToInsDel collect( pool_r );
00544       MIL << "GetResolvablesToInsDel: " << endl << collect << endl;
00545       dellist_r.swap( collect._toDelete );
00546       instlist_r.swap( collect._toInstall );
00547       srclist_r.swap( collect._toSrcinstall );
00548     }
00549 
00551   } // namespace target
00554 } // namespace zypp

Generated on Thu Jul 6 00:07:28 2006 for zypp by  doxygen 1.4.6