Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / repo / PackageProvider.cc
index 8bd7601..fd52e1e 100644 (file)
@@ -25,7 +25,6 @@
 #include "zypp/ZConfig.h"
 #include "zypp/RepoInfo.h"
 #include "zypp/RepoManager.h"
-#include "zypp/SrcPackage.h"
 
 #include "zypp/ZYppFactory.h"
 #include "zypp/Target.h"
@@ -41,27 +40,6 @@ namespace zypp
   namespace repo
   {
     ///////////////////////////////////////////////////////////////////
-    /// \class RpmSigCheckException
-    /// \brief Exception thrown by \ref PackageProviderImpl::rpmSigFileChecker
-    ///////////////////////////////////////////////////////////////////
-    class RpmSigCheckException : public FileCheckException
-    {
-    public:
-      RpmSigCheckException( repo::DownloadResolvableReport::Action action_r, std::string msg_r = "RpmSigCheckException" )
-      : FileCheckException( std::move(msg_r) )
-      , _action( std::move(action_r) )
-      {}
-
-      /** Users final decision how to proceed */
-      const repo::DownloadResolvableReport::Action & action() const
-      { return _action; }
-
-    private:
-      repo::DownloadResolvableReport::Action _action;
-    };
-
-
-    ///////////////////////////////////////////////////////////////////
     // class PackageProviderPolicy
     ///////////////////////////////////////////////////////////////////
 
@@ -74,58 +52,47 @@ namespace zypp
       return false;
     }
 
-    ///////////////////////////////////////////////////////////////////
-    /// \class PackageProvider::Impl
-    /// \brief PackageProvider implementation interface.
-    ///////////////////////////////////////////////////////////////////
-    struct PackageProvider::Impl : private base::NonCopyable
-    {
-      Impl() {}
-      virtual ~Impl() {}
-
-      /** Provide the package.
-       * The basic workflow.
-       * \throws Exception.
-       */
-      virtual ManagedFile providePackage() const = 0;
-
-      /** Provide the package if it is cached. */
-      virtual ManagedFile providePackageFromCache() const = 0;
-
-      /** Whether the package is cached. */
-      virtual bool isCached() const = 0;
-    };
 
     ///////////////////////////////////////////////////////////////////
-    /// \class PackageProviderImpl<TPackage>
-    /// \brief PackageProvider implementation for \c Package and \c SrcPackage
+    /// \class PackageProvider::Impl
+    /// \brief PackageProvider implementation.
     ///////////////////////////////////////////////////////////////////
