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