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 Exception & excpt )
108 ERR << "Failed to provide Package " << _package << endl;
111 ZYPP_RETHROW( excpt );
116 report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() );
117 MIL << "provided Package " << _package << " at " << ret << endl;
121 ManagedFile PackageProvider::doProvidePackage() const
124 RepoInfo info = _package->repoInfo();
125 // FIXME we only support the first url for now.
126 if ( info.baseUrlsEmpty() )
127 ZYPP_THROW(Exception("No url in repository."));
129 url = * info.baseUrlsBegin();
131 // check whether to process patch/delta rpms
132 if ( MediaManager::downloads(url) || ZConfig::instance().download_use_deltarpm_always() )
134 std::list<DeltaRpm> deltaRpms;
135 if ( ZConfig::instance().download_use_deltarpm() )
137 _deltas.deltaRpms( _package ).swap( deltaRpms );
140 if ( ! ( deltaRpms.empty() )
141 && queryInstalled() )
143 if ( ! deltaRpms.empty() && applydeltarpm::haveApplydeltarpm() )
145 for( std::list<DeltaRpm>::const_iterator it = deltaRpms.begin();
146 it != deltaRpms.end(); ++it )
148 DBG << "tryDelta " << *it << endl;
149 ManagedFile ret( tryDelta( *it ) );
150 if ( ! ret->empty() )
157 // no patch/delta -> provide full package
159 OnMediaLocation loc = _package->location();
161 ProvideFilePolicy policy;
162 policy.progressCB( bind( &PackageProvider::progressPackageDownload, this, _1 ) );
163 policy.failOnChecksumErrorCB( bind( &PackageProvider::failOnChecksumError, this ) );
164 return _access.provideFile( _package->repoInfo(), loc, policy );
167 ManagedFile PackageProvider::tryDelta( const DeltaRpm & delta_r ) const
169 if ( delta_r.baseversion().edition() != Edition::noedition
170 && ! queryInstalled( delta_r.baseversion().edition() ) )
171 return ManagedFile();
173 if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) )
174 return ManagedFile();
176 report()->startDeltaDownload( delta_r.location().filename(),
177 delta_r.location().downloadSize() );
181 ProvideFilePolicy policy;
182 policy.progressCB( bind( &PackageProvider::progressDeltaDownload, this, _1 ) );
183 delta = _access.provideFile( delta_r.repository().info(), delta_r.location(), policy );
185 catch ( const Exception & excpt )
187 report()->problemDeltaDownload( excpt.asUserString() );
188 return ManagedFile();
190 report()->finishDeltaDownload();
192 report()->startDeltaApply( delta );
193 if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) )
195 report()->problemDeltaApply( _("applydeltarpm check failed.") );
196 return ManagedFile();
199 Pathname destination( Pathname::dirname( delta ) / defRpmFileName( _package ) );
201 if ( ! delta.getDispose() )
203 // There is no cleanup method associated with the deta. Thus the
204 // delta is not a temporary file, and we don't want to write in
205 // the package into this directory.
206 destination = filesystem::TmpPath::defaultLocation() / defRpmFileName( _package );
209 if ( ! applydeltarpm::provide( delta, destination,
210 bind( &PackageProvider::progressDeltaApply, this, _1 ) ) )
212 report()->problemDeltaApply( _("applydeltarpm failed.") );
213 return ManagedFile();
215 report()->finishDeltaApply();
217 return ManagedFile( destination, filesystem::unlink );
220 PackageProvider::ScopedGuard PackageProvider::newReport() const
222 _report.reset( new Report );
223 return shared_ptr<void>( static_cast<void*>(0),
224 // custom deleter calling _report.reset()
225 // (cast required as reset is overloaded)
226 bind( mem_fun_ref( static_cast<void (shared_ptr<Report>::*)()>(&shared_ptr<Report>::reset) ),
230 PackageProvider::Report & PackageProvider::report() const
233 bool PackageProvider::progressDeltaDownload( int value ) const
234 { return report()->progressDeltaDownload( value ); }
236 void PackageProvider::progressDeltaApply( int value ) const
237 { return report()->progressDeltaApply( value ); }
239 bool PackageProvider::progressPackageDownload( int value ) const
240 { return report()->progress( value, _package ); }
242 bool PackageProvider::failOnChecksumError() const
244 std::string package_str = _package->name() + "-" + _package->edition().asString();
246 // TranslatorExplanation %s = package being checked for integrity
247 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() ) ) )
249 case repo::DownloadResolvableReport::RETRY:
252 case repo::DownloadResolvableReport::IGNORE:
253 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
255 case repo::DownloadResolvableReport::ABORT:
256 ZYPP_THROW(AbortRequestException("User requested to abort"));
261 return true; // anyway a failure
264 bool PackageProvider::queryInstalled( const Edition & ed_r ) const
265 { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
268 /////////////////////////////////////////////////////////////////
270 ///////////////////////////////////////////////////////////////////
271 /////////////////////////////////////////////////////////////////
273 ///////////////////////////////////////////////////////////////////