-    template <class TPackage>
-    class PackageProviderImpl : public PackageProvider::Impl
+    class PackageProvider::Impl : private base::NonCopyable
     {
-      typedef typename TPackage::constPtr TPackagePtr; // Package or SrcPackage
       typedef callback::UserData UserData;
     public:
       /** Ctor taking the Package to provide. */
-      PackageProviderImpl( RepoMediaAccess & access_r, const TPackagePtr & package_r,
-                          const PackageProviderPolicy & policy_r )
+      Impl( RepoMediaAccess & access_r,
+           const Package::constPtr & package_r,
+           const DeltaCandidates & deltas_r,
+           const PackageProviderPolicy & policy_r )
       : _policy( policy_r )
       , _package( package_r )
+      , _deltas( deltas_r )
       , _access( access_r )
       , _retry(false)
       {}
 
-      virtual ~PackageProviderImpl() {}
+      virtual ~Impl() {}
+
+      /** Factory method providing the appropriate implementation.
+       * Called by PackageProvider ctor. Returned pointer should be
+       * immediately wrapped into a smartpointer.
+       */
+      static Impl * factoryMake( RepoMediaAccess & access_r,
+                                const Package::constPtr & package_r,
+                                const DeltaCandidates & deltas_r,
+                                const PackageProviderPolicy & policy_r );
 
     public:
       /** Provide the package.
        * The basic workflow.
        * \throws Exception.
        */
-      virtual ManagedFile providePackage() const;
+      ManagedFile providePackage() const;
 
       /** Provide the package if it is cached. */
-      virtual ManagedFile providePackageFromCache() const
+      ManagedFile providePackageFromCache() const
       {
        ManagedFile ret( doProvidePackageFromCache() );
        if ( ! ( ret->empty() ||  _package->repoInfo().keepPackages() ) )
@@ -134,22 +101,24 @@ namespace zypp
       }
 
       /** Whether the package is cached. */
-      virtual bool isCached() const
+      bool isCached() const
       { return ! doProvidePackageFromCache()->empty(); }
 
     protected:
-      typedef PackageProviderImpl<TPackage>    Base;
+      typedef PackageProvider::Impl    Base;
       typedef callback::SendReport<repo::DownloadResolvableReport>     Report;
 
       /** Lookup the final rpm in cache.
        *
-       * A cache hit will return a non empty ManagedFile and an empty one on cache miss.
+       * A non empty ManagedFile will be returned to the caller.
        *
        * \note File disposal depending on the repos keepPackages setting
        * are not set here, but in \ref providePackage or \ref providePackageFromCache.
+       *
+       * \note The provoided default implementation returns an empty ManagedFile
+       * (cache miss).
        */
-      ManagedFile doProvidePackageFromCache() const
-      { return ManagedFile( _package->cachedLocation() ); }
+      virtual ManagedFile doProvidePackageFromCache() const = 0;
 
       /** Actually provide the final rpm.
        * Report start/problem/finish and retry loop are hadled by \ref providePackage.
@@ -165,16 +134,7 @@ namespace zypp
        * \note The provided default implementation retrieves the packages default
        * location.
        */
-      virtual ManagedFile doProvidePackage() const
-      {
-       ManagedFile ret;
-       OnMediaLocation loc = _package->location();
-
-       ProvideFilePolicy policy;
-       policy.progressCB( bind( &Base::progressPackageDownload, this, _1 ) );
-       policy.fileChecker( bind( &Base::rpmSigFileChecker, this, _1 ) );
-       return _access.provideFile( _package->repoInfo(), loc, policy );
-      }
+      virtual ManagedFile doProvidePackage() const = 0;
 
     protected:
       /** Access to the DownloadResolvableReport */
@@ -185,73 +145,9 @@ namespace zypp
       bool progressPackageDownload( int value ) const
       {        return report()->progress( value, _package ); }
 
-
-      /** \name Validate a rpm packages signature.
-       *
-       * This is the \ref FileChecker passed down to the \ref Fetcher to validate
-       * a provided rpm package. This builtin checker includes the workflow
-       * communicating with the user in case of a problem with the package
-       * signature.
-       *
-       * \throws RpmSigCheckException if the package is not accepted, propagating
-       * the users decision how to proceed (\ref DownloadResolvableReport::Action).
-       *
-       * \note This check is also needed, if the the rpm is built locally by using
-       * delta rpms! \ref \see RpmPackageProvider
-       */
-      //@{
-      void rpmSigFileChecker( const Pathname & file_r ) const
-      {
-       const RepoInfo & info = _package->repoInfo();
-       if ( info.pkgGpgCheck() )
-       {
-         UserData userData( "pkgGpgCheck" );
-         ResObject::constPtr roptr( _package );        // gcc6 needs it more explcit. Has problem deducing
-         userData.set( "ResObject", roptr );           // a type for '_package->asKind<ResObject>()'...
-         /*legacy:*/userData.set( "Package", roptr->asKind<Package>() );
-         userData.set( "Localpath", file_r );
-         RpmDb::CheckPackageResult res = packageSigCheck( file_r, info.pkgGpgCheckIsMandatory(), userData );
-
-         // publish the checkresult, even if it is OK. Apps may want to report something...
-         report()->pkgGpgCheck( userData );
-
-         if ( res != RpmDb::CHK_OK )
-         {
-           if ( userData.hasvalue( "Action" ) )        // pkgGpgCheck report provided an user error action
-           {
-             resolveSignatureErrorAction( userData.get( "Action", repo::DownloadResolvableReport::ABORT ) );
-           }
-           else if ( userData.haskey( "Action" ) )     // pkgGpgCheck requests the default problem report (wo. details)
-           {
-             defaultReportSignatureError( res );
-           }
-           else                                        // no advice from user => usedefaults
-           {
-             switch ( res )
-             {
-               case RpmDb::CHK_OK:             // Signature is OK
-                 break;
-
-               case RpmDb::CHK_NOKEY:          // Public key is unavailable
-               case RpmDb::CHK_NOTFOUND:       // Signature is unknown type
-               case RpmDb::CHK_FAIL:           // Signature does not verify
-               case RpmDb::CHK_NOTTRUSTED:     // Signature is OK, but key is not trusted
-               case RpmDb::CHK_ERROR:          // File does not exist or can't be opened
-               case RpmDb::CHK_NOSIG:          // File is unsigned
-               default:
-                 // report problem (w. details), throw if to abort, else retry/ignore
-                 defaultReportSignatureError( res, str::Str() << userData.get<RpmDb::CheckPackageDetail>( "CheckPackageDetail" ) );
-                 break;
-             }
-           }
-         }
-       }
-      }
-
       typedef target::rpm::RpmDb RpmDb;
 
-      /** Actual rpm package signature check. */
-      RpmDb::CheckPackageResult packageSigCheck( const Pathname & path_r, bool isMandatory_r, UserData & userData ) const
+      RpmDb::CheckPackageResult packageSigCheck( const Pathname & path_r, UserData & userData ) const
       {
        if ( !_target )
          _target = getZYpp()->getTarget();
@@ -259,14 +155,7 @@ namespace zypp
        RpmDb::CheckPackageResult ret = RpmDb::CHK_ERROR;
        RpmDb::CheckPackageDetail detail;
        if ( _target )
-       {
-         ret = _target->rpmDb().checkPackageSignature( path_r, detail );
-         if ( ret == RpmDb::CHK_NOSIG && !isMandatory_r )
-         {
-           WAR << "Relax CHK_NOSIG: Config says unsigned packages are OK" << endl;
-           ret = RpmDb::CHK_OK;
-         }
-       }
+         ret = _target->rpmDb().checkPackage( path_r, detail );
        else
          detail.push_back( RpmDb::CheckPackageDetail::value_type( ret, "OOps. Target is not initialized!" ) );
 
@@ -275,20 +164,22 @@ namespace zypp
        return ret;
       }
 
-      /** React on signature verification error user action.
+      /** React on signature verification error user action
        * \note: IGNORE == accept insecure file (no SkipRequestException!)
        */
       void resolveSignatureErrorAction( repo::DownloadResolvableReport::Action action_r ) const
       {
        switch ( action_r )
        {
+         case repo::DownloadResolvableReport::RETRY:
+           _retry = true;
+           break;
          case repo::DownloadResolvableReport::IGNORE:
            WAR << _package->asUserString() << ": " << "User requested to accept insecure file" << endl;
            break;
          default:
-         case repo::DownloadResolvableReport::RETRY:
          case repo::DownloadResolvableReport::ABORT:
-           ZYPP_THROW(RpmSigCheckException(action_r,"Signature verification failed"));
+           ZYPP_THROW(AbortRequestException("User requested to abort"));
            break;
        }
       }
@@ -302,11 +193,11 @@ namespace zypp
          msg << "\n" << detail_r;
        resolveSignatureErrorAction( report()->problem( _package, repo::DownloadResolvableReport::INVALID, msg.str() ) );
       }
