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       getResolvablesToInsDel( pool_r, to_uninstall, to_install, to_srcinstall );
00166 
00167       if ( policy_r.restrictToMedia() ) {
00168         MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
00169       }
00170 
00171       commit (to_uninstall, policy_r, pool_r );
00172 
00173       if (policy_r.restrictToMedia() == 0) {                    // commit all
00174         result._remaining = commit( to_install, policy_r, pool_r );
00175         result._srcremaining = commit( to_srcinstall, policy_r, pool_r );
00176       }
00177       else
00178       {
00179         TargetImpl::PoolItemList current_install;
00180         TargetImpl::PoolItemList current_srcinstall;
00181 
00182         // Collect until the 1st package from an unwanted media occurs.
00183         // Further collection could violate install order.
00184         bool hitUnwantedMedia = false;
00185         for (TargetImpl::PoolItemList::iterator it = to_install.begin(); it != to_install.end(); ++it)
00186         {
00187           ResObject::constPtr res( it->resolvable() );
00188 
00189           if ( hitUnwantedMedia
00190                || ( res->sourceMediaNr() && res->sourceMediaNr() != policy_r.restrictToMedia() ) )
00191             {
00192               hitUnwantedMedia = true;
00193               result._remaining.push_back( *it );
00194             }
00195           else
00196             {
00197               current_install.push_back( *it );
00198             }
00199         }
00200 
00201         TargetImpl::PoolItemList bad = commit( current_install, policy_r, pool_r );
00202         result._remaining.insert(result._remaining.end(), bad.begin(), bad.end());
00203 
00204         for (TargetImpl::PoolItemList::iterator it = to_srcinstall.begin(); it != to_srcinstall.end(); ++it)
00205         {
00206           Resolvable::constPtr res( it->resolvable() );
00207           Package::constPtr pkg( asKind<Package>(res) );
00208           if (pkg && policy_r.restrictToMedia() != pkg->sourceMediaNr()) // check medianr for packages only
00209           {
00210             XXX << "Package " << *pkg << ", wrong media " << pkg->sourceMediaNr() << endl;
00211             result._srcremaining.push_back( *it );
00212           }
00213           else {
00214             current_srcinstall.push_back( *it );
00215           }
00216         }
00217         bad = commit( current_srcinstall, policy_r, pool_r );
00218         result._srcremaining.insert(result._srcremaining.end(), bad.begin(), bad.end());
00219       }
00220 
00221 
00222       result._result = (to_install.size() - result._remaining.size());
00223       return result;
00224     }
00225 
00226 
00227     TargetImpl::PoolItemList
00228     TargetImpl::commit( const TargetImpl::PoolItemList & items_r,
00229                         const ZYppCommitPolicy & policy_r,
00230                         const ResPool & pool_r )
00231     {
00232       TargetImpl::PoolItemList remaining;
00233 
00234       MIL << "TargetImpl::commit(<list>" << policy_r << ")" << endl;
00235 
00236       bool abort = false;
00237 
00238       // remember the last used source (if any)
00239       Source_Ref lastUsedSource;
00240 
00241       for (TargetImpl::PoolItemList::const_iterator it = items_r.begin(); it != items_r.end(); it++)
00242       {
00243         if (isKind<Package>(it->resolvable()))
00244         {
00245           Package::constPtr p = dynamic_pointer_cast<const Package>(it->resolvable());
00246           if (it->status().isToBeInstalled())
00247           {
00248             Pathname localfile;
00249             try {
00250                 localfile = p->source().providePackage(p);
00251             }
00252             catch( const source::SkipRequestedException & e )
00253             {
00254                 ZYPP_CAUGHT( e );
00255                 WAR << "Skipping package " << p << " in commit" << endl;
00256                 continue;
00257             }
00258 
00259             lastUsedSource = p->source();                       // remember the package source
00260 
00261 #warning Exception handling
00262             // create a installation progress report proxy
00263             RpmInstallPackageReceiver progress( it->resolvable() );
00264             progress.connect();
00265             bool success = true;
00266             unsigned flags = 0;
00267             if (p->installOnly()) flags |= rpm::RpmDb::RPMINST_NOUPGRADE;
00268             if (policy_r.dryRun()) flags |= rpm::RpmDb::RPMINST_TEST;
00269             if (policy_r.rpmNoSignature()) flags |= rpm::RpmDb::RPMINST_NOSIGNATURE;
00270 
00271             try {
00272               progress.tryLevel( target::rpm::InstallResolvableReport::RPM );
00273               rpm().installPackage( localfile, flags );
00274 
00275               if( progress.aborted() )
00276               {
00277                 WAR << "commit aborted by the user" << endl;
00278                 progress.disconnect();
00279                 abort = true;
00280                 break;
00281               }
00282 
00283             }
00284             catch (Exception & excpt_r) {
00285               ZYPP_CAUGHT(excpt_r);
00286               WAR << "Install failed, retrying with --nodeps" << endl;
00287               if (policy_r.dryRun()) {
00288                   WAR << "dry run failed" << endl;
00289                   progress.disconnect();
00290                   break;
00291               }
00292 
00293               try {
00294                 progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS );
00295                 flags |= rpm::RpmDb::RPMINST_NODEPS;
00296                 rpm().installPackage( localfile, flags );
00297 
00298                 if( progress.aborted() )
00299                 {
00300                   WAR << "commit aborted by the user" << endl;
00301                   abort = true;
00302                   progress.disconnect();
00303                   break;
00304                 }
00305               }
00306               catch (Exception & excpt_r)
00307               {
00308                 ZYPP_CAUGHT(excpt_r);
00309                 WAR << "Install failed again, retrying with --force --nodeps" << endl;
00310 
00311                 try {
00312                   progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE );
00313                   flags |= rpm::RpmDb::RPMINST_FORCE;
00314                   rpm().installPackage( localfile, flags );
00315                 }
00316                 catch (Exception & excpt_r) {
00317                   remaining.push_back( *it );
00318                   success = false;
00319                   ZYPP_CAUGHT(excpt_r);
00320                 }
00321 
00322                 if( progress.aborted() )
00323                 {
00324                     WAR << "commit aborted by the user" << endl;
00325                     abort = true;
00326                     progress.disconnect();
00327                     break;
00328                 }
00329               }
00330             }
00331             if (success
00332                 && !policy_r.dryRun())
00333             {
00334               it->status().resetTransact( ResStatus::USER );
00335             }
00336             progress.disconnect();
00337             p->source().releaseFile( p->location(), p->sourceMediaNr() );
00338           }
00339           else
00340           {
00341             bool success = true;
00342 
00343             RpmRemovePackageReceiver progress( it->resolvable() );
00344             progress.connect();
00345             unsigned flags = rpm::RpmDb::RPMINST_NODEPS;
00346             if (policy_r.dryRun()) flags |= rpm::RpmDb::RPMINST_TEST;
00347             try {
00348               rpm().removePackage( p, flags );
00349             }
00350             catch (Exception & excpt_r) {
00351               WAR << "removal of " << p << " failed";
00352               success = false;
00353               ZYPP_CAUGHT( excpt_r );
00354             }
00355             if (success
00356                 && !policy_r.dryRun())
00357             {
00358               it->status().resetTransact( ResStatus::USER );
00359             }
00360             progress.disconnect();
00361           }
00362         }
00363         else if (!policy_r.dryRun()) // other resolvables (non-Package)
00364         {
00365           if ( isStorageEnabled() )
00366           {
00367             if (it->status().isToBeInstalled())
00368             {
00369               bool success = false;
00370               try
00371               {
00372                 if (isKind<Message>(it->resolvable()))
00373                 {
00374                   Message::constPtr m = dynamic_pointer_cast<const Message>(it->resolvable());
00375                   std::string text = m->text().asString();
00376 
00377                   callback::SendReport<target::MessageResolvableReport> report;
00378 
00379                   report->show( m );
00380 
00381                   MIL << "Displaying the text '" << text << "'" << endl;
00382                 }
00383                 else if (isKind<Script>(it->resolvable()))
00384                 {
00385                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
00386                   Pathname p = s->do_script();
00387                   if (p != "" && p != "/")
00388                   {
00389                     chmod( p.asString().c_str(), S_IRUSR|S_IXUSR );     // "r-x------"
00390                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
00391                     if (! prog)
00392                       ZYPP_THROW(Exception("Cannot run the script"));
00393                     int retval = prog->close();
00394                     delete prog;
00395                     if (retval != 0)
00396                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
00397                   }
00398                   else
00399                   {
00400                     ERR << "Do script not defined" << endl;
00401                   }
00402                 }
00403                 else if (!isKind<Atom>(it->resolvable()))       // atoms are re-created from the patch data, no need to save them
00404                 {
00405                   // #160792 do not just add, also remove older versions
00406                   if (true) // !installOnly - only on Package?!
00407                   {
00408                     // this would delete the same item over and over
00409                     //for (PoolItem_Ref old = Helper::findInstalledItem (pool_r, *it); old; )
00410                     PoolItem_Ref old = Helper::findInstalledItem (pool_r, *it);
00411                     if (old)
00412                     {
00413                       _storage.deleteObject(old.resolvable());
00414                     }
00415                   }
00416                   _storage.storeObject(it->resolvable());
00417                 }
00418                 success = true;
00419               }
00420               catch (Exception & excpt_r)
00421               {
00422                 ZYPP_CAUGHT(excpt_r);
00423                 WAR << "Install of Resolvable from storage failed" << endl;
00424               }
00425               if (success)
00426                 it->status().resetTransact( ResStatus::USER );
00427             }
00428             else
00429             {                                   // isToBeUninstalled
00430               bool success = false;
00431               try
00432               {
00433                 if (isKind<Message>(it->resolvable()))
00434                 {
00435                   DBG << "Uninstalling message - no-op" << endl;
00436                 }
00437                 else if (isKind<Script>(it->resolvable()))
00438                 {
00439                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
00440                   Pathname p = s->undo_script();
00441                   if (! s->undo_available())
00442                   {
00443                     DBG << "Undo script not available" << endl;
00444                   }
00445                   if (p != "" && p != "/")
00446                   {
00447                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
00448                     if (! prog)
00449                       ZYPP_THROW(Exception("Cannot run the script"));
00450                     int retval = prog->close();
00451                     delete prog;
00452                     if (retval != 0)
00453                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
00454                   }
00455                   else
00456                   {
00457                     ERR << "Undo script not defined" << endl;
00458                   }
00459                 }
00460                 else
00461                 {
00462                   _storage.deleteObject(it->resolvable());
00463                 }
00464                 success = true;
00465               }
00466               catch (Exception & excpt_r)
00467               {
00468                 ZYPP_CAUGHT(excpt_r);
00469                 WAR << "Uninstall of Resolvable from storage failed" << endl;
00470               }
00471               if (success)
00472                 it->status().resetTransact( ResStatus::USER );
00473             }
00474           }
00475           else
00476           {
00477             WAR << "storage target disabled" << std::endl;
00478           }
00479 
00480         }  // other resolvables
00481 
00482       } // for
00483 
00484       // we're done with the commit, release the source media
00485       //   In the case of a single media, end of commit means we don't need _this_
00486       //   media any more.
00487       //   In the case of 'commit any media', end of commit means we're completely
00488       //   done and don't need the source's media anyways.
00489 
00490       if (lastUsedSource) {             // if a source was used
00491         lastUsedSource.release();       //  release their medias
00492       }
00493 
00494       if( abort )
00495         ZYPP_THROW( TargetAbortedException( N_("Target commit aborted by user.") ) );
00496 
00497       return remaining;
00498     }
00499 
00500     rpm::RpmDb & TargetImpl::rpm()
00501     { return _rpm; }
00502 
00503     bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
00504     { return _rpm.hasFile(path_str, name_str); }
00505 
00508     ResObject::constPtr TargetImpl::whoOwnsFile (const std::string & path_str) const
00509     {
00510         string name = _rpm.whoOwnsFile (path_str);
00511         if (name.empty())
00512             return NULL;
00513 
00514         for (ResStore::const_iterator it = _store.begin(); it != _store.end(); ++it) {
00515             if ((*it)->name() == name) {
00516                 return *it;
00517             }
00518         }
00519         return NULL;
00520     }
00521 
00523     bool TargetImpl::setInstallationLogfile(const Pathname & path_r)
00524     {
00525       return rpm::RpmDb::setInstallationLogfile(path_r);
00526     }
00527 
00528     void
00529     TargetImpl::getResolvablesToInsDel ( const ResPool pool_r,
00530                                          TargetImpl::PoolItemList & dellist_r,
00531                                          TargetImpl::PoolItemList & instlist_r,
00532                                          TargetImpl::PoolItemList & srclist_r ) const
00533     {
00534       pool::GetResolvablesToInsDel collect( pool_r );
00535       MIL << "GetResolvablesToInsDel: " << endl << collect << endl;
00536       dellist_r.swap( collect._toDelete );
00537       instlist_r.swap( collect._toInstall );
00538       srclist_r.swap( collect._toSrcinstall );
00539     }
00540 
00542   } // namespace target
00545 } // namespace zypp

Generated on Mon Jun 5 19:10:45 2006 for zypp by  doxygen 1.4.6