libzypp 17.35.11
serviceswf.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include "serviceswf.h"
10
11
15#include <zypp-core/zyppng/pipelines/MTry>
16#include <zypp-core/zyppng/pipelines/Await>
17#include <zypp-core/zyppng/io/Process>
22#include <zypp/Target.h>
24
25#include <zypp/ng/Context>
29
30#undef ZYPP_BASE_LOGGER_LOGGROUP
31#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager"
32
34
35 using namespace zyppng::operators;
36
37
38 namespace {
39
41 // if file:// or dir:// path we must prefix with the root_r
42 const auto &scheme = serviceUrl.getScheme();
43 if ( !root.empty() && (scheme == "dir" || scheme == "file") ) {
44 serviceUrl.setPathName ( root / zypp::Pathname(serviceUrl.getPathName()) );
45 }
46 return serviceUrl;
47 }
48
49 template <class Executor, class OpType>
50 struct FetchRIMServiceLogic : public LogicBase<Executor, OpType>
51 {
52 protected:
54
55 public:
57 using RepoMgrRefType = RepoManagerRef<ZyppContextRefType>;
58
59 FetchRIMServiceLogic( ZyppContextRefType &&ctx, zypp::Pathname &&root_r, ServiceInfo &&service, ProgressObserverRef &&myProgress )
60 : _ctx( std::move(ctx) )
61 , _root_r( std::move(root_r) )
62 , _service( std::move(service) )
63 , _myProgress( std::move(myProgress) )
64 {}
65
66
68
69 using namespace zyppng::operators;
70
71 return zyppng::mtry( [this]{
72 // repoindex.xml must be fetched always without using cookies (bnc #573897)
74 serviceUrl.setQueryParam( "cookies", "0" );
76 })
77 | and_then( [this]( zypp::Url serviceUrl ){ return _ctx->provider()->attachMedia( serviceUrl, ProvideMediaSpec() ); })
78 | and_then( [this]( auto mediaHandle ) { return _ctx->provider()->provide( mediaHandle, "repo/repoindex.xml", ProvideFileSpec() ); } )
79 | and_then( [this]( auto provideResult ) {
80 try {
81
82 zypp::RepoInfoList repos;
83 auto callback = [&]( const zypp::RepoInfo &r) { repos.push_back(r); return true; };
84
86 _service.setProbedTtl( reader.ttl() ); // hack! Modifying the const Service to set parsed TTL
87
88 return make_expected_success( std::make_pair( _service, std::move(repos) ) );
89
90 } catch ( const zypp::Exception &e ) {
91 //Reader throws a bare exception, we need to translate it into something our calling
92 //code expects and handles (bnc#1116840)
93 ZYPP_CAUGHT ( e );
95 ex.remember( e );
97 }
98 });
99 }
100
101 private:
102 ZyppContextRefType _ctx;
105 ProgressObserverRef _myProgress;
106 };
107
108
109 template <class Executor, class OpType>
110 struct FetchPluginServiceLogic : public LogicBase<Executor, OpType>
111 {
112 protected:
114
115 public:
117 using RepoMgrRefType = RepoManagerRef<ZyppContextRefType>;
119
120 FetchPluginServiceLogic( ZyppContextRefType &&ctx, zypp::Pathname &&root_r, ServiceInfo &&service, ProgressObserverRef &&myProgress )
121 : _ctx( std::move(ctx) )
122 , _root_r( std::move(root_r) )
123 , _service( std::move(service) )
124 , _myProgress( std::move(myProgress) )
125 {}
126
127
128 MaybeAsyncRef<Ret> execute() {
129 using namespace zyppng::operators;
130
131 // bsc#1080693: Service script needs to be executed chrooted to the RepoManagers rootDir.
132 // The service is not aware of the rootDir, so it's explicitly passed and needs to be
133 // stripped from the URLs path.
134 auto stripped = zypp::Pathname::stripprefix( _root_r, _service.url().getPathName() ).asString();
135
136 return executor()->runPlugin( std::move(stripped) )
137 | and_then( [this]( int exitCode ) {
138
139 if ( exitCode != 0 ) {
140 // ServicePluginInformalException:
141 // Ignore this error but we'd like to report it somehow...
142 ERR << "Capture plugin error:[" << std::endl << _stderrBuf << std::endl << ']' << std::endl;
143 return Ret::error( ZYPP_EXCPT_PTR( zypp::repo::ServicePluginInformalException( _service, _stderrBuf ) ) );
144 }
145
146 try {
147 zypp::RepoInfoList repos;
148 auto callback = [&]( const zypp::RepoInfo &r) { repos.push_back(r); return true; };
149
150 std::stringstream buffer( _stdoutBuf );
151 zypp::parser::RepoFileReader parser( buffer, callback );
152 return make_expected_success( std::make_pair( _service, std::move(repos) ) );
153
154 } catch (...) {
155 return Ret::error( std::current_exception () );
156 }
157 });
158 }
159
160 protected:
161 ZyppContextRefType _ctx;
164 ProgressObserverRef _myProgress;
165 std::string _stdoutBuf;
166 std::string _stderrBuf;
167 };
168
169
170 struct SyncFetchPluginService : FetchPluginServiceLogic<SyncFetchPluginService, SyncOp< expected< std::pair<zypp::ServiceInfo, RepoInfoList> >>>
171 {
172 using FetchPluginServiceLogic::FetchPluginServiceLogic;
173 expected<int> runPlugin( std::string command ) {
174 try {
175 std::stringstream buffer;
176
178 args.reserve( 3 );
179 args.push_back( "/bin/sh" );
180 args.push_back( "-c" );
181 args.push_back( command );
182
184 prog >> buffer;
185 _stdoutBuf = buffer.str();
186
187 int retCode = prog.close();
188 if ( retCode != 0 ) {
189 // ServicePluginInformalException:
190 // Ignore this error but we'd like to report it somehow...
191 prog.stderrGetUpTo( _stderrBuf, '\0' );
192 }
194 } catch ( ... ) {
196 }
197 }
198 };
199
200 struct ASyncFetchPluginService : FetchPluginServiceLogic<ASyncFetchPluginService, AsyncOp< expected< std::pair<zypp::ServiceInfo, RepoInfoList> >>>
201 {
202 using FetchPluginServiceLogic::FetchPluginServiceLogic;
203 AsyncOpRef<expected<int>> runPlugin( std::string command ) {
204 using namespace zyppng::operators;
205
206 const char *args[] = {
207 "/bin/sh",
208 "-c",
209 command.c_str(),
210 nullptr
211 };
212
214 pluginProcess->setChroot ( _root_r );
215
216 // make sure our process is actually running, if not finalize right away
217 if ( !pluginProcess->start( args ) || !pluginProcess->isRunning () ) {
218 return makeReadyResult ( finalize( std::move(pluginProcess) ) );
219 }
220
221 return std::move(pluginProcess)
222 | await<Process>( &Process::sigFinished ) // wait for finished sig
223 | [this]( ProcessRef proc ) { return finalize( std::move(proc) ); };
224 }
225
226 expected<int> finalize( ProcessRef proc ) {
227 if ( proc->isRunning () ) {
228 proc->stop ( SIGKILL );
229 return expected<int>::error( ZYPP_EXCPT_PTR( zypp::Exception("Bug, plugin process was still running after receiving sigFinished")) );
230 }
231
232 _stdoutBuf = proc->readAll( Process::StdOut ).asString();
233 if ( proc->exitStatus() != 0 ) {
234 _stderrBuf = proc->readAll( Process::StdErr ).asString();
235 }
236
237 return make_expected_success ( proc->exitStatus () );
238 }
239 };
240
241
242 }
243
245 {
246 if ( service.type() == zypp::repo::ServiceType::PLUGIN )
247 return ASyncFetchPluginService::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) );
248 else
249 return SimpleExecutor<FetchRIMServiceLogic, AsyncOp<expected< std::pair<zypp::ServiceInfo, RepoInfoList> >>>::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) );
250 }
251
253 {
254 if ( service.type() == zypp::repo::ServiceType::PLUGIN )
255 return SyncFetchPluginService::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) );
256 else
257 return SimpleExecutor<FetchRIMServiceLogic, SyncOp<expected< std::pair<zypp::ServiceInfo, RepoInfoList> >>>::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) );
258 }
259
260
261
262 namespace {
263 template<typename ContextRefType>
264 auto probeServiceLogic( ContextRefType ctx, const zypp::Url &url ) {
265
266 constexpr bool isAsync = std::is_same_v<ContextRefType, ContextRef>;
269
270 return ctx->provider()->attachMedia( url, ProvideMediaSpec() )
271 | and_then( [ctx]( MediaHandle medium ) { return ctx->provider()->provide( medium, "/repo/repoindex.xml", ProvideFileSpec().setCheckExistsOnly()); } )
272 | [url]( expected<ProvideRes> result ) {
273 if ( result )
274 return expected<zypp::repo::ServiceType>::success( zypp::repo::ServiceType::RIS );
275
276 try{
277 std::rethrow_exception( result.error() );
278 } catch ( const zypp::media::MediaFileNotFoundException &e ) {
279 // fall through
280 } catch ( const zypp::media::MediaException &e ) {
281 ZYPP_CAUGHT(e);
282 // TranslatorExplanation '%s' is an URL
283 zypp::repo::RepoException enew(zypp::str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
284 enew.remember(e);
286 }
287 catch ( const zypp::Exception &e ) {
288 ZYPP_CAUGHT(e);
289 // TranslatorExplanation '%s' is an URL
290 zypp::Exception enew(zypp::str::form( _("Unknown error reading from '%s'"), url.asString().c_str() ));
291 enew.remember(e);
293 }
294 catch ( ... ) {
295 // TranslatorExplanation '%s' is an URL
296 zypp::Exception enew(zypp::str::form( _("Unknown error reading from '%s'"), url.asString().c_str() ));
297 enew.remember( std::current_exception() );
299 }
300
301 return expected<zypp::repo::ServiceType>::success( zypp::repo::ServiceType::NONE );
302 };
303 }
304 }
305
310
315
316 namespace {
317 template <class Executor, class OpType>
318 struct RefreshServiceLogic : public LogicBase<Executor, OpType>
319 {
320 protected:
322
323 public:
325 using RepoMgrRefType = RepoManagerRef<ZyppContextRefType>;
326 using Ret = expected<void>;
327
328 RefreshServiceLogic( RepoMgrRefType &&repoMgr, zypp::ServiceInfo &&info, zypp::RepoManager::RefreshServiceOptions options )
329 : _repoMgr( std::move(repoMgr) )
330 , _service( std::move(info) )
331 , _options(options)
332 { }
333
335 // if the type is unknown, try probing.
336 if ( _service.type() == zypp::repo::ServiceType::NONE ) {
337
338 return probeServiceType( _repoMgr->zyppContext(), adaptServiceUrlToChroot( _service.url(), _repoMgr->options().rootDir ) )
339 | and_then( [this]( zypp::repo::ServiceType type ){
340 _service.setProbedType( type ); // lazy init!
341 _serviceModified = true;
343 } );
344
345 }
347 }
348
349 MaybeAsyncRef<Ret> execute() {
350
351 try {
352 assert_alias( _service ).unwrap();
353 assert_url( _service ).unwrap();
354 } catch (...) {
355 return makeReadyResult(Ret::error(ZYPP_FWD_CURRENT_EXCPT()));
356 }
357
358 MIL << "Going to refresh service '" << _service.alias() << "', url: " << _service.url() << ", opts: " << _options << std::endl;
359
361 {
362 // Service defines a TTL; maybe we can re-use existing data without refresh.
363 zypp::Date lrf = _service.lrf();
364 if ( lrf )
365 {
367 if ( lrf <= now )
368 {
369 if ( (lrf+=_service.ttl()) > now ) // lrf+= !
370 {
371 MIL << "Skip: '" << _service.alias() << "' metadata valid until " << lrf << std::endl;
372 return makeReadyResult( Ret::success() );
373 }
374 }
375 else
376 WAR << "Force: '" << _service.alias() << "' metadata last refresh in the future: " << lrf << std::endl;
377 }
378 }
379
381
382 return probeServiceIfNeeded () // if the type is unknown, try probing.
383 | and_then( [this]() {
384 // FIXME bsc#1080693: Shortcoming of (plugin)services (and repos as well) is that they
385 // are not aware of the RepoManagers rootDir. The service url, as created in known_services,
386 // contains the full path to the script. The script however has to be executed chrooted.
387 // Repos would need to know the RepoMangers rootDir to use the correct vars.d to replace
388 // repos variables. Until RepoInfoBase is aware if the rootDir, we need to explicitly pass it
389 // to ServiceRepos.
390 return fetchRepoListfromService( _repoMgr->zyppContext(), _repoMgr->options().rootDir, _service, nullptr );
391 } )
392 | [this]( expected<std::pair<zypp::ServiceInfo, RepoInfoList>> serviceReposExp ) {
393
394 if ( !serviceReposExp ) {
395 try {
396 std::rethrow_exception( serviceReposExp.error() );
397
399 /* ignore ServicePluginInformalException and throw later */
401 } catch ( ... ) {
402 // all other errors cancel the operation
403 return Ret::error( ZYPP_FWD_CURRENT_EXCPT() );
404 }
405 }
406
407 std::pair<zypp::ServiceInfo, RepoInfoList> serviceRepos = serviceReposExp.is_valid() ? std::move( serviceReposExp.get() ) : std::make_pair( _service, RepoInfoList{} );
408
409 // get target distro identifier
410 std::string servicesTargetDistro = _repoMgr->options().servicesTargetDistro;
411 if ( servicesTargetDistro.empty() ) {
412 servicesTargetDistro = zypp::Target::targetDistribution( zypp::Pathname() );
413 }
414 DBG << "ServicesTargetDistro: " << servicesTargetDistro << std::endl;
415
416 // filter repos by target distro
417 RepoCollector collector( servicesTargetDistro );
418 std::for_each( serviceRepos.second.begin(), serviceRepos.second.end(), [&]( const auto &r ){ collector.collect(r); } );
419
420 if ( _service.ttl () != serviceRepos.first.ttl () ) {
421 // repoindex.xml changed ttl
422 if ( !serviceRepos.first.ttl() )
423 serviceRepos.first.setLrf( zypp::Date() ); // don't need lrf when zero ttl
424
425 _serviceModified = true;
426 }
427
428 // service was maybe updated
429 _service = serviceRepos.first;
430
432 // On the fly remember the new repo states as defined the reopoindex.xml.
433 // Move into ServiceInfo later.
435
436 // set service alias and base url for all collected repositories
437 for_( it, collector.repos.begin(), collector.repos.end() )
438 {
439 // First of all: Prepend service alias:
440 it->setAlias( zypp::str::form( "%s:%s", _service.alias().c_str(), it->alias().c_str() ) );
441 // set reference to the parent service
442 it->setService( _service.alias() );
443
444 // remember the new parsed repo state
445 newRepoStates[it->alias()] = *it;
446
447 // - If the repo url was not set by the repoindex parser, set service's url.
448 // - Libzypp currently has problem with separate url + path handling so just
449 // append a path, if set, to the baseurls
450 // - Credentials in the url authority will be extracted later, either if the
451 // repository is added or if we check for changed urls.
452 zypp::Pathname path;
453 if ( !it->path().empty() )
454 {
455 if ( it->path() != "/" )
456 path = it->path();
457 it->setPath("");
458 }
459
460 if ( it->baseUrlsEmpty() )
461 {
462 zypp::Url url( _service.rawUrl() );
463 if ( !path.empty() )
464 url.setPathName( url.getPathName() / path );
465 it->setBaseUrl( std::move(url) );
466 }
467 else if ( !path.empty() )
468 {
469 RepoInfo::url_set urls( it->rawBaseUrls() );
470 for ( zypp::Url & url : urls )
471 {
472 url.setPathName( url.getPathName() / path );
473 }
474 it->setBaseUrls( std::move(urls) );
475 }
476 }
477
479 // Now compare collected repos with the ones in the system...
480 //
481 RepoInfoList oldRepos;
482 _repoMgr->getRepositoriesInService( _service.alias(), std::back_inserter( oldRepos ) );
483
485 // find old repositories to remove...
486 for_( oldRepo, oldRepos.begin(), oldRepos.end() )
487 {
488 if ( ! foundAliasIn( oldRepo->alias(), collector.repos ) )
489 {
490 if ( oldRepo->enabled() )
491 {
492 // Currently enabled. If this was a user modification remember the state.
493 const auto & last = _service.repoStates().find( oldRepo->alias() );
494 if ( last != _service.repoStates().end() && ! last->second.enabled )
495 {
496 DBG << "Service removes user enabled repo " << oldRepo->alias() << std::endl;
497 _service.addRepoToEnable( oldRepo->alias() );
498 _serviceModified = true;
499 }
500 else
501 DBG << "Service removes enabled repo " << oldRepo->alias() << std::endl;
502 }
503 else
504 DBG << "Service removes disabled repo " << oldRepo->alias() << std::endl;
505
506 auto remRes = _repoMgr->removeRepository( *oldRepo );
507 if ( !remRes ) return Ret::error( remRes.error() );
508 }
509 }
510
511
513 // create missing repositories and modify existing ones if needed...
514 zypp::UrlCredentialExtractor urlCredentialExtractor( _repoMgr->options().rootDir ); // To collect any credentials stored in repo URLs
515 for_( it, collector.repos.begin(), collector.repos.end() )
516 {
517 // User explicitly requested the repo being enabled?
518 // User explicitly requested the repo being disabled?
519 // And hopefully not both ;) If so, enable wins.
520
521 zypp::TriBool toBeEnabled( zypp::indeterminate ); // indeterminate - follow the service request
522 DBG << "Service request to " << (it->enabled()?"enable":"disable") << " service repo " << it->alias() << std::endl;
523
525 {
526 DBG << "Opt RefreshService_restoreStatus " << it->alias() << std::endl;
527 // this overrides any pending request!
528 // Remove from enable request list.
529 // NOTE: repoToDisable is handled differently.
530 // It gets cleared on each refresh.
531 _service.delRepoToEnable( it->alias() );
532 // toBeEnabled stays indeterminate!
533 }
534 else
535 {
536 if ( _service.repoToEnableFind( it->alias() ) )
537 {
538 DBG << "User request to enable service repo " << it->alias() << std::endl;
539 toBeEnabled = true;
540 // Remove from enable request list.
541 // NOTE: repoToDisable is handled differently.
542 // It gets cleared on each refresh.
543 _service.delRepoToEnable( it->alias() );
544 _serviceModified = true;
545 }
546 else if ( _service.repoToDisableFind( it->alias() ) )
547 {
548 DBG << "User request to disable service repo " << it->alias() << std::endl;
549 toBeEnabled = false;
550 }
551 }
552
553 RepoInfoList::iterator oldRepo( findAlias( it->alias(), oldRepos ) );
554 if ( oldRepo == oldRepos.end() )
555 {
556 // Not found in oldRepos ==> a new repo to add
557
558 // Make sure the service repo is created with the appropriate enablement
559 if ( ! indeterminate(toBeEnabled) )
560 it->setEnabled( ( bool ) toBeEnabled );
561
562 DBG << "Service adds repo " << it->alias() << " " << (it->enabled()?"enabled":"disabled") << std::endl;
563 const auto &addRes = _repoMgr->addRepository( *it );
564 if (!addRes) return Ret::error( addRes.error() );
565 }
566 else
567 {
568 // ==> an exising repo to check
569 bool oldRepoModified = false;
570
571 if ( indeterminate(toBeEnabled) )
572 {
573 // No user request: check for an old user modificaton otherwise follow service request.
574 // NOTE: Assert toBeEnabled is boolean afterwards!
575 if ( oldRepo->enabled() == it->enabled() )
576 toBeEnabled = it->enabled(); // service requests no change to the system
578 {
579 toBeEnabled = it->enabled(); // RefreshService_restoreStatus forced
580 DBG << "Opt RefreshService_restoreStatus " << it->alias() << " forces " << (toBeEnabled?"enabled":"disabled") << std::endl;
581 }
582 else
583 {
584 const auto & last = _service.repoStates().find( oldRepo->alias() );
585 if ( last == _service.repoStates().end() || last->second.enabled != it->enabled() )
586 toBeEnabled = it->enabled(); // service request has changed since last refresh -> follow
587 else
588 {
589 toBeEnabled = oldRepo->enabled(); // service request unchaned since last refresh -> keep user modification
590 DBG << "User modified service repo " << it->alias() << " may stay " << (toBeEnabled?"enabled":"disabled") << std::endl;
591 }
592 }
593 }
594
595 // changed enable?
596 if ( toBeEnabled == oldRepo->enabled() )
597 {
598 DBG << "Service repo " << it->alias() << " stays " << (oldRepo->enabled()?"enabled":"disabled") << std::endl;
599 }
600 else if ( toBeEnabled )
601 {
602 DBG << "Service repo " << it->alias() << " gets enabled" << std::endl;
603 oldRepo->setEnabled( true );
604 oldRepoModified = true;
605 }
606 else
607 {
608 DBG << "Service repo " << it->alias() << " gets disabled" << std::endl;
609 oldRepo->setEnabled( false );
610 oldRepoModified = true;
611 }
612
613 // all other attributes follow the service request:
614
615 // changed name (raw!)
616 if ( oldRepo->rawName() != it->rawName() )
617 {
618 DBG << "Service repo " << it->alias() << " gets new NAME " << it->rawName() << std::endl;
619 oldRepo->setName( it->rawName() );
620 oldRepoModified = true;
621 }
622
623 // changed autorefresh
624 if ( oldRepo->autorefresh() != it->autorefresh() )
625 {
626 DBG << "Service repo " << it->alias() << " gets new AUTOREFRESH " << it->autorefresh() << std::endl;
627 oldRepo->setAutorefresh( it->autorefresh() );
628 oldRepoModified = true;
629 }
630
631 // changed priority?
632 if ( oldRepo->priority() != it->priority() )
633 {
634 DBG << "Service repo " << it->alias() << " gets new PRIORITY " << it->priority() << std::endl;
635 oldRepo->setPriority( it->priority() );
636 oldRepoModified = true;
637 }
638
639 // changed url?
640 {
641 RepoInfo::url_set newUrls( it->rawBaseUrls() );
642 urlCredentialExtractor.extract( newUrls ); // Extract! to prevent passwds from disturbing the comparison below
643 if ( oldRepo->rawBaseUrls() != newUrls )
644 {
645 DBG << "Service repo " << it->alias() << " gets new URLs " << newUrls << std::endl;
646 oldRepo->setBaseUrls( std::move(newUrls) );
647 oldRepoModified = true;
648 }
649 }
650
651 // changed gpg check settings?
652 // ATM only plugin services can set GPG values.
653 if ( _service.type() == zypp::repo::ServiceType::PLUGIN )
654 {
655 zypp::TriBool ogpg[3]; // Gpg RepoGpg PkgGpg
657 oldRepo->getRawGpgChecks( ogpg[0], ogpg[1], ogpg[2] );
658 it-> getRawGpgChecks( ngpg[0], ngpg[1], ngpg[2] );
659 #define Z_CHKGPG(I,N) \
660 if ( ! sameTriboolState( ogpg[I], ngpg[I] ) ) \
661 { \
662 DBG << "Service repo " << it->alias() << " gets new "#N"Check " << ngpg[I] << std::endl; \
663 oldRepo->set##N##Check( ngpg[I] ); \
664 oldRepoModified = true; \
665 }
666 Z_CHKGPG( 0, Gpg );
667 Z_CHKGPG( 1, RepoGpg );
668 Z_CHKGPG( 2, PkgGpg );
669 #undef Z_CHKGPG
670 }
671
672 // save if modified:
673 if ( oldRepoModified )
674 {
675 auto modRes = _repoMgr->modifyRepository( oldRepo->alias(), *oldRepo );
676 if ( !modRes ) return Ret::error( modRes.error() );
677 }
678 }
679 }
680
681 // Unlike reposToEnable, reposToDisable is always cleared after refresh.
682 if ( ! _service.reposToDisableEmpty() )
683 {
684 _service.clearReposToDisable();
685 _serviceModified = true;
686 }
687
688 // Remember original service request for next refresh
689 if ( _service.repoStates() != newRepoStates )
690 {
691 _service.setRepoStates( std::move(newRepoStates) );
692 _serviceModified = true;
693 }
694
696 // save service if modified: (unless a plugin service)
697 if ( _service.type() != zypp::repo::ServiceType::PLUGIN )
698 {
699 if ( _service.ttl() )
700 {
701 _service.setLrf( zypp::Date::now() ); // remember last refresh
702 _serviceModified = true; // or use a cookie file
703 }
704
705 if ( _serviceModified )
706 {
707 // write out modified service file.
708 auto modRes = _repoMgr->modifyService( _service.alias(), _service );
709 if ( !modRes ) return Ret::error( modRes.error() );
710 }
711 }
712
713 if ( _informalError ) {
714 return Ret::error( std::make_exception_ptr (_informalError.value()) );
715 }
716
717 return Ret::success( );
718 };
719 }
720
721
722 RepoMgrRefType _repoMgr;
725
726 // NOTE: It might be necessary to modify and rewrite the service info.
727 // Either when probing the type, or when adjusting the repositories
728 // enable/disable state.:
729 bool _serviceModified = false;
730
731 // FIXME Ugly hack: ServiceRepos may throw ServicePluginInformalException
732 // which is actually a notification. Using an exception for this
733 // instead of signal/callback is bad. Needs to be fixed here, in refreshServices()
734 // and in zypper.
735 std::optional<zypp::repo::ServicePluginInformalException> _informalError;
736 };
737 }
738
743
748
749}
Interface of repoindex.xml file reader.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
Store and operate on date (time_t).
Definition Date.h:33
static Date now()
Return the current time.
Definition Date.h:78
Base class for Exception.
Definition Exception.h:147
ExternalProgram extended to offer reading programs stderr.
std::vector< std::string > Arguments
What is known about a repository.
Definition RepoInfo.h:72
std::list< Url > url_set
Definition RepoInfo.h:108
Service data.
Definition ServiceInfo.h:37
repo::ServiceType type() const
Service type.
std::map< std::string, RepoState > RepoStates
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Definition Target.cc:102
Extract credentials in Url authority and store them via CredentialManager.
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 setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition Url.cc:768
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
Definition Pathname.cc:281
bool empty() const
Test for an empty path.
Definition Pathname.h:116
Just inherits Exception to separate media exceptions.
Read repository data from a .repo file.
Reads through a repoindex.xml file and collects repositories.
Exception for repository handling.
Service plugin has trouble providing the metadata but this should not be treated as error.
static Ptr create()
Definition process.cpp:49
SignalProxy< void(int)> sigFinished()
Definition process.cpp:294
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
Definition provideres.h:36
static expected success(ConsParams &&...params)
Definition expected.h:115
static expected error(ConsParams &&...params)
Definition expected.h:126
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
Definition Arch.h:364
typename conditional< B, T, F >::type conditional_t
Definition TypeTraits.h:39
RefreshServiceFlags RefreshServiceOptions
Options tuning RefreshService.
@ RefreshService_restoreStatus
Force restoring repo enabled/disabled status.
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:30
AsyncOpRef< expected< void > > refreshService(AsyncRepoManagerRef repoMgr, ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options)
AsyncOpRef< expected< std::pair< zypp::ServiceInfo, RepoInfoList > > > fetchRepoListfromService(ContextRef ctx, zypp::Pathname root_r, ServiceInfo service, ProgressObserverRef myProgress)
AsyncOpRef< expected< zypp::repo::ServiceType > > probeServiceType(ContextRef ctx, const zypp::Url &url)
auto and_then(Fun &&function)
Definition expected.h:623
Exp mtry(F &&f, Args &&...args)
Definition mtry.h:28
expected< void > assert_url(const ServiceInfo &info)
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
Definition asyncop.h:297
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition expected.h:397
expected< void > assert_alias(const RepoInfo &info)
Definition repomanager.h:57
RepoManagerRef< SyncContextRef > SyncRepoManagerRef
Definition repomanager.h:48
RepoManagerRef< ContextRef > AsyncRepoManagerRef
Definition repomanager.h:51
Iterator findAlias(const std::string &alias_r, Iterator begin_r, Iterator end_r)
Find alias_r in repo/service container.
Definition repomanager.h:98
bool foundAliasIn(const std::string &alias_r, Iterator begin_r, Iterator end_r)
Check if alias_r is present in repo/service container.
Definition repomanager.h:84
ProgressObserverRef _myProgress
DlContextRefType _ctx
Definition rpmmd.cc:69
RepoMgrRefType _repoMgr
bool _serviceModified
#define Z_CHKGPG(I, N)
zypp::Pathname _root_r
std::optional< zypp::repo::ServicePluginInformalException > _informalError
std::string _stderrBuf
std::string _stdoutBuf
ServiceInfo _service
zypp::RepoManager::RefreshServiceOptions _options
static constexpr RefreshServiceBit RefreshService_restoreStatus
Definition RepoManager.h:92
static constexpr RefreshServiceBit RefreshService_forceRefresh
Definition RepoManager.h:93
RepoManagerFlags::RefreshServiceFlags RefreshServiceOptions
Options tuning RefreshService.
Definition RepoManager.h:98
Service type enumeration.
Definition ServiceType.h:27
Simple callback to collect the results.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#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 _(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