-      //@}
 
     protected:
       PackageProviderPolicy    _policy;
-      TPackagePtr              _package;
+      Package::constPtr                _package;
+      DeltaCandidates          _deltas;
       RepoMediaAccess &                _access;
 
     private:
@@ -329,8 +220,24 @@ namespace zypp
     };
     ///////////////////////////////////////////////////////////////////
 
-    template <class TPackage>
-    ManagedFile PackageProviderImpl<TPackage>::providePackage() const
+    /** Default implementation (cache miss). */
+    ManagedFile PackageProvider::Impl::doProvidePackageFromCache() const
+    { return ManagedFile(); }
+
+    /** Default implementation (provide full package) */
+    ManagedFile PackageProvider::Impl::doProvidePackage() const
+    {
+      ManagedFile ret;
+      OnMediaLocation loc = _package->location();
+
+      ProvideFilePolicy policy;
+      policy.progressCB( bind( &Base::progressPackageDownload, this, _1 ) );
+      return _access.provideFile( _package->repoInfo(), loc, policy );
+    }
+
+    ///////////////////////////////////////////////////////////////////
+
+    ManagedFile PackageProvider::Impl::providePackage() const
     {
       ScopedGuard guardReport( newReport() );
 
@@ -380,7 +287,6 @@ namespace zypp
 
       MIL << "provide Package " << _package << endl;
       Url url = * info.baseUrlsBegin();
-      try {
       do {
         _retry = false;
        if ( ! ret->empty() )
@@ -392,6 +298,46 @@ namespace zypp
         try
           {
             ret = doProvidePackage();
+
+           if ( info.pkgGpgCheck() )
+           {
+             UserData userData( "pkgGpgCheck" );
+             userData.set( "Package", _package );
+             userData.set( "Localpath", ret.value() );
+             RpmDb::CheckPackageResult res = packageSigCheck( ret, userData );
+             // publish the checkresult, even if it is OK. Apps may want to report something...
+             report()->pkgGpgCheck( userData );
+USR << "CHK: " << res << endl;
+             if ( res != RpmDb::CHK_OK )
+             {
+               if ( userData.hasvalue( "Action" ) )    // pkgGpgCheck report provided an user error action
+               {
+                 resolveSignatureErrorAction( userData.get( "Action", repo::DownloadResolvableReport::ABORT ) );
+               }
+               else if ( userData.haskey( "Action" ) ) // pkgGpgCheck requests the default problem report (wo. details)
+               {
+                 defaultReportSignatureError( res );
+               }
+               else                                    // no advice from user => usedefaults
+               {
+                 switch ( res )
+                 {
+                   case RpmDb::CHK_OK:         // Signature is OK
+                     break;
+
+                   case RpmDb::CHK_NOKEY:      // Public key is unavailable
+                   case RpmDb::CHK_NOTFOUND:   // Signature is unknown type
+                   case RpmDb::CHK_FAIL:       // Signature does not verify
+                   case RpmDb::CHK_NOTTRUSTED: // Signature is OK, but key is not trusted
+                   case RpmDb::CHK_ERROR:      // File does not exist or can't be opened
+                   default:
+                     // report problem (w. details), throw if to abort, else retry/ignore
+                     defaultReportSignatureError( res, str::Str() << userData.get<RpmDb::CheckPackageDetail>( "CheckPackageDetail" ) );
+                     break;
+                 }
+               }
+             }
+           }
           }
         catch ( const UserRequestException & excpt )
           {
@@ -399,28 +345,6 @@ namespace zypp
            if ( ! _retry )
              ZYPP_RETHROW( excpt );
           }
-       catch ( const RpmSigCheckException & excpt )
-         {
-           ERR << "Failed to provide Package " << _package << endl;
-           if ( ! _retry )
-           {
-             // Signature verification error was already reported by the
-             // rpmSigFileChecker. Just handle the users action decision:
-             switch ( excpt.action() )
-             {
-               case repo::DownloadResolvableReport::RETRY:
-                 _retry = true;
-                 break;
-               case repo::DownloadResolvableReport::IGNORE:
-                 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
-                 break;
-               default:
-               case repo::DownloadResolvableReport::ABORT:
-                 ZYPP_THROW(AbortRequestException("User requested to abort"));
-                 break;
-             }
-           }
-         }
         catch ( const FileCheckException & excpt )
           {
            ERR << "Failed to provide Package " << _package << endl;
@@ -436,10 +360,11 @@ namespace zypp
                case repo::DownloadResolvableReport::IGNORE:
                  ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
                  break;
-               default:
                case repo::DownloadResolvableReport::ABORT:
                  ZYPP_THROW(AbortRequestException("User requested to abort"));
                  break;
+               default:
+                 break;
              }
            }
          }
@@ -463,20 +388,16 @@ namespace zypp
                       case repo::DownloadResolvableReport::IGNORE:
                         ZYPP_THROW(SkipRequestException("User requested skip of file", excpt));
                         break;
-                      default:
                       case repo::DownloadResolvableReport::ABORT:
                         ZYPP_THROW(AbortRequestException("User requested to abort", excpt));
                         break;
+                      default:
+                        ZYPP_RETHROW( excpt );
+                        break;
                 }
               }
           }
       } while ( _retry );
