libzypp 17.32.2
RepoManager.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
13#include <cstdlib>
14#include <iostream>
15#include <fstream>
16#include <list>
17#include <map>
18#include <algorithm>
19#include <chrono>
20
21#include <zypp-core/base/InputStream>
22#include <zypp-core/Digest.h>
23#include <zypp/base/LogTools.h>
24#include <zypp/base/Gettext.h>
25#include <zypp-core/base/DefaultIntegral>
26#include <zypp/base/Function.h>
27#include <zypp/base/Regex.h>
28#include <zypp/PathInfo.h>
29#include <zypp/TmpPath.h>
30
31#include <zypp/ServiceInfo.h>
33#include <zypp/RepoManager.h>
36
38#include <zypp-media/auth/CredentialManager>
39#include <zypp-media/MediaException>
40#include <zypp/MediaSetAccess.h>
41#include <zypp/ExternalProgram.h>
42#include <zypp/ManagedFile.h>
43
48
49#include <zypp/Target.h> // for Target::targetDistribution() for repo index services
50#include <zypp/ZYppFactory.h> // to get the Target from ZYpp instance
51#include <zypp/HistoryLog.h> // to write history :O)
52
53#include <zypp/ZYppCallbacks.h>
54
55#include "sat/Pool.h"
57#include <zypp/base/Algorithm.h>
58
59
60// zyppng related includes
61#include <zypp-core/zyppng/pipelines/Lift>
65
66
67using std::endl;
68using std::string;
69using namespace zypp::repo;
70
71#define OPT_PROGRESS const ProgressData::ReceiverFnc & = ProgressData::ReceiverFnc()
72
74namespace zypp
75{
77 namespace env
78 {
81 {
82 const char * env = getenv("ZYPP_PLUGIN_APPDATA_FORCE_COLLECT");
83 return( env && str::strToBool( env, true ) );
84 }
85 } // namespace env
87
88 namespace
89 {
93 class MediaMounter
94 {
95 public:
97 MediaMounter( const Url & url_r )
98 {
100 _mid = mediamanager.open( url_r );
101 mediamanager.attach( _mid );
102 }
103
104 MediaMounter(const MediaMounter &) = delete;
105 MediaMounter(MediaMounter &&) = delete;
106 MediaMounter &operator=(const MediaMounter &) = delete;
107 MediaMounter &operator=(MediaMounter &&) = delete;
108
110 ~MediaMounter()
111 {
113 mediamanager.release( _mid );
114 mediamanager.close( _mid );
115 }
116
121 Pathname getPathName( const Pathname & path_r = Pathname() ) const
122 {
124 return mediamanager.localPath( _mid, path_r );
125 }
126
127 private:
129 };
131 } // namespace
133
134 std::list<RepoInfo> readRepoFile( const Url & repo_file )
135 {
138
140 DBG << "reading repo file " << repoFileUrl << ", local path: " << local << endl;
141
143 }
144
151 {
152 public:
154 : RepoManagerBaseImpl(std::move(opt)),
155 _pluginRepoverification(_options.pluginsPath / "repoverification",
156 _options.rootDir) {
157 init_knownServices();
158 init_knownRepositories();
159 }
160
161 Impl(const Impl &) = default;
162 Impl(Impl &&) = delete;
163 Impl &operator=(const Impl &) = delete;
164 Impl &operator=(Impl &&) = delete;
165
166 ~Impl() override
167 {
168 // trigger appdata refresh if some repos change
169 if ( ( _reposDirty || env::ZYPP_PLUGIN_APPDATA_FORCE_COLLECT() )
170 && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) )
171 {
172 try {
173 std::list<Pathname> entries;
174 filesystem::readdir( entries, _options.pluginsPath/"appdata", false );
175 if ( ! entries.empty() )
176 {
178 cmd.push_back( "<" ); // discard stdin
179 cmd.push_back( ">" ); // discard stdout
180 cmd.push_back( "PROGRAM" ); // [2] - fix index below if changing!
181 for ( const auto & rinfo : repos() )
182 {
183 if ( ! rinfo.enabled() )
184 continue;
185 cmd.push_back( "-R" );
186 cmd.push_back( rinfo.alias() );
187 cmd.push_back( "-t" );
188 cmd.push_back( rinfo.type().asString() );
189 cmd.push_back( "-p" );
190 cmd.push_back( (rinfo.metadataPath()/rinfo.path()).asString() ); // bsc#1197684: path to the repodata/ directory inside the cache
191 }
192
193 for_( it, entries.begin(), entries.end() )
194 {
195 PathInfo pi( *it );
196 //DBG << "/tmp/xx ->" << pi << endl;
197 if ( pi.isFile() && pi.userMayRX() )
198 {
199 // trigger plugin
200 cmd[2] = pi.asString(); // [2] - PROGRAM
201 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
202 }
203 }
204 }
205 }
206 catch (...) {} // no throw in dtor
207 }
208 }
209
210 public:
211 RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo & info, const Url & url, RawMetadataRefreshPolicy policy );
212
214
215 void buildCache( const RepoInfo & info, CacheBuildPolicy policy, OPT_PROGRESS );
216
217 repo::RepoType probe( const Url & url, const Pathname & path = Pathname() ) const;
218
219 void loadFromCache( const RepoInfo & info, OPT_PROGRESS );
220
221 void addRepository( const RepoInfo & info, OPT_PROGRESS );
222
223 void addRepositories( const Url & url, OPT_PROGRESS );
224
225 void removeRepository ( const RepoInfo & info, OPT_PROGRESS ) override;
226
227 public:
228 void refreshServices( const RefreshServiceOptions & options_r );
229
230 void refreshService( const std::string & alias, const RefreshServiceOptions & options_r );
232 { refreshService( service.alias(), options_r ); }
233
234 repo::ServiceType probeService( const Url & url ) const;
235
237
238 private:
240
241 private:
242 friend Impl * rwcowClone<Impl>( const Impl * rhs );
244 Impl * clone() const
245 { return new Impl( *this ); }
246 };
248
250 inline std::ostream & operator<<( std::ostream & str, const RepoManager::Impl & obj )
251 { return str << "RepoManager::Impl"; }
252
253 RepoManager::RefreshCheckStatus RepoManager::Impl::checkIfToRefreshMetadata( const RepoInfo & info, const Url & url, RawMetadataRefreshPolicy policy )
254 {
255 using namespace zyppng::operators;
256 using zyppng::operators::operator|;
257
258 refreshGeoIPData( { url } );
259
260 auto ctx = zyppng::SyncContext::create();
261 auto res = zyppng::repo::SyncRefreshContext::create( ctx, info, _options )
262 | and_then( [&]( zyppng::repo::SyncRefreshContextRef &&refCtx ) {
263 refCtx->setPolicy ( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
264 return ctx->provider()->attachMedia( url, zyppng::ProvideMediaSpec() )
265 | and_then( [ r = std::move(refCtx) ]( auto &&mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::checkIfToRefreshMetadata ( std::move(r), mediaHandle, nullptr ); } );
266 } );
267
268 if ( !res ) {
269 ZYPP_RETHROW ( res.error() );
270 }
271 return static_cast<RepoManager::RefreshCheckStatus>(res.get());
272 }
273
274
275 void RepoManager::Impl::refreshMetadata( const RepoInfo & info, RawMetadataRefreshPolicy policy, const ProgressData::ReceiverFnc & progress )
276 {
277 using namespace zyppng;
278 using namespace zyppng::operators;
279 using zyppng::operators::operator|;
280
281 // make sure geoIP data is up 2 date
282 refreshGeoIPData( info.baseUrls() );
283
284 // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1)
286
287 // we will throw this later if no URL checks out fine
288 RepoException rexception( info, PL_("Valid metadata not found at specified URL",
289 "Valid metadata not found at specified URLs",
290 info.baseUrlsSize() ) );
291
292
293 auto ctx = SyncContext::create();
294
295 // helper callback in case the repo type changes on the remote
296 const auto &updateProbedType = [&]( repo::RepoType repokind ) {
297 // update probed type only for repos in system
298 for_( it, repoBegin(), repoEnd() )
299 {
300 if ( info.alias() == (*it).alias() )
301 {
303 modifiedrepo.setType( repokind );
304 // don't modify .repo in refresh.
305 // modifyRepository( info.alias(), modifiedrepo );
306 break;
307 }
308 }
309 };
310
311 // try urls one by one
312 for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin(); it != info.baseUrlsEnd(); ++it )
313 {
314 try {
315 auto res = zyppng::repo::SyncRefreshContext::create( ctx, info, _options )
316 | and_then( [&]( zyppng::repo::SyncRefreshContextRef refCtx ) {
317 refCtx->setPolicy( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
318 // in case probe detects a different repokind, update our internal repos
320 return ctx->provider()->attachMedia( *it, zyppng::ProvideMediaSpec() )
321 | and_then( [ refCtx ]( auto mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), std::move(mediaHandle), nullptr); } );
322 });
323
324 if ( !res ) {
325 ZYPP_RETHROW( res.error() );
326 }
327 if ( ! isTmpRepo( info ) )
328 reposManip(); // remember to trigger appdata refresh
329
330 // we are done.
331 return;
332
333 } catch ( const zypp::Exception &e ) {
334 ERR << "Trying another url..." << endl;
335
336 // remember the exception caught for the *first URL*
337 // if all other URLs fail, the rexception will be thrown with the
338 // cause of the problem of the first URL remembered
339 if (it == info.baseUrlsBegin())
340 rexception.remember( e );
341 else
342 rexception.addHistory( e.asUserString() );
343 }
344 } // for every url
345 ERR << "No more urls..." << endl;
347
348 }
349
350 void RepoManager::Impl::buildCache( const RepoInfo & info, CacheBuildPolicy policy, const ProgressData::ReceiverFnc & progressrcv )
351 {
352 assert_alias(info);
353 Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
354 Pathname productdatapath = rawproductdata_path_for_repoinfo( _options, info );
355
356 if( filesystem::assert_dir(_options.repoCachePath) )
357 {
358 Exception ex(str::form( _("Can't create %s"), _options.repoCachePath.c_str()) );
359 ZYPP_THROW(ex);
360 }
361 RepoStatus raw_metadata_status = metadataStatus(info);
362 if ( raw_metadata_status.empty() )
363 {
364 /* if there is no cache at this point, we refresh the raw
365 in case this is the first time - if it's !autorefresh,
366 we may still refresh */
367 refreshMetadata(info, RefreshIfNeeded, progressrcv );
368 raw_metadata_status = metadataStatus(info);
369 }
370
371 bool needs_cleaning = false;
372 if ( isCached( info ) )
373 {
374 MIL << info.alias() << " is already cached." << endl;
375 RepoStatus cache_status = cacheStatus(info);
376
378 {
379 MIL << info.alias() << " cache is up to date with metadata." << endl;
380 if ( policy == BuildIfNeeded )
381 {
382 // On the fly add missing solv.idx files for bash completion.
383 const Pathname & base = solv_path_for_repoinfo( _options, info);
384 if ( ! PathInfo(base/"solv.idx").isExist() )
385 sat::updateSolvFileIndex( base/"solv" );
386
387 return;
388 }
389 else {
390 MIL << info.alias() << " cache rebuild is forced" << endl;
391 }
392 }
393
394 needs_cleaning = true;
395 }
396
397 ProgressData progress(100);
399 progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
400 progress.name(str::form(_("Building repository '%s' cache"), info.label().c_str()));
401 progress.toMin();
402
403 if (needs_cleaning)
404 {
405 cleanCache(info);
406 }
407
408 MIL << info.alias() << " building cache..." << info.type() << endl;
409
410 Pathname base = solv_path_for_repoinfo( _options, info);
411
412 if( filesystem::assert_dir(base) )
413 {
414 Exception ex(str::form( _("Can't create %s"), base.c_str()) );
415 ZYPP_THROW(ex);
416 }
417
418 if( ! PathInfo(base).userMayW() )
419 {
420 Exception ex(str::form( _("Can't create cache at %s - no writing permissions."), base.c_str()) );
421 ZYPP_THROW(ex);
422 }
423 Pathname solvfile = base / "solv";
424
425 // do we have type?
427
428 // if the type is unknown, try probing.
429 switch ( repokind.toEnum() )
430 {
431 case RepoType::NONE_e:
432 // unknown, probe the local metadata
433 repokind = probeCache( productdatapath );
434 break;
435 default:
436 break;
437 }
438
439 MIL << "repo type is " << repokind << endl;
440
441 switch ( repokind.toEnum() )
442 {
443 case RepoType::RPMMD_e :
444 case RepoType::YAST2_e :
446 {
447 // Take care we unlink the solvfile on exception
450
452 cmd.push_back( PathInfo( "/usr/bin/repo2solv" ).isFile() ? "repo2solv" : "repo2solv.sh" );
453 // repo2solv expects -o as 1st arg!
454 cmd.push_back( "-o" );
455 cmd.push_back( solvfile.asString() );
456 cmd.push_back( "-X" ); // autogenerate pattern from pattern-package
457 // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages
458
460 {
461 forPlainDirs.reset( new MediaMounter( info.url() ) );
462 // recusive for plaindir as 2nd arg!
463 cmd.push_back( "-R" );
464 // FIXME this does only work form dir: URLs
465 cmd.push_back( forPlainDirs->getPathName( info.path() ).c_str() );
466 }
467 else
468 cmd.push_back( productdatapath.asString() );
469
471 std::string errdetail;
472
473 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
474 WAR << " " << output;
475 errdetail += output;
476 }
477
478 int ret = prog.close();
479 if ( ret != 0 )
480 {
481 RepoException ex(info, str::form( _("Failed to cache repo (%d)."), ret ));
482 ex.addHistory( str::Str() << prog.command() << endl << errdetail << prog.execError() ); // errdetail lines are NL-terminaled!
483 ZYPP_THROW(ex);
484 }
485
486 // We keep it.
488 sat::updateSolvFileIndex( solvfile ); // content digest for zypper bash completion
489 }
490 break;
491 default:
492 ZYPP_THROW(RepoUnknownTypeException( info, _("Unhandled repository type") ));
493 break;
494 }
495 // update timestamp and checksum
496 setCacheStatus(info, raw_metadata_status);
497 MIL << "Commit cache.." << endl;
498 progress.toMax();
499 }
500
502
503
510 repo::RepoType RepoManager::Impl::probe( const Url & url, const Pathname & path ) const
511 {
512 using namespace zyppng;
513 using namespace zyppng::operators;
514 using zyppng::operators::operator|;
515
516 auto ctx = zyppng::SyncContext::create();
517 auto res = ctx->provider()->attachMedia( url, zyppng::ProvideMediaSpec() )
518 | and_then( [&]( auto mediaHandle ) {
519 return zyppng::RepoManagerWorkflow::probeRepoType( ctx, mediaHandle, path );
520 });
521
522 if ( !res ) {
523 ZYPP_RETHROW ( res.error() );
524 }
525 return res.get();
526 }
527
529
530 void RepoManager::Impl::loadFromCache( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
531 {
532 try
533 {
535 }
536 catch ( const Exception & exp )
537 {
538 ZYPP_CAUGHT( exp );
539 MIL << "Try to handle exception by rebuilding the solv-file" << endl;
540 cleanCache( info, progressrcv );
541 buildCache( info, BuildIfNeeded, progressrcv );
542
543 sat::Pool::instance().addRepoSolv( solv_path_for_repoinfo(_options, info) / "solv", info );
544 }
545 }
546
548
549 void RepoManager::Impl::addRepository( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
550 {
551 assert_alias(info);
552
553 ProgressData progress(100);
555 progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
556 progress.name(str::form(_("Adding repository '%s'"), info.label().c_str()));
557 progress.toMin();
558
559 MIL << "Try adding repo " << info << endl;
560
561 RepoInfo tosave = info;
562 if ( repos().find(tosave) != repos().end() )
564
565 // check the first url for now
566 if ( _options.probe )
567 {
568 DBG << "unknown repository type, probing" << endl;
570
571 RepoType probedtype( probe( tosave.url(), info.path() ) );
572 if ( probedtype == RepoType::NONE )
574 else
575 tosave.setType(probedtype);
576 }
577
578 progress.set(50);
579
581
582 progress.toMax();
583 MIL << "done" << endl;
584 }
585
586
587 void RepoManager::Impl::addRepositories( const Url & url, const ProgressData::ReceiverFnc & progressrcv )
588 {
589 std::list<RepoInfo> repos = readRepoFile(url);
590 for ( std::list<RepoInfo>::const_iterator it = repos.begin();
591 it != repos.end();
592 ++it )
593 {
594 // look if the alias is in the known repos.
595 for_ ( kit, repoBegin(), repoEnd() )
596 {
597 if ( (*it).alias() == (*kit).alias() )
598 {
599 ERR << "To be added repo " << (*it).alias() << " conflicts with existing repo " << (*kit).alias() << endl;
601 }
602 }
603 }
604
605 std::string filename = Pathname(url.getPathName()).basename();
606
607 if ( filename == Pathname() )
608 {
609 // TranslatorExplanation '%s' is an URL
610 ZYPP_THROW(RepoException(str::form( _("Invalid repo file name at '%s'"), url.asString().c_str() )));
611 }
612
613 // assert the directory exists
614 filesystem::assert_dir(_options.knownReposPath);
615
616 Pathname repofile = generateNonExistingName(_options.knownReposPath, filename);
617 // now we have a filename that does not exists
618 MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << endl;
619
620 std::ofstream file(repofile.c_str());
621 if (!file)
622 {
623 // TranslatorExplanation '%s' is a filename
624 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
625 }
626
627 for ( std::list<RepoInfo>::iterator it = repos.begin();
628 it != repos.end();
629 ++it )
630 {
631 MIL << "Saving " << (*it).alias() << endl;
632 it->dumpAsIniOn(file);
633 it->setFilepath(repofile);
634 it->setMetadataPath( rawcache_path_for_repoinfo( _options, *it ) );
635 it->setPackagesPath( packagescache_path_for_repoinfo( _options, *it ) );
636 reposManip().insert(*it);
637
638 HistoryLog(_options.rootDir).addRepository(*it);
639 }
640
641 MIL << "done" << endl;
642 }
643
644 void RepoManager::Impl::removeRepository(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv )
645 {
648 removeRepositoryImpl( info, std::ref(adapt) );
649 }
650
652 //
653 // Services
654 //
656
657 void RepoManager::Impl::refreshServices( const RefreshServiceOptions & options_r )
658 {
659 // copy the set of services since refreshService
660 // can eventually invalidate the iterator
661 ServiceSet services( serviceBegin(), serviceEnd() );
662 for_( it, services.begin(), services.end() )
663 {
664 if ( !it->enabled() )
665 continue;
666
667 try {
668 refreshService(*it, options_r);
669 }
671 { ;/* ignore ServicePluginInformalException */ }
672 }
673 }
674
675 void RepoManager::Impl::refreshService( const std::string & alias, const RefreshServiceOptions & options_r )
676 {
677 ServiceInfo service( getService( alias ) );
678 assert_alias( service );
679 assert_url( service );
680 MIL << "Going to refresh service '" << service.alias() << "', url: " << service.url() << ", opts: " << options_r << endl;
681
682 if ( service.ttl() && !( options_r.testFlag( RefreshService_forceRefresh) || options_r.testFlag( RefreshService_restoreStatus ) ) )
683 {
684 // Service defines a TTL; maybe we can re-use existing data without refresh.
685 Date lrf = service.lrf();
686 if ( lrf )
687 {
688 Date now( Date::now() );
689 if ( lrf <= now )
690 {
691 if ( (lrf+=service.ttl()) > now ) // lrf+= !
692 {
693 MIL << "Skip: '" << service.alias() << "' metadata valid until " << lrf << endl;
694 return;
695 }
696 }
697 else
698 WAR << "Force: '" << service.alias() << "' metadata last refresh in the future: " << lrf << endl;
699 }
700 }
701
702 // NOTE: It might be necessary to modify and rewrite the service info.
703 // Either when probing the type, or when adjusting the repositories
704 // enable/disable state.:
705 bool serviceModified = false;
706
708
709 // if the type is unknown, try probing.
710 if ( service.type() == repo::ServiceType::NONE )
711 {
712 repo::ServiceType type = probeService( service.url() );
713 if ( type != ServiceType::NONE )
714 {
715 service.setProbedType( type ); // lazy init!
716 serviceModified = true;
717 }
718 }
719
720 // get target distro identifier
721 std::string servicesTargetDistro = _options.servicesTargetDistro;
722 if ( servicesTargetDistro.empty() )
723 {
724 servicesTargetDistro = Target::targetDistribution( Pathname() );
725 }
726 DBG << "ServicesTargetDistro: " << servicesTargetDistro << endl;
727
728 // parse it
729 Date::Duration origTtl = service.ttl(); // FIXME Ugly hack: const service.ttl modified when parsing
730 RepoCollector collector(servicesTargetDistro);
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::pair<DefaultIntegral<bool,false>, repo::ServicePluginInformalException> uglyHack;
736 try {
737 // FIXME bsc#1080693: Shortcoming of (plugin)services (and repos as well) is that they
738 // are not aware of the RepoManagers rootDir. The service url, as created in known_services,
739 // contains the full path to the script. The script however has to be executed chrooted.
740 // Repos would need to know the RepoMangers rootDir to use the correct vars.d to replace
741 // repos variables. Until RepoInfoBase is aware if the rootDir, we need to explicitly pass it
742 // to ServiceRepos.
743 ServiceRepos( _options.rootDir, service, bind( &RepoCollector::collect, &collector, _1 ) );
744 }
746 {
747 /* ignore ServicePluginInformalException and throw later */
748 uglyHack.first = true;
749 uglyHack.second = e;
750 }
751 if ( service.ttl() != origTtl ) // repoindex.xml changed ttl
752 {
753 if ( !service.ttl() )
754 service.setLrf( Date() ); // don't need lrf when zero ttl
755 serviceModified = true;
756 }
758 // On the fly remember the new repo states as defined the reopoindex.xml.
759 // Move into ServiceInfo later.
761
762 // set service alias and base url for all collected repositories
763 for_( it, collector.repos.begin(), collector.repos.end() )
764 {
765 // First of all: Prepend service alias:
766 it->setAlias( str::form( "%s:%s", service.alias().c_str(), it->alias().c_str() ) );
767 // set reference to the parent service
768 it->setService( service.alias() );
769
770 // remember the new parsed repo state
771 newRepoStates[it->alias()] = *it;
772
773 // - If the repo url was not set by the repoindex parser, set service's url.
774 // - Libzypp currently has problem with separate url + path handling so just
775 // append a path, if set, to the baseurls
776 // - Credentials in the url authority will be extracted later, either if the
777 // repository is added or if we check for changed urls.
778 Pathname path;
779 if ( !it->path().empty() )
780 {
781 if ( it->path() != "/" )
782 path = it->path();
783 it->setPath("");
784 }
785
786 if ( it->baseUrlsEmpty() )
787 {
788 Url url( service.rawUrl() );
789 if ( !path.empty() )
790 url.setPathName( url.getPathName() / path );
791 it->setBaseUrl( std::move(url) );
792 }
793 else if ( !path.empty() )
794 {
795 RepoInfo::url_set urls( it->rawBaseUrls() );
796 for ( Url & url : urls )
797 {
798 url.setPathName( url.getPathName() / path );
799 }
800 it->setBaseUrls( std::move(urls) );
801 }
802 }
803
805 // Now compare collected repos with the ones in the system...
806 //
807 RepoInfoList oldRepos;
808 getRepositoriesInService( service.alias(), std::back_inserter( oldRepos ) );
809
811 // find old repositories to remove...
812 for_( oldRepo, oldRepos.begin(), oldRepos.end() )
813 {
814 if ( ! foundAliasIn( oldRepo->alias(), collector.repos ) )
815 {
816 if ( oldRepo->enabled() )
817 {
818 // Currently enabled. If this was a user modification remember the state.
819 const auto & last = service.repoStates().find( oldRepo->alias() );
820 if ( last != service.repoStates().end() && ! last->second.enabled )
821 {
822 DBG << "Service removes user enabled repo " << oldRepo->alias() << endl;
823 service.addRepoToEnable( oldRepo->alias() );
824 serviceModified = true;
825 }
826 else
827 DBG << "Service removes enabled repo " << oldRepo->alias() << endl;
828 }
829 else
830 DBG << "Service removes disabled repo " << oldRepo->alias() << endl;
831
832 removeRepository( *oldRepo );
833 }
834 }
835
837 // create missing repositories and modify existing ones if needed...
838 UrlCredentialExtractor urlCredentialExtractor( _options.rootDir ); // To collect any credentials stored in repo URLs
839 for_( it, collector.repos.begin(), collector.repos.end() )
840 {
841 // User explicitly requested the repo being enabled?
842 // User explicitly requested the repo being disabled?
843 // And hopefully not both ;) If so, enable wins.
844
845 TriBool toBeEnabled( indeterminate ); // indeterminate - follow the service request
846 DBG << "Service request to " << (it->enabled()?"enable":"disable") << " service repo " << it->alias() << endl;
847
848 if ( options_r.testFlag( RefreshService_restoreStatus ) )
849 {
850 DBG << "Opt RefreshService_restoreStatus " << it->alias() << endl;
851 // this overrides any pending request!
852 // Remove from enable request list.
853 // NOTE: repoToDisable is handled differently.
854 // It gets cleared on each refresh.
855 service.delRepoToEnable( it->alias() );
856 // toBeEnabled stays indeterminate!
857 }
858 else
859 {
860 if ( service.repoToEnableFind( it->alias() ) )
861 {
862 DBG << "User request to enable service repo " << it->alias() << endl;
863 toBeEnabled = true;
864 // Remove from enable request list.
865 // NOTE: repoToDisable is handled differently.
866 // It gets cleared on each refresh.
867 service.delRepoToEnable( it->alias() );
868 serviceModified = true;
869 }
870 else if ( service.repoToDisableFind( it->alias() ) )
871 {
872 DBG << "User request to disable service repo " << it->alias() << endl;
873 toBeEnabled = false;
874 }
875 }
876
877 RepoInfoList::iterator oldRepo( findAlias( it->alias(), oldRepos ) );
878 if ( oldRepo == oldRepos.end() )
879 {
880 // Not found in oldRepos ==> a new repo to add
881
882 // Make sure the service repo is created with the appropriate enablement
883 if ( ! indeterminate(toBeEnabled) )
884 it->setEnabled( ( bool ) toBeEnabled );
885
886 DBG << "Service adds repo " << it->alias() << " " << (it->enabled()?"enabled":"disabled") << endl;
887 addRepository( *it );
888 }
889 else
890 {
891 // ==> an exising repo to check
892 bool oldRepoModified = false;
893
894 if ( indeterminate(toBeEnabled) )
895 {
896 // No user request: check for an old user modificaton otherwise follow service request.
897 // NOTE: Assert toBeEnabled is boolean afterwards!
898 if ( oldRepo->enabled() == it->enabled() )
899 toBeEnabled = it->enabled(); // service requests no change to the system
900 else if (options_r.testFlag( RefreshService_restoreStatus ) )
901 {
902 toBeEnabled = it->enabled(); // RefreshService_restoreStatus forced
903 DBG << "Opt RefreshService_restoreStatus " << it->alias() << " forces " << (toBeEnabled?"enabled":"disabled") << endl;
904 }
905 else
906 {
907 const auto & last = service.repoStates().find( oldRepo->alias() );
908 if ( last == service.repoStates().end() || last->second.enabled != it->enabled() )
909 toBeEnabled = it->enabled(); // service request has changed since last refresh -> follow
910 else
911 {
912 toBeEnabled = oldRepo->enabled(); // service request unchaned since last refresh -> keep user modification
913 DBG << "User modified service repo " << it->alias() << " may stay " << (toBeEnabled?"enabled":"disabled") << endl;
914 }
915 }
916 }
917
918 // changed enable?
919 if ( toBeEnabled == oldRepo->enabled() )
920 {
921 DBG << "Service repo " << it->alias() << " stays " << (oldRepo->enabled()?"enabled":"disabled") << endl;
922 }
923 else if ( toBeEnabled )
924 {
925 DBG << "Service repo " << it->alias() << " gets enabled" << endl;
926 oldRepo->setEnabled( true );
927 oldRepoModified = true;
928 }
929 else
930 {
931 DBG << "Service repo " << it->alias() << " gets disabled" << endl;
932 oldRepo->setEnabled( false );
933 oldRepoModified = true;
934 }
935
936 // all other attributes follow the service request:
937
938 // changed name (raw!)
939 if ( oldRepo->rawName() != it->rawName() )
940 {
941 DBG << "Service repo " << it->alias() << " gets new NAME " << it->rawName() << endl;
942 oldRepo->setName( it->rawName() );
943 oldRepoModified = true;
944 }
945
946 // changed autorefresh
947 if ( oldRepo->autorefresh() != it->autorefresh() )
948 {
949 DBG << "Service repo " << it->alias() << " gets new AUTOREFRESH " << it->autorefresh() << endl;
950 oldRepo->setAutorefresh( it->autorefresh() );
951 oldRepoModified = true;
952 }
953
954 // changed priority?
955 if ( oldRepo->priority() != it->priority() )
956 {
957 DBG << "Service repo " << it->alias() << " gets new PRIORITY " << it->priority() << endl;
958 oldRepo->setPriority( it->priority() );
959 oldRepoModified = true;
960 }
961
962 // changed url?
963 {
964 RepoInfo::url_set newUrls( it->rawBaseUrls() );
965 urlCredentialExtractor.extract( newUrls ); // Extract! to prevent passwds from disturbing the comparison below
966 if ( oldRepo->rawBaseUrls() != newUrls )
967 {
968 DBG << "Service repo " << it->alias() << " gets new URLs " << newUrls << endl;
969 oldRepo->setBaseUrls( std::move(newUrls) );
970 oldRepoModified = true;
971 }
972 }
973
974 // changed gpg check settings?
975 // ATM only plugin services can set GPG values.
976 if ( service.type() == ServiceType::PLUGIN )
977 {
978 TriBool ogpg[3]; // Gpg RepoGpg PkgGpg
979 TriBool ngpg[3];
980 oldRepo->getRawGpgChecks( ogpg[0], ogpg[1], ogpg[2] );
981 it-> getRawGpgChecks( ngpg[0], ngpg[1], ngpg[2] );
982#define Z_CHKGPG(I,N) \
983 if ( ! sameTriboolState( ogpg[I], ngpg[I] ) ) \
984 { \
985 DBG << "Service repo " << it->alias() << " gets new "#N"Check " << ngpg[I] << endl; \
986 oldRepo->set##N##Check( ngpg[I] ); \
987 oldRepoModified = true; \
988 }
989 Z_CHKGPG( 0, Gpg );
990 Z_CHKGPG( 1, RepoGpg );
991 Z_CHKGPG( 2, PkgGpg );
992#undef Z_CHKGPG
993 }
994
995 // save if modified:
996 if ( oldRepoModified )
997 {
998 modifyRepository( oldRepo->alias(), *oldRepo );
999 }
1000 }
1001 }
1002
1003 // Unlike reposToEnable, reposToDisable is always cleared after refresh.
1004 if ( ! service.reposToDisableEmpty() )
1005 {
1006 service.clearReposToDisable();
1007 serviceModified = true;
1008 }
1009
1010 // Remember original service request for next refresh
1011 if ( service.repoStates() != newRepoStates )
1012 {
1013 service.setRepoStates( std::move(newRepoStates) );
1014 serviceModified = true;
1015 }
1016
1018 // save service if modified: (unless a plugin service)
1019 if ( service.type() != ServiceType::PLUGIN )
1020 {
1021 if ( service.ttl() )
1022 {
1023 service.setLrf( Date::now() ); // remember last refresh
1024 serviceModified = true; // or use a cookie file
1025 }
1026
1027 if ( serviceModified )
1028 {
1029 // write out modified service file.
1030 modifyService( service.alias(), service );
1031 }
1032 }
1033
1034 if ( uglyHack.first )
1035 {
1036 throw( uglyHack.second ); // intentionally not ZYPP_THROW
1037 }
1038 }
1039
1041
1042 repo::ServiceType RepoManager::Impl::probeService( const Url & url ) const
1043 {
1044 try
1045 {
1047 if ( access.doesFileExist("/repo/repoindex.xml") )
1049 }
1050 catch ( const media::MediaException &e )
1051 {
1052 ZYPP_CAUGHT(e);
1053 // TranslatorExplanation '%s' is an URL
1054 RepoException enew(str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
1055 enew.remember(e);
1057 }
1058 catch ( const Exception &e )
1059 {
1060 ZYPP_CAUGHT(e);
1061 // TranslatorExplanation '%s' is an URL
1062 Exception enew(str::form( _("Unknown error reading from '%s'"), url.asString().c_str() ));
1063 enew.remember(e);
1065 }
1066
1068 }
1069
1070 void RepoManager::Impl::refreshGeoIPData ( const RepoInfo::url_set &urls )
1071 {
1072 try {
1073
1074 if ( !ZConfig::instance().geoipEnabled() ) {
1075 MIL << "GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl;
1076 return;
1077 }
1078
1079 std::vector<std::string> hosts;
1080 for ( const auto &baseUrl : urls ) {
1081 const auto &host = baseUrl.getHost();
1082 if ( zypp::any_of( ZConfig::instance().geoipHostnames(), [&host]( const auto &elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) {
1083 hosts.push_back( host );
1084 break;
1085 }
1086 }
1087
1088 if ( hosts.empty() ) {
1089 MIL << "No configured geoip URL found, not updating geoip data" << std::endl;
1090 return;
1091 }
1092
1093 const auto &geoIPCache = ZConfig::instance().geoipCachePath();
1094
1095 if ( filesystem::assert_dir( geoIPCache ) != 0 ) {
1096 MIL << "Unable to create cache directory for GeoIP." << std::endl;
1097 return;
1098 }
1099
1100 if ( !PathInfo(geoIPCache).userMayRWX() ) {
1101 MIL << "No access rights for the GeoIP cache directory." << std::endl;
1102 return;
1103 }
1104
1105 // remove all older cache entries
1106 filesystem::dirForEachExt( geoIPCache, []( const Pathname &dir, const filesystem::DirEntry &entry ){
1107 if ( entry.type != filesystem::FT_FILE )
1108 return true;
1109
1110 PathInfo pi( dir/entry.name );
1111 auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t( pi.mtime() );
1112 if ( age < std::chrono::hours(24) )
1113 return true;
1114
1115 MIL << "Removing GeoIP file for " << entry.name << " since it's older than 24hrs." << std::endl;
1116 filesystem::unlink( dir/entry.name );
1117 return true;
1118 });
1119
1120 // go over all found hostnames
1121 std::for_each( hosts.begin(), hosts.end(), [ & ]( const std::string &hostname ) {
1122
1123 // do not query files that are still there
1124 if ( zypp::PathInfo( geoIPCache / hostname ).isExist() ) {
1125 MIL << "Skipping GeoIP request for " << hostname << " since a valid cache entry exists." << std::endl;
1126 return;
1127 }
1128
1129 MIL << "Query GeoIP for " << hostname << std::endl;
1130
1131 zypp::Url url;
1132 try
1133 {
1134 url.setHost(hostname);
1135 url.setScheme("https");
1136 }
1137 catch(const zypp::Exception &e )
1138 {
1139 ZYPP_CAUGHT(e);
1140 MIL << "Ignoring invalid GeoIP hostname: " << hostname << std::endl;
1141 return;
1142 }
1143
1144 MediaSetAccess acc( url );
1145 zypp::ManagedFile file;
1146 try {
1147 // query the file from the server
1148 file = zypp::ManagedFile (acc.provideOptionalFile("/geoip"), filesystem::unlink );
1149
1150 } catch ( const zypp::Exception &e ) {
1151 ZYPP_CAUGHT(e);
1152 MIL << "Failed to query GeoIP from hostname: " << hostname << std::endl;
1153 return;
1154 }
1155 if ( !file->empty() ) {
1156
1157 constexpr auto writeHostToFile = []( const Pathname &fName, const std::string &host ){
1158 std::ofstream out;
1159 out.open( fName.asString(), std::ios_base::trunc );
1160 if ( out.is_open() ) {
1161 out << host << std::endl;
1162 } else {
1163 MIL << "Failed to create/open GeoIP cache file " << fName << std::endl;
1164 }
1165 };
1166
1167 std::string geoipMirror;
1168 try {
1169 xml::Reader reader( *file );
1170 if ( reader.seekToNode( 1, "host" ) ) {
1171 const auto &str = reader.nodeText().asString();
1172
1173 // make a dummy URL to ensure the hostname is valid
1175 testUrl.setHost(str);
1176 testUrl.setScheme("https");
1177
1178 if ( testUrl.isValid() ) {
1179 MIL << "Storing geoIP redirection: " << hostname << " -> " << str << std::endl;
1180 geoipMirror = str;
1181 }
1182
1183 } else {
1184 MIL << "No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl;
1185 }
1186 } catch ( const zypp::Exception &e ) {
1187 ZYPP_CAUGHT(e);
1188 MIL << "Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl;
1189 }
1190
1191 writeHostToFile( geoIPCache / hostname, geoipMirror );
1192 }
1193 });
1194
1195 } catch ( const zypp::Exception &e ) {
1196 ZYPP_CAUGHT(e);
1197 MIL << "Failed to query GeoIP data." << std::endl;
1198 }
1199 }
1200
1202 //
1203 // CLASS NAME : RepoManager
1204 //
1206
1207 RepoManager::RepoManager( RepoManagerOptions opt )
1208 : _pimpl( new Impl(std::move(opt)) )
1209 {}
1210
1213
1215 { return _pimpl->repoEmpty(); }
1216
1218 { return _pimpl->repoSize(); }
1219
1221 { return _pimpl->repoBegin(); }
1222
1225
1226 RepoInfo RepoManager::getRepo( const std::string & alias ) const
1227 { return _pimpl->getRepo( alias ); }
1228
1229 bool RepoManager::hasRepo( const std::string & alias ) const
1230 { return _pimpl->hasRepo( alias ); }
1231
1233 {
1234 std::string ret( url_r.getScheme() );
1235 if ( ret.empty() )
1236 ret = "repo-";
1237 else
1238 ret += "-";
1239
1240 std::string host( url_r.getHost() );
1241 if ( ! host.empty() )
1242 {
1243 ret += host;
1244 ret += "-";
1245 }
1246
1247 static Date::ValueType serial = Date::now();
1248 ret += Digest::digest( Digest::sha1(), str::hexstring( ++serial ) +url_r.asCompleteString() ).substr(0,8);
1249 return ret;
1250 }
1251
1253 { return _pimpl->metadataStatus( info ); }
1254
1256 { return _pimpl->checkIfToRefreshMetadata( info, url, policy ); }
1257
1259 { return _pimpl->metadataPath( info ); }
1260
1262 { return _pimpl->packagesPath( info ); }
1263
1265 { return _pimpl->refreshMetadata( info, policy, progressrcv ); }
1266
1268 { return _pimpl->cleanMetadata( info, progressrcv ); }
1269
1271 { return _pimpl->cleanPackages( info, progressrcv ); }
1272
1274 { return _pimpl->cacheStatus( info ); }
1275
1277 { return _pimpl->buildCache( info, policy, progressrcv ); }
1278
1280 { return _pimpl->cleanCache( info, progressrcv ); }
1281
1282 bool RepoManager::isCached( const RepoInfo &info ) const
1283 { return _pimpl->isCached( info ); }
1284
1286 { return _pimpl->loadFromCache( info, progressrcv ); }
1287
1289 { return _pimpl->cleanCacheDirGarbage( progressrcv ); }
1290
1291 repo::RepoType RepoManager::probe( const Url & url, const Pathname & path ) const
1292 { return _pimpl->probe( url, path ); }
1293
1295 { return _pimpl->probe( url ); }
1296
1298 { return _pimpl->addRepository( info, progressrcv ); }
1299
1301 { return _pimpl->addRepositories( url, progressrcv ); }
1302
1304 { return _pimpl->removeRepository( info, progressrcv ); }
1305
1307 { return _pimpl->modifyRepository( alias, newinfo, progressrcv ); }
1308
1310 { return _pimpl->getRepositoryInfo( alias ); }
1311
1313 { return _pimpl->getRepositoryInfo( url, urlview ); }
1314
1316 { return _pimpl->serviceEmpty(); }
1317
1319 { return _pimpl->serviceSize(); }
1320
1323
1326
1327 ServiceInfo RepoManager::getService( const std::string & alias ) const
1328 { return _pimpl->getService( alias ); }
1329
1330 bool RepoManager::hasService( const std::string & alias ) const
1331 { return _pimpl->hasService( alias ); }
1332
1334 { return _pimpl->probeService( url ); }
1335
1336 void RepoManager::addService( const std::string & alias, const Url& url )
1337 { return _pimpl->addService( alias, url ); }
1338
1339 void RepoManager::addService( const ServiceInfo & service )
1340 { return _pimpl->addService( service ); }
1341
1342 void RepoManager::removeService( const std::string & alias )
1343 { return _pimpl->removeService( alias ); }
1344
1346 { return _pimpl->removeService( service ); }
1347
1349 { return _pimpl->refreshServices( options_r ); }
1350
1351 void RepoManager::refreshService( const std::string & alias, const RefreshServiceOptions & options_r )
1352 { return _pimpl->refreshService( alias, options_r ); }
1353
1354 void RepoManager::refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r )
1355 { return _pimpl->refreshService( service, options_r ); }
1356
1357 void RepoManager::modifyService( const std::string & oldAlias, const ServiceInfo & service )
1358 { return _pimpl->modifyService( oldAlias, service ); }
1359
1361 { return _pimpl->refreshGeoIPData( urls ); }
1362
1364
1365 std::ostream & operator<<( std::ostream & str, const RepoManager & obj )
1366 { return str << *obj._pimpl; }
1367
1369} // namespace zypp
#define Z_CHKGPG(I, N)
#define OPT_PROGRESS
media::MediaAccessId _mid
RepoManager implementation.
std::ostream & operator<<(std::ostream &str, const RepoManager::Impl &obj)
Stream output.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
void resetDispose()
Set no dispose function.
void reset()
Reset to default Ctor values.
shared_ptr< Impl > _pimpl
time_t Duration
Definition Date.h:39
time_t ValueType
Definition Date.h:38
static Date now()
Return the current time.
Definition Date.h:78
std::string digest()
get hex string representation of the digest
Definition Digest.cc:238
static const std::string & sha1()
sha1
Definition Digest.cc:44
Base class for Exception.
Definition Exception.h:147
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::vector< std::string > Arguments
Writing the zypp history file.
Definition HistoryLog.h:57
void addRepository(const RepoInfo &repo)
Log a newly added repository.
Media access layer responsible for handling files distributed on a set of media with media change and...
static ManagedFile provideFileFromUrl(const Url &file_url, ProvideFileOptions options=PROVIDE_DEFAULT)
Provides file from url.
Maintain [min,max] and counter (value) for progress counting.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
What is known about a repository.
Definition RepoInfo.h:72
transform_iterator< repo::RepoVariablesUrlReplacer, url_set::const_iterator > urls_const_iterator
Definition RepoInfo.h:110
repo::RepoType type() const
Type of repository,.
Definition RepoInfo.cc:602
urls_size_type baseUrlsSize() const
number of repository urls
Definition RepoInfo.cc:653
Url url() const
Pars pro toto: The first repository url.
Definition RepoInfo.h:136
urls_const_iterator baseUrlsEnd() const
iterator that points at end of repository urls
Definition RepoInfo.cc:650
Pathname path() const
Repository path.
Definition RepoInfo.cc:635
url_set baseUrls() const
The complete set of repository urls.
Definition RepoInfo.cc:629
urls_const_iterator baseUrlsBegin() const
iterator that points at begin of repository urls
Definition RepoInfo.cc:647
std::list< Url > url_set
Definition RepoInfo.h:108
Track changing files or directories.
Definition RepoStatus.h:41
Service data.
Definition ServiceInfo.h:37
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
void setHost(const std::string &host)
Set the hostname or IP in the URL authority.
Definition Url.cc:752
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Definition Url.cc:672
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:925
Wrapper class for stat/lstat.
Definition PathInfo.h:222
bool empty() const
Test for an empty path.
Definition Pathname.h:114
Just inherits Exception to separate media exceptions.
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
Repository already exists and some unique attribute can't be duplicated.
Exception for repository handling.
std::string label() const
Label for use in messages for the user interface.
std::string alias() const
unique identifier for this source.
thrown when it was impossible to determine this repo type.
Service plugin has trouble providing the metadata but this should not be treated as error.
Retrieval of repository list for a service.
static Pool instance()
Singleton ctor.
Definition Pool.h:55
xmlTextReader based interface to iterate xml streams.
Definition Reader.h:96
Repository metadata verification beyond GPG.
static expected< repo::RefreshContextRef< ZyppContextRefType > > create(ZyppContextRefType zyppContext, zypp::RepoInfo info, zypp::RepoManagerOptions opts)
Definition refresh.cc:28
SignalProxy< void(zypp::repo::RepoType)> sigProbedTypeChanged()
Definition refresh.cc:131
Definition Arch.h:364
String related utilities and Regular expression matching.
bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT()
To trigger appdata refresh unconditionally.
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:701
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:320
int dirForEachExt(const Pathname &dir_r, const function< bool(const Pathname &, const DirEntry &)> &fnc_r)
Simiar to.
Definition PathInfo.cc:594
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 strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:429
std::string hexstring(char n, int w=4)
Definition String.h:324
int compareCI(const C_Str &lhs, const C_Str &rhs)
Definition String.h:983
Easy-to use interface to the ZYPP dependency resolver.
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.
bool isTmpRepo(const RepoInfo &info_r)
Whether repo is not under RM control and provides its own methadata paths.
std::list< RepoInfo > readRepoFile(const Url &repo_file)
Parses repo_file and returns a list of RepoInfo objects corresponding to repositories found within th...
void assert_alias(const RepoInfo &info)
Pathname solv_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the solv cache path for a repository.
std::list< RepoInfo > repositories_in_file(const Pathname &file)
Reads RepoInfo's from a repo file.
Pathname packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
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,...
bool any_of(const Container &c, Fnc &&cb)
Definition Algorithm.h:76
void assert_url(const ServiceInfo &info)
void assert_urls(const RepoInfo &info)
bool foundAliasIn(const std::string &alias_r, Iterator begin_r, Iterator end_r)
Check if alias_r is present in repo/service container.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Iterator findAlias(const std::string &alias_r, Iterator begin_r, Iterator end_r)
Find alias_r in repo/service container.
AsyncOpRef< expected< zypp::repo::RepoType > > probeRepoType(ContextRef ctx, ProvideMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath={})
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > buildCache(repo::AsyncRefreshContextRef refCtx, ProgressObserverRef progressObserver=nullptr)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > refreshMetadata(repo::AsyncRefreshContextRef refCtx, ProvideMediaHandle medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, ProvideMediaHandle medium, ProgressObserverRef progressObserver=nullptr)
RawMetadataRefreshPolicy
Definition refresh.h:31
Simple callback to collect the results.
bool collect(const RepoInfo &repo)
void loadFromCache(const RepoInfo &info, OPT_PROGRESS)
void addProbedRepository(const RepoInfo &info, repo::RepoType probedType)
Repo manager settings.
creates and provides information about known sources.
bool hasRepo(const std::string &alias) const
Return whether there is a known repository for alias.
void cleanCacheDirGarbage(const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Remove any subdirectories of cache directories which no longer belong to any of known repositories.
void cleanMetadata(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Clean local metadata.
bool serviceEmpty() const
Gets true if no service is in RepoManager (so no one in specified location)
bool hasService(const std::string &alias) const
Return whether there is a known service for alias.
RefreshCheckStatus
Possibly return state of checkIfRefreshMEtadata function.
RefreshCheckStatus checkIfToRefreshMetadata(const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy)
Impl * clone() const
clone for RWCOW_pointer
ServiceSet::const_iterator ServiceConstIterator
Definition RepoManager.h:67
void refreshService(const ServiceInfo &service, const RefreshServiceOptions &options_r)
void addRepository(const RepoInfo &info, OPT_PROGRESS)
void addService(const std::string &alias, const Url &url)
Adds a new service by its alias and URL.
Impl & operator=(Impl &&)=delete
bool isCached(const RepoInfo &info) const
Whether a repository exists in cache.
void loadFromCache(const RepoInfo &info, OPT_PROGRESS)
void refreshMetadata(const RepoInfo &info, RawMetadataRefreshPolicy policy, OPT_PROGRESS)
void removeService(const std::string &alias)
Removes service specified by its name.
void refreshService(const std::string &alias, const RefreshServiceOptions &options_r)
void buildCache(const RepoInfo &info, CacheBuildPolicy policy, OPT_PROGRESS)
RepoInfo getRepo(const std::string &alias) const
Find RepoInfo by alias or return RepoInfo::noRepo.
repo::ServiceType probeService(const Url &url) const
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
Impl & operator=(const Impl &)=delete
void cleanCache(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
clean local cache
RefreshServiceFlags RefreshServiceOptions
Options tuning RefreshService.
bool repoEmpty() const
Pathname metadataPath(const RepoInfo &info) const
Path where the metadata is downloaded and kept.
zypp_private::repo::PluginRepoverification _pluginRepoverification
ServiceSet::size_type ServiceSizeType
Definition RepoManager.h:68
Pathname packagesPath(const RepoInfo &info) const
Path where the rpm packages are downloaded and kept.
RepoStatus cacheStatus(const RepoInfo &info) const
Status of metadata cache.
void removeRepository(const RepoInfo &info, OPT_PROGRESS) override
void refreshGeoIp(const RepoInfo::url_set &urls)
ServiceConstIterator serviceEnd() const
Iterator to place behind last service in internal storage.
ServiceConstIterator serviceBegin() const
Iterator to first service in internal storage.
repo::RepoType probe(const Url &url, const Pathname &path=Pathname()) const
Impl(Impl &&)=delete
RepoSizeType repoSize() const
void modifyRepository(const std::string &alias, const RepoInfo &newinfo, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Modify repository attributes.
RepoInfo getRepositoryInfo(const std::string &alias, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Find a matching repository info.
ServiceSizeType serviceSize() const
Gets count of service in RepoManager (in specified location)
void addRepositories(const Url &url, OPT_PROGRESS)
ServiceInfo getService(const std::string &alias) const
Finds ServiceInfo by alias or return ServiceInfo::noService.
RepoSet::size_type RepoSizeType
Definition RepoManager.h:73
void refreshServices(const RefreshServiceOptions &options_r)
Impl(const Impl &)=default
RepoConstIterator repoBegin() const
void cleanPackages(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Clean local package cache.
RepoConstIterator repoEnd() const
RepoStatus metadataStatus(const RepoInfo &info) const
Status of local metadata.
void modifyService(const std::string &oldAlias, const ServiceInfo &service)
Modifies service file (rewrites it with new values) and underlying repositories if needed.
RepoSet::const_iterator RepoConstIterator
Definition RepoManager.h:72
static std::string makeStupidAlias(const Url &url_r=Url())
Some stupid string but suitable as alias for your url if nothing better is available.
Impl(RepoManagerOptions &&opt)
void refreshGeoIPData(const RepoInfo::url_set &urls)
Listentry returned by readdir.
Definition PathInfo.h:502
Temporarily disable MediaChangeReport Sometimes helpful to suppress interactive messages connected to...
Repository type enumeration.
Definition RepoType.h:28
static const RepoType NONE
Definition RepoType.h:32
static const RepoType RPMPLAINDIR
Definition RepoType.h:31
Functor replacing repository variables.
Service type enumeration.
Definition ServiceType.h:27
static const ServiceType NONE
No service set.
Definition ServiceType.h:34
static const ServiceType RIS
Repository Index Service (RIS) (formerly known as 'Novell Update' (NU) service)
Definition ServiceType.h:32
static const ServiceType PLUGIN
Plugin services are scripts installed on your system that provide the package manager with repositori...
Definition ServiceType.h:43
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:212
Url::asString() view options.
Definition UrlBase.h:40
#define ZYPP_LOCAL
Definition Globals.h:59
#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:441
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:437
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:429
#define PL_(MSG1, MSG2, N)
Definition Gettext.h:40
#define _(MSG)
Definition Gettext.h:37
#define DBG
Definition Logger.h:95
#define MIL
Definition Logger.h:96
#define ERR
Definition Logger.h:98
#define WAR
Definition Logger.h:97