libzypp: zypp/repo/RepoProvideFile.cc Source File

libzypp 17.38.9

RepoProvideFile.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <zypp-core/ng/pipelines/transform.h>
13#include <iostream>
14#include <fstream>
15#include <sstream>
16#include <set>
17
18#include <zypp-core/base/Gettext.h>
19#include <zypp-core/base/Logger.h>
20#include <zypp-core/base/String.h>
21#include <utility>
22#include <zypp-core/base/UserRequestException>
23#include <zypp/repo/RepoProvideFile.h>
24#include <zypp/ZYppCallbacks.h>
25#include <zypp/MediaSetAccess.h>
26#include <zypp/ZConfig.h>
27#include <zypp/ZYppFactory.h>
28#include <zypp/repo/SUSEMediaVerifier.h>
29#include <zypp/repo/RepoException.h>
30
31#include <zypp/repo/SUSEMediaVerifier.h>
32#include <zypp/repo/RepoException.h>
33#include <zypp/FileChecker.h>
34#include <zypp/Fetcher.h>
35
36using std::endl;
37using std::set;
38
40namespace zypp
41{
43 namespace repo
44 {
45
47 //
48 // provideFile
49 //
51
53 namespace
54 {
55
61 struct DownloadFileReportHack : public callback::ReceiveReport<media::DownloadProgressReport>
62 {
63 using BaseType = callback::ReceiveReport<ReportType>;
64 using RedirectType = function<bool (int)>;
65
66 DownloadFileReportHack(RedirectType &&redirect_r)
67 : _oldRec(Distributor::instance().getReceiver()),
68 _redirect(std::move(redirect_r)) {
69 connect();
70 }
71
72 DownloadFileReportHack(const DownloadFileReportHack &) = delete;
73 DownloadFileReportHack(DownloadFileReportHack &&) = delete;
74 DownloadFileReportHack &operator=(const DownloadFileReportHack &) = delete;
75 DownloadFileReportHack &operator=(DownloadFileReportHack &&) = delete;
76
77 ~DownloadFileReportHack() override
78 { if ( _oldRec ) Distributor::instance().setReceiver( *_oldRec ); else Distributor::instance().noReceiver(); }
79
80 void start( const Url & file, Pathname localfile ) override
81 {
82 if ( _oldRec )
83 _oldRec->start( file, localfile );
84 else
85 BaseType::start( file, localfile );
86 }
87
88 bool progress( int value, const Url & file, double dbps_avg = -1, double dbps_current = -1 ) override
89 {
90 bool ret = true;
91 if ( _oldRec )
92 ret &= _oldRec->progress( value, file, dbps_avg, dbps_current );
93 if ( _redirect )
94 ret &= _redirect( value );
95 return ret;
96 }
97
98 Action problem( const Url & file, Error error, const std::string & description ) override
99 {
100 if ( _oldRec )
101 return _oldRec->problem( file, error, description );
102 return BaseType::problem( file, error, description );
103 }
104 void finish( const Url & file, Error error, const std::string & reason ) override
105 {
106 if ( _oldRec )
107 _oldRec->finish( file, error, reason );
108 else
109 BaseType::finish( file, error, reason );
110 }
111
112 private:
113 Receiver * _oldRec;
114 RedirectType _redirect;
115 };
116
118 } // namespace
120
121 ManagedFile provideFile( RepoInfo repo_r,
122 const OnMediaLocation & loc_r,
123 const ProvideFilePolicy & policy_r )
124 {
125 RepoMediaAccess access;
126 return access.provideFile(std::move(repo_r), loc_r, policy_r );
127 }
128
129 std::vector<Pathname> repositoryCachePaths( RepoInfo repo_r )
130 {
131 std::vector<Pathname> paths;
132
133 // Add the writable location first
134 paths.push_back( repo_r.packagesPath() );
135
136 // Add the configured path if it differs (i.e. is read-only)
137 const Pathname & cfg { repo_r.systemPackagesPath() };
138 if ( cfg != paths[0] )
139 paths.push_back( cfg );
140
141 return paths;
142 }
143
145 class RepoMediaAccess::Impl
146 {
147 public:
148 Impl(ProvideFilePolicy &&defaultPolicy_r)
149 : _defaultPolicy(std::move(defaultPolicy_r)) {}
150
151 Impl(const Impl &) = delete;
152 Impl(Impl &&) = delete;
153 Impl &operator=(const Impl &) = delete;
154 Impl &operator=(Impl &&) = delete;
155
156 ~Impl()
157 {
158 std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
159 for ( it = _medias.begin();
160 it != _medias.end();
161 ++it )
162 {
163 it->second->release();
164 }
165 }
166
174 shared_ptr<MediaSetAccess> mediaAccessForUrl( const MirroredOrigin &origin, RepoInfo repo )
175 {
176 if ( !origin.isValid() )
177 return nullptr;
178
179 std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
180 it = _medias.find( origin.authority().url() ); // primary Url is the key
181 shared_ptr<MediaSetAccess> media;
182 if ( it != _medias.end() )
183 {
184 media = it->second;
185 }
186 else
187 {
188 media.reset( new MediaSetAccess( origin ) );
189 _medias[origin.authority().url()] = media;
190 }
191 setVerifierForRepo( repo, media );
192 return media;
193 }
194
195 private:
196 void setVerifierForRepo( const RepoInfo& repo, const shared_ptr<MediaSetAccess>& media )
197 {
198 // Always set the MediaSetAccess label.
199 media->setLabel( repo.name() );
200
201 // set a verifier if the repository has it
202
203 Pathname mediafile = repo.metadataPath() + "/media.1/media";
204 if ( ! repo.metadataPath().empty() )
205 {
206 if ( PathInfo(mediafile).isExist() )
207 {
208 std::map<shared_ptr<MediaSetAccess>, RepoInfo>::const_iterator it;
209 it = _verifier.find(media);
210 if ( it != _verifier.end() )
211 {
212 if ( it->second.alias() == repo.alias() )
213 {
214 // this media is already using this repo verifier
215 return;
216 }
217 }
218
219 SUSEMediaVerifier lverifier { mediafile };
220 if ( lverifier ) {
221 DBG << "Verifier for repo '" << repo.alias() << "':" << lverifier << endl;
222 for ( media::MediaNr i = 1; i <= lverifier.totalMedia(); ++i ) {
223 media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( lverifier, i ) );
224 media->setVerifier( i, verifier);
225 }
226 _verifier[media] = repo;
227 }
228 else {
229 WAR << "Invalid verifier for repo '" << repo.alias() << "' in '" << repo.metadataPath() << "': " << lverifier << endl;
230 }
231 }
232 else
233 {
234 DBG << "No media verifier for repo '" << repo.alias() << "' media.1/media does not exist in '" << repo.metadataPath() << "'" << endl;
235 }
236 }
237 else
238 {
239 WAR << "'" << repo.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
240 }
241 }
242
243 private:
244 std::map<shared_ptr<MediaSetAccess>, RepoInfo> _verifier;
245 std::map<Url, shared_ptr<MediaSetAccess> > _medias;
246
247 public:
248 ProvideFilePolicy _defaultPolicy;
249 };
250
251
252
253 RepoMediaAccess::RepoMediaAccess( ProvideFilePolicy defaultPolicy_r )
254 : _impl( new Impl( std::move(defaultPolicy_r) ) )
255 {}
256
257 RepoMediaAccess::~RepoMediaAccess()
258 {}
259
260 void RepoMediaAccess::setDefaultPolicy( const ProvideFilePolicy & policy_r )
261 { _impl->_defaultPolicy = policy_r; }
262
263 const ProvideFilePolicy & RepoMediaAccess::defaultPolicy() const
264 { return _impl->_defaultPolicy; }
265
266 ManagedFile RepoMediaAccess::provideFile( const RepoInfo& repo_r,
267 const OnMediaLocation & loc_rx,
268 const ProvideFilePolicy & policy_r )
269 {
270 const OnMediaLocation locWithPath( OnMediaLocation(loc_rx).prependPath( repo_r.path() ) );
271
272 MIL << locWithPath << endl;
273 // Arrange DownloadFileReportHack to receive the source::DownloadFileReport
274 // and redirect download progress triggers to call the ProvideFilePolicy
275 // callback.
276 DownloadFileReportHack dumb( std::bind( std::mem_fn(&ProvideFilePolicy::progress), std::ref(policy_r), _1 ) );
277
278 RepoException repo_excpt(repo_r,
279 str::form(_("Can't provide file '%s' from repository '%s'"),
280 locWithPath.filename().c_str(),
281 repo_r.alias().c_str() ) );
282
283 const auto &repoOrigins = repo_r.repoOrigins();
284
285 if ( repoOrigins.empty() ) {
286 repo_excpt.remember(RepoException(_("No url in repository.")));
287 ZYPP_THROW(repo_excpt);
288 }
289
290 Fetcher fetcher;
291
292 bool first = true;
293 for ( const auto& path : repositoryCachePaths(repo_r) ) {
294 // The first element will be the writeable cache.
295 // Add it to the cache.
296 fetcher.addCachePath( path );
297 MIL << "Added cache path " << path << endl;
298 if (first) {
299 // Add the preloaded version of the previous cache and mark it as "clean it later".
300 Pathname preloadPath = path / ".preload";
301 fetcher.addCachePath( preloadPath, Fetcher::CleanFiles );
302 MIL << "Added cache path " << preloadPath << endl;
303
304 first = false;
305 }
306 }
307
308 // Test whether download destination is writable, if not
309 // switch into the tmpspace (e.g. bnc#755239, download and
310 // install srpms as user).
311 Pathname destinationDir( repo_r.packagesPath() );
312
313 PathInfo pi( destinationDir );
314 if ( ! pi.isExist() )
315 {
316 // try to create it...
317 assert_dir( destinationDir );
318 pi();
319 }
320
321 // Suppress (interactive) media::MediaChangeReport if we have fallback URLs
322 media::ScopedDisableMediaChangeReport guard( repoOrigins.hasFallbackUrls() );
323 for ( const auto &origin : repoOrigins )
324 {
325
326 if ( !origin.isValid() ) {
327 MIL << "Skipping empty Url group" << std::endl;
328 continue;
329 }
330
331 try
332 {
333 MIL << "Providing file of repo '" << repo_r.alias() << "' from: ";
334 std::for_each( origin.begin (), origin.end(), [&]( const OriginEndpoint &u ){
335 MIL << u << ", ";
336 });
337 MIL << std::endl;
338
339 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl( origin, repo_r );
340 if ( !access )
341 continue;
342
343 fetcher.enqueue( locWithPath, policy_r.fileChecker() );
344 fetcher.start( destinationDir, *access );
345
346 // reached if no exception has been thrown, so this is the correct file
347 // LEGACY NOTE:
348 // DeltaRpms e.g are in fact optional resources (tagged in OnMediaLocation).
349 // They should actually return a ManagedFile(). But I don't know if there is
350 // already code which requests optional files but relies on provideFile returning
351 // a ManagedFile holding the path even if it does not exist. So I keep it this way.
352
353 ManagedFile ret { destinationDir / Fetcher::mapToCachePath( locWithPath ) };
354 if ( !repo_r.keepPackages() )
355 {
356 ret.setDispose( filesystem::unlink );
357 }
358
359 MIL << "provideFile at " << ret << endl;
360 return ret;
361 }
362 catch ( const UserRequestException & excpt )
363 {
364 ZYPP_RETHROW( excpt );
365 }
366 catch ( const FileCheckException & excpt )
367 {
368 ZYPP_RETHROW( excpt );
369 }
370 catch ( const Exception &e )
371 {
372 ZYPP_CAUGHT( e );
373
374 repo_excpt.remember(e);
375
376 WAR << "Trying next url" << endl;
377 continue;
378 }
379 } // iteration over urls
380
381 ZYPP_THROW(repo_excpt);
382 return ManagedFile(); // not reached
383 }
384
385 Pathname RepoMediaAccess::mapToCachePath( const RepoInfo & repo_r, const OnMediaLocation & resource_r )
386 {
387 // While our implementation is based on the Fetcher:
388 return Fetcher::mapToCachePath( repo_r.path() / resource_r.filename() );
389 }
390
392 } // namespace repo
395} // namespace zypp
ZYPP_RETHROW
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:479
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
Fetcher.h
FileChecker.h
Gettext.h
_
#define _(MSG)
Definition Gettext.h:39
Logger.h
DBG
#define DBG
Definition Logger.h:102
MIL
#define MIL
Definition Logger.h:103
WAR
#define WAR
Definition Logger.h:104
MediaSetAccess.h
RepoException.h
RepoProvideFile.h
SUSEMediaVerifier.h
String.h
ZConfig.h
ZYppCallbacks.h
ZYppFactory.h
shared_ptr
zypp::AutoDispose::setDispose
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Definition AutoDispose.h:167
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::Exception::remember
void remember(const Exception &old_r)
Store an other Exception as history.
Definition Exception.cc:154
zypp::Fetcher
This class allows to retrieve a group of files in a confortable way, providing some smartness that do...
Definition Fetcher.h:112
zypp::Fetcher::CleanFiles
@ CleanFiles
Definition Fetcher.h:315
zypp::Fetcher::start
void start(const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
start the transfer to a destination directory dest_dir The media has to be provides with setMediaSetA...
Definition Fetcher.cc:978
zypp::Fetcher::mapToCachePath
static Pathname mapToCachePath(Pathname remotePath_r)
Map a resource filename to a local path below a destDir.
Definition Fetcher.cc:990
zypp::Fetcher::enqueue
void enqueue(const OnMediaLocation &resource, const FileChecker &checker=FileChecker())
Enqueue a object for transferal, they will not be transferred until start() is called.
Definition Fetcher.cc:952
zypp::Fetcher::addCachePath
void addCachePath(const Pathname &cache_dir)
adds a directory to the list of directories where to look for cached files
Definition Fetcher.cc:958
zypp::FileCheckException
Definition filecheckexception.h:18
zypp::MediaSetAccess
Media access layer responsible for handling files distributed on a set of media with media change and...
Definition MediaSetAccess.h:82
zypp::MirroredOrigin
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
Definition MirroredOrigin.h:170
zypp::MirroredOrigin::isValid
bool isValid() const
Definition MirroredOrigin.cc:219
zypp::MirroredOrigin::authority
const OriginEndpoint & authority() const
Definition MirroredOrigin.cc:205
zypp::OnMediaLocation
Describes a resource file located on a medium.
Definition onmedialocation.h:37
zypp::OnMediaLocation::filename
const Pathname & filename() const
The path to the resource on the medium.
Definition onmedialocation.cc:90
zypp::OriginEndpoint
Represents a single, configurable network endpoint, combining a URL with specific access settings.
Definition MirroredOrigin.h:41
zypp::OriginEndpoint::url
const zypp::Url & url() const
Definition MirroredOrigin.cc:53
zypp::ProvideFilePolicy
Policy for provideFile and RepoMediaAccess.
Definition ProvideFilePolicy.h:31
zypp::ProvideFilePolicy::fileChecker
ProvideFilePolicy & fileChecker(FileChecker fileChecker_r)
Add a FileCecker passed down to the Fetcher.
Definition ProvideFilePolicy.h:45
zypp::ProvideFilePolicy::progress
bool progress(int value) const
Evaluate callback.
Definition ProvideFilePolicy.cc:28
zypp::RepoInfo
What is known about a repository.
Definition RepoInfo.h:72
zypp::RepoInfo::repoOrigins
MirroredOriginSet repoOrigins() const
The repodata origins.
Definition RepoInfo.cc:790
zypp::RepoInfo::keepPackages
bool keepPackages() const
Whether packages downloaded from this repository will be kept in local cache.
Definition RepoInfo.cc:828
zypp::RepoInfo::path
Pathname path() const
Repository path.
Definition RepoInfo.cc:879
zypp::RepoInfo::packagesPath
Pathname packagesPath() const
packagesPath Checks if the effective user is allowed to write into the system package cache.
Definition RepoInfo.cc:840
zypp::RepoInfo::systemPackagesPath
Pathname systemPackagesPath() const
Returns a path to the system-defined package cache.
Definition RepoInfo.cc:837
zypp::UserRequestException
Base for exceptions caused by explicit user request.
Definition userrequestexception.h:65
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::isExist
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::filesystem::Pathname::c_str
const char * c_str() const
String representation.
Definition Pathname.h:113
zypp::repo::RepoException
Exception for repository handling.
Definition RepoException.h:38
zypp::repo::RepoInfoBase::alias
std::string alias() const
unique identifier for this source.
Definition RepoInfoBase.cc:110
zypp::repo::RepoMediaAccess::Impl
Definition RepoProvideFile.cc:146
zypp::repo::RepoMediaAccess::Impl::_verifier
std::map< shared_ptr< MediaSetAccess >, RepoInfo > _verifier
Definition RepoProvideFile.cc:244
zypp::repo::RepoMediaAccess::Impl::_defaultPolicy
ProvideFilePolicy _defaultPolicy
Definition RepoProvideFile.cc:248
zypp::repo::RepoMediaAccess::Impl::mediaAccessForUrl
shared_ptr< MediaSetAccess > mediaAccessForUrl(const MirroredOrigin &origin, RepoInfo repo)
Provide a MediaSetAccess for url with label and verifier adjusted.
Definition RepoProvideFile.cc:174
zypp::repo::RepoMediaAccess::Impl::~Impl
~Impl()
Definition RepoProvideFile.cc:156
zypp::repo::RepoMediaAccess::Impl::Impl
Impl(const Impl &)=delete
zypp::repo::RepoMediaAccess::Impl::operator=
Impl & operator=(Impl &&)=delete
zypp::repo::RepoMediaAccess::Impl::Impl
Impl(ProvideFilePolicy &&defaultPolicy_r)
Definition RepoProvideFile.cc:148
zypp::repo::RepoMediaAccess::Impl::_medias
std::map< Url, shared_ptr< MediaSetAccess > > _medias
Definition RepoProvideFile.cc:245
zypp::repo::RepoMediaAccess::Impl::Impl
Impl(Impl &&)=delete
zypp::repo::RepoMediaAccess::Impl::setVerifierForRepo
void setVerifierForRepo(const RepoInfo &repo, const shared_ptr< MediaSetAccess > &media)
Definition RepoProvideFile.cc:196
zypp::repo::RepoMediaAccess::Impl::operator=
Impl & operator=(const Impl &)=delete
zypp::repo::RepoMediaAccess
Provides files from different repos.
Definition RepoProvideFile.h:73
zypp::repo::RepoMediaAccess::setDefaultPolicy
void setDefaultPolicy(const ProvideFilePolicy &policy_r)
Set a new default ProvideFilePolicy.
Definition RepoProvideFile.cc:260
zypp::repo::RepoMediaAccess::_impl
RW_pointer< Impl > _impl
Definition RepoProvideFile.h:127
zypp::repo::RepoMediaAccess::~RepoMediaAccess
~RepoMediaAccess()
Definition RepoProvideFile.cc:257
zypp::repo::RepoMediaAccess::RepoMediaAccess
RepoMediaAccess(ProvideFilePolicy defaultPolicy_r=ProvideFilePolicy())
Ctor taking the default ProvideFilePolicy.
Definition RepoProvideFile.cc:253
zypp::repo::RepoMediaAccess::mapToCachePath
static Pathname mapToCachePath(const RepoInfo &repo_r, const OnMediaLocation &resource_r)
Map a resource filename to a local path below a repositories cache.
Definition RepoProvideFile.cc:385
zypp::repo::RepoMediaAccess::defaultPolicy
const ProvideFilePolicy & defaultPolicy() const
Get the current default ProvideFilePolicy.
Definition RepoProvideFile.cc:263
zypp::repo::RepoMediaAccess::provideFile
ManagedFile provideFile(const RepoInfo &repo_r, const OnMediaLocation &loc_r, const ProvideFilePolicy &policy_r)
Provide a file from a Repository.
Definition RepoProvideFile.cc:266
zypp::repo::SUSEMediaVerifier
Implementation of the traditional SUSE media verifier.
Definition SUSEMediaVerifier.h:28
zypp::repo::SUSEMediaVerifier::totalMedia
media::MediaNr totalMedia() const
The total number of media in this set (or 0 if not known).
Definition SUSEMediaVerifier.cc:145
std
Definition ansi.h:855
zypp::filesystem::unlink
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:719
zypp::media
Definition MediaNetworkRequestExecutor.h:22
zypp::media::MediaNr
unsigned int MediaNr
Definition MediaManager.h:32
zypp::media::MediaVerifierRef
zypp::RW_pointer< MediaVerifierBase > MediaVerifierRef
A shared reference to the MediaVerifier implementation.
Definition MediaManager.h:107
zypp::repo
Definition DeltaCandidates.cc:30
zypp::repo::provideFile
ManagedFile provideFile(RepoInfo repo_r, const OnMediaLocation &loc_r, const ProvideFilePolicy &policy_r)
Provide a file from a Repository.
Definition RepoProvideFile.cc:121
zypp::repo::repositoryCachePaths
std::vector< Pathname > repositoryCachePaths(RepoInfo repo_r)
returns a set of paths.
Definition RepoProvideFile.cc:129
zypp::sat::operator=
SolvableSpec & operator=(const SolvableSpec &)=default
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::ManagedFile
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
zypp::media::ScopedDisableMediaChangeReport
Temporarily disable MediaChangeReport Sometimes helpful to suppress interactive messages connected to...
Definition ZYppCallbacks.h:354
transform.h