-      } catch(...){
-       // bsc#1045735: Be sure no invalid files stay in the cache!
-       if ( ! ret->empty() )
-         ret.setDispose( filesystem::unlink );
-       throw;
-      }
 
       report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() );
       MIL << "provided Package " << _package << " at " << ret << endl;
@@ -486,20 +407,21 @@ namespace zypp
 
     ///////////////////////////////////////////////////////////////////
     /// \class RpmPackageProvider
-    /// \brief RPM PackageProvider implementation (with deltarpm processing).
+    /// \brief RPM PackageProvider implementation.
     ///////////////////////////////////////////////////////////////////
-    class RpmPackageProvider : public PackageProviderImpl<Package>
+    class RpmPackageProvider : public PackageProvider::Impl
     {
     public:
       RpmPackageProvider( RepoMediaAccess & access_r,
                          const Package::constPtr & package_r,
                          const DeltaCandidates & deltas_r,
                          const PackageProviderPolicy & policy_r )
-      : PackageProviderImpl<Package>( access_r, package_r, policy_r )
-      , _deltas( deltas_r )
+      : PackageProvider::Impl( access_r, package_r, deltas_r, policy_r )
       {}
 
     protected:
+      virtual ManagedFile doProvidePackageFromCache() const;
+
       virtual ManagedFile doProvidePackage() const;
 
     private:
@@ -515,18 +437,27 @@ namespace zypp
 
       bool queryInstalled( const Edition & ed_r = Edition() ) const
       { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
-
-    private:
-      DeltaCandidates          _deltas;
     };
     ///////////////////////////////////////////////////////////////////
 
+    ManagedFile RpmPackageProvider::doProvidePackageFromCache() const
+    {
+      return ManagedFile( _package->cachedLocation() );
+    }
+
     ManagedFile RpmPackageProvider::doProvidePackage() const
     {
+      Url url;
+      RepoInfo info = _package->repoInfo();
+      // FIXME we only support the first url for now.
+      if ( info.baseUrlsEmpty() )
+        ZYPP_THROW(Exception("No url in repository."));
+      else
+        url = * info.baseUrlsBegin();
+
       // check whether to process patch/delta rpms
-      // FIXME we only check the first url for now.
       if ( ZConfig::instance().download_use_deltarpm()
-       && ( _package->repoInfo().url().schemeIsDownloading() || ZConfig::instance().download_use_deltarpm_always() ) )
+       && ( url.schemeIsDownloading() || ZConfig::instance().download_use_deltarpm_always() ) )
       {
        std::list<DeltaRpm> deltaRpms;
        _deltas.deltaRpms( _package ).swap( deltaRpms );
@@ -579,83 +510,70 @@ namespace zypp
           return ManagedFile();
         }
 
-      // Build the package
-      Pathname cachedest( _package->repoInfo().packagesPath() / _package->location().filename() );
-      Pathname builddest( cachedest.extend( ".drpm" ) );
+      // build the package and put it into the cache
+      Pathname destination( _package->repoInfo().packagesPath() / _package->location().filename() );
 
-      if ( ! applydeltarpm::provide( delta, builddest,
+      if ( ! applydeltarpm::provide( delta, destination,
                                      bind( &RpmPackageProvider::progressDeltaApply, this, _1 ) ) )
         {
           report()->problemDeltaApply( _("applydeltarpm failed.") );
           return ManagedFile();
         }
-      ManagedFile builddestCleanup( builddest, filesystem::unlink );
       report()->finishDeltaApply();
 
-      // Check and move it into the cache
-      // Here the rpm itself is ready. If the packages sigcheck fails, it
-      // makes no sense to return a ManagedFile() and fallback to download the
-      // full rpm. It won't be different. So let the exceptions escape...
-      rpmSigFileChecker( builddest );
-      if ( filesystem::hardlinkCopy( builddest, cachedest ) != 0 )
-       ZYPP_THROW( Exception( str::Str() << "Can't hardlink/copy " << builddest << " to " << cachedest ) );
-
-      return ManagedFile( cachedest, filesystem::unlink );
+      return ManagedFile( destination, filesystem::unlink );
     }
 
+#if 0
     ///////////////////////////////////////////////////////////////////
-    // class PackageProvider
+    /// \class PluginPackageProvider
+    /// \brief Plugin PackageProvider implementation.
+    ///
+    /// Basically downloads the default package and calls a
+    /// 'stem'2rpm plugin to cteate the final .rpm package.
     ///////////////////////////////////////////////////////////////////
-    namespace factory
+    class PluginPackageProvider : public PackageProvider::Impl
     {
-      inline PackageProvider::Impl * make( RepoMediaAccess & access_r, const PoolItem & pi_r,
-                                          const DeltaCandidates & deltas_r,
-                                          const PackageProviderPolicy & policy_r )
+    public:
+      PluginPackageProvider( const std::string & stem_r,
+                            RepoMediaAccess & access_r,
+                            const Package::constPtr & package_r,
+                            const DeltaCandidates & deltas_r,
+                            const PackageProviderPolicy & policy_r )
+      : Base( access_r, package_r, deltas_r, policy_r )
+      {}
+
+    protected:
+      virtual ManagedFile doProvidePackageFromCache() const
       {
-       if ( pi_r.satSolvable().isKind<Package>() )
-         return new RpmPackageProvider( access_r, pi_r->asKind<Package>(), deltas_r, policy_r );
-       else if ( pi_r.satSolvable().isKind<SrcPackage>() )
-         return new PackageProviderImpl<SrcPackage>( access_r, pi_r->asKind<SrcPackage>(), policy_r );
-       else
-         ZYPP_THROW( Exception( str::Str() << "Don't know how to cache non-package " << pi_r.satSolvable().asUserString() ) );
+       return Base::doProvidePackageFromCache();
       }
 
-      inline PackageProvider::Impl * make( RepoMediaAccess & access_r, const PoolItem & pi_r,
-                                                 const PackageProviderPolicy & policy_r )
+      virtual ManagedFile doProvidePackage() const
       {
-       if ( pi_r.satSolvable().isKind<Package>() )
-         return new PackageProviderImpl<Package>( access_r, pi_r->asKind<Package>(), policy_r );
-       else if ( pi_r.satSolvable().isKind<SrcPackage>() )
-         return new PackageProviderImpl<SrcPackage>( access_r, pi_r->asKind<SrcPackage>(), policy_r );
-       else
-         ZYPP_THROW( Exception( str::Str() << "Don't know how to cache non-package " << pi_r.satSolvable().asUserString() ) );
+       return Base::doProvidePackage();
       }
-
-      inline PackageProvider::Impl * make( RepoMediaAccess & access_r, const Package::constPtr & package_r,
-                                          const DeltaCandidates & deltas_r,
-                                          const PackageProviderPolicy & policy_r )
-      { return new RpmPackageProvider( access_r, package_r, deltas_r, policy_r ); }
-
-    } // namespace factory
+    };
     ///////////////////////////////////////////////////////////////////
+#endif
 
-    PackageProvider::PackageProvider( RepoMediaAccess & access_r, const PoolItem & pi_r,
-                                     const DeltaCandidates & deltas_r, const PackageProviderPolicy & policy_r )
-
-    : _pimpl( factory::make( access_r, pi_r, deltas_r, policy_r ) )
-    {}
+    ///////////////////////////////////////////////////////////////////
+    // class PackageProvider
+    ///////////////////////////////////////////////////////////////////
 
-    PackageProvider::PackageProvider( RepoMediaAccess & access_r, const PoolItem & pi_r,
-                                     const PackageProviderPolicy & policy_r )
-    : _pimpl( factory::make( access_r, pi_r, policy_r ) )
-    {}
+    PackageProvider::Impl * PackageProvider::Impl::factoryMake( RepoMediaAccess & access_r,
+                                                               const Package::constPtr & package_r,
+                                                               const DeltaCandidates & deltas_r,
+                                                               const PackageProviderPolicy & policy_r )
+    {
+      return new RpmPackageProvider( access_r, package_r, deltas_r, policy_r );
+    }
 
-    /* legacy */
     PackageProvider::PackageProvider( RepoMediaAccess & access_r,
                                      const Package::constPtr & package_r,
                                      const DeltaCandidates & deltas_r,
                                      const PackageProviderPolicy & policy_r )
-    : _pimpl( factory::make( access_r, package_r, deltas_r, policy_r ) )
+    : _pimpl( Impl::factoryMake( access_r, package_r, deltas_r, policy_r ) )
     {}
 
     PackageProvider::~PackageProvider()