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