00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <sstream>
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Gettext.h"
00016 #include "zypp/base/UserRequestException.h"
00017
00018 #include "zypp/Repository.h"
00019 #include "zypp/repo/PackageProvider.h"
00020 #include "zypp/repo/RepoProvideFile.h"
00021 #include "zypp/repo/Applydeltarpm.h"
00022 #include "zypp/repo/PackageDelta.h"
00023 #include "zypp/detail/ImplConnect.h"
00024
00025 #include "zypp/ZConfig.h"
00026 #include "zypp/RepoInfo.h"
00027 #include "zypp/Repository.h"
00028 #include "zypp/media/MediaManager.h"
00029
00030 using std::endl;
00031 using zypp::media::MediaManager;
00032
00034 namespace zypp
00035 {
00036
00037 namespace repo
00038 {
00039
00041
00042
00043
00045
00046 bool PackageProviderPolicy::queryInstalled( const std::string & name_r,
00047 const Edition & ed_r,
00048 const Arch & arch_r ) const
00049 {
00050 if ( _queryInstalledCB )
00051 return _queryInstalledCB( name_r, ed_r, arch_r );
00052 return false;
00053 }
00054
00056
00057
00058
00060
00062 namespace
00063 {
00064
00065 inline std::string defRpmFileName( const Package::constPtr & package )
00066 {
00067 std::ostringstream ret;
00068 ret << package->name() << '-' << package->edition() << '.' << package->arch() << ".rpm";
00069 return ret.str();
00070 }
00071
00073 }
00075 PackageProvider::PackageProvider( RepoMediaAccess &access,
00076 const Package::constPtr & package,
00077 const DeltaCandidates & deltas,
00078 const PackageProviderPolicy & policy_r )
00079 : _policy( policy_r )
00080 , _package( package )
00081 , _implPtr( detail::ImplConnect::resimpl( _package ) )
00082 , _deltas(deltas)
00083 , _access(access)
00084 {}
00085
00086 PackageProvider::~PackageProvider()
00087 {}
00088
00089 ManagedFile PackageProvider::providePackage() const
00090 {
00091 Url url;
00092 RepoInfo info = _package->repository().info();
00093
00094 if ( info.baseUrlsEmpty() )
00095 ZYPP_THROW(Exception("No url in repository."));
00096 else
00097 url = * info.baseUrlsBegin();
00098
00099 MIL << "provide Package " << _package << endl;
00100 ScopedGuard guardReport( newReport() );
00101 ManagedFile ret;
00102 do {
00103 _retry = false;
00104 report()->start( _package, url );
00105 try
00106 {
00107 ret = doProvidePackage();
00108 }
00109 catch ( const Exception & excpt )
00110 {
00111 ERR << "Failed to provide Package " << _package << endl;
00112 if ( ! _retry )
00113 {
00114 ZYPP_RETHROW( excpt );
00115 }
00116 }
00117 } while ( _retry );
00118
00119 report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() );
00120 MIL << "provided Package " << _package << " at " << ret << endl;
00121 return ret;
00122 }
00123
00124 ManagedFile PackageProvider::doProvidePackage() const
00125 {
00126 Url url;
00127 RepoInfo info = _package->repository().info();
00128
00129 if ( info.baseUrlsEmpty() )
00130 ZYPP_THROW(Exception("No url in repository."));
00131 else
00132 url = * info.baseUrlsBegin();
00133
00134
00135 if ( MediaManager::downloads(url) )
00136 {
00137 std::list<DeltaRpm> deltaRpms;
00138 if ( ZConfig::instance().download_use_deltarpm() )
00139 {
00140 _deltas.deltaRpms( _package ).swap( deltaRpms );
00141 }
00142
00143 std::list<PatchRpm> patchRpms;
00144 if ( ZConfig::instance().download_use_patchrpm() )
00145 {
00146 _deltas.patchRpms( _package ).swap( patchRpms );
00147 }
00148
00149 if ( ! ( deltaRpms.empty() && patchRpms.empty() )
00150 && queryInstalled() )
00151 {
00152 if ( ! deltaRpms.empty() && applydeltarpm::haveApplydeltarpm() )
00153 {
00154 for( std::list<DeltaRpm>::const_iterator it = deltaRpms.begin();
00155 it != deltaRpms.end(); ++it )
00156 {
00157 DBG << "tryDelta " << *it << endl;
00158 ManagedFile ret( tryDelta( *it ) );
00159 if ( ! ret->empty() )
00160 return ret;
00161 }
00162 }
00163
00164 if ( ! patchRpms.empty() )
00165 {
00166 for( std::list<PatchRpm>::const_iterator it = patchRpms.begin();
00167 it != patchRpms.end(); ++it )
00168 {
00169 DBG << "tryPatch " << *it << endl;
00170 ManagedFile ret( tryPatch( *it ) );
00171 if ( ! ret->empty() )
00172 return ret;
00173 }
00174 }
00175 }
00176 }
00177 else
00178 {
00179
00180 std::list<PatchRpm> patchRpms;
00181 if ( ZConfig::instance().download_use_patchrpm() )
00182 {
00183 _deltas.patchRpms( _package ).swap( patchRpms );
00184 }
00185
00186 if ( ! patchRpms.empty() && queryInstalled() )
00187 {
00188 for( std::list<PatchRpm>::const_iterator it = patchRpms.begin();
00189 it != patchRpms.end(); ++it )
00190 {
00191 DBG << "tryPatch " << *it << endl;
00192 ManagedFile ret( tryPatch( *it ) );
00193 if ( ! ret->empty() )
00194 return ret;
00195 }
00196 }
00197 }
00198
00199
00200 ManagedFile ret;
00201 OnMediaLocation loc = _package->location();
00202
00203 ProvideFilePolicy policy;
00204 policy.progressCB( bind( &PackageProvider::progressPackageDownload, this, _1 ) );
00205 policy.failOnChecksumErrorCB( bind( &PackageProvider::failOnChecksumError, this ) );
00206 return _access.provideFile( _package->repository(), loc, policy );
00207 }
00208
00209 ManagedFile PackageProvider::tryDelta( const DeltaRpm & delta_r ) const
00210 {
00211 if ( delta_r.baseversion().edition() != Edition::noedition
00212 && ! queryInstalled( delta_r.baseversion().edition() ) )
00213 return ManagedFile();
00214
00215 if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) )
00216 return ManagedFile();
00217
00218 report()->startDeltaDownload( delta_r.location().filename(),
00219 delta_r.location().downloadSize() );
00220 ManagedFile delta;
00221 try
00222 {
00223 ProvideFilePolicy policy;
00224 policy.progressCB( bind( &PackageProvider::progressDeltaDownload, this, _1 ) );
00225 delta = _access.provideFile( _package->repository(), delta_r.location(), policy );
00226 }
00227 catch ( const Exception & excpt )
00228 {
00229 report()->problemDeltaDownload( excpt.asUserString() );
00230 return ManagedFile();
00231 }
00232 report()->finishDeltaDownload();
00233
00234 report()->startDeltaApply( delta );
00235 if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) )
00236 {
00237 report()->problemDeltaApply( _("applydeltarpm check failed.") );
00238 return ManagedFile();
00239 }
00240
00241 Pathname destination( Pathname::dirname( delta ) / defRpmFileName( _package ) );
00242
00243
00244
00245
00246
00247
00248 if ( ! applydeltarpm::provide( delta, destination,
00249 bind( &PackageProvider::progressDeltaApply, this, _1 ) ) )
00250 {
00251 report()->problemDeltaApply( _("applydeltarpm failed.") );
00252 return ManagedFile();
00253 }
00254 report()->finishDeltaApply();
00255
00256 return ManagedFile( destination, filesystem::unlink );
00257 }
00258
00259 ManagedFile PackageProvider::tryPatch( const PatchRpm & patch_r ) const
00260 {
00261
00262 const PatchRpm::BaseVersions & baseversions( patch_r.baseversions() );
00263
00264 if ( std::find_if( baseversions.begin(), baseversions.end(),
00265 bind( &PackageProvider::queryInstalled, this, _1 ) )
00266 == baseversions.end() )
00267 return ManagedFile();
00268
00269 report()->startPatchDownload( patch_r.location().filename(),
00270 patch_r.location().downloadSize() );
00271 ManagedFile patch;
00272 try
00273 {
00274 ProvideFilePolicy policy;
00275 policy.progressCB( bind( &PackageProvider::progressPatchDownload, this, _1 ) );
00276 patch = _access.provideFile( _package->repository(), patch_r.location(), policy );
00277 }
00278 catch ( const Exception & excpt )
00279 {
00280 report()->problemPatchDownload( excpt.asUserString() );
00281 return ManagedFile();
00282 }
00283 report()->finishPatchDownload();
00284
00285 return patch;
00286 }
00287
00288 PackageProvider::ScopedGuard PackageProvider::newReport() const
00289 {
00290 _report.reset( new Report );
00291 return shared_ptr<void>( static_cast<void*>(0),
00292
00293
00294 bind( mem_fun_ref( static_cast<void (shared_ptr<Report>::*)()>(&shared_ptr<Report>::reset) ),
00295 ref(_report) ) );
00296 }
00297
00298 PackageProvider::Report & PackageProvider::report() const
00299 { return *_report; }
00300
00301 bool PackageProvider::progressDeltaDownload( int value ) const
00302 { return report()->progressDeltaDownload( value ); }
00303
00304 void PackageProvider::progressDeltaApply( int value ) const
00305 { return report()->progressDeltaApply( value ); }
00306
00307 bool PackageProvider::progressPatchDownload( int value ) const
00308 { return report()->progressPatchDownload( value ); }
00309
00310 bool PackageProvider::progressPackageDownload( int value ) const
00311 { return report()->progress( value, _package ); }
00312
00313 bool PackageProvider::failOnChecksumError() const
00314 {
00315 std::string package_str = _package->name() + "-" + _package->edition().asString();
00316
00317
00318 switch ( report()->problem( _package, repo::DownloadResolvableReport::INVALID, str::form(_("Package %s fails integrity check. Do you want to retry?"), package_str.c_str() ) ) )
00319 {
00320 case repo::DownloadResolvableReport::RETRY:
00321 _retry = true;
00322 break;
00323 case repo::DownloadResolvableReport::IGNORE:
00324 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
00325 break;
00326 case repo::DownloadResolvableReport::ABORT:
00327 ZYPP_THROW(AbortRequestException("User requested to abort"));
00328 break;
00329 default:
00330 break;
00331 }
00332 return true;
00333 }
00334
00335 bool PackageProvider::queryInstalled( const Edition & ed_r ) const
00336 { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
00337
00338
00340 }
00343 }