libzypp 17.34.1
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>
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 {
99 media::MediaManager mediamanager;
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 {
112 media::MediaManager mediamanager;
113 mediamanager.release( _mid );
114 mediamanager.close( _mid );
115 }
116
121 Pathname getPathName( const Pathname & path_r = Pathname() ) const
122 {
123 media::MediaManager mediamanager;
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 {
137 Url repoFileUrl { replaceVars(repo_file) };
138
139 ManagedFile local = MediaSetAccess::provideFileFromUrl( repoFileUrl );
140 DBG << "reading repo file " << repoFileUrl << ", local path: " << local << endl;
141
142 return repositories_in_file(local);
143 }
144
145 std::ostream & operator<<( std::ostream & str, RepoManager::RawMetadataRefreshPolicy obj )
146 {
147 switch ( obj ) {
148#define OUTS(V) case RepoManager::V: str << #V; break
149 OUTS( RefreshIfNeeded );
150 OUTS( RefreshForced );
151 OUTS( RefreshIfNeededIgnoreDelay );
152#undef OUTS
153 }
154 return str;
155 }
156
157 std::ostream & operator<<( std::ostream & str, RepoManager::RefreshCheckStatus obj )
158 {
159 switch ( obj ) {
160#define OUTS(V) case RepoManager::V: str << #V; break
161 OUTS( REFRESH_NEEDED );
162 OUTS( REPO_UP_TO_DATE );
163 OUTS( REPO_CHECK_DELAYED );
164#undef OUTS
165 }
166 return str;
167 }
168
169 std::ostream & operator<<( std::ostream & str, RepoManager::CacheBuildPolicy obj )
170 {
171 switch ( obj ) {
172#define OUTS(V) case RepoManager::V: str << #V; break
173 OUTS( BuildIfNeeded );
174 OUTS( BuildForced );
175#undef OUTS
176 }
177 return str;
178 }
179
186 {
187 public:
189 : RepoManagerBaseImpl(std::move(opt)),
190 _pluginRepoverification(_options.pluginsPath / "repoverification",
191 _options.rootDir) {
192 init_knownServices();
193 init_knownRepositories();
194 }
195
196 Impl(const Impl &) = default;
197 Impl(Impl &&) = delete;
198 Impl &operator=(const Impl &) = delete;
199 Impl &operator=(Impl &&) = delete;
200
201 ~Impl() override
202 {
203 // trigger appdata refresh if some repos change
204 if ( ( _reposDirty || env::ZYPP_PLUGIN_APPDATA_FORCE_COLLECT() )
205 && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) )
206 {
207 try {
208 std::list<Pathname> entries;
209 filesystem::readdir( entries, _options.pluginsPath/"appdata", false );
210 if ( ! entries.empty() )
211 {
213 cmd.push_back( "<" ); // discard stdin
214 cmd.push_back( ">" ); // discard stdout
215 cmd.push_back( "PROGRAM" ); // [2] - fix index below if changing!
216 for ( const auto & rinfo : repos() )
217 {
218 if ( ! rinfo.enabled() )
219 continue;
220 cmd.push_back( "-R" );
221 cmd.push_back( rinfo.alias() );
222 cmd.push_back( "-t" );
223 cmd.push_back( rinfo.type().asString() );
224 cmd.push_back( "-p" );
225 cmd.push_back( (rinfo.metadataPath()/rinfo.path()).asString() ); // bsc#1197684: path to the repodata/ directory inside the cache
226 }
227
228 for_( it, entries.begin(), entries.end() )
229 {
230 PathInfo pi( *it );
231 //DBG << "/tmp/xx ->" << pi << endl;
232 if ( pi.isFile() && pi.userMayRX() )
233 {
234 // trigger plugin
235 cmd[2] = pi.asString(); // [2] - PROGRAM
236 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
237 }
238 }
239 }
240 }
241 catch (...) {} // no throw in dtor
242 }
243 }
244
245 public:
246 RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo & info, const Url & url, RawMetadataRefreshPolicy policy );
247
248 void refreshMetadata( const RepoInfo & info, RawMetadataRefreshPolicy policy, OPT_PROGRESS );
249
250 void buildCache( const RepoInfo & info, CacheBuildPolicy policy, OPT_PROGRESS );
251
252 repo::RepoType probe( const Url & url, const Pathname & path = Pathname() ) const;
253
254 void loadFromCache( const RepoInfo & info, OPT_PROGRESS );
255
256 void addRepository( const RepoInfo & info, OPT_PROGRESS );
257
258 void addRepositories( const Url & url, OPT_PROGRESS );
259
260 void removeRepository ( const RepoInfo & info, OPT_PROGRESS ) override;
261
262 public:
263 void refreshServices( const RefreshServiceOptions & options_r );
264
265 void refreshService( const std::string & alias, const RefreshServiceOptions & options_r );
266 void refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r )
267 { refreshService( service.alias(), options_r ); }
268
269 repo::ServiceType probeService( const Url & url ) const;
270
271 void refreshGeoIPData ( const RepoInfo::url_set &urls );
272
273 private:
275
276 private:
277 friend Impl * rwcowClone<Impl>( const Impl * rhs );
279 Impl * clone() const
280 { return new Impl( *this ); }
281 };
283
285 inline std::ostream & operator<<( std::ostream & str, const RepoManager::Impl & obj )
286 { return str << "RepoManager::Impl"; }
287
289 {
290 // Hotfix for bsc#1223094: No media access for CD/DVD unless rawchache is missing
291 if ( url.schemeIsVolatile() ) {
293 }
294
295 using namespace zyppng::operators;
296 using zyppng::operators::operator|;
297
298 refreshGeoIPData( { url } );
299
300 auto ctx = zyppng::SyncContext::create();
302 | and_then( [&]( zyppng::repo::SyncRefreshContextRef &&refCtx ) {
303 refCtx->setPolicy ( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
304 return ctx->provider()->attachMedia( url, zyppng::ProvideMediaSpec() )
305 | and_then( [ r = std::move(refCtx) ]( auto &&mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::checkIfToRefreshMetadata ( std::move(r), mediaHandle, nullptr ); } );
306 } );
307
308 if ( !res ) {
309 ZYPP_RETHROW ( res.error() );
310 }
311 return static_cast<RepoManager::RefreshCheckStatus>(res.get());
312 }
313
314
316 {
317 using namespace zyppng;
318 using namespace zyppng::operators;
319 using zyppng::operators::operator|;
320
321 // make sure geoIP data is up 2 date
322 refreshGeoIPData( info.baseUrls() );
323
324 // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1)
326
327 // we will throw this later if no URL checks out fine
328 RepoException rexception( info, PL_("Valid metadata not found at specified URL",
329 "Valid metadata not found at specified URLs",
330 info.baseUrlsSize() ) );
331
332
333 auto ctx = SyncContext::create();
334
335 // helper callback in case the repo type changes on the remote
336 const auto &updateProbedType = [&]( repo::RepoType repokind ) {
337 // update probed type only for repos in system
338 for_( it, repoBegin(), repoEnd() )
339 {
340 if ( info.alias() == (*it).alias() )
341 {
342 RepoInfo modifiedrepo = *it;
343 modifiedrepo.setType( repokind );
344 // don't modify .repo in refresh.
345 // modifyRepository( info.alias(), modifiedrepo );
346 break;
347 }
348 }
349 };
350
351 // try urls one by one
352 for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin(); it != info.baseUrlsEnd(); ++it )
353 {
354 // Hotfix for bsc#1223094: No media access for CD/DVD unless rawchache is missing
355 if ( it->schemeIsVolatile() && not metadataStatus( info ).empty() ) {
356 // we are done.
357 return;
358 }
359
360 try {
361 auto res = zyppng::repo::SyncRefreshContext::create( ctx, info, _options )
362 | and_then( [&]( zyppng::repo::SyncRefreshContextRef refCtx ) {
363 refCtx->setPolicy( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
364 // in case probe detects a different repokind, update our internal repos
365 refCtx->connectFunc( &zyppng::repo::SyncRefreshContext::sigProbedTypeChanged, updateProbedType );
366 return ctx->provider()->attachMedia( *it, zyppng::ProvideMediaSpec() )
367 | and_then( [ refCtx ]( auto mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), std::move(mediaHandle), nullptr); } );
368 });
369
370 if ( !res ) {
371 ZYPP_RETHROW( res.error() );
372 }
373 if ( ! isTmpRepo( info ) )
374 reposManip(); // remember to trigger appdata refresh
375
376 // we are done.
377 return;
378
379 } catch ( const zypp::Exception &e ) {
380 ERR << "Trying another url..." << endl;
381
382 // remember the exception caught for the *first URL*
383 // if all other URLs fail, the rexception will be thrown with the
384 // cause of the problem of the first URL remembered
385 if (it == info.baseUrlsBegin())
386 rexception.remember( e );
387 else
388 rexception.addHistory( e.asUserString() );
389 }
390 } // for every url
391 ERR << "No more urls..." << endl;
392 ZYPP_THROW(rexception);
393
394 }
395
397 {
398 assert_alias(info);
399 Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
400 Pathname productdatapath = rawproductdata_path_for_repoinfo( _options, info );
401
402 if( filesystem::assert_dir(_options.repoCachePath) )
403 {
404 Exception ex(str::form( _("Can't create %s"), _options.repoCachePath.c_str()) );
405 ZYPP_THROW(ex);
406 }
407 RepoStatus raw_metadata_status = metadataStatus(info);
408 if ( raw_metadata_status.empty() )
409 {
410 /* if there is no cache at this point, we refresh the raw
411 in case this is the first time - if it's !autorefresh,
412 we may still refresh */
413 refreshMetadata(info, RefreshIfNeeded, progressrcv );
414 raw_metadata_status = metadataStatus(info);
415 }
416
417 bool needs_cleaning = false;
418 if ( isCached( info ) )
419 {
420 MIL << info.alias() << " is already cached." << endl;
421 RepoStatus cache_status = cacheStatus(info);
422
423 if ( cache_status == raw_metadata_status )
424 {
425 MIL << info.alias() << " cache is up to date with metadata." << endl;
426 if ( policy == BuildIfNeeded )
427 {
428 // On the fly add missing solv.idx files for bash completion.
429 const Pathname & base = solv_path_for_repoinfo( _options, info);
430 if ( ! PathInfo(base/"solv.idx").isExist() )
431 sat::updateSolvFileIndex( base/"solv" );
432
433 return;
434 }
435 else {
436 MIL << info.alias() << " cache rebuild is forced" << endl;
437 }
438 }
439
440 needs_cleaning = true;
441 }
442
443 ProgressData progress(100);
445 progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
446 progress.name(str::form(_("Building repository '%s' cache"), info.label().c_str()));
447 progress.toMin();
448
449 if (needs_cleaning)
450 {
451 cleanCache(info);
452 }
453
454 MIL << info.alias() << " building cache..." << info.type() << endl;
455
456 Pathname base = solv_path_for_repoinfo( _options, info);
457
458 if( filesystem::assert_dir(base) )
459 {
460 Exception ex(str::form( _("Can't create %s"), base.c_str()) );
461 ZYPP_THROW(ex);
462 }
463
464 if( ! PathInfo(base).userMayW() )
465 {
466 Exception ex(str::form( _("Can't create cache at %s - no writing permissions."), base.c_str()) );
467 ZYPP_THROW(ex);
468 }
469 Pathname solvfile = base / "solv";
470
471 // do we have type?
472 repo::RepoType repokind = info.type();
473
474 // if the type is unknown, try probing.
475 switch ( repokind.toEnum() )
476 {
477 case RepoType::NONE_e:
478 // unknown, probe the local metadata
479 repokind = probeCache( productdatapath );
480 break;
481 default:
482 break;
483 }
484
485 MIL << "repo type is " << repokind << endl;
486
487 switch ( repokind.toEnum() )
488 {
489 case RepoType::RPMMD_e :
490 case RepoType::YAST2_e :
492 {
493 // Take care we unlink the solvfile on exception
494 ManagedFile guard( solvfile, filesystem::unlink );
495 scoped_ptr<MediaMounter> forPlainDirs;
496
498 cmd.push_back( PathInfo( "/usr/bin/repo2solv" ).isFile() ? "repo2solv" : "repo2solv.sh" );
499 // repo2solv expects -o as 1st arg!
500 cmd.push_back( "-o" );
501 cmd.push_back( solvfile.asString() );
502 cmd.push_back( "-X" ); // autogenerate pattern from pattern-package
503 // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages
504
505 if ( repokind == RepoType::RPMPLAINDIR )
506 {
507 forPlainDirs.reset( new MediaMounter( info.url() ) );
508 // recusive for plaindir as 2nd arg!
509 cmd.push_back( "-R" );
510 // FIXME this does only work form dir: URLs
511 cmd.push_back( forPlainDirs->getPathName( info.path() ).c_str() );
512 }
513 else
514 cmd.push_back( productdatapath.asString() );
515
517 std::string errdetail;
518
519 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
520 WAR << " " << output;
521 errdetail += output;
522 }
523
524 int ret = prog.close();
525 if ( ret != 0 )
526 {
527 RepoException ex(info, str::form( _("Failed to cache repo (%d)."), ret ));
528 ex.addHistory( str::Str() << prog.command() << endl << errdetail << prog.execError() ); // errdetail lines are NL-terminaled!
529 ZYPP_THROW(ex);
530 }
531
532 // We keep it.
533 guard.resetDispose();
534 sat::updateSolvFileIndex( solvfile ); // content digest for zypper bash completion
535 }
536 break;
537 default:
538 ZYPP_THROW(RepoUnknownTypeException( info, _("Unhandled repository type") ));
539 break;
540 }
541 // update timestamp and checksum
542 setCacheStatus(info, raw_metadata_status);
543 MIL << "Commit cache.." << endl;
544 progress.toMax();
545 }
546
548
549
556 repo::RepoType RepoManager::Impl::probe( const Url & url, const Pathname & path ) const
557 {
558 using namespace zyppng;
559 using namespace zyppng::operators;
560 using zyppng::operators::operator|;
561
562 auto ctx = zyppng::SyncContext::create();
563 auto res = ctx->provider()->attachMedia( url, zyppng::ProvideMediaSpec() )
564 | and_then( [&]( auto mediaHandle ) {
565 return zyppng::RepoManagerWorkflow::probeRepoType( ctx, mediaHandle, path );
566 });
567
568 if ( !res ) {
569 ZYPP_RETHROW ( res.error() );
570 }
571 return res.get();
572 }
573
575
577 {
578 try
579 {
580 RepoManagerBaseImpl::loadFromCache( info, progressrcv );
581 }
582 catch ( const Exception & exp )
583 {
584 ZYPP_CAUGHT( exp );
585 MIL << "Try to handle exception by rebuilding the solv-file" << endl;
586 cleanCache( info, progressrcv );
587 buildCache( info, BuildIfNeeded, progressrcv );
588
589 sat::Pool::instance().addRepoSolv( solv_path_for_repoinfo(_options, info) / "solv", info );
590 }
591 }
592
594
596 {
597 assert_alias(info);
598
599 ProgressData progress(100);
601 progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
602 progress.name(str::form(_("Adding repository '%s'"), info.label().c_str()));
603 progress.toMin();
604
605 MIL << "Try adding repo " << info << endl;
606
607 RepoInfo tosave = info;
608 if ( repos().find(tosave) != repos().end() )
610
611 // check the first url for now
612 if ( _options.probe )
613 {
614 DBG << "unknown repository type, probing" << endl;
615 assert_urls(tosave);
616
617 RepoType probedtype( probe( tosave.url(), info.path() ) );
618 if ( probedtype == RepoType::NONE )
620 else
621 tosave.setType(probedtype);
622 }
623
624 progress.set(50);
625
627
628 progress.toMax();
629 MIL << "done" << endl;
630 }
631
632
633 void RepoManager::Impl::addRepositories( const Url & url, const ProgressData::ReceiverFnc & progressrcv )
634 {
635 std::list<RepoInfo> repos = readRepoFile(url);
636 for ( std::list<RepoInfo>::const_iterator it = repos.begin();
637 it != repos.end();
638 ++it )
639 {
640 // look if the alias is in the known repos.
641 for_ ( kit, repoBegin(), repoEnd() )
642 {
643 if ( (*it).alias() == (*kit).alias() )
644 {
645 ERR << "To be added repo " << (*it).alias() << " conflicts with existing repo " << (*kit).alias() << endl;
647 }
648 }
649 }
650
651 std::string filename = Pathname(url.getPathName()).basename();
652
653 if ( filename == Pathname() )
654 {
655 // TranslatorExplanation '%s' is an URL
656 ZYPP_THROW(RepoException(str::form( _("Invalid repo file name at '%s'"), url.asString().c_str() )));
657 }
658
659 // assert the directory exists
660 filesystem::assert_dir(_options.knownReposPath);
661
662 Pathname repofile = generateNonExistingName(_options.knownReposPath, filename);
663 // now we have a filename that does not exists
664 MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << endl;
665
666 std::ofstream file(repofile.c_str());
667 if (!file)
668 {
669 // TranslatorExplanation '%s' is a filename
670 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
671 }
672
673 for ( std::list<RepoInfo>::iterator it = repos.begin();
674 it != repos.end();
675 ++it )
676 {
677 MIL << "Saving " << (*it).alias() << endl;
678 it->dumpAsIniOn(file);
679 it->setFilepath(repofile);
680 it->setMetadataPath( rawcache_path_for_repoinfo( _options, *it ) );
681 it->setPackagesPath( packagescache_path_for_repoinfo( _options, *it ) );
682 reposManip().insert(*it);
683
684 HistoryLog(_options.rootDir).addRepository(*it);
685 }
686
687 MIL << "done" << endl;
688 }
689
691 {
693 ProgressReportAdaptor adapt( progressrcv, report );
694 removeRepositoryImpl( info, std::ref(adapt) );
695 }
696
698 //
699 // Services
700 //
702
704 {
705 // copy the set of services since refreshService
706 // can eventually invalidate the iterator
708 for_( it, services.begin(), services.end() )
709 {
710 if ( !it->enabled() )
711 continue;
712
713 try {
714 refreshService(*it, options_r);
715 }
716 catch ( const repo::ServicePluginInformalException & e )
717 { ;/* ignore ServicePluginInformalException */ }
718 }
719 }
720
721 void RepoManager::Impl::refreshService( const std::string & alias, const RefreshServiceOptions & options_r )
722 {
723 ServiceInfo service( getService( alias ) );
724 assert_alias( service );
725 assert_url( service );
726 MIL << "Going to refresh service '" << service.alias() << "', url: " << service.url() << ", opts: " << options_r << endl;
727
728 if ( service.ttl() && !( options_r.testFlag( RefreshService_forceRefresh) || options_r.testFlag( RefreshService_restoreStatus ) ) )
729 {
730 // Service defines a TTL; maybe we can re-use existing data without refresh.
731 Date lrf = service.lrf();
732 if ( lrf )
733 {
734 Date now( Date::now() );
735 if ( lrf <= now )
736 {
737 if ( (lrf+=service.ttl()) > now ) // lrf+= !
738 {
739 MIL << "Skip: '" << service.alias() << "' metadata valid until " << lrf << endl;
740 return;
741 }
742 }
743 else
744 WAR << "Force: '" << service.alias() << "' metadata last refresh in the future: " << lrf << endl;
745 }
746 }
747
748 // NOTE: It might be necessary to modify and rewrite the service info.
749 // Either when probing the type, or when adjusting the repositories
750 // enable/disable state.:
751 bool serviceModified = false;
752
754
755 // if the type is unknown, try probing.
756 if ( service.type() == repo::ServiceType::NONE )
757 {
758 repo::ServiceType type = probeService( service.url() );
759 if ( type != ServiceType::NONE )
760 {
761 service.setProbedType( type ); // lazy init!
762 serviceModified = true;
763 }
764 }
765
766 // get target distro identifier
767 std::string servicesTargetDistro = _options.servicesTargetDistro;
768 if ( servicesTargetDistro.empty() )
769 {
770 servicesTargetDistro = Target::targetDistribution( Pathname() );
771 }
772 DBG << "ServicesTargetDistro: " << servicesTargetDistro << endl;
773
774 // parse it
775 Date::Duration origTtl = service.ttl(); // FIXME Ugly hack: const service.ttl modified when parsing
776 RepoCollector collector(servicesTargetDistro);
777 // FIXME Ugly hack: ServiceRepos may throw ServicePluginInformalException
778 // which is actually a notification. Using an exception for this
779 // instead of signal/callback is bad. Needs to be fixed here, in refreshServices()
780 // and in zypper.
781 std::pair<DefaultIntegral<bool,false>, repo::ServicePluginInformalException> uglyHack;
782 try {
783 // FIXME bsc#1080693: Shortcoming of (plugin)services (and repos as well) is that they
784 // are not aware of the RepoManagers rootDir. The service url, as created in known_services,
785 // contains the full path to the script. The script however has to be executed chrooted.
786 // Repos would need to know the RepoMangers rootDir to use the correct vars.d to replace
787 // repos variables. Until RepoInfoBase is aware if the rootDir, we need to explicitly pass it
788 // to ServiceRepos.
789 ServiceRepos( _options.rootDir, service, bind( &RepoCollector::collect, &collector, _1 ) );
790 }
791 catch ( const repo::ServicePluginInformalException & e )
792 {
793 /* ignore ServicePluginInformalException and throw later */
794 uglyHack.first = true;
795 uglyHack.second = e;
796 }
797 if ( service.ttl() != origTtl ) // repoindex.xml changed ttl
798 {
799 if ( !service.ttl() )
800 service.setLrf( Date() ); // don't need lrf when zero ttl
801 serviceModified = true;
802 }
804 // On the fly remember the new repo states as defined the reopoindex.xml.
805 // Move into ServiceInfo later.
806 ServiceInfo::RepoStates newRepoStates;
807
808 // set service alias and base url for all collected repositories
809 for_( it, collector.repos.begin(), collector.repos.end() )
810 {
811 // First of all: Prepend service alias:
812 it->setAlias( str::form( "%s:%s", service.alias().c_str(), it->alias().c_str() ) );
813 // set reference to the parent service
814 it->setService( service.alias() );
815
816 // remember the new parsed repo state
817 newRepoStates[it->alias()] = *it;
818
819 // - If the repo url was not set by the repoindex parser, set service's url.
820 // - Libzypp currently has problem with separate url + path handling so just
821 // append a path, if set, to the baseurls
822 // - Credentials in the url authority will be extracted later, either if the
823 // repository is added or if we check for changed urls.
824 Pathname path;
825 if ( !it->path().empty() )
826 {
827 if ( it->path() != "/" )
828 path = it->path();
829 it->setPath("");
830 }
831
832 if ( it->baseUrlsEmpty() )
833 {
834 Url url( service.rawUrl() );
835 if ( !path.empty() )
836 url.setPathName( url.getPathName() / path );
837 it->setBaseUrl( std::move(url) );
838 }
839 else if ( !path.empty() )
840 {
841 RepoInfo::url_set urls( it->rawBaseUrls() );
842 for ( Url & url : urls )
843 {
844 url.setPathName( url.getPathName() / path );
845 }
846 it->setBaseUrls( std::move(urls) );
847 }
848 }
849
851 // Now compare collected repos with the ones in the system...
852 //
853 RepoInfoList oldRepos;
854 getRepositoriesInService( service.alias(), std::back_inserter( oldRepos ) );
855
857 // find old repositories to remove...
858 for_( oldRepo, oldRepos.begin(), oldRepos.end() )
859 {
860 if ( ! foundAliasIn( oldRepo->alias(), collector.repos ) )
861 {
862 if ( oldRepo->enabled() )
863 {
864 // Currently enabled. If this was a user modification remember the state.
865 const auto & last = service.repoStates().find( oldRepo->alias() );
866 if ( last != service.repoStates().end() && ! last->second.enabled )
867 {
868 DBG << "Service removes user enabled repo " << oldRepo->alias() << endl;
869 service.addRepoToEnable( oldRepo->alias() );
870 serviceModified = true;
871 }
872 else
873 DBG << "Service removes enabled repo " << oldRepo->alias() << endl;
874 }
875 else
876 DBG << "Service removes disabled repo " << oldRepo->alias() << endl;
877
878 removeRepository( *oldRepo );
879 }
880 }
881
883 // create missing repositories and modify existing ones if needed...
884 UrlCredentialExtractor urlCredentialExtractor( _options.rootDir ); // To collect any credentials stored in repo URLs
885 for_( it, collector.repos.begin(), collector.repos.end() )
886 {
887 // User explicitly requested the repo being enabled?
888 // User explicitly requested the repo being disabled?
889 // And hopefully not both ;) If so, enable wins.
890
891 TriBool toBeEnabled( indeterminate ); // indeterminate - follow the service request
892 DBG << "Service request to " << (it->enabled()?"enable":"disable") << " service repo " << it->alias() << endl;
893
894 if ( options_r.testFlag( RefreshService_restoreStatus ) )
895 {
896 DBG << "Opt RefreshService_restoreStatus " << it->alias() << endl;
897 // this overrides any pending request!
898 // Remove from enable request list.
899 // NOTE: repoToDisable is handled differently.
900 // It gets cleared on each refresh.
901 service.delRepoToEnable( it->alias() );
902 // toBeEnabled stays indeterminate!
903 }
904 else
905 {
906 if ( service.repoToEnableFind( it->alias() ) )
907 {
908 DBG << "User request to enable service repo " << it->alias() << endl;
909 toBeEnabled = true;
910 // Remove from enable request list.
911 // NOTE: repoToDisable is handled differently.
912 // It gets cleared on each refresh.
913 service.delRepoToEnable( it->alias() );
914 serviceModified = true;
915 }
916 else if ( service.repoToDisableFind( it->alias() ) )
917 {
918 DBG << "User request to disable service repo " << it->alias() << endl;
919 toBeEnabled = false;
920 }
921 }
922
923 RepoInfoList::iterator oldRepo( findAlias( it->alias(), oldRepos ) );
924 if ( oldRepo == oldRepos.end() )
925 {
926 // Not found in oldRepos ==> a new repo to add
927
928 // Make sure the service repo is created with the appropriate enablement
929 if ( ! indeterminate(toBeEnabled) )
930 it->setEnabled( ( bool ) toBeEnabled );
931
932 DBG << "Service adds repo " << it->alias() << " " << (it->enabled()?"enabled":"disabled") << endl;
933 addRepository( *it );
934 }
935 else
936 {
937 // ==> an exising repo to check
938 bool oldRepoModified = false;
939
940 if ( indeterminate(toBeEnabled) )
941 {
942 // No user request: check for an old user modificaton otherwise follow service request.
943 // NOTE: Assert toBeEnabled is boolean afterwards!
944 if ( oldRepo->enabled() == it->enabled() )
945 toBeEnabled = it->enabled(); // service requests no change to the system
946 else if (options_r.testFlag( RefreshService_restoreStatus ) )
947 {
948 toBeEnabled = it->enabled(); // RefreshService_restoreStatus forced
949 DBG << "Opt RefreshService_restoreStatus " << it->alias() << " forces " << (toBeEnabled?"enabled":"disabled") << endl;
950 }
951 else
952 {
953 const auto & last = service.repoStates().find( oldRepo->alias() );
954 if ( last == service.repoStates().end() || last->second.enabled != it->enabled() )
955 toBeEnabled = it->enabled(); // service request has changed since last refresh -> follow
956 else
957 {
958 toBeEnabled = oldRepo->enabled(); // service request unchaned since last refresh -> keep user modification
959 DBG << "User modified service repo " << it->alias() << " may stay " << (toBeEnabled?"enabled":"disabled") << endl;
960 }
961 }
962 }
963
964 // changed enable?
965 if ( toBeEnabled == oldRepo->enabled() )
966 {
967 DBG << "Service repo " << it->alias() << " stays " << (oldRepo->enabled()?"enabled":"disabled") << endl;
968 }
969 else if ( toBeEnabled )
970 {
971 DBG << "Service repo " << it->alias() << " gets enabled" << endl;
972 oldRepo->setEnabled( true );
973 oldRepoModified = true;
974 }
975 else
976 {
977 DBG << "Service repo " << it->alias() << " gets disabled" << endl;
978 oldRepo->setEnabled( false );
979 oldRepoModified = true;
980 }
981
982 // all other attributes follow the service request:
983
984 // changed name (raw!)
985 if ( oldRepo->rawName() != it->rawName() )
986 {
987 DBG << "Service repo " << it->alias() << " gets new NAME " << it->rawName() << endl;
988 oldRepo->setName( it->rawName() );
989 oldRepoModified = true;
990 }
991
992 // changed autorefresh
993 if ( oldRepo->autorefresh() != it->autorefresh() )
994 {
995 DBG << "Service repo " << it->alias() << " gets new AUTOREFRESH " << it->autorefresh() << endl;
996 oldRepo->setAutorefresh( it->autorefresh() );
997 oldRepoModified = true;
998 }
999
1000 // changed priority?
1001 if ( oldRepo->priority() != it->priority() )
1002 {
1003 DBG << "Service repo " << it->alias() << " gets new PRIORITY " << it->priority() << endl;
1004 oldRepo->setPriority( it->priority() );
1005 oldRepoModified = true;
1006 }
1007
1008 // changed url?
1009 {
1010 RepoInfo::url_set newUrls( it->rawBaseUrls() );
1011 urlCredentialExtractor.extract( newUrls ); // Extract! to prevent passwds from disturbing the comparison below
1012 if ( oldRepo->rawBaseUrls() != newUrls )
1013 {
1014 DBG << "Service repo " << it->alias() << " gets new URLs " << newUrls << endl;
1015 oldRepo->setBaseUrls( std::move(newUrls) );
1016 oldRepoModified = true;
1017 }
1018 }
1019
1020 // changed gpg check settings?
1021 // ATM only plugin services can set GPG values.
1022 if ( service.type() == ServiceType::PLUGIN )
1023 {
1024 TriBool ogpg[3]; // Gpg RepoGpg PkgGpg
1025 TriBool ngpg[3];
1026 oldRepo->getRawGpgChecks( ogpg[0], ogpg[1], ogpg[2] );
1027 it-> getRawGpgChecks( ngpg[0], ngpg[1], ngpg[2] );
1028#define Z_CHKGPG(I,N) \
1029 if ( ! sameTriboolState( ogpg[I], ngpg[I] ) ) \
1030 { \
1031 DBG << "Service repo " << it->alias() << " gets new "#N"Check " << ngpg[I] << endl; \
1032 oldRepo->set##N##Check( ngpg[I] ); \
1033 oldRepoModified = true; \
1034 }
1035 Z_CHKGPG( 0, Gpg );
1036 Z_CHKGPG( 1, RepoGpg );
1037 Z_CHKGPG( 2, PkgGpg );
1038#undef Z_CHKGPG
1039 }
1040
1041 // save if modified:
1042 if ( oldRepoModified )
1043 {
1044 modifyRepository( oldRepo->alias(), *oldRepo );
1045 }
1046 }
1047 }
1048
1049 // Unlike reposToEnable, reposToDisable is always cleared after refresh.
1050 if ( ! service.reposToDisableEmpty() )
1051 {
1052 service.clearReposToDisable();
1053 serviceModified = true;
1054 }
1055
1056 // Remember original service request for next refresh
1057 if ( service.repoStates() != newRepoStates )
1058 {
1059 service.setRepoStates( std::move(newRepoStates) );
1060 serviceModified = true;
1061 }
1062
1064 // save service if modified: (unless a plugin service)
1065 if ( service.type() != ServiceType::PLUGIN )
1066 {
1067 if ( service.ttl() )
1068 {
1069 service.setLrf( Date::now() ); // remember last refresh
1070 serviceModified = true; // or use a cookie file
1071 }
1072
1073 if ( serviceModified )
1074 {
1075 // write out modified service file.
1076 modifyService( service.alias(), service );
1077 }
1078 }
1079
1080 if ( uglyHack.first )
1081 {
1082 throw( uglyHack.second ); // intentionally not ZYPP_THROW
1083 }
1084 }
1085
1087
1089 {
1090 try
1091 {
1092 MediaSetAccess access(url);
1093 if ( access.doesFileExist("/repo/repoindex.xml") )
1094 return repo::ServiceType::RIS;
1095 }
1096 catch ( const media::MediaException &e )
1097 {
1098 ZYPP_CAUGHT(e);
1099 // TranslatorExplanation '%s' is an URL
1100 RepoException enew(str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
1101 enew.remember(e);
1102 ZYPP_THROW(enew);
1103 }
1104 catch ( const Exception &e )
1105 {
1106 ZYPP_CAUGHT(e);
1107 // TranslatorExplanation '%s' is an URL
1108 Exception enew(str::form( _("Unknown error reading from '%s'"), url.asString().c_str() ));
1109 enew.remember(e);
1110 ZYPP_THROW(enew);
1111 }
1112
1113 return repo::ServiceType::NONE;
1114 }
1115
1117 {
1118 try {
1119
1120 if ( !ZConfig::instance().geoipEnabled() ) {
1121 MIL << "GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl;
1122 return;
1123 }
1124
1125 std::vector<std::string> hosts;
1126 for ( const auto &baseUrl : urls ) {
1127 const auto &host = baseUrl.getHost();
1128 if ( zypp::any_of( ZConfig::instance().geoipHostnames(), [&host]( const auto &elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) {
1129 hosts.push_back( host );
1130 break;
1131 }
1132 }
1133
1134 if ( hosts.empty() ) {
1135 MIL << "No configured geoip URL found, not updating geoip data" << std::endl;
1136 return;
1137 }
1138
1139 const auto &geoIPCache = ZConfig::instance().geoipCachePath();
1140
1141 if ( filesystem::assert_dir( geoIPCache ) != 0 ) {
1142 MIL << "Unable to create cache directory for GeoIP." << std::endl;
1143 return;
1144 }
1145
1146 if ( !PathInfo(geoIPCache).userMayRWX() ) {
1147 MIL << "No access rights for the GeoIP cache directory." << std::endl;
1148 return;
1149 }
1150
1151 // remove all older cache entries
1152 filesystem::dirForEachExt( geoIPCache, []( const Pathname &dir, const filesystem::DirEntry &entry ){
1153 if ( entry.type != filesystem::FT_FILE )
1154 return true;
1155
1156 PathInfo pi( dir/entry.name );
1157 auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t( pi.mtime() );
1158 if ( age < std::chrono::hours(24) )
1159 return true;
1160
1161 MIL << "Removing GeoIP file for " << entry.name << " since it's older than 24hrs." << std::endl;
1162 filesystem::unlink( dir/entry.name );
1163 return true;
1164 });
1165
1166 // go over all found hostnames
1167 std::for_each( hosts.begin(), hosts.end(), [ & ]( const std::string &hostname ) {
1168
1169 // do not query files that are still there
1170 if ( zypp::PathInfo( geoIPCache / hostname ).isExist() ) {
1171 MIL << "Skipping GeoIP request for " << hostname << " since a valid cache entry exists." << std::endl;
1172 return;
1173 }
1174
1175 MIL << "Query GeoIP for " << hostname << std::endl;
1176
1177 zypp::Url url;
1178 try
1179 {
1180 url.setHost(hostname);
1181 url.setScheme("https");
1182 }
1183 catch(const zypp::Exception &e )
1184 {
1185 ZYPP_CAUGHT(e);
1186 MIL << "Ignoring invalid GeoIP hostname: " << hostname << std::endl;
1187 return;
1188 }
1189
1190 MediaSetAccess acc( url );
1191 zypp::ManagedFile file;
1192 try {
1193 // query the file from the server
1195
1196 } catch ( const zypp::Exception &e ) {
1197 ZYPP_CAUGHT(e);
1198 MIL << "Failed to query GeoIP from hostname: " << hostname << std::endl;
1199 return;
1200 }
1201 if ( !file->empty() ) {
1202
1203 constexpr auto writeHostToFile = []( const Pathname &fName, const std::string &host ){
1204 std::ofstream out;
1205 out.open( fName.asString(), std::ios_base::trunc );
1206 if ( out.is_open() ) {
1207 out << host << std::endl;
1208 } else {
1209 MIL << "Failed to create/open GeoIP cache file " << fName << std::endl;
1210 }
1211 };
1212
1213 std::string geoipMirror;
1214 try {
1215 xml::Reader reader( *file );
1216 if ( reader.seekToNode( 1, "host" ) ) {
1217 const auto &str = reader.nodeText().asString();
1218
1219 // make a dummy URL to ensure the hostname is valid
1220 zypp::Url testUrl;
1221 testUrl.setHost(str);
1222 testUrl.setScheme("https");
1223
1224 if ( testUrl.isValid() ) {
1225 MIL << "Storing geoIP redirection: " << hostname << " -> " << str << std::endl;
1226 geoipMirror = str;
1227 }
1228
1229 } else {
1230 MIL << "No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl;
1231 }
1232 } catch ( const zypp::Exception &e ) {
1233 ZYPP_CAUGHT(e);
1234 MIL << "Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl;
1235 }
1236
1237 writeHostToFile( geoIPCache / hostname, geoipMirror );
1238 }
1239 });
1240
1241 } catch ( const zypp::Exception &e ) {
1242 ZYPP_CAUGHT(e);
1243 MIL << "Failed to query GeoIP data." << std::endl;
1244 }
1245 }
1246
1248 //
1249 // CLASS NAME : RepoManager
1250 //
1252
1254 : _pimpl( new Impl(std::move(opt)) )
1255 {}
1256
1259
1261 { return _pimpl->repoEmpty(); }
1262
1265
1268
1271
1272 RepoInfo RepoManager::getRepo( const std::string & alias ) const
1273 { return _pimpl->getRepo( alias ); }
1274
1275 bool RepoManager::hasRepo( const std::string & alias ) const
1276 { return _pimpl->hasRepo( alias ); }
1277
1278 std::string RepoManager::makeStupidAlias( const Url & url_r )
1279 {
1280 std::string ret( url_r.getScheme() );
1281 if ( ret.empty() )
1282 ret = "repo-";
1283 else
1284 ret += "-";
1285
1286 std::string host( url_r.getHost() );
1287 if ( ! host.empty() )
1288 {
1289 ret += host;
1290 ret += "-";
1291 }
1292
1293 static Date::ValueType serial = Date::now();
1294 ret += Digest::digest( Digest::sha1(), str::hexstring( ++serial ) +url_r.asCompleteString() ).substr(0,8);
1295 return ret;
1296 }
1297
1299 { return _pimpl->metadataStatus( info ); }
1300
1303
1305 { return _pimpl->metadataPath( info ); }
1306
1308 { return _pimpl->packagesPath( info ); }
1309
1311 { return _pimpl->refreshMetadata( info, policy, progressrcv ); }
1312
1313 void RepoManager::cleanMetadata( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
1314 { return _pimpl->cleanMetadata( info, progressrcv ); }
1315
1316 void RepoManager::cleanPackages( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
1317 { return _pimpl->cleanPackages( info, progressrcv ); }
1318
1320 { return _pimpl->cacheStatus( info ); }
1321
1322 void RepoManager::buildCache( const RepoInfo &info, CacheBuildPolicy policy, const ProgressData::ReceiverFnc & progressrcv )
1323 { return _pimpl->buildCache( info, policy, progressrcv ); }
1324
1325 void RepoManager::cleanCache( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
1326 { return _pimpl->cleanCache( info, progressrcv ); }
1327
1328 bool RepoManager::isCached( const RepoInfo &info ) const
1329 { return _pimpl->isCached( info ); }
1330
1331 void RepoManager::loadFromCache( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
1332 { return _pimpl->loadFromCache( info, progressrcv ); }
1333
1335 { return _pimpl->cleanCacheDirGarbage( progressrcv ); }
1336
1337 repo::RepoType RepoManager::probe( const Url & url, const Pathname & path ) const
1338 { return _pimpl->probe( url, path ); }
1339
1341 { return _pimpl->probe( url ); }
1342
1343 void RepoManager::addRepository( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
1344 { return _pimpl->addRepository( info, progressrcv ); }
1345
1346 void RepoManager::addRepositories( const Url &url, const ProgressData::ReceiverFnc & progressrcv )
1347 { return _pimpl->addRepositories( url, progressrcv ); }
1348
1349 void RepoManager::removeRepository( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
1350 { return _pimpl->removeRepository( info, progressrcv ); }
1351
1352 void RepoManager::modifyRepository( const std::string &alias, const RepoInfo & newinfo, const ProgressData::ReceiverFnc & progressrcv )
1353 { return _pimpl->modifyRepository( alias, newinfo, progressrcv ); }
1354
1355 RepoInfo RepoManager::getRepositoryInfo( const std::string &alias, const ProgressData::ReceiverFnc & progressrcv )
1356 { return _pimpl->getRepositoryInfo( alias ); }
1357
1358 RepoInfo RepoManager::getRepositoryInfo( const Url & url, const url::ViewOption & urlview, const ProgressData::ReceiverFnc & progressrcv )
1359 { return _pimpl->getRepositoryInfo( url, urlview ); }
1360
1362 { return _pimpl->serviceEmpty(); }
1363
1366
1369
1372
1373 ServiceInfo RepoManager::getService( const std::string & alias ) const
1374 { return _pimpl->getService( alias ); }
1375
1376 bool RepoManager::hasService( const std::string & alias ) const
1377 { return _pimpl->hasService( alias ); }
1378
1380 { return _pimpl->probeService( url ); }
1381
1382 void RepoManager::addService( const std::string & alias, const Url& url )
1383 { return _pimpl->addService( alias, url ); }
1384
1385 void RepoManager::addService( const ServiceInfo & service )
1386 { return _pimpl->addService( service ); }
1387
1388 void RepoManager::removeService( const std::string & alias )
1389 { return _pimpl->removeService( alias ); }
1390
1392 { return _pimpl->removeService( service ); }
1393
1395 { return _pimpl->refreshServices( options_r ); }
1396
1397 void RepoManager::refreshService( const std::string & alias, const RefreshServiceOptions & options_r )
1398 { return _pimpl->refreshService( alias, options_r ); }
1399
1400 void RepoManager::refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r )
1401 { return _pimpl->refreshService( service, options_r ); }
1402
1403 void RepoManager::modifyService( const std::string & oldAlias, const ServiceInfo & service )
1404 { return _pimpl->modifyService( oldAlias, service ); }
1405
1407 { return _pimpl->refreshGeoIPData( urls ); }
1408
1410
1411 std::ostream & operator<<( std::ostream & str, const RepoManager & obj )
1412 { return str << *obj._pimpl; }
1413
1415} // namespace zypp
#define Z_CHKGPG(I, N)
#define OPT_PROGRESS
media::MediaAccessId _mid
#define OUTS(V)
void resetDispose()
Set no dispose function.
Store and operate on date (time_t).
Definition Date.h:33
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
std::string asUserString() const
Translated error message as string suitable for the user.
Definition Exception.cc:101
void addHistory(const std::string &msg_r)
Add some message text to the history.
Definition Exception.cc:159
void remember(const Exception &old_r)
Store an other Exception as history.
Definition Exception.cc:124
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.
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.
Pathname provideOptionalFile(const Pathname &file, unsigned media_nr=1)
Provides an optional file from media media_nr.
bool doesFileExist(const Pathname &file, unsigned media_nr=1)
Checks if a file exists on the specified media, with user callbacks.
Maintain [min,max] and counter (value) for progress counting.
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
bool toMax()
Set counter value to current max value (unless no range).
void name(const std::string &name_r)
Set counter name.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
bool toMin()
Set counter value to current min value.
bool set(value_type val_r)
Set new counter value.
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
void setType(const repo::RepoType &t)
set the repository type
Definition RepoInfo.cc:568
std::list< Url > url_set
Definition RepoInfo.h:108
creates and provides information about known sources.
Definition RepoManager.h:58
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.
@ REFRESH_NEEDED
refresh is needed
@ REPO_UP_TO_DATE
repository not changed
ServiceSet::const_iterator ServiceConstIterator
Definition RepoManager.h:67
void addService(const std::string &alias, const Url &url)
Adds a new service by its alias and URL.
bool isCached(const RepoInfo &info) const
Whether a repository exists in cache.
void removeService(const std::string &alias)
Removes service specified by its name.
RepoInfo getRepo(const std::string &alias) const
Find RepoInfo by alias or return RepoInfo::noRepo.
repo::ServiceType probeService(const Url &url) const
Probe the type or the service.
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
void cleanCache(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
clean local cache
RefreshServiceFlags RefreshServiceOptions
Options tuning RefreshService.
void refreshServices(const RefreshServiceOptions &options_r=RefreshServiceOptions())
Refreshes all enabled services.
void addRepository(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Adds a repository to the list of known repositories.
bool repoEmpty() const
Pathname metadataPath(const RepoInfo &info) const
Path where the metadata is downloaded and kept.
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 addRepositories(const Url &url, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Adds repositores from a repo file to the list of known repositories.
void refreshMetadata(const RepoInfo &info, RawMetadataRefreshPolicy policy=RefreshIfNeeded, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Refresh local raw cache.
void refreshGeoIp(const RepoInfo::url_set &urls)
void refreshService(const std::string &alias, const RefreshServiceOptions &options_r=RefreshServiceOptions())
Refresh specific service.
ServiceConstIterator serviceEnd() const
Iterator to place behind last service in internal storage.
@ RefreshService_forceRefresh
Force refresh even if TTL is not reached.
Definition RepoManager.h:97
@ RefreshService_restoreStatus
Force restoring repo enabled/disabled status.
Definition RepoManager.h:96
ServiceConstIterator serviceBegin() const
Iterator to first service in internal storage.
RepoSizeType repoSize() const
void modifyRepository(const std::string &alias, const RepoInfo &newinfo, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Modify repository attributes.
Iterable< ServiceConstIterator > services() const
Iterate the known services.
void removeRepository(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Remove the best matching repository from known repos list.
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)
ServiceInfo getService(const std::string &alias) const
Finds ServiceInfo by alias or return ServiceInfo::noService.
RefreshCheckStatus checkIfToRefreshMetadata(const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy=RefreshIfNeeded)
Checks whether to refresh metadata for specified repository and url.
RepoSet::size_type RepoSizeType
Definition RepoManager.h:73
RepoConstIterator repoBegin() const
Iterable< RepoConstIterator > repos() const
Iterate the known repositories.
void buildCache(const RepoInfo &info, CacheBuildPolicy policy=BuildIfNeeded, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Refresh local cache.
RepoManager(RepoManagerOptions options=RepoManagerOptions())
void getRepositoriesInService(const std::string &alias, OutputIterator out) const
fill to output iterator repositories in service name.
void loadFromCache(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Load resolvables into the pool.
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.
repo::RepoType probe(const Url &url, const Pathname &path) const
Probe repo metadata type.
Track changing files or directories.
Definition RepoStatus.h:41
bool empty() const
Whether the status is empty (empty checksum)
Service data.
Definition ServiceInfo.h:37
repo::ServiceType type() const
Service type.
Date::Duration ttl() const
Sugested TTL between two metadata auto-refreshs.
void setLrf(Date lrf_r)
Set date of last refresh.
Date lrf() const
Date of last refresh (if known).
bool repoToDisableFind(const std::string &alias_r) const
Whether alias_r is mentioned in ReposToDisable.
bool repoToEnableFind(const std::string &alias_r) const
Whether alias_r is mentioned in ReposToEnable.
const RepoStates & repoStates() const
Access the remembered repository states.
std::map< std::string, RepoState > RepoStates
Url url() const
The service url.
void setProbedType(const repo::ServiceType &t) const
Lazy init service type.
Url rawUrl() const
The service raw url (no variables replaced)
void addRepoToEnable(const std::string &alias_r)
Add alias_r to the set of ReposToEnable.
void clearReposToDisable()
Clear the set of ReposToDisable.
void delRepoToEnable(const std::string &alias_r)
Remove alias_r from the set of ReposToEnable.
void setRepoStates(RepoStates newStates_r)
Remember a new set of repository states.
bool reposToDisableEmpty() const
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.
bool extract(Url &url_r)
Remember credentials stored in URL authority stripping the passowrd from url_r.
Url manipulation class.
Definition Url.h:92
std::string getScheme() const
Returns the scheme name of the URL.
Definition Url.cc:537
std::string asCompleteString() const
Returns a complete string representation of the Url object.
Definition Url.cc:509
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
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition Url.cc:592
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
static bool schemeIsVolatile(const std::string &scheme_r)
cd dvd
Definition Url.cc:473
Pathname geoipCachePath() const
Path where the geoip caches are kept (/var/cache/zypp/geoip)
Definition ZConfig.cc:1135
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:925
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
Definition PathInfo.h:222
const std::string & asString() const
Return current Pathname as String.
Definition PathInfo.h:249
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
bool empty() const
Test for an empty path.
Definition Pathname.h:116
Just inherits Exception to separate media exceptions.
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
MediaAccessId open(const Url &url, const Pathname &preferred_attach_point="")
Opens the media access for specified with the url.
void attach(MediaAccessId accessId)
Attach the media using the concrete handler (checks all devices).
void close(MediaAccessId accessId)
Close the media access with specified id.
void release(MediaAccessId accessId, const std::string &ejectDev="")
Release the attached media and optionally eject.
Pathname localPath(MediaAccessId accessId, const Pathname &pathname) const
Shortcut for 'localRoot() + pathname', but returns an empty pathname if media is not attached.
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.
Repository addRepoSolv(const Pathname &file_r, const std::string &name_r)
Load Solvables from a solv-file into a Repository named name_r.
Definition Pool.cc:185
static Pool instance()
Singleton ctor.
Definition Pool.h:55
xmlTextReader based interface to iterate xml streams.
Definition Reader.h:96
XmlString nodeText()
If the current node is not empty, advances the reader to the next node, and returns the value.
Definition Reader.cc:122
bool seekToNode(int depth_r, const std::string &name_r)
Definition Reader.cc:194
std::string asString() const
Explicit conversion to std::string.
Definition XmlString.h:77
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:133
Definition Arch.h:364
String related utilities and Regular expression matching.
Namespace intended to collect all environment variables we use.
Definition Env.h:23
bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT()
To trigger appdata refresh unconditionally.
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
unsigned int MediaAccessId
Media manager access Id type.
Definition MediaSource.h:30
SolvableSpec & operator=(const SolvableSpec &)=default
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.
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:30
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 > > 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)
RepoInfo getRepositoryInfo(const std::string &alias)
RepoInfo getRepo(const std::string &alias) const
void cleanCache(const RepoInfo &info, OPT_PROGRESS)
void removeService(const std::string &alias)
ServiceConstIterator serviceEnd() const
void loadFromCache(const RepoInfo &info, OPT_PROGRESS)
RepoConstIterator repoEnd() const
bool hasService(const std::string &alias) const
void cleanPackages(const RepoInfo &info, OPT_PROGRESS, bool isAutoClean=false)
RepoStatus cacheStatus(const RepoInfo &info) const
bool hasRepo(const std::string &alias) const
std::set< ServiceInfo > ServiceSet
ServiceInfo typedefs.
void modifyRepository(const std::string &alias, const RepoInfo &newinfo_r, OPT_PROGRESS)
void cleanMetadata(const RepoInfo &info, OPT_PROGRESS)
Pathname packagesPath(const RepoInfo &info) const
void modifyService(const std::string &oldAlias, const ServiceInfo &newService)
RepoSizeType repoSize() const
static RepoStatus metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
ServiceInfo getService(const std::string &alias) const
RepoConstIterator repoBegin() const
void cleanCacheDirGarbage(OPT_PROGRESS)
bool isCached(const RepoInfo &info) const
ServiceSizeType serviceSize() const
void addService(const ServiceInfo &service)
void addProbedRepository(const RepoInfo &info, repo::RepoType probedType)
ServiceConstIterator serviceBegin() const
Pathname metadataPath(const RepoInfo &info) const
Repo manager settings.
RepoManager implementation.
void refreshService(const std::string &alias, const RefreshServiceOptions &options_r)
Impl & operator=(const Impl &)=delete
repo::ServiceType probeService(const Url &url) const
void refreshServices(const RefreshServiceOptions &options_r)
std::ostream & operator<<(std::ostream &str, const RepoManager::Impl &obj)
Stream output.
Impl(RepoManagerOptions &&opt)
void refreshMetadata(const RepoInfo &info, RawMetadataRefreshPolicy policy, OPT_PROGRESS)
Impl(Impl &&)=delete
Impl * clone() const
clone for RWCOW_pointer
void buildCache(const RepoInfo &info, CacheBuildPolicy policy, OPT_PROGRESS)
void addRepository(const RepoInfo &info, OPT_PROGRESS)
void loadFromCache(const RepoInfo &info, OPT_PROGRESS)
Impl(const Impl &)=default
void refreshGeoIPData(const RepoInfo::url_set &urls)
void addRepositories(const Url &url, OPT_PROGRESS)
void removeRepository(const RepoInfo &info, OPT_PROGRESS) override
zypp_private::repo::PluginRepoverification _pluginRepoverification
RefreshCheckStatus checkIfToRefreshMetadata(const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy)
void refreshService(const ServiceInfo &service, const RefreshServiceOptions &options_r)
repo::RepoType probe(const Url &url, const Pathname &path=Pathname()) const
Probe the metadata type of a repository located at url.
Impl & operator=(Impl &&)=delete
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:29
Type toEnum() const
Definition RepoType.h:49
static const RepoType NONE
Definition RepoType.h:33
static const RepoType RPMPLAINDIR
Definition RepoType.h:32
Functor replacing repository variables.
Service type enumeration.
Definition ServiceType.h:27
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:61
#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: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
Interface to gettext.