1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/repo/PackageProvider.cc
14 #include "zypp/repo/PackageDelta.h"
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/Gettext.h"
17 #include "zypp/base/UserRequestException.h"
18 #include "zypp/repo/PackageProvider.h"
19 #include "zypp/repo/RepoProvideFile.h"
20 #include "zypp/repo/Applydeltarpm.h"
21 #include "zypp/repo/PackageDelta.h"
23 #include "zypp/TmpPath.h"
24 #include "zypp/ZConfig.h"
25 #include "zypp/RepoInfo.h"
26 #include "zypp/media/MediaManager.h"
29 using zypp::media::MediaManager;
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////
40 // CLASS NAME : PackageProviderPolicy
42 ///////////////////////////////////////////////////////////////////
44 bool PackageProviderPolicy::queryInstalled( const std::string & name_r,
46 const Arch & arch_r ) const
48 if ( _queryInstalledCB )
49 return _queryInstalledCB( name_r, ed_r, arch_r );
53 ///////////////////////////////////////////////////////////////////
55 // CLASS NAME : PackageProvider
57 ///////////////////////////////////////////////////////////////////
59 ///////////////////////////////////////////////////////////////////
61 { /////////////////////////////////////////////////////////////////
63 inline std::string defRpmFileName( const Package::constPtr & package )
65 std::ostringstream ret;
66 ret << package->name() << '-' << package->edition() << '.' << package->arch() << ".rpm";
70 /////////////////////////////////////////////////////////////////
72 ///////////////////////////////////////////////////////////////////
73 PackageProvider::PackageProvider( RepoMediaAccess &access,
74 const Package::constPtr & package,
75 const DeltaCandidates & deltas,
76 const PackageProviderPolicy & policy_r )
83 PackageProvider::~PackageProvider()
86 ManagedFile PackageProvider::providePackage() const
89 RepoInfo info = _package->repoInfo();
90 // FIXME we only support the first url for now.
91 if ( info.baseUrlsEmpty() )
92 ZYPP_THROW(Exception("No url in repository."));
94 url = * info.baseUrlsBegin();
96 MIL << "provide Package " << _package << endl;
97 ScopedGuard guardReport( newReport() );
101 report()->start( _package, url );
102 try // ELIMINATE try/catch by providing a log-guard
104 ret = doProvidePackage();
106 catch ( const UserRequestException & excpt )
108 // UserRequestException e.g. from failOnChecksumError was already reported.
109 ERR << "Failed to provide Package " << _package << endl;
112 ZYPP_RETHROW( excpt );
115 catch ( const Exception & excpt )
117 ERR << "Failed to provide Package " << _package << endl;
120 // Aything else gets reported
121 std::string package_str = _package->name() + "-" + _package->edition().asString();
123 // TranslatorExplanation %s = name of the package being processed.
124 std::string detail_str( str::form(_("Failed to provide Package %s. Do you want to retry retrieval?"), package_str.c_str() ) );
125 detail_str += str::form( "\n\n%s", excpt.asUserHistory().c_str() );
127 switch ( report()->problem( _package, repo::DownloadResolvableReport::IO, detail_str.c_str() ) )
129 case repo::DownloadResolvableReport::RETRY:
132 case repo::DownloadResolvableReport::IGNORE:
133 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
135 case repo::DownloadResolvableReport::ABORT:
136 ZYPP_THROW(AbortRequestException("User requested to abort"));
139 ZYPP_RETHROW( excpt );
146 report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() );
147 MIL << "provided Package " << _package << " at " << ret << endl;
151 ManagedFile PackageProvider::doProvidePackage() const
154 RepoInfo info = _package->repoInfo();
155 // FIXME we only support the first url for now.
156 if ( info.baseUrlsEmpty() )
157 ZYPP_THROW(Exception("No url in repository."));
159 url = * info.baseUrlsBegin();
161 // check whether to process patch/delta rpms
162 if ( MediaManager::downloads(url) || ZConfig::instance().download_use_deltarpm_always() )
164 std::list<DeltaRpm> deltaRpms;
165 if ( ZConfig::instance().download_use_deltarpm() )
167 _deltas.deltaRpms( _package ).swap( deltaRpms );
170 if ( ! ( deltaRpms.empty() )
171 && queryInstalled() )
173 if ( ! deltaRpms.empty() && applydeltarpm::haveApplydeltarpm() )
175 for( std::list<DeltaRpm>::const_iterator it = deltaRpms.begin();
176 it != deltaRpms.end(); ++it )
178 DBG << "tryDelta " << *it << endl;
179 ManagedFile ret( tryDelta( *it ) );
180 if ( ! ret->empty() )
187 // no patch/delta -> provide full package
189 OnMediaLocation loc = _package->location();
191 ProvideFilePolicy policy;
192 policy.progressCB( bind( &PackageProvider::progressPackageDownload, this, _1 ) );
193 policy.failOnChecksumErrorCB( bind( &PackageProvider::failOnChecksumError, this ) );
194 return _access.provideFile( _package->repoInfo(), loc, policy );
197 ManagedFile PackageProvider::tryDelta( const DeltaRpm & delta_r ) const
199 if ( delta_r.baseversion().edition() != Edition::noedition
200 && ! queryInstalled( delta_r.baseversion().edition() ) )
201 return ManagedFile();
203 if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) )
204 return ManagedFile();
206 report()->startDeltaDownload( delta_r.location().filename(),
207 delta_r.location().downloadSize() );
211 ProvideFilePolicy policy;
212 policy.progressCB( bind( &PackageProvider::progressDeltaDownload, this, _1 ) );
213 delta = _access.provideFile( delta_r.repository().info(), delta_r.location(), policy );
215 catch ( const Exception & excpt )
217 report()->problemDeltaDownload( excpt.asUserHistory() );
218 return ManagedFile();
220 report()->finishDeltaDownload();
222 report()->startDeltaApply( delta );
223 if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) )
225 report()->problemDeltaApply( _("applydeltarpm check failed.") );
226 return ManagedFile();
229 Pathname destination( Pathname::dirname( delta ) / defRpmFileName( _package ) );
231 if ( ! delta.getDispose() )
233 // There is no cleanup method associated with the deta. Thus the
234 // delta is not a temporary file, and we don't want to write in
235 // the package into this directory.
236 destination = filesystem::TmpPath::defaultLocation() / defRpmFileName( _package );
239 if ( ! applydeltarpm::provide( delta, destination,
240 bind( &PackageProvider::progressDeltaApply, this, _1 ) ) )
242 report()->problemDeltaApply( _("applydeltarpm failed.") );
243 return ManagedFile();
245 report()->finishDeltaApply();
247 return ManagedFile( destination, filesystem::unlink );
250 PackageProvider::ScopedGuard PackageProvider::newReport() const
252 _report.reset( new Report );
253 return shared_ptr<void>( static_cast<void*>(0),
254 // custom deleter calling _report.reset()
255 // (cast required as reset is overloaded)
256 bind( mem_fun_ref( static_cast<void (shared_ptr<Report>::*)()>(&shared_ptr<Report>::reset) ),
260 PackageProvider::Report & PackageProvider::report() const
263 bool PackageProvider::progressDeltaDownload( int value ) const
264 { return report()->progressDeltaDownload( value ); }
266 void PackageProvider::progressDeltaApply( int value ) const
267 { return report()->progressDeltaApply( value ); }
269 bool PackageProvider::progressPackageDownload( int value ) const
270 { return report()->progress( value, _package ); }
272 bool PackageProvider::failOnChecksumError() const
274 std::string package_str = _package->name() + "-" + _package->edition().asString();
276 // TranslatorExplanation %s = package being checked for integrity
277 switch ( report()->problem( _package, repo::DownloadResolvableReport::INVALID, str::form(_("Package %s seems to be corrupted during transfer. Do you want to retry retrieval?"), package_str.c_str() ) ) )
279 case repo::DownloadResolvableReport::RETRY:
282 case repo::DownloadResolvableReport::IGNORE:
283 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
285 case repo::DownloadResolvableReport::ABORT:
286 ZYPP_THROW(AbortRequestException("User requested to abort"));
291 return true; // anyway a failure
294 bool PackageProvider::queryInstalled( const Edition & ed_r ) const
295 { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
298 /////////////////////////////////////////////////////////////////
300 ///////////////////////////////////////////////////////////////////
301 /////////////////////////////////////////////////////////////////
303 ///////////////////////////////////////////////////////////////////