libzypp 17.35.12
repomanagerwf.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include "repomanagerwf.h"
10
12
14#include <zypp-core/zyppng/io/Process>
15#include <zypp-core/zyppng/pipelines/MTry>
16#include <zypp-core/zyppng/pipelines/Algorithm>
17#include <zypp-media/MediaException>
18#include <zypp-media/ng/Provide>
19#include <zypp-media/ng/ProvideSpec>
20
22#include <zypp/HistoryLog.h>
23#include <zypp/base/Algorithm.h>
24#include <zypp/ng/Context>
28#include <zypp/ng/repomanager.h>
29
30#include <utility>
31#include <fstream>
32
33#undef ZYPP_BASE_LOGGER_LOGGROUP
34#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager"
35
37
38 using namespace zyppng::operators;
39
40 namespace {
41
42 template <class Executor, class OpType>
43 struct ProbeRepoLogic : public LogicBase<Executor, OpType>
44 {
45 protected:
46 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
47
48 public:
49 using ZyppContextRefType = std::conditional_t<zyppng::detail::is_async_op_v<OpType>, ContextRef, SyncContextRef >;
50 using ProvideType = typename remove_smart_ptr_t<ZyppContextRefType>::ProvideType;
51 using MediaHandle = typename ProvideType::MediaHandle;
52 using LazyMediaHandle = typename ProvideType::LazyMediaHandle;
53 using ProvideRes = typename ProvideType::Res;
54
55 ProbeRepoLogic(ZyppContextRefType zyppCtx, LazyMediaHandle &&medium, zypp::Pathname &&path, std::optional<zypp::Pathname> &&targetPath )
56 : _zyppContext(std::move(zyppCtx))
57 , _medium(std::move(medium))
58 , _path(std::move(path))
59 , _targetPath(std::move(targetPath))
60 {}
61
62 MaybeAsyncRef<expected<zypp::repo::RepoType>> execute( ) {
63 const auto &url = _medium.baseUrl();
64 MIL << "going to probe the repo type at " << url << " (" << _path << ")" << std::endl;
65
66 if ( url.getScheme() == "dir" && ! zypp::PathInfo( url.getPathName()/_path ).isDir() ) {
67 // Handle non existing local directory in advance
68 MIL << "Probed type NONE (not exists) at " << url << " (" << _path << ")" << std::endl;
70 }
71
72 // prepare exception to be thrown if the type could not be determined
73 // due to a media exception. We can't throw right away, because of some
74 // problems with proxy servers returning an incorrect error
75 // on ftp file-not-found(bnc #335906). Instead we'll check another types
76 // before throwing.
77
78 std::shared_ptr<ProvideType> providerRef = _zyppContext->provider();
79
80 // TranslatorExplanation '%s' is an URL
81 _error = zypp::repo::RepoException (zypp::str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
82
83 return providerRef->attachMediaIfNeeded( _medium )
84 | and_then([this, providerRef]( MediaHandle medium )
85 {
86 // first try rpmmd
87 return providerRef->provide( medium, _path/"repodata/repomd.xml", ProvideFileSpec().setCheckExistsOnly( !_targetPath.has_value() ) )
88 | and_then( maybeCopyResultToDest("repodata/repomd.xml") )
90 // try susetags if rpmmd fails and remember the error
91 | or_else( [this, providerRef, medium]( std::exception_ptr err ) {
92 try {
93 std::rethrow_exception (err);
94 } catch ( const zypp::media::MediaFileNotFoundException &e ) {
95 // do nothing
96 ;
97 } catch( const zypp::media::MediaException &e ) {
98 DBG << "problem checking for repodata/repomd.xml file" << std::endl;
99 _error.remember ( err );
100 _gotMediaError = true;
101 } catch( ... ) {
102 // any other error, we give up
104 }
105 return providerRef->provide( medium, _path/"content", ProvideFileSpec().setCheckExistsOnly( !_targetPath.has_value() ) )
106 | and_then( maybeCopyResultToDest("content") )
108 })
109 // no rpmmd and no susetags!
110 | or_else( [this, medium]( std::exception_ptr err ) {
111
112 try {
113 std::rethrow_exception (err);
114 } catch ( const zypp::media::MediaFileNotFoundException &e ) {
115 // do nothing
116 ;
117 } catch( const zypp::media::MediaException &e ) {
118 DBG << "problem checking for content file" << std::endl;
119 _error.remember ( err );
120 _gotMediaError = true;
121 } catch( zypp::Exception &e ) {
122 _error.remember(e);
123 // any other error, we give up
125 } catch(...) {
126 // any other error, we give up
128 }
129
130 const auto &url = medium.baseUrl();
131
132 // if it is a non-downloading URL denoting a directory (bsc#1191286: and no plugin)
133 if ( ! ( url.schemeIsDownloading() || url.schemeIsPlugin() ) ) {
134
135 if ( medium.localPath() && zypp::PathInfo(medium.localPath().value()/_path).isDir() ) {
136 // allow empty dirs for now
137 MIL << "Probed type RPMPLAINDIR at " << url << " (" << _path << ")" << std::endl;
139 }
140 }
141
142 if( _gotMediaError )
144
145 MIL << "Probed type NONE at " << url << " (" << _path << ")" << std::endl;
147 })
148 ;
149 });
150 }
151
152 private:
157 auto maybeCopyResultToDest ( std::string &&subPath ) {
158 return [this, subPath = std::move(subPath)]( ProvideRes file ) -> MaybeAsyncRef<expected<void>> {
159 if ( _targetPath ) {
160 MIL << "Target path is set, copying " << file.file() << " to " << *_targetPath/subPath << std::endl;
161 return std::move(file)
162 | ProvideType::copyResultToDest( _zyppContext->provider(), *_targetPath/subPath)
163 | and_then([]( zypp::ManagedFile file ){ file.resetDispose(); return expected<void>::success(); } );
164 }
166 };
167 }
168
169 private:
170 ZyppContextRefType _zyppContext;
173 std::optional<zypp::Pathname> _targetPath;
174
176 bool _gotMediaError = false;
177 };
178
179 template <class RefreshContextRef>
180 auto probeRepoLogic( RefreshContextRef ctx, RepoInfo repo, std::optional<zypp::Pathname> targetPath)
181 {
182 using namespace zyppng::operators;
183 return ctx->provider()->prepareMedia( repo.url(), zyppng::ProvideMediaSpec() )
184 | and_then( [ctx, path = repo.path() ]( auto &&mediaHandle ) {
185 return probeRepoType( ctx, std::forward<decltype(mediaHandle)>(mediaHandle), path );
186 });
187 }
188 }
189
190 AsyncOpRef<expected<zypp::repo::RepoType> > probeRepoType(ContextRef ctx, AsyncLazyMediaHandle medium, zypp::Pathname path, std::optional<zypp::Pathname> targetPath)
191 {
192 return SimpleExecutor< ProbeRepoLogic, AsyncOp<expected<zypp::repo::RepoType>> >::run( std::move(ctx), std::move(medium), std::move(path), std::move(targetPath) );
193 }
194
195 expected<zypp::repo::RepoType> probeRepoType(SyncContextRef ctx, SyncLazyMediaHandle medium, zypp::Pathname path, std::optional<zypp::Pathname> targetPath )
196 {
197 return SimpleExecutor< ProbeRepoLogic, SyncOp<expected<zypp::repo::RepoType>> >::run( std::move(ctx), std::move(medium), std::move(path), std::move(targetPath) );
198 }
199
200 AsyncOpRef<expected<zypp::repo::RepoType> > probeRepoType( ContextRef ctx, RepoInfo repo, std::optional<zypp::Pathname> targetPath )
201 {
202 return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) );
203 }
204
205 expected<zypp::repo::RepoType> probeRepoType ( SyncContextRef ctx, RepoInfo repo, std::optional<zypp::Pathname> targetPath )
206 {
207 return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) );
208 }
209
210
211 namespace {
212 template <class ZyppContextRef>
213 auto readRepoFileLogic( ZyppContextRef ctx, zypp::Url repoFileUrl )
214 {
215 using namespace zyppng::operators;
216 return ctx->provider()->provide( repoFileUrl, ProvideFileSpec() )
217 | and_then([repoFileUrl]( auto local ){
218 DBG << "reading repo file " << repoFileUrl << ", local path: " << local.file() << std::endl;
219 return repositories_in_file( local.file() );
220 });
221 }
222 }
223
225 {
226 return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) );
227 }
228
229 expected<std::list<RepoInfo> > readRepoFile(SyncContextRef ctx, zypp::Url repoFileUrl)
230 {
231 return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) );
232 }
233
234 namespace {
235
236 template<typename Executor, class OpType>
237 struct CheckIfToRefreshMetadataLogic : public LogicBase<Executor, OpType> {
238
239 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
240 public:
241
242 using RefreshContextRefType = std::conditional_t<zyppng::detail::is_async_op_v<OpType>, repo::AsyncRefreshContextRef, repo::SyncRefreshContextRef>;
243 using ZyppContextRefType = typename RefreshContextRefType::element_type::ContextRefType;
244 using ZyppContextType = typename RefreshContextRefType::element_type::ContextType;
245 using ProvideType = typename ZyppContextType::ProvideType;
246 using LazyMediaHandle = typename ProvideType::LazyMediaHandle;
247 using MediaHandle = typename ProvideType::MediaHandle;
248 using ProvideRes = typename ProvideType::Res;
249
250 CheckIfToRefreshMetadataLogic( RefreshContextRefType refCtx, LazyMediaHandle &&medium, ProgressObserverRef progressObserver )
251 : _refreshContext(std::move(refCtx))
252 , _progress(std::move( progressObserver ))
253 , _medium(std::move( medium ))
254 {}
255
256 MaybeAsyncRef<expected<repo::RefreshCheckStatus>> execute( ) {
257
258 MIL << "Going to CheckIfToRefreshMetadata" << std::endl;
259
260 return assert_alias( _refreshContext->repoInfo() )
261 | and_then( [this] {
262
263 const auto &info = _refreshContext->repoInfo();
264 MIL << "Check if to refresh repo " << _refreshContext->repoInfo().alias() << " at " << _medium.baseUrl() << " (" << info.type() << ")" << std::endl;
265
266 // first check old (cached) metadata
268 })
269 | and_then( [this](zypp::RepoStatus oldstatus) {
270
271 const auto &info = _refreshContext->repoInfo();
272
273 if ( oldstatus.empty() ) {
274 MIL << "No cached metadata, going to refresh" << std::endl;
276 }
277
278 if ( _medium.baseUrl().schemeIsVolatile() ) {
279 MIL << "Never refresh CD/DVD" << std::endl;
281 }
282
284 MIL << "Forced refresh!" << std::endl;
286 }
287
288 if ( _medium.baseUrl().schemeIsLocal() ) {
290 }
291
292 // Check whether repo.refresh.delay applies...
294 {
295 // bsc#1174016: Prerequisite to skipping the refresh is that metadata
296 // and solv cache status match. They will not, if the repos URL was
297 // changed e.g. due to changed repovars.
299 if ( !cachestatus ) return makeReadyResult( expected<repo::RefreshCheckStatus>::error(cachestatus.error()) );
300
301 if ( oldstatus == *cachestatus ) {
302 // difference in seconds
303 double diff = ::difftime( (zypp::Date::ValueType)zypp::Date::now(), (zypp::Date::ValueType)oldstatus.timestamp() ) / 60;
304 const auto refDelay = _refreshContext->zyppContext()->config().repo_refresh_delay();
305 if ( diff < refDelay ) {
306 if ( diff < 0 ) {
307 WAR << "Repository '" << info.alias() << "' was refreshed in the future!" << std::endl;
308 }
309 else {
310 MIL << "Repository '" << info.alias()
311 << "' has been refreshed less than repo.refresh.delay ("
312 << refDelay
313 << ") minutes ago. Advising to skip refresh" << std::endl;
315 }
316 }
317 }
318 else {
319 MIL << "Metadata and solv cache don't match. Check data on server..." << std::endl;
320 }
321 }
322
323 return info.type() | [this]( zypp::repo::RepoType repokind ) {
324 // if unknown: probe it
325 if ( repokind == zypp::repo::RepoType::NONE )
326 return probeRepoType( _refreshContext->zyppContext(), _medium, _refreshContext->repoInfo().path()/*, _refreshContext->targetDir()*/ );
328 } | and_then([this, oldstatus]( zypp::repo::RepoType repokind ) {
329
330 // make sure to remember the repo type
331 _refreshContext->repoInfo().setProbedType( repokind );
332
333 auto dlContext = std::make_shared<repo::DownloadContext<ZyppContextRefType>>( _refreshContext->zyppContext(), _refreshContext->repoInfo(), _refreshContext->targetDir() );
334 return RepoDownloaderWorkflow::repoStatus ( dlContext, _medium )
335 | and_then( [this, dlContext, oldstatus]( zypp::RepoStatus newstatus ){
336 // check status
337 if ( oldstatus == newstatus ) {
338 MIL << "repo has not changed" << std::endl;
341 }
342 else { // includes newstatus.empty() if e.g. repo format changed
343 MIL << "repo has changed, going to refresh" << std::endl;
344 MIL << "Old status: " << oldstatus << " New Status: " << newstatus << std::endl;
346 }
347 });
348 });
349 });
350 }
351
352 protected:
353 RefreshContextRefType _refreshContext;
354 ProgressObserverRef _progress;
356 };
357 }
358
359 AsyncOpRef<expected<repo::RefreshCheckStatus> > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle<Provide> medium, ProgressObserverRef progressObserver)
360 {
361 return SimpleExecutor< CheckIfToRefreshMetadataLogic , AsyncOp<expected<repo::RefreshCheckStatus>> >::run( std::move(refCtx), std::move(medium), std::move(progressObserver) );
362 }
363
364 expected<repo::RefreshCheckStatus> checkIfToRefreshMetadata(repo::SyncRefreshContextRef refCtx, LazyMediaHandle<MediaSyncFacade> medium, ProgressObserverRef progressObserver)
365 {
366 return SimpleExecutor< CheckIfToRefreshMetadataLogic , SyncOp<expected<repo::RefreshCheckStatus>> >::run( std::move(refCtx), std::move(medium), std::move(progressObserver) );
367 }
368
369
370 namespace {
371
372 template<typename Executor, class OpType>
373 struct RefreshMetadataLogic : public LogicBase<Executor, OpType>{
374
375 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
376
377 public:
378
379 using RefreshContextRefType = std::conditional_t<zyppng::detail::is_async_op_v<OpType>, repo::AsyncRefreshContextRef, repo::SyncRefreshContextRef>;
380 using ZyppContextRefType = typename RefreshContextRefType::element_type::ContextRefType;
381 using ZyppContextType = typename RefreshContextRefType::element_type::ContextType;
382 using ProvideType = typename ZyppContextType::ProvideType;
383 using MediaHandle = typename ProvideType::MediaHandle;
384 using LazyMediaHandle = typename ProvideType::LazyMediaHandle;
385 using ProvideRes = typename ProvideType::Res;
386
387 using DlContextType = repo::DownloadContext<ZyppContextRefType>;
388 using DlContextRefType = std::shared_ptr<DlContextType>;
389
390 RefreshMetadataLogic( RefreshContextRefType refCtx, LazyMediaHandle &&medium, ProgressObserverRef progressObserver )
391 : _refreshContext(std::move(refCtx))
392 , _progress ( std::move( progressObserver ) )
393 , _medium ( std::move( medium ) )
394 { }
395
396 MaybeAsyncRef<expected<RefreshContextRefType>> execute() {
397
398 return assert_alias( _refreshContext->repoInfo() )
399 | and_then( [this](){ return assert_urls( _refreshContext->repoInfo() ); })
400 | and_then( [this](){ return checkIfToRefreshMetadata ( _refreshContext, _medium, _progress ); })
401 | and_then( [this]( repo::RefreshCheckStatus status ){
402
403 MIL << "RefreshCheckStatus returned: " << status << std::endl;
404
405 // check whether to refresh metadata
406 // if the check fails for this url, it throws, so another url will be checked
408 return makeReadyResult ( expected<RefreshContextRefType>::success( std::move(_refreshContext) ) );
409
410 MIL << "Going to refresh metadata from " << _medium.baseUrl() << std::endl;
411
412 // bsc#1048315: Always re-probe in case of repo format change.
413 // TODO: Would be sufficient to verify the type and re-probe
414 // if verification failed (or type is RepoType::NONE)
415 return probeRepoType ( _refreshContext->zyppContext(), _medium, _refreshContext->repoInfo().path() /*, _refreshContext->targetDir()*/ )
416 | and_then([this]( zypp::repo::RepoType repokind ) {
417
418 auto &info = _refreshContext->repoInfo();
419
420 if ( info.type() != repokind ) {
421 _refreshContext->setProbedType( repokind );
422 // Adjust the probed type in RepoInfo
423 info.setProbedType( repokind ); // lazy init!
424 }
425
426 // no need to continue with an unknown type
427 if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e )
429
430 const zypp::Pathname &mediarootpath = _refreshContext->rawCachePath();
431 if( zypp::filesystem::assert_dir(mediarootpath) ) {
432 auto exception = ZYPP_EXCPT_PTR (zypp::Exception(zypp::str::form( _("Can't create %s"), mediarootpath.c_str() )));
433 return makeReadyResult( expected<DlContextRefType>::error( std::move(exception) ));
434 }
435
436 auto dlContext = std::make_shared<DlContextType>( _refreshContext->zyppContext(), _refreshContext->repoInfo(), _refreshContext->targetDir() );
437 dlContext->setPluginRepoverification( _refreshContext->pluginRepoverification() );
438
439 return RepoDownloaderWorkflow::download ( dlContext, _medium, _progress );
440
441 })
442 | and_then([this]( DlContextRefType && ) {
443
444 // ok we have the metadata, now exchange
445 // the contents
446 _refreshContext->saveToRawCache();
447 // if ( ! isTmpRepo( info ) )
448 // reposManip(); // remember to trigger appdata refresh
449
450 // we are done.
451 return expected<RefreshContextRefType>::success( std::move(_refreshContext) );
452 });
453 });
454 }
455
456 RefreshContextRefType _refreshContext;
457 ProgressObserverRef _progress;
460
461 };
462 }
463
464 AsyncOpRef<expected<repo::AsyncRefreshContextRef> > refreshMetadata( repo::AsyncRefreshContextRef refCtx, LazyMediaHandle<Provide> medium, ProgressObserverRef progressObserver )
465 {
466 return SimpleExecutor<RefreshMetadataLogic, AsyncOp<expected<repo::AsyncRefreshContextRef>>>::run( std::move(refCtx), std::move(medium), std::move(progressObserver));
467 }
468
469 expected<repo::SyncRefreshContextRef> refreshMetadata( repo::SyncRefreshContextRef refCtx, LazyMediaHandle<MediaSyncFacade> medium, ProgressObserverRef progressObserver )
470 {
471 return SimpleExecutor<RefreshMetadataLogic, SyncOp<expected<repo::SyncRefreshContextRef>>>::run( std::move(refCtx), std::move(medium), std::move(progressObserver));
472 }
473
474 namespace {
475 template <class RefreshContextRef>
476 auto refreshMetadataLogic( RefreshContextRef refCtx, ProgressObserverRef progressObserver)
477 {
478 // small shared helper struct to pass around the exception and to remember that we tried the first URL
479 struct ExHelper {
480 bool isFirst;
481 // we will throw this later if no URL checks out fine
482 zypp::repo::RepoException rexception;
483 };
484
485 auto helper = std::make_shared<ExHelper>( ExHelper{
486 false,
487 zypp::repo::RepoException { refCtx->repoInfo(), PL_("Valid metadata not found at specified URL",
488 "Valid metadata not found at specified URLs",
489 refCtx->repoInfo().baseUrlsSize() ) }
490 });
491
492 // the actual logic pipeline, attaches the medium and tries to refresh from it
493 auto refreshPipeline = [ refCtx, progressObserver ]( zypp::Url url ){
494 return refCtx->zyppContext()->provider()->prepareMedia( url, zyppng::ProvideMediaSpec() )
495 | and_then( [ refCtx , progressObserver]( auto mediaHandle ) mutable { return refreshMetadata ( std::move(refCtx), std::move(mediaHandle), progressObserver ); } );
496 };
497
498 // predicate that accepts only valid results, and in addition collects all errors in rexception
499 auto predicate = [ info = refCtx->repoInfo(), helper ]( const expected<RefreshContextRef> &res ) -> bool{
500 if ( !res ) {
501 try {
502 ZYPP_RETHROW( res.error() );
503 } catch ( const zypp::Exception &e ) {
504 ERR << "Trying another url..." << std::endl;
505
506 // remember the exception caught for the *first URL*
507 // if all other URLs fail, the rexception will be thrown with the
508 // cause of the problem of the first URL remembered
509 if ( helper->isFirst ) {
510 helper->rexception.remember( e );
511 helper->isFirst = false;
512 } else {
513 helper->rexception.addHistory( e.asUserString() );
514 }
515 }
516 return false;
517 }
518 return true;
519 };
520
521 // now go over the urls until we find one that works
522 return refCtx->repoInfo().baseUrls()
523 | firstOf( std::move(refreshPipeline), expected<RefreshContextRef>::error( std::make_exception_ptr(NotFoundException()) ), std::move(predicate) )
524 | [helper]( expected<RefreshContextRef> result ) {
525 if ( !result ) {
526 // none of the URLs worked
527 ERR << "No more urls..." << std::endl;
528 return expected<RefreshContextRef>::error( ZYPP_EXCPT_PTR(helper->rexception) );
529 }
530 // we are done.
531 return result;
532 };
533 }
534 }
535
536 AsyncOpRef<expected<repo::AsyncRefreshContextRef> > refreshMetadata( repo::AsyncRefreshContextRef refCtx, ProgressObserverRef progressObserver) {
537 return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) );
538 }
539
540 expected<repo::SyncRefreshContextRef> refreshMetadata( repo::SyncRefreshContextRef refCtx, ProgressObserverRef progressObserver) {
541 return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) );
542 }
543
544
545 namespace {
546
547 template <typename ZyppCtxRef> struct Repo2SolvOp;
548
549 template <>
550 struct Repo2SolvOp<ContextRef> : public AsyncOp<expected<void>>
551 {
552 Repo2SolvOp() { }
553
555 MIL << "Starting repo2solv for repo " << repo.alias () << std::endl;
556 auto me = std::make_shared<Repo2SolvOp<ContextRef>>();
557 me->_repo = std::move(repo);
558 me->_proc = Process::create();
559 me->_proc->connect( &Process::sigFinished, *me, &Repo2SolvOp<ContextRef>::procFinished );
560 me->_proc->connect( &Process::sigReadyRead, *me, &Repo2SolvOp<ContextRef>::readyRead );
561
562 std::vector<const char *> argsIn;
563 argsIn.reserve ( args.size() );
564 std::for_each( args.begin (), args.end(), [&]( const std::string &s ) { argsIn.push_back(s.data()); });
565 argsIn.push_back (nullptr);
566 me->_proc->setOutputChannelMode ( Process::Merged );
567 if (!me->_proc->start( argsIn.data() )) {
568 return makeReadyResult( expected<void>::error(ZYPP_EXCPT_PTR(zypp::repo::RepoException ( me->_repo, _("Failed to cache repo ( unable to start repo2solv ).") ))) );
569 }
570 return me;
571 }
572
573 void readyRead (){
574 const ByteArray &data = _proc->readLine();
575 const std::string &line = data.asString();
576 WAR << " " << line;
577 _errdetail += line;
578 }
579
580 void procFinished( int ret ) {
581
582 while ( _proc->canReadLine() )
583 readyRead();
584
585 if ( ret != 0 ) {
586 zypp::repo::RepoException ex( _repo, zypp::str::form( _("Failed to cache repo (%d)."), ret ));
587 ex.addHistory( zypp::str::Str() << _proc->executedCommand() << std::endl << _errdetail << _proc->execError() ); // errdetail lines are NL-terminaled!
588 setReady( expected<void>::error(ZYPP_EXCPT_PTR(ex)) );
589 return;
590 }
591 setReady( expected<void>::success() );
592 }
593
594 private:
595 ProcessRef _proc;
597 std::string _errdetail;
598 };
599
600 template <>
601 struct Repo2SolvOp<SyncContextRef>
602 {
605 std::string errdetail;
606
607 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
608 WAR << " " << output;
609 errdetail += output;
610 }
611
612 int ret = prog.close();
613 if ( ret != 0 )
614 {
615 zypp::repo::RepoException ex(repo, zypp::str::form( _("Failed to cache repo (%d)."), ret ));
616 ex.addHistory( zypp::str::Str() << prog.command() << std::endl << errdetail << prog.execError() ); // errdetail lines are NL-terminaled!
618 }
620 }
621 };
622
623 template<typename Executor, class OpType>
624 struct BuildCacheLogic : public LogicBase<Executor, OpType>{
625
626 using RefreshContextRefType = std::conditional_t<zyppng::detail::is_async_op_v<OpType>, repo::AsyncRefreshContextRef, repo::SyncRefreshContextRef>;
627 using ZyppContextRefType = typename RefreshContextRefType::element_type::ContextRefType;
628 using ZyppContextType = typename RefreshContextRefType::element_type::ContextType;
629 using ProvideType = typename ZyppContextType::ProvideType;
630 using MediaHandle = typename ProvideType::MediaHandle;
631 using ProvideRes = typename ProvideType::Res;
632
633 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
634
635 BuildCacheLogic( RefreshContextRefType &&refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef &&progressObserver )
636 : _refCtx( std::move(refCtx) )
637 , _policy( policy )
638 , _progressObserver( std::move(progressObserver) )
639 {}
640
641 MaybeAsyncRef<expected<RefreshContextRefType>> execute() {
642
643 ProgressObserver::setup ( _progressObserver, zypp::str::form(_("Building repository '%s' cache"), _refCtx->repoInfo().label().c_str()), 100 );
644
645 return assert_alias(_refCtx->repoInfo() )
646 | and_then( mtry( [this] {
647 _mediarootpath = rawcache_path_for_repoinfo( _refCtx->repoManagerOptions(), _refCtx->repoInfo() ).unwrap();
648 _productdatapath = rawproductdata_path_for_repoinfo( _refCtx->repoManagerOptions(), _refCtx->repoInfo() ).unwrap();
649 }))
650 | and_then( [this] {
651
652 const auto &options = _refCtx->repoManagerOptions();
653
654 if( zypp::filesystem::assert_dir( options.repoCachePath ) ) {
655 auto ex = ZYPP_EXCPT_PTR( zypp::Exception (zypp::str::form( _("Can't create %s"), options.repoCachePath.c_str()) ) );
656 return expected<RepoStatus>::error( std::move(ex) );
657 }
658
659 return RepoManager<ZyppContextRefType>::metadataStatus( _refCtx->repoInfo(), options );
660
661 }) | and_then( [this](RepoStatus raw_metadata_status ) {
662
663 if ( raw_metadata_status.empty() )
664 {
665 /* if there is no cache at this point, we refresh the raw
666 in case this is the first time - if it's !autorefresh,
667 we may still refresh */
668 return refreshMetadata( _refCtx, ProgressObserver::makeSubTask( _progressObserver ) )
669 | and_then([this]( auto /*refCtx*/) { return RepoManager<ZyppContextRefType>::metadataStatus( _refCtx->repoInfo(), _refCtx->repoManagerOptions() ); } );
670 }
671 return makeReadyResult( make_expected_success (raw_metadata_status) );
672
673 }) | and_then( [this]( RepoStatus raw_metadata_status ) {
674
675 bool needs_cleaning = false;
676 const auto &info = _refCtx->repoInfo();
677 if ( _refCtx->repoManager()->isCached( info ) )
678 {
679 MIL << info.alias() << " is already cached." << std::endl;
680 expected<RepoStatus> cache_status = RepoManager<ZyppContextRefType>::cacheStatus( info, _refCtx->repoManagerOptions() );
681 if ( !cache_status )
682 return makeReadyResult( expected<void>::error(cache_status.error()) );
683
684 if ( *cache_status == raw_metadata_status )
685 {
686 MIL << info.alias() << " cache is up to date with metadata." << std::endl;
688 {
689 // On the fly add missing solv.idx files for bash completion.
690 return makeReadyResult(
691 solv_path_for_repoinfo( _refCtx->repoManagerOptions(), info)
692 | and_then([this]( zypp::Pathname base ){
693 if ( ! zypp::PathInfo(base/"solv.idx").isExist() )
694 return mtry( zypp::sat::updateSolvFileIndex, base/"solv" );
695 return expected<void>::success ();
696 })
697 );
698 }
699 else {
700 MIL << info.alias() << " cache rebuild is forced" << std::endl;
701 }
702 }
703
704 needs_cleaning = true;
705 }
706
707 ProgressObserver::start( _progressObserver );
708
709 if (needs_cleaning)
710 {
711 auto r = _refCtx->repoManager()->cleanCache(info);
712 if ( !r )
713 return makeReadyResult( expected<void>::error(r.error()) );
714 }
715
716 MIL << info.alias() << " building cache..." << info.type() << std::endl;
717
718 expected<zypp::Pathname> base = solv_path_for_repoinfo( _refCtx->repoManagerOptions(), info);
719 if ( !base )
721
723 {
724 zypp::Exception ex(zypp::str::form( _("Can't create %s"), base->c_str()) );
726 }
727
728 if( ! zypp::PathInfo(*base).userMayW() )
729 {
730 zypp::Exception ex(zypp::str::form( _("Can't create cache at %s - no writing permissions."), base->c_str()) );
732 }
733
734 zypp::Pathname solvfile = *base / "solv";
735
736 // do we have type?
737 zypp::repo::RepoType repokind = info.type();
738
739 // if the type is unknown, try probing.
740 switch ( repokind.toEnum() )
741 {
743 // unknown, probe the local metadata
744 repokind = RepoManager<ZyppContextRefType>::probeCache( _productdatapath );
745 break;
746 default:
747 break;
748 }
749
750 MIL << "repo type is " << repokind << std::endl;
751
752 return mountIfRequired( repokind, info )
753 | and_then([this, repokind, solvfile = std::move(solvfile) ]( std::optional<MediaHandle> forPlainDirs ) mutable {
754
755 const auto &info = _refCtx->repoInfo();
756
757 switch ( repokind.toEnum() )
758 {
762 {
763 // Take care we unlink the solvfile on error
765
767#ifdef ZYPP_REPO2SOLV_PATH
768 cmd.push_back( ZYPP_REPO2SOLV_PATH );
769#else
770 cmd.push_back( zypp::PathInfo( "/usr/bin/repo2solv" ).isFile() ? "repo2solv" : "repo2solv.sh" );
771#endif
772 // repo2solv expects -o as 1st arg!
773 cmd.push_back( "-o" );
774 cmd.push_back( solvfile.asString() );
775 cmd.push_back( "-X" ); // autogenerate pattern from pattern-package
776 // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages
777
778 if ( repokind == zypp::repo::RepoType::RPMPLAINDIR )
779 {
780 // recusive for plaindir as 2nd arg!
781 cmd.push_back( "-R" );
782
783 std::optional<zypp::Pathname> localPath = forPlainDirs.has_value() ? forPlainDirs->localPath() : zypp::Pathname();
784 if ( !localPath )
785 return makeReadyResult( expected<void>::error( ZYPP_EXCPT_PTR( zypp::repo::RepoException( zypp::str::Format(_("Failed to cache repo %1%")) % _refCtx->repoInfo() ))) );
786
787 // FIXME this does only work for dir: URLs
788 cmd.push_back( (*localPath / info.path().absolutename()).c_str() );
789 }
790 else
791 cmd.push_back( _productdatapath.asString() );
792
793 return Repo2SolvOp<ZyppContextRefType>::run( info, std::move(cmd) )
794 | and_then( [this, guard = std::move(guard), solvfile = std::move(solvfile) ]() mutable {
795 // We keep it.
796 guard.resetDispose();
797 return mtry( zypp::sat::updateSolvFileIndex, solvfile ); // content digest for zypper bash completion
798 });
799 }
800 break;
801 default:
802 return makeReadyResult( expected<void>::error( ZYPP_EXCPT_PTR(zypp::repo::RepoUnknownTypeException( info, _("Unhandled repository type") )) ) );
803 break;
804 }
805 })
806 | and_then([this, raw_metadata_status](){
807 // update timestamp and checksum
808 return _refCtx->repoManager()->setCacheStatus( _refCtx->repoInfo(), raw_metadata_status );
809 });
810 })
811 | and_then( [this](){
812 MIL << "Commit cache.." << std::endl;
814 return make_expected_success ( _refCtx );
815
816 })
817 | or_else ( [this]( std::exception_ptr e ) {
820 });
821 }
822
823 private:
824 MaybeAsyncRef<expected<std::optional<MediaHandle>>> mountIfRequired ( zypp::repo::RepoType repokind, zypp::RepoInfo info ) {
825 if ( repokind != zypp::repo::RepoType::RPMPLAINDIR )
826 return makeReadyResult( make_expected_success( std::optional<MediaHandle>() ));
827
828 return _refCtx->zyppContext()->provider()->attachMedia( info.url(), ProvideMediaSpec() )
829 | and_then( [this]( MediaHandle handle ) {
830 return makeReadyResult( make_expected_success( std::optional<MediaHandle>( std::move(handle)) ));
831 });
832 }
833
834 private:
835 RefreshContextRefType _refCtx;
837 ProgressObserverRef _progressObserver;
838
841 };
842 }
843
844 AsyncOpRef<expected<repo::AsyncRefreshContextRef> > buildCache(repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
845 {
846 return SimpleExecutor<BuildCacheLogic, AsyncOp<expected<repo::AsyncRefreshContextRef>>>::run( std::move(refCtx), policy, std::move(progressObserver));
847 }
848
849 expected<repo::SyncRefreshContextRef> buildCache(repo::SyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
850 {
851 return SimpleExecutor<BuildCacheLogic, SyncOp<expected<repo::SyncRefreshContextRef>>>::run( std::move(refCtx), policy, std::move(progressObserver));
852 }
853
854
855 // Add repository logic
856 namespace {
857
858 template<typename Executor, class OpType>
859 struct AddRepoLogic : public LogicBase<Executor, OpType>{
860
862
863 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
864
865 AddRepoLogic( RepoManagerPtrType &&repoMgrRef, RepoInfo &&info, ProgressObserverRef &&myProgress )
866 : _repoMgrRef( std::move(repoMgrRef) )
867 , _info( std::move(info) )
868 , _myProgress ( std::move(myProgress) )
869 {}
870
871 MaybeAsyncRef<expected<RepoInfo> > execute() {
872 using namespace zyppng::operators;
873
874 return assert_alias(_info)
875 | and_then([this]( ) {
876
877 MIL << "Try adding repo " << _info << std::endl;
878 ProgressObserver::setup( _myProgress, zypp::str::form(_("Adding repository '%s'"), _info.label().c_str()) );
879 ProgressObserver::start( _myProgress );
880
881 if ( _repoMgrRef->repos().find(_info) != _repoMgrRef->repos().end() )
883
884 // check the first url for now
885 if ( _repoMgrRef->options().probe )
886 {
887 DBG << "unknown repository type, probing" << std::endl;
888 return assert_urls(_info)
889 | and_then([this]{ return probeRepoType( _repoMgrRef->zyppContext(), _info ); })
890 | and_then([this]( zypp::repo::RepoType probedtype ) {
891
892 if ( probedtype == zypp::repo::RepoType::NONE )
894
895 RepoInfo tosave = _info;
896 tosave.setType(probedtype);
897 return make_expected_success(tosave);
898 });
899 }
900 return makeReadyResult( make_expected_success(_info) );
901 })
902 | inspect( operators::setProgress( _myProgress, 50 ) )
903 | and_then( [this]( RepoInfo tosave ){ return _repoMgrRef->addProbedRepository( tosave, tosave.type() ); })
904 | and_then( [this]( RepoInfo updated ) {
905 ProgressObserver::finish( _myProgress );
906 MIL << "done" << std::endl;
907 return expected<RepoInfo>::success( updated );
908 })
909 | or_else( [this]( std::exception_ptr e) {
911 MIL << "done" << std::endl;
913 })
914 ;
915 }
916
917 RepoManagerPtrType _repoMgrRef;
919 ProgressObserverRef _myProgress;
920 };
921 };
922
923 AsyncOpRef<expected<RepoInfo> > addRepository( AsyncRepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress )
924 {
925 return SimpleExecutor<AddRepoLogic, AsyncOp<expected<RepoInfo>>>::run( std::move(mgr), std::move(info), std::move(myProgress) );
926 }
927
928 expected<RepoInfo> addRepository( SyncRepoManagerRef mgr, const RepoInfo &info, ProgressObserverRef myProgress )
929 {
930 return SimpleExecutor<AddRepoLogic, SyncOp<expected<RepoInfo>>>::run( std::move(mgr), RepoInfo(info), std::move(myProgress) );
931 }
932
933 namespace {
934
935 template<typename Executor, class OpType>
936 struct AddReposLogic : public LogicBase<Executor, OpType>{
937
939 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
940
941 AddReposLogic( RepoManagerPtrType &&repoMgrRef, zypp::Url &&url, ProgressObserverRef &&myProgress )
942 : _repoMgrRef( std::move(repoMgrRef) )
943 , _url( std::move(url) )
944 , _myProgress ( std::move(myProgress) )
945 {}
946
947 MaybeAsyncRef<expected<void>> execute() {
948 using namespace zyppng::operators;
949
951 | and_then([this]( zypp::Url repoFileUrl ) { return readRepoFile( _repoMgrRef->zyppContext(), std::move(repoFileUrl) ); } )
952 | and_then([this]( std::list<RepoInfo> repos ) {
953
954 for ( std::list<RepoInfo>::const_iterator it = repos.begin();
955 it != repos.end();
956 ++it )
957 {
958 // look if the alias is in the known repos.
959 for_ ( kit, _repoMgrRef->repoBegin(), _repoMgrRef->repoEnd() )
960 {
961 if ( (*it).alias() == (*kit).alias() )
962 {
963 ERR << "To be added repo " << (*it).alias() << " conflicts with existing repo " << (*kit).alias() << std::endl;
965 }
966 }
967 }
968
969 std::string filename = zypp::Pathname(_url.getPathName()).basename();
970 if ( filename == zypp::Pathname() )
971 {
972 // TranslatorExplanation '%s' is an URL
973 return expected<void>::error(ZYPP_EXCPT_PTR(zypp::repo::RepoException(zypp::str::form( _("Invalid repo file name at '%s'"), _url.asString().c_str() ))));
974 }
975
976 const auto &options = _repoMgrRef->options();
977
978 // assert the directory exists
979 zypp::filesystem::assert_dir( options.knownReposPath );
980
981 zypp::Pathname repofile = _repoMgrRef->generateNonExistingName( options.knownReposPath, filename );
982 // now we have a filename that does not exists
983 MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << std::endl;
984
985 std::ofstream file(repofile.c_str());
986 if (!file)
987 {
988 // TranslatorExplanation '%s' is a filename
989 return expected<void>::error(ZYPP_EXCPT_PTR( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), repofile.c_str() ))));
990 }
991
992 for ( std::list<RepoInfo>::iterator it = repos.begin();
993 it != repos.end();
994 ++it )
995 {
996 MIL << "Saving " << (*it).alias() << std::endl;
997
998 const auto &rawCachePath = rawcache_path_for_repoinfo( options, *it );
999 if ( !rawCachePath ) return expected<void>::error(rawCachePath.error());
1000
1001 const auto &pckCachePath = packagescache_path_for_repoinfo( options, *it ) ;
1002 if ( !pckCachePath ) return expected<void>::error(pckCachePath.error());
1003
1004 it->dumpAsIniOn(file);
1005 it->setFilepath(repofile);
1006 it->setMetadataPath( *rawCachePath );
1007 it->setPackagesPath( *pckCachePath );
1008 _repoMgrRef->reposManip().insert(*it);
1009
1010 zypp::HistoryLog( _repoMgrRef->options().rootDir).addRepository(*it);
1011 }
1012
1013 MIL << "done" << std::endl;
1014 return expected<void>::success();
1015 });
1016 }
1017
1018 private:
1019 RepoManagerPtrType _repoMgrRef;
1021 ProgressObserverRef _myProgress;
1022 };
1023
1024 }
1025
1026 AsyncOpRef<expected<void>> addRepositories( AsyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress )
1027 {
1028 return SimpleExecutor<AddReposLogic, AsyncOp<expected<void>>>::run( std::move(mgr), std::move(url), std::move(myProgress) );
1029 }
1030
1031 expected<void> addRepositories( SyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress)
1032 {
1033 return SimpleExecutor<AddReposLogic, SyncOp<expected<void>>>::run( std::move(mgr), std::move(url), std::move(myProgress) );
1034 }
1035
1036
1037 namespace {
1038
1039 template<typename Executor, class OpType>
1040 struct RefreshGeoIpLogic : public LogicBase<Executor, OpType>{
1041 protected:
1042 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
1043
1044 public:
1045 using ZyppContextRefType = std::conditional_t<zyppng::detail::is_async_op_v<OpType>, ContextRef, SyncContextRef >;
1046 using ZyppContextType = typename ZyppContextRefType::element_type;
1047 using ProvideType = typename ZyppContextType::ProvideType;
1048 using MediaHandle = typename ProvideType::MediaHandle;
1049 using ProvideRes = typename ProvideType::Res;
1050
1051
1052 RefreshGeoIpLogic( ZyppContextRefType &&zyppCtx, RepoInfo::url_set &&urls )
1053 : _zyppCtx( std::move(zyppCtx) )
1054 , _urls( std::move(urls) )
1055 { }
1056
1057 MaybeAsyncRef<expected<void>> execute() {
1058
1059 using namespace zyppng::operators;
1060
1061 if ( !_zyppCtx->config().geoipEnabled() ) {
1062 MIL << "GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl;
1064 }
1065
1066 std::vector<std::string> hosts;
1067 for ( const auto &baseUrl : _urls ) {
1068 const auto &host = baseUrl.getHost();
1069 if ( zypp::any_of( _zyppCtx->config().geoipHostnames(), [&host]( const auto &elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) {
1070 hosts.push_back( host );
1071 break;
1072 }
1073 }
1074
1075 if ( hosts.empty() ) {
1076 MIL << "No configured geoip URL found, not updating geoip data" << std::endl;
1078 }
1079
1080 _geoIPCache = _zyppCtx->config().geoipCachePath();
1081
1082 if ( zypp::filesystem::assert_dir( _geoIPCache ) != 0 ) {
1083 MIL << "Unable to create cache directory for GeoIP." << std::endl;
1085 }
1086
1087 if ( !zypp::PathInfo(_geoIPCache).userMayRWX() ) {
1088 MIL << "No access rights for the GeoIP cache directory." << std::endl;
1090 }
1091
1092 // remove all older cache entries
1093 zypp::filesystem::dirForEachExt( _geoIPCache, []( const zypp::Pathname &dir, const zypp::filesystem::DirEntry &entry ) {
1094 if ( entry.type != zypp::filesystem::FT_FILE )
1095 return true;
1096
1097 zypp::PathInfo pi( dir/entry.name );
1098 auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t( pi.mtime() );
1099 if ( age < std::chrono::hours(24) )
1100 return true;
1101
1102 MIL << "Removing GeoIP file for " << entry.name << " since it's older than 24hrs." << std::endl;
1103 zypp::filesystem::unlink( dir/entry.name );
1104 return true;
1105 });
1106
1107 auto firstOfCb = [this]( std::string hostname ) {
1108
1109 // do not query files that are still there
1110 if ( zypp::PathInfo( _geoIPCache / hostname ).isExist() ) {
1111 MIL << "Skipping GeoIP request for " << hostname << " since a valid cache entry exists." << std::endl;
1112 return makeReadyResult(false);
1113 }
1114
1115 MIL << "Query GeoIP for " << hostname << std::endl;
1116
1117 zypp::Url url;
1118 try {
1119 url.setHost(hostname);
1120 url.setScheme("https");
1121
1122 } catch(const zypp::Exception &e ) {
1123 ZYPP_CAUGHT(e);
1124 MIL << "Ignoring invalid GeoIP hostname: " << hostname << std::endl;
1125 return makeReadyResult(false);
1126 }
1127
1128 // always https ,but attaching makes things easier
1129 return _zyppCtx->provider()->attachMedia( url, ProvideMediaSpec() )
1130 | and_then( [this]( MediaHandle provideHdl ) { return _zyppCtx->provider()->provide( provideHdl, "/geoip", ProvideFileSpec() ); })
1131 | inspect_err( [hostname]( const std::exception_ptr& ){ MIL << "Failed to query GeoIP from hostname: " << hostname << std::endl; } )
1132 | and_then( [hostname, this]( ProvideRes provideRes ) {
1133
1134 // here we got something from the server, we will stop after this hostname and mark the process as success()
1135
1136 constexpr auto writeHostToFile = []( const zypp::Pathname &fName, const std::string &host ){
1137 std::ofstream out;
1138 out.open( fName.asString(), std::ios_base::trunc );
1139 if ( out.is_open() ) {
1140 out << host << std::endl;
1141 } else {
1142 MIL << "Failed to create/open GeoIP cache file " << fName << std::endl;
1143 }
1144 };
1145
1146 std::string geoipMirror;
1147 try {
1148 zypp::xml::Reader reader( provideRes.file() );
1149 if ( reader.seekToNode( 1, "host" ) ) {
1150 const auto &str = reader.nodeText().asString();
1151
1152 // make a dummy URL to ensure the hostname is valid
1153 zypp::Url testUrl;
1154 testUrl.setHost(str);
1155 testUrl.setScheme("https");
1156
1157 if ( testUrl.isValid() ) {
1158 MIL << "Storing geoIP redirection: " << hostname << " -> " << str << std::endl;
1159 geoipMirror = str;
1160 }
1161
1162 } else {
1163 MIL << "No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl;
1164 }
1165 } catch ( const zypp::Exception &e ) {
1166 ZYPP_CAUGHT(e);
1167 MIL << "Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl;
1168 }
1169
1170 writeHostToFile( _geoIPCache / hostname, geoipMirror );
1171 return expected<void>::success(); // need to return a expected<> due to and_then requirements
1172 })
1173 | []( expected<void> res ) { return res.is_valid(); };
1174 };
1175
1176 return std::move(hosts)
1177 | firstOf( std::move(firstOfCb), false, zyppng::detail::ContinueUntilValidPredicate() )
1178 | []( bool foundGeoIP ){
1179
1180 if ( foundGeoIP ) {
1181 MIL << "Successfully queried GeoIP data." << std::endl;
1182 return expected<void>::success ();
1183 }
1184
1185 MIL << "Failed to query GeoIP data." << std::endl;
1186 return expected<void>::error( std::make_exception_ptr( zypp::Exception("No valid geoIP url found" )) );
1187
1188 };
1189 }
1190
1191 private:
1192 ZyppContextRefType _zyppCtx;
1195
1196 };
1197 }
1198
1200 {
1201 return SimpleExecutor<RefreshGeoIpLogic, AsyncOp<expected<void>>>::run( std::move(ctx), std::move(urls) );
1202 }
1203
1205 {
1206 return SimpleExecutor<RefreshGeoIpLogic, SyncOp<expected<void>>>::run( std::move(ctx), std::move(urls) );
1207 }
1208
1209
1210
1211}
Predicate predicate
Definition PoolQuery.cc:314
void resetDispose()
Set no dispose function.
std::string asString() const
Definition ByteArray.h:24
time_t ValueType
Definition Date.h:38
static Date now()
Return the current time.
Definition Date.h:78
Base class for Exception.
Definition Exception.h:147
std::string asUserString() const
Translated error message as string suitable for the user.
Definition Exception.cc:118
void addHistory(const std::string &msg_r)
Add some message text to the history.
Definition Exception.cc:176
void remember(const Exception &old_r)
Store an other Exception as history.
Definition Exception.cc:141
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
int close() override
Wait for the progamm to complete.
const std::string & command() const
The command we're executing.
std::vector< std::string > Arguments
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
Writing the zypp history file.
Definition HistoryLog.h:57
void addRepository(const RepoInfo &repo)
Log a newly added repository.
What is known about a repository.
Definition RepoInfo.h:72
repo::RepoType type() const
Type of repository,.
Definition RepoInfo.cc:602
Url url() const
Pars pro toto: The first repository url.
Definition RepoInfo.h:136
Pathname path() const
Repository path.
Definition RepoInfo.cc:635
void setType(const repo::RepoType &t)
set the repository type
Definition RepoInfo.cc:568
std::list< Url > url_set
Definition RepoInfo.h:108
Track changing files or directories.
Definition RepoStatus.h:41
Date timestamp() const
The time the data were changed the last time.
bool empty() const
Whether the status is empty (empty checksum)
Url manipulation class.
Definition Url.h:92
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:501
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition Url.cc:608
void setHost(const std::string &host)
Set the hostname or IP in the URL authority.
Definition Url.cc:752
bool isValid() const
Verifies the Url.
Definition Url.cc:493
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Definition Url.cc:672
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
Definition PathInfo.h:222
const char * c_str() const
String representation.
Definition Pathname.h:112
const std::string & asString() const
String representation.
Definition Pathname.h:93
std::string basename() const
Return the last component of this path.
Definition Pathname.h:130
Just inherits Exception to separate media exceptions.
Repository already exists and some unique attribute can't be duplicated.
Exception for repository handling.
std::string alias() const
unique identifier for this source.
thrown when it was impossible to determine this repo type.
xmlTextReader based interface to iterate xml streams.
Definition Reader.h:96
SignalProxy< void()> sigReadyRead()
Definition iodevice.cc:368
static Ptr create()
Definition process.cpp:49
SignalProxy< void(int)> sigFinished()
Definition process.cpp:294
static ProgressObserverRef makeSubTask(ProgressObserverRef parentProgress, float weight=1.0, const std::string &label=std::string(), int steps=100)
static void setup(ProgressObserverRef progress, const std::string &label=std::string(), int steps=100)
static void finish(ProgressObserverRef progress, ProgressObserver::FinishResult result=ProgressObserver::Success)
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
Definition provideres.h:36
const zypp::Pathname file() const
Definition provideres.cc:21
expected< RepoStatus > cacheStatus(const RepoInfo &info) const
static expected< void > touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
static zypp::repo::RepoType probeCache(const zypp::Pathname &path_r)
Probe Metadata in a local cache directory.
static expected< RepoStatus > metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
static expected success(ConsParams &&...params)
Definition expected.h:115
static expected error(ConsParams &&...params)
Definition expected.h:126
bool is_valid() const
Definition expected.h:141
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
Definition Arch.h:364
typename conditional< B, T, F >::type conditional_t
Definition TypeTraits.h:39
String related utilities and Regular expression matching.
RefreshCheckStatus
Possibly return state of RepoManager::checkIfToRefreshMetadata function.
@ REFRESH_NEEDED
refresh is needed
@ REPO_UP_TO_DATE
repository not changed
@ REPO_CHECK_DELAYED
refresh is delayed due to settings
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:324
int dirForEachExt(const Pathname &dir_r, const function< bool(const Pathname &, const DirEntry &)> &fnc_r)
Simiar to.
Definition PathInfo.cc:598
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
Definition Pool.cc:286
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
bool any_of(const Container &c, Fnc &&cb)
Definition Algorithm.h:76
AsyncOpRef< expected< repo::AsyncDownloadContextRef > > download(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver=nullptr)
AsyncOpRef< expected< zypp::RepoStatus > > repoStatus(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle)
AsyncOpRef< expected< zypp::repo::RepoType > > probeRepoType(ContextRef ctx, AsyncLazyMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath)
AsyncOpRef< expected< RepoInfo > > addRepository(AsyncRepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress)
AsyncOpRef< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< std::list< RepoInfo > > > readRepoFile(ContextRef ctx, zypp::Url repoFileUrl)
AsyncOpRef< expected< void > > refreshGeoIPData(ContextRef ctx, RepoInfo::url_set urls)
AsyncOpRef< expected< void > > addRepositories(AsyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > refreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > buildCache(repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
auto or_else(Fun &&function)
Definition expected.h:630
auto and_then(Fun &&function)
Definition expected.h:623
auto setProgress(ProgressObserverRef progressObserver, double progrValue, std::optional< std::string > newStr={})
auto inspect_err(Fun &&function)
Definition expected.h:644
auto inspect(Fun &&function)
Definition expected.h:637
auto mtry(Fun &&function)
Definition mtry.h:58
expected< void > assert_urls(const RepoInfo &info)
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
Definition asyncop.h:297
std::shared_ptr< AsyncOp< T > > AsyncOpRef
Definition asyncop.h:255
typename remove_smart_ptr< T >::type remove_smart_ptr_t
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition expected.h:397
expected< zypp::Pathname > rawcache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw cache path for a repository, this is usually /var/cache/zypp/alias.
expected< void > assert_alias(const RepoInfo &info)
Definition repomanager.h:57
auto firstOf(Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate=detail::ContinueUntilValidPredicate())
Definition algorithm.h:149
RepoManagerRef< SyncContextRef > SyncRepoManagerRef
Definition repomanager.h:48
expected< zypp::Pathname > solv_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the solv cache path for a repository.
zypp::RepoInfo RepoInfo
Definition repomanager.h:36
expected< std::list< RepoInfo > > repositories_in_file(const zypp::Pathname &file)
Reads RepoInfo's from a repo file.
RepoManagerRef< ContextRef > AsyncRepoManagerRef
Definition repomanager.h:51
expected< zypp::Pathname > packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
expected< zypp::Pathname > rawproductdata_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw product metadata path for a repository, this is inside the raw cache dir,...
RepoManagerPtrType _repoMgrRef
std::string _errdetail
zypp::Pathname _path
ZyppContextRefType _zyppContext
zypp::Url _url
RepoInfo _info
RepoInfo::url_set _urls
std::optional< zypp::Pathname > _targetPath
zypp::RepoInfo _repo
zypp::Pathname _productdatapath
RefreshContextRefType _refreshContext
zypp::Pathname _geoIPCache
zypp::repo::RepoException _error
zypp::RepoManagerFlags::CacheBuildPolicy _policy
ProgressObserverRef _progress
ProcessRef _proc
RefreshContextRefType _refCtx
ZyppContextRefType _zyppCtx
bool _gotMediaError
ProgressObserverRef _myProgress
LazyMediaHandle _medium
zypp::Pathname _mediarootpath
ProgressObserverRef _progressObserver
Listentry returned by readdir.
Definition PathInfo.h:502
Repository type enumeration.
Definition RepoType.h:29
static const RepoType YAST2
Definition RepoType.h:31
Type toEnum() const
Definition RepoType.h:49
static const RepoType RPMMD
Definition RepoType.h:30
static const RepoType NONE
Definition RepoType.h:33
static const RepoType RPMPLAINDIR
Definition RepoType.h:32
Functor replacing repository variables.
Convenient building of std::string with boost::format.
Definition String.h:253
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:212
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:444
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:440
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:428
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Definition Exception.h:436
#define PL_(MSG1, MSG2, N)
Definition Gettext.h:42
#define _(MSG)
Definition Gettext.h:39
#define DBG
Definition Logger.h:97
#define MIL
Definition Logger.h:98
#define ERR
Definition Logger.h:100
#define WAR
Definition Logger.h:99