libzypp 17.37.1
RepoProvideFile.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
13#include <iostream>
14#include <fstream>
15#include <sstream>
16#include <set>
17
18#include <zypp/base/Gettext.h>
19#include <zypp/base/Logger.h>
20#include <zypp/base/String.h>
21#include <utility>
22#include <zypp-core/base/UserRequestException>
24#include <zypp/ZYppCallbacks.h>
25#include <zypp/MediaSetAccess.h>
26#include <zypp/ZConfig.h>
27#include <zypp/ZYppFactory.h>
30
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
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
131 {
132 public:
133 Impl(ProvideFilePolicy &&defaultPolicy_r)
134 : _defaultPolicy(std::move(defaultPolicy_r)) {}
135
136 Impl(const Impl &) = delete;
137 Impl(Impl &&) = delete;
138 Impl &operator=(const Impl &) = delete;
139 Impl &operator=(Impl &&) = delete;
140
142 {
143 std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
144 for ( it = _medias.begin();
145 it != _medias.end();
146 ++it )
147 {
148 it->second->release();
149 }
150 }
151
160 {
161 if ( !urls.size () )
162 return nullptr;
163
164 std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
165 it = _medias.find( urls.front() ); // primary Url is the key
167 if ( it != _medias.end() )
168 {
169 media = it->second;
170 }
171 else
172 {
173 auto mediaUrls = zyppng::transform( urls, []( const zypp::Url &url ) { return media::MediaUrl(url); } );
174 media.reset( new MediaSetAccess( std::move(mediaUrls) ) );
175 _medias[urls.front()] = media;
176 }
178 return media;
179 }
180
181 private:
183 {
184 // Always set the MediaSetAccess label.
185 media->setLabel( repo.name() );
186
187 // set a verifier if the repository has it
188
189 Pathname mediafile = repo.metadataPath() + "/media.1/media";
190 if ( ! repo.metadataPath().empty() )
191 {
192 if ( PathInfo(mediafile).isExist() )
193 {
194 std::map<shared_ptr<MediaSetAccess>, RepoInfo>::const_iterator it;
195 it = _verifier.find(media);
196 if ( it != _verifier.end() )
197 {
198 if ( it->second.alias() == repo.alias() )
199 {
200 // this media is already using this repo verifier
201 return;
202 }
203 }
204
205 SUSEMediaVerifier lverifier { mediafile };
206 if ( lverifier ) {
207 DBG << "Verifier for repo '" << repo.alias() << "':" << lverifier << endl;
208 for ( media::MediaNr i = 1; i <= lverifier.totalMedia(); ++i ) {
209 media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( lverifier, i ) );
210 media->setVerifier( i, verifier);
211 }
213 }
214 else {
215 WAR << "Invalid verifier for repo '" << repo.alias() << "' in '" << repo.metadataPath() << "': " << lverifier << endl;
216 }
217 }
218 else
219 {
220 DBG << "No media verifier for repo '" << repo.alias() << "' media.1/media does not exist in '" << repo.metadataPath() << "'" << endl;
221 }
222 }
223 else
224 {
225 WAR << "'" << repo.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
226 }
227 }
228
229 private:
230 std::map<shared_ptr<MediaSetAccess>, RepoInfo> _verifier;
231 std::map<Url, shared_ptr<MediaSetAccess> > _medias;
232
233 public:
235 };
236
237
238
240 : _impl( new Impl( std::move(defaultPolicy_r) ) )
241 {}
242
245
247 { _impl->_defaultPolicy = policy_r; }
248
250 { return _impl->_defaultPolicy; }
251
253 const OnMediaLocation & loc_rx,
254 const ProvideFilePolicy & policy_r )
255 {
256 const OnMediaLocation locWithPath( OnMediaLocation(loc_rx).prependPath( repo_r.path() ) );
257
258 MIL << locWithPath << endl;
259 // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport
260 // and redirect download progress triggers to call the ProvideFilePolicy
261 // callback.
262 DownloadFileReportHack dumb( std::bind( std::mem_fn(&ProvideFilePolicy::progress), std::ref(policy_r), _1 ) );
263
264 RepoException repo_excpt(repo_r,
265 str::form(_("Can't provide file '%s' from repository '%s'"),
266 locWithPath.filename().c_str(),
267 repo_r.alias().c_str() ) );
268
269 if ( repo_r.effectiveBaseUrlsEmpty() )
270 {
271 repo_excpt.remember(RepoException(_("No url in repository.")));
272 ZYPP_THROW(repo_excpt);
273 }
274
275 Fetcher fetcher;
276 fetcher.addCachePath( repo_r.packagesPath() );
277 MIL << "Added cache path " << repo_r.packagesPath() << endl;
279 MIL << "Added cache path " << repo_r.predownloadPath() << endl;
280
281 // Test whether download destination is writable, if not
282 // switch into the tmpspace (e.g. bnc#755239, download and
283 // install srpms as user).
284 Pathname destinationDir( repo_r.packagesPath() );
285
286 PathInfo pi( destinationDir );
287 if ( ! pi.isExist() )
288 {
289 // try to create it...
290 assert_dir( destinationDir );
291 pi();
292 }
293 if ( geteuid() != 0 && ! pi.userMayW() )
294 {
295 WAR << "Destination dir '" << destinationDir << "' is not user writable, using tmp space." << endl;
296 destinationDir = getZYpp()->tmpPath() / destinationDir;
297 assert_dir( destinationDir );
298 fetcher.addCachePath( destinationDir );
299 MIL << "Added cache path " << destinationDir << endl;
300 }
301
302 // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1)
303 media::ScopedDisableMediaChangeReport guard( repo_r.effectiveBaseUrls().size() > 1 );
304
305 const auto &groupedBaseUrls = repo_r.groupedBaseUrls ();
306 for ( auto it = groupedBaseUrls.begin(); it != groupedBaseUrls.end();
307 /* incremented in the loop */ )
308 {
309 // primary Url and maybe mirrors if the url is downloading
310 std::vector<Url> urls( *it );
311 ++it;
312
313 if ( urls.empty () ) {
314 MIL << "Skipping empty Url group" << std::endl;
315 continue;
316 }
317
318 try
319 {
320 MIL << "Providing file of repo '" << repo_r.alias() << "' from: ";
321 std::for_each( urls.begin (), urls.end(), [&]( const zypp::Url &u ){
322 MIL << u << ", ";
323 });
324 MIL << std::endl;
325
326 shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl( urls, repo_r );
327 if ( !access )
328 continue;
329
330 fetcher.enqueue( locWithPath, policy_r.fileChecker() );
331 fetcher.start( destinationDir, *access );
332
333 // reached if no exception has been thrown, so this is the correct file
334 ManagedFile ret( destinationDir + locWithPath.filename() );
335 if ( !repo_r.keepPackages() )
336 {
338 }
339
340 MIL << "provideFile at " << ret << endl;
341 return ret;
342 }
343 catch ( const UserRequestException & excpt )
344 {
345 ZYPP_RETHROW( excpt );
346 }
347 catch ( const FileCheckException & excpt )
348 {
349 ZYPP_RETHROW( excpt );
350 }
351 catch ( const Exception &e )
352 {
353 ZYPP_CAUGHT( e );
354
355 repo_excpt.remember(e);
356
357 WAR << "Trying next url" << endl;
358 continue;
359 }
360 } // iteration over urls
361
362 ZYPP_THROW(repo_excpt);
363 return ManagedFile(); // not reached
364 }
365
367 } // namespace repo
370} // namespace zypp
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Base class for Exception.
Definition Exception.h:153
void remember(const Exception &old_r)
Store an other Exception as history.
Definition Exception.cc:154
This class allows to retrieve a group of files in a confortable way, providing some smartness that do...
Definition Fetcher.h:104
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:927
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:901
void addCachePath(const Pathname &cache_dir)
adds a directory to the list of directories where to look for cached files
Definition Fetcher.cc:907
Media access layer responsible for handling files distributed on a set of media with media change and...
Describes a resource file located on a medium.
const Pathname & filename() const
The path to the resource on the medium.
Policy for provideFile and RepoMediaAccess.
ProvideFilePolicy & fileChecker(FileChecker fileChecker_r)
Add a FileCecker passed down to the Fetcher.
bool progress(int value) const
Evaluate callback.
What is known about a repository.
Definition RepoInfo.h:72
Pathname predownloadPath() const
Path where this repo packages are predownloaded.
Definition RepoInfo.cc:723
url_set effectiveBaseUrls() const
The complete set of effective repository urls.
Definition RepoInfo.cc:702
bool keepPackages() const
Whether packages downloaded from this repository will be kept in local cache.
Definition RepoInfo.cc:735
Pathname path() const
Repository path.
Definition RepoInfo.cc:783
std::vector< std::vector< Url > > groupedBaseUrls() const
Returns the currently known effective baseUrls in groups, where each group contains a primary base ur...
Definition RepoInfo.cc:798
Pathname packagesPath() const
Path where this repo packages are cached.
Definition RepoInfo.cc:744
bool effectiveBaseUrlsEmpty() const
whether effective repository urls are available
Definition RepoInfo.cc:697
Url manipulation class.
Definition Url.h:93
Base for exceptions caused by explicit user request.
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
Definition ZYppFactory.h:77
Wrapper class for stat/lstat.
Definition PathInfo.h:226
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
const char * c_str() const
String representation.
Definition Pathname.h:112
Exception for repository handling.
std::string alias() const
unique identifier for this source.
std::map< shared_ptr< MediaSetAccess >, RepoInfo > _verifier
shared_ptr< MediaSetAccess > mediaAccessForUrl(const std::vector< Url > &urls, RepoInfo repo)
Provide a MediaSetAccess for url with label and verifier adjusted.
Impl & operator=(Impl &&)=delete
Impl(ProvideFilePolicy &&defaultPolicy_r)
std::map< Url, shared_ptr< MediaSetAccess > > _medias
void setVerifierForRepo(const RepoInfo &repo, const shared_ptr< MediaSetAccess > &media)
Impl & operator=(const Impl &)=delete
Provides files from different repos.
void setDefaultPolicy(const ProvideFilePolicy &policy_r)
Set a new default ProvideFilePolicy.
RepoMediaAccess(ProvideFilePolicy defaultPolicy_r=ProvideFilePolicy())
Ctor taking the default ProvideFilePolicy.
const ProvideFilePolicy & defaultPolicy() const
Get the current default ProvideFilePolicy.
ManagedFile provideFile(const RepoInfo &repo_r, const OnMediaLocation &loc_r, const ProvideFilePolicy &policy_r)
Provide a file from a Repository.
Implementation of the traditional SUSE media verifier.
Definition Arch.h:364
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
unsigned int MediaNr
zypp::RW_pointer< MediaVerifierBase > MediaVerifierRef
A shared reference to the MediaVerifier implementation.
ManagedFile provideFile(RepoInfo repo_r, const OnMediaLocation &loc_r, const ProvideFilePolicy &policy_r)
Provide a file from a Repository.
SolvableSpec & operator=(const SolvableSpec &)=default
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
Url details namespace.
Definition UrlBase.cc:58
Easy-to use interface to the ZYPP dependency resolver.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
Container< Ret > transform(Container< Msg, CArgs... > &&val, Transformation &&transformation)
Definition transform.h:31
Temporarily disable MediaChangeReport Sometimes helpful to suppress interactive messages connected to...
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:479
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define _(MSG)
Definition Gettext.h:39
#define DBG
Definition Logger.h:99
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101
Interface to gettext.