libzypp 17.35.19
repomanager.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9
10#include "repomanager.h"
12
13#include <solv/solvversion.h>
14
18#include <zypp-core/zyppng/pipelines/MTry>
19#include <zypp-core/zyppng/pipelines/Transform>
20#include <zypp-core/zyppng/ui/ProgressObserver>
22#include <zypp/HistoryLog.h>
23#include <zypp/ZConfig.h>
24#include <zypp/ZYppCallbacks.h>
25#include <zypp/base/LogTools.h>
28#include <zypp/sat/Pool.h>
32
38
39#include <fstream>
40#include <utility>
41
42#undef ZYPP_BASE_LOGGER_LOGGROUP
43#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager"
44
46 bool IGotIt(); // in readonly-mode
47}
48
49
50namespace zyppng
51{
52 namespace env
53 {
56 {
57 const char * env = getenv("ZYPP_PLUGIN_APPDATA_FORCE_COLLECT");
58 return( env && zypp::str::strToBool( env, true ) );
59 }
60 } // namespace env
61
62 namespace {
68 inline void cleanupNonRepoMetadataFolders( const zypp::Pathname & cachePath_r,
69 const zypp::Pathname & defaultCachePath_r,
70 const std::list<std::string> & repoEscAliases_r )
71 {
72 if ( cachePath_r != defaultCachePath_r )
73 return;
74
75 std::list<std::string> entries;
76 if ( zypp::filesystem::readdir( entries, cachePath_r, false ) == 0 )
77 {
78 entries.sort();
79 std::set<std::string> oldfiles;
80 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
81 std::inserter( oldfiles, oldfiles.end() ) );
82
83 // bsc#1178966: Files or symlinks here have been created by the user
84 // for whatever purpose. It's our cache, so we purge them now before
85 // they may later conflict with directories we need.
87 for ( const std::string & old : oldfiles )
88 {
89 if ( old == zypp::Repository::systemRepoAlias() ) // don't remove the @System solv file
90 continue;
91 pi( cachePath_r/old );
92 if ( pi.isDir() )
94 else
96 }
97 }
98 }
99 } // namespace
100
102 {
103 switch ( obj ) {
104#define OUTS(V) case zypp::RepoManagerFlags::V: str << #V; break
105 OUTS( RefreshIfNeeded );
106 OUTS( RefreshForced );
107 OUTS( RefreshIfNeededIgnoreDelay );
108#undef OUTS
109 }
110 return str;
111 }
112
114 {
115 switch ( obj ) {
116#define OUTS(V) case zypp::RepoManagerFlags::V: str << #V; break
117 OUTS( REFRESH_NEEDED );
118 OUTS( REPO_UP_TO_DATE );
119 OUTS( REPO_CHECK_DELAYED );
120#undef OUTS
121 }
122 return str;
123 }
124
126 {
127 switch ( obj ) {
128#define OUTS(V) case zypp::RepoManagerFlags::V: str << #V; break
129 OUTS( BuildIfNeeded );
130 OUTS( BuildForced );
131#undef OUTS
132 }
133 return str;
134 }
135
136
137 std::string filenameFromAlias(const std::string &alias_r, const std::string &stem_r)
138 {
139 std::string filename( alias_r );
140 // replace slashes with underscores
141 zypp::str::replaceAll( filename, "/", "_" );
142
143 filename = zypp::Pathname(filename).extend("."+stem_r).asString();
144 MIL << "generating filename for " << stem_r << " [" << alias_r << "] : '" << filename << "'" << std::endl;
145 return filename;
146 }
147
149 {
150 // skip repositories meant for other distros than specified
151 if (!targetDistro.empty()
152 && !repo.targetDistribution().empty()
153 && repo.targetDistribution() != targetDistro)
154 {
155 MIL
156 << "Skipping repository meant for '" << repo.targetDistribution()
157 << "' distribution (current distro is '"
158 << targetDistro << "')." << std::endl;
159
160 return true;
161 }
162
163 repos.push_back(repo);
164 return true;
165 }
166
168 {
169 try {
170 MIL << "repo file: " << file << std::endl;
171 RepoCollector collector;
172 zypp::parser::RepoFileReader parser( file, std::bind( &RepoCollector::collect, &collector, std::placeholders::_1 ) );
173 return expected<std::list<RepoInfo>>::success( std::move(collector.repos) );
174 } catch ( ... ) {
176 }
177 }
178
188 template <typename ZContextRef>
189 std::list<RepoInfo> repositories_in_dir( ZContextRef zyppContext, const zypp::Pathname &dir )
190 {
191 MIL << "directory " << dir << std::endl;
192 std::list<RepoInfo> repos;
193 bool nonroot( geteuid() != 0 );
194 if ( nonroot && ! zypp::PathInfo(dir).userMayRX() )
195 {
196 JobReportHelper(zyppContext).warning( zypp::str::Format(_("Cannot read repo directory '%1%': Permission denied")) % dir );
197 }
198 else
199 {
200 std::list<zypp::Pathname> entries;
201 if ( zypp::filesystem::readdir( entries, dir, false ) != 0 )
202 {
203 // TranslatorExplanation '%s' is a pathname
204 ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str())));
205 }
206
207 zypp::str::regex allowedRepoExt("^\\.repo(_[0-9]+)?$");
208 for ( std::list<zypp::Pathname>::const_iterator it = entries.begin(); it != entries.end(); ++it )
209 {
210 if ( zypp::str::regex_match(it->extension(), allowedRepoExt) )
211 {
212 if ( nonroot && ! zypp::PathInfo(*it).userMayR() )
213 {
214 JobReportHelper(zyppContext).warning( zypp::str::Format(_("Cannot read repo file '%1%': Permission denied")) % *it );
215 }
216 else
217 {
218 const std::list<RepoInfo> tmp( repositories_in_file( *it ).unwrap() );
219 repos.insert( repos.end(), tmp.begin(), tmp.end() );
220 }
221 }
222 }
223 }
224 return repos;
225 }
226
228 {
229 if ( info.baseUrlsEmpty() )
232 }
233
235 { return not zypp::PathInfo(path_r/".no_auto_prune").isExist(); }
236
237
238 template <typename ZyppContextRefType>
240 : _zyppContext( std::move(zyppCtx) )
241 , _options( std::move(opt) )
242 , _pluginRepoverification( _options.pluginsPath / "repoverification",
243 _options.rootDir)
244 {
245
246 }
247
248 template <typename ZyppContextRefType>
250 {
251 // trigger appdata refresh if some repos change
252 if ( ( _reposDirty || env::ZYPP_PLUGIN_APPDATA_FORCE_COLLECT() )
253 && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) )
254 {
255 try {
256 std::list<zypp::Pathname> entries;
257 zypp::filesystem::readdir( entries, _options.pluginsPath/"appdata", false );
258 if ( ! entries.empty() )
259 {
261 cmd.push_back( "<" ); // discard stdin
262 cmd.push_back( ">" ); // discard stdout
263 cmd.push_back( "PROGRAM" ); // [2] - fix index below if changing!
264 for ( const auto & rinfo : repos() )
265 {
266 if ( ! rinfo.enabled() )
267 continue;
268 cmd.push_back( "-R" );
269 cmd.push_back( rinfo.alias() );
270 cmd.push_back( "-t" );
271 cmd.push_back( rinfo.type().asString() );
272 cmd.push_back( "-p" );
273 cmd.push_back( (rinfo.metadataPath()/rinfo.path()).asString() ); // bsc#1197684: path to the repodata/ directory inside the cache
274 }
275
276 for_( it, entries.begin(), entries.end() )
277 {
278 zypp::PathInfo pi( *it );
279 //DBG << "/tmp/xx ->" << pi << endl;
280 if ( pi.isFile() && pi.userMayRX() )
281 {
282 // trigger plugin
283 cmd[2] = pi.asString(); // [2] - PROGRAM
285 }
286 }
287 }
288 }
289 catch (...) {} // no throw in dtor
290 }
291 }
292
293 template<typename ZyppContextRefType>
295 {
296 using namespace zyppng::operators;
297 return
298 init_knownServices()
299 | and_then( [this](){ return init_knownRepositories(); } );
300 }
301
302 template<typename ZyppContextRefType>
307
308 template <typename ZyppContextRefType>
310 {
311 try {
312 using namespace zyppng::operators;
313
314 // ATTENTION when making this pipeline async
315 // consider moving it into a workflow object
316 // this var is caputured by ref to modify it from
317 // inside the pipeline, which would break.
319
320 return rawcache_path_for_repoinfo( options, info )
321 | and_then( [&]( zypp::Pathname mrPath ) {
322 mediarootpath = std::move(mrPath);
323 return rawproductdata_path_for_repoinfo( options, info );
324 })
327 // If unknown, probe the local metadata
329 repokind = probeCache( productdatapath );
330
331 // NOTE: The calling code expects an empty RepoStatus being returned
332 // if the metadata cache is empty. So additional components like the
333 // RepoInfos status are joined after the switch IFF the status is not
334 // empty.huhu
335 RepoStatus status;
336 switch ( repokind.toEnum() )
337 {
339 status = RepoStatus( productdatapath/"repodata/repomd.xml");
340 if ( info.requireStatusWithMediaFile() )
341 status = status && RepoStatus( mediarootpath/"media.1/media" );
342 break;
343
345 status = RepoStatus( productdatapath/"content" ) && RepoStatus( mediarootpath/"media.1/media" );
346 break;
347
349 // Dir status at last refresh. Plaindir uses the cookiefile as pseudo metadata index file.
350 // It gets touched if the refresh check finds the data being up-to-date. That's why we use
351 // the files mtime as timestamp (like the RepoStatus ctor in the other cases above).
353 break;
354
356 // Return default RepoStatus in case of RepoType::NONE
357 // indicating it should be created?
358 // ZYPP_THROW(RepoUnknownTypeException());
359 break;
360 }
361
362 if ( ! status.empty() )
363 status = status && RepoStatus( info );
364
365 return expected<RepoStatus>::success(status);
366 });
367 } catch (...) {
369 }
370 }
371
372 template <typename ZyppContextRefType>
374 {
375 return metadataStatus( info, _options );
376 }
377
378 template <typename ZyppContextRefType>
380 {
381 try {
382
383 ProgressObserver::setup( myProgress, _("Cleaning metadata"), 100 );
384 ProgressObserver::start( myProgress );
385 zypp::filesystem::recursive_rmdir( _zyppContext->config().geoipCachePath() );
386 ProgressObserver::setCurrent ( myProgress, 50 );
388 ProgressObserver::finish ( myProgress );
389
390 } catch ( ... ) {
391 ProgressObserver::finish ( myProgress, ProgressObserver::Error );
393 }
395 }
396
397 template <typename ZyppContextRefType>
399 {
400 try {
401 ProgressObserver::setup( myProgress, _("Cleaning packages"), 100 );
402 ProgressObserver::start( myProgress );
403
404 // bsc#1204956: Tweak to prevent auto pruning package caches
406 if ( not isAutoClean || autoPruneInDir( rpc.dirname() ) )
408
409 ProgressObserver::finish ( myProgress );
410
411 } catch (...) {
412 ProgressObserver::finish ( myProgress, ProgressObserver::Error );
414 }
415
417 }
418
424 template <typename ZyppContextRefType>
426 {
427 MIL << "going to probe the cached repo at " << path_r << std::endl;
428
430
431 if ( zypp::PathInfo(path_r/"/repodata/repomd.xml").isFile() )
433 else if ( zypp::PathInfo(path_r/"/content").isFile() )
435 else if ( zypp::PathInfo(path_r/"/cookie").isFile() )
437
438 MIL << "Probed cached type " << ret << " at " << path_r << std::endl;
439 return ret;
440 }
441
442 template <typename ZyppContextRefType>
444 {
445 try {
446 MIL << "Going to clean up garbage in cache dirs" << std::endl;
447
448 std::list<zypp::Pathname> cachedirs;
449 cachedirs.push_back(_options.repoRawCachePath);
450 cachedirs.push_back(_options.repoPackagesCachePath);
451 cachedirs.push_back(_options.repoSolvCachePath);
452
453 ProgressObserver::setup( myProgress, _("Cleaning up cache dirs"), cachedirs.size() );
454 ProgressObserver::start( myProgress );
455
456 for( const auto &dir : cachedirs )
457 {
458 // increase progress on end of every iteration
459 zypp_defer {
460 ProgressObserver::increase( myProgress );
461 };
462
463 if ( zypp::PathInfo(dir).isExist() )
464 {
465 std::list<zypp::Pathname> entries;
466 if ( zypp::filesystem::readdir( entries, dir, false ) != 0 )
467 // TranslatorExplanation '%s' is a pathname
468 ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str())));
469
470 if ( !entries.size() )
471 continue;
472
473 auto dirProgress = ProgressObserver::makeSubTask( myProgress, 1.0, zypp::str::Format( _("Cleaning up directory: %1%") ) % dir, entries.size() );
474 for( const auto &subdir : entries )
475 {
476 // if it does not belong known repo, make it disappear
477 bool found = false;
478 for_( r, repoBegin(), repoEnd() )
479 if ( subdir.basename() == r->escaped_alias() )
480 { found = true; break; }
481
482 if ( ! found && ( zypp::Date::now()-zypp::PathInfo(subdir).mtime() > zypp::Date::day ) )
484
485 ProgressObserver::increase( dirProgress );
486 }
487 ProgressObserver::finish( dirProgress );
488 }
489 }
490 } catch (...) {
491 // will finish all subprogress children
492 ProgressObserver::finish ( myProgress, ProgressObserver::Error );
494 }
495 ProgressObserver::finish ( myProgress );
497 }
498
499 template <typename ZyppContextRefType>
501 {
502 try {
503 ProgressObserver::setup( myProgress, _("Cleaning cache"), 100 );
504 ProgressObserver::start( myProgress );
505
506 MIL << "Removing raw metadata cache for " << info.alias() << std::endl;
508
509 ProgressObserver::finish( myProgress );
511
512 } catch (...) {
513 // will finish all subprogress children
514 ProgressObserver::finish ( myProgress, ProgressObserver::Error );
516 }
517 }
518
519 template <typename ZyppContextRefType>
521 {
522 using namespace zyppng::operators;
523 return zyppng::mtry( [this, info, myProgress](){
524 ProgressObserver::setup( myProgress, _("Loading from cache"), 3 );
525 ProgressObserver::start( myProgress );
526
527 assert_alias(info).unwrap();
528 zypp::Pathname solvfile = solv_path_for_repoinfo(_options, info).unwrap() / "solv";
529
530 if ( ! zypp::PathInfo(solvfile).isExist() )
532
533 _zyppContext->satPool().reposErase( info.alias() );
534
535 ProgressObserver::increase ( myProgress );
536
537 zypp::Repository repo = _zyppContext->satPool().addRepoSolv( solvfile, info );
538
539 ProgressObserver::increase ( myProgress );
540
541 // test toolversion in order to rebuild solv file in case
542 // it was written by a different libsolv-tool parser.
545 repo.eraseFromPool();
546 ZYPP_THROW(zypp::Exception(zypp::str::Str() << "Solv-file was created by '"<<toolversion<<"'-parser (want "<<LIBSOLV_TOOLVERSION<<")."));
547 }
548 })
549 | or_else( [this, info, myProgress]( std::exception_ptr exp ) {
550 ZYPP_CAUGHT( exp );
551 MIL << "Try to handle exception by rebuilding the solv-file" << std::endl;
552 return cleanCache( info, ProgressObserver::makeSubTask( myProgress ) )
553 | and_then([this, info, myProgress]{
554 return buildCache ( info, zypp::RepoManagerFlags::BuildIfNeeded, ProgressObserver::makeSubTask( myProgress ) );
555 })
556 | and_then( mtry([this, info = info]{
557 _zyppContext->satPool().addRepoSolv( solv_path_for_repoinfo(_options, info).unwrap() / "solv", info );
558 }));
559 })
561 ProgressObserver::finish ( myProgress );
563 })
564 | or_else([myProgress]( auto ex ){
565 ProgressObserver::finish ( myProgress, ProgressObserver::Error );
567 })
568 ;
569 }
570
571 template <typename ZyppContextRefType>
573 {
574 try {
575 auto tosave = info;
576
577 // assert the directory exists
579
580 zypp::Pathname repofile = generateNonExistingName(
581 _options.knownReposPath, generateFilename(tosave));
582 // now we have a filename that does not exists
583 MIL << "Saving repo in " << repofile << std::endl;
584
585 std::ofstream file(repofile.c_str());
586 if (!file)
587 {
588 // TranslatorExplanation '%s' is a filename
589 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
590 }
591
592 tosave.dumpAsIniOn(file);
593 tosave.setFilepath(repofile);
594 tosave.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ).unwrap() );
595 tosave.setPackagesPath( packagescache_path_for_repoinfo( _options, tosave ).unwrap() );
596 reposManip().insert(tosave);
597
598 // check for credentials in Urls
599 zypp::UrlCredentialExtractor( _options.rootDir ).collect( tosave.baseUrls() );
600
602
603 // return the new repoinfo
605
606 } catch (...) {
608 }
609 }
610
611 template <typename ZyppContextRefType>
613 {
614 try {
615 ProgressObserver::setup( myProgress, zypp::str::form(_("Removing repository '%s'"), info.label().c_str()), 1 );
616 ProgressObserver::start( myProgress );
617
618 MIL << "Going to delete repo " << info.alias() << std::endl;
619
620 for( const auto &repo : repos() )
621 {
622 // they can be the same only if the provided is empty, that means
623 // the provided repo has no alias
624 // then skip
625 if ( (!info.alias().empty()) && ( info.alias() != repo.alias() ) )
626 continue;
627
628 // TODO match by url
629
630 // we have a matching repository, now we need to know
631 // where it does come from.
632 RepoInfo todelete = repo;
633 if (todelete.filepath().empty())
634 {
635 ZYPP_THROW(zypp::repo::RepoException( todelete, _("Can't figure out where the repo is stored.") ));
636 }
637 else
638 {
639 // figure how many repos are there in the file:
640 std::list<RepoInfo> filerepos = repositories_in_file(todelete.filepath()).unwrap();
641 if ( filerepos.size() == 0 // bsc#984494: file may have already been deleted
642 ||(filerepos.size() == 1 && filerepos.front().alias() == todelete.alias() ) )
643 {
644 // easy: file does not exist, contains no or only the repo to delete: delete the file
645 int ret = zypp::filesystem::unlink( todelete.filepath() );
646 if ( ! ( ret == 0 || ret == ENOENT ) )
647 {
648 // TranslatorExplanation '%s' is a filename
649 ZYPP_THROW(zypp::repo::RepoException( todelete, zypp::str::form( _("Can't delete '%s'"), todelete.filepath().c_str() )));
650 }
651 MIL << todelete.alias() << " successfully deleted." << std::endl;
652 }
653 else
654 {
655 // there are more repos in the same file
656 // write them back except the deleted one.
657 //TmpFile tmp;
658 //std::ofstream file(tmp.path().c_str());
659
660 // assert the directory exists
661 zypp::filesystem::assert_dir(todelete.filepath().dirname());
662
663 std::ofstream file(todelete.filepath().c_str());
664 if (!file)
665 {
666 // TranslatorExplanation '%s' is a filename
667 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), todelete.filepath().c_str() )));
668 }
669 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
670 fit != filerepos.end();
671 ++fit )
672 {
673 if ( (*fit).alias() != todelete.alias() )
674 (*fit).dumpAsIniOn(file);
675 }
676 }
677
678 // now delete it from cache
679 if ( isCached(todelete) )
680 cleanCache( todelete, ProgressObserver::makeSubTask( myProgress, 0.2 )).unwrap();
681 // now delete metadata (#301037)
682 cleanMetadata( todelete, ProgressObserver::makeSubTask( myProgress, 0.4 )).unwrap();
683 cleanPackages( todelete, ProgressObserver::makeSubTask( myProgress, 0.4 ), true/*isAutoClean*/ ).unwrap();
684 reposManip().erase(todelete);
685 MIL << todelete.alias() << " successfully deleted." << std::endl;
687
688 ProgressObserver::finish(myProgress);
690 } // else filepath is empty
691 }
692 // should not be reached on a sucess workflow
694 } catch (...) {
695 ProgressObserver::finish( myProgress, ProgressObserver::Error );
696 return expected<void>::error( std::current_exception () );
697 }
698 }
699
700 template <typename ZyppContextRefType>
702 {
703 try {
704
705 ProgressObserver::setup( myProgress, _("Modifying repository"), 5 );
706 ProgressObserver::start( myProgress );
707
708 RepoInfo toedit = getRepositoryInfo(alias).unwrap();
709 RepoInfo newinfo( newinfo_r ); // need writable copy to upadte housekeeping data
710
711 // check if the new alias already exists when renaming the repo
712 if ( alias != newinfo.alias() && hasRepo( newinfo.alias() ) )
713 {
715 }
716
717 if (toedit.filepath().empty())
718 {
719 ZYPP_THROW(zypp::repo::RepoException( toedit, _("Can't figure out where the repo is stored.") ));
720 }
721 else
722 {
723 ProgressObserver::increase( myProgress );
724 // figure how many repos are there in the file:
725 std::list<RepoInfo> filerepos = repositories_in_file(toedit.filepath()).unwrap();
726
727 // there are more repos in the same file
728 // write them back except the deleted one.
729 //TmpFile tmp;
730 //std::ofstream file(tmp.path().c_str());
731
732 // assert the directory exists
733 zypp::filesystem::assert_dir(toedit.filepath().dirname());
734
735 std::ofstream file(toedit.filepath().c_str());
736 if (!file)
737 {
738 // TranslatorExplanation '%s' is a filename
739 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), toedit.filepath().c_str() )));
740 }
741 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
742 fit != filerepos.end();
743 ++fit )
744 {
745 // if the alias is different, dump the original
746 // if it is the same, dump the provided one
747 if ( (*fit).alias() != toedit.alias() )
748 (*fit).dumpAsIniOn(file);
749 else
750 newinfo.dumpAsIniOn(file);
751 }
752
753 ProgressObserver::increase( myProgress );
754
755 if ( toedit.enabled() && !newinfo.enabled() )
756 {
757 // On the fly remove solv.idx files for bash completion if a repo gets disabled.
758 const zypp::Pathname solvidx = solv_path_for_repoinfo(_options, newinfo).unwrap()/"solv.idx";
759 if ( zypp::PathInfo(solvidx).isExist() )
761 }
762
763 newinfo.setFilepath(toedit.filepath());
764 newinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ).unwrap() );
765 newinfo.setPackagesPath( packagescache_path_for_repoinfo( _options, newinfo ).unwrap() );
766
767 ProgressObserver::increase( myProgress );
768
769 reposManip().erase(toedit);
770 reposManip().insert(newinfo);
771
772 ProgressObserver::increase( myProgress );
773
774 // check for credentials in Urls
775 zypp::UrlCredentialExtractor( _options.rootDir ).collect( newinfo.baseUrls() );
777 MIL << "repo " << alias << " modified" << std::endl;
778
779 ProgressObserver::finish ( myProgress );
781 }
782
783 } catch ( ... ) {
784 ProgressObserver::finish ( myProgress, ProgressObserver::Error );
786 }
787 }
788
789 template <typename ZyppContextRefType>
791 {
792 try {
793 RepoConstIterator it( findAlias( alias, repos() ) );
794 if ( it != repos().end() )
795 return make_expected_success(*it);
796 RepoInfo info;
797 info.setAlias( alias );
799 } catch ( ... ) {
800 return expected<RepoInfo>::error( std::current_exception () );
801 }
802 }
803
804
805 template <typename ZyppContextRefType>
807 {
808 try {
809
810 for_( it, repoBegin(), repoEnd() )
811 {
812 for_( urlit, (*it).baseUrlsBegin(), (*it).baseUrlsEnd() )
813 {
814 if ( (*urlit).asString(urlview) == url.asString(urlview) )
815 return make_expected_success(*it);
816 }
817 }
818 RepoInfo info;
819 info.setBaseUrl( url );
821
822 } catch ( ... ) {
823 return expected<RepoInfo>::error( std::current_exception () );
824 }
825 }
826
827 template<typename ZyppContextRefType>
829 {
830 using namespace zyppng::operators;
832 RepoManagerWorkflow::refreshGeoIPData( _zyppContext, {url} )
834 | and_then( [this, url, policy]( zyppng::repo::RefreshContextRef<ZyppContextRefType> &&refCtx ) {
835 refCtx->setPolicy ( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
836 return _zyppContext->provider()->prepareMedia( url, zyppng::ProvideMediaSpec() )
837 | and_then( [ r = std::move(refCtx) ]( auto mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::checkIfToRefreshMetadata ( std::move(r), std::move(mediaHandle), nullptr ); } );
838 })
839 );
840 }
841
842 template<typename ZyppContextRefType>
844 {
845 using namespace zyppng::operators;
846 // helper callback in case the repo type changes on the remote
847 // do NOT capture by reference here, since this is possibly executed async
848 const auto &updateProbedType = [this, info = info]( zypp::repo::RepoType repokind ) {
849 // update probed type only for repos in system
850 for( const auto &repo : repos() ) {
851 if ( info.alias() == repo.alias() )
852 {
853 RepoInfo modifiedrepo = repo;
854 modifiedrepo.setType( repokind );
855 // don't modify .repo in refresh.
856 // modifyRepository( info.alias(), modifiedrepo );
857 break;
858 }
859 }
860 };
861
863 // make sure geoIP data is up 2 date, but ignore errors
864 RepoManagerWorkflow::refreshGeoIPData( _zyppContext, info.baseUrls() )
865 | [this, info = info](auto) { return zyppng::repo::RefreshContext<ZyppContextRefType>::create( _zyppContext, info, shared_this<RepoManager<ZyppContextRefType>>()); }
866 | and_then( [policy, myProgress, cb = updateProbedType]( repo::RefreshContextRef<ZyppContextRefType> refCtx ) {
867 refCtx->setPolicy( static_cast<repo::RawMetadataRefreshPolicy>( policy ) );
868 // in case probe detects a different repokind, update our internal repos
870
872 })
873 | and_then([rMgr = shared_this<RepoManager<ZyppContextRefType>>()]( repo::RefreshContextRef<ZyppContextRefType> ctx ) {
874
875 if ( ! isTmpRepo( ctx->repoInfo() ) )
876 rMgr->reposManip(); // remember to trigger appdata refresh
877
878 return expected<void>::success ();
879 }));
880 }
881
882 template<typename ZyppContextRefType>
883 std::vector<std::pair<RepoInfo, expected<void>>> RepoManager<ZyppContextRefType>::refreshMetadata( std::vector<RepoInfo> infos, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress )
884 {
885 using namespace zyppng::operators;
886
887 ProgressObserver::setup( myProgress, "Refreshing repositories" , 1 );
888
889 auto r = std::move(infos)
890 | transform( [this, policy, myProgress]( const RepoInfo &info ) {
891
892 auto subProgress = ProgressObserver::makeSubTask( myProgress, 1.0, zypp::str::Str() << _("Refreshing Repository: ") << info.alias(), 3 );
893
894 // helper callback in case the repo type changes on the remote
895 // do NOT capture by reference here, since this is possibly executed async
896 const auto &updateProbedType = [this, info = info]( zypp::repo::RepoType repokind ) {
897 // update probed type only for repos in system
898 for( const auto &repo : repos() ) {
899 if ( info.alias() == repo.alias() )
900 {
901 RepoInfo modifiedrepo = repo;
902 modifiedrepo.setType( repokind );
903 // don't modify .repo in refresh.
904 // modifyRepository( info.alias(), modifiedrepo );
905 break;
906 }
907 }
908 };
909
911
912 return
913 // make sure geoIP data is up 2 date, but ignore errors
914 RepoManagerWorkflow::refreshGeoIPData( _zyppContext, info.baseUrls() )
915 | [sharedThis, info = info](auto) { return zyppng::repo::RefreshContext<ZyppContextRefType>::create( sharedThis->_zyppContext, info, sharedThis); }
917 | and_then( [policy, subProgress, cb = updateProbedType]( repo::RefreshContextRef<ZyppContextRefType> refCtx ) {
918 refCtx->setPolicy( static_cast<repo::RawMetadataRefreshPolicy>( policy ) );
919 // in case probe detects a different repokind, update our internal repos
921
922 return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), ProgressObserver::makeSubTask( subProgress ) );
923 })
925 | and_then([subProgress]( repo::RefreshContextRef<ZyppContextRefType> ctx ) {
926
927 if ( ! isTmpRepo( ctx->repoInfo() ) )
928 ctx->repoManager()->reposManip(); // remember to trigger appdata refresh
929
930 return zyppng::RepoManagerWorkflow::buildCache ( std::move(ctx), CacheBuildPolicy::BuildIfNeeded, ProgressObserver::makeSubTask( subProgress ) );
931 })
933 | [ info = info, subProgress ]( expected<repo::RefreshContextRef<ZyppContextRefType>> result ) {
934 if ( result ) {
935 ProgressObserver::finish( subProgress, ProgressObserver::Success );
936 return std::make_pair(info, expected<void>::success() );
937 } else {
938 ProgressObserver::finish( subProgress, ProgressObserver::Error );
939 return std::make_pair(info, expected<void>::error( result.error() ) );
940 }
941 };
942 }
943 | [myProgress]( auto res ) {
944 ProgressObserver::finish( myProgress, ProgressObserver::Success );
945 return res;
946 }
947 );
948
949 return joinPipeline( _zyppContext, r );
950 }
951
958 template<typename ZyppContextRefType>
960 {
961 using namespace zyppng::operators;
963 RepoManagerWorkflow::refreshGeoIPData( _zyppContext, {url} )
964 | [this, url=url](auto) { return _zyppContext->provider()->prepareMedia( url, zyppng::ProvideMediaSpec() ); }
965 | and_then( [this, path = path]( auto mediaHandle ) {
966 return RepoManagerWorkflow::probeRepoType( _zyppContext, std::forward<decltype(mediaHandle)>(mediaHandle), path );
967 }));
968 }
969
970 template<typename ZyppContextRefType>
972 {
973 using namespace zyppng::operators;
976 | and_then( [policy, myProgress]( repo::RefreshContextRef<ZyppContextRefType> refCtx ) {
977 return zyppng::RepoManagerWorkflow::buildCache ( std::move(refCtx), policy, myProgress );
978 })
979 | and_then([]( auto ){ return expected<void>::success(); })
980 );
981 }
982
983 template<typename ZyppContextRefType>
985 {
986 return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepository( shared_this<RepoManager<ZyppContextRefType>>(), info, std::move(myProgress) ) );
987 }
988
989 template<typename ZyppContextRefType>
991 {
992 using namespace zyppng::operators;
993 return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepositories( shared_this<RepoManager<ZyppContextRefType>>(), url, std::move(myProgress)));
994 }
995
996 template <typename ZyppContextRefType>
998 {
999 return joinPipeline( _zyppContext, RepoServicesWorkflow::probeServiceType ( _zyppContext, url ) );
1000 }
1001
1002 template <typename ZyppContextRefType>
1004 {
1005 try {
1006
1007 assert_alias( service ).unwrap();
1008
1009 // check if service already exists
1010 if ( hasService( service.alias() ) )
1012
1013 // Writable ServiceInfo is needed to save the location
1014 // of the .service file. Finaly insert into the service list.
1015 ServiceInfo toSave( service );
1016 saveService( toSave ).unwrap();
1017 _services.insert( toSave );
1018
1019 // check for credentials in Url
1021
1022 MIL << "added service " << toSave.alias() << std::endl;
1023
1024 } catch ( ... ) {
1025 return expected<void>::error( std::current_exception () );
1026 }
1027
1028 return expected<void>::success();
1029 }
1030
1031 template<typename ZyppContextRefType>
1033 {
1034 return joinPipeline ( _zyppContext, RepoServicesWorkflow::refreshService( shared_this<RepoManager<ZyppContextRefType>>(), getService( alias ), options_r ) );
1035 }
1036
1040 template<typename ZyppContextRefType>
1042 {
1043 using namespace zyppng::operators;
1044 // copy the set of services since refreshService
1045 // can eventually invalidate the iterator
1046 ServiceSet servicesCopy( serviceBegin(), serviceEnd() );
1047
1048 // convert the set into a vector, transform needs a container with push_back support
1049 std::vector<ServiceInfo> servicesVec;
1050 std::copy( std::make_move_iterator(servicesCopy.begin()), std::make_move_iterator(servicesCopy.end()), std::back_inserter(servicesVec));
1051
1052 return joinPipeline( _zyppContext,
1053 std::move(servicesVec)
1054 | transform( [options_r, this]( ServiceInfo i ){ return RepoServicesWorkflow::refreshService( shared_this<RepoManager<ZyppContextRefType>>(), i, options_r ); } )
1055 | join()
1056 | collect()
1057 );
1058 }
1059
1061
1062 template <typename ZyppContextRefType>
1064 {
1065 try {
1066 MIL << "Going to delete service " << alias << std::endl;
1067
1068 const ServiceInfo & service = getService( alias );
1069
1070 zypp::Pathname location = service.filepath();
1071 if( location.empty() )
1072 {
1073 ZYPP_THROW(zypp::repo::ServiceException( service, _("Can't figure out where the service is stored.") ));
1074 }
1075
1078
1079 // only one service definition in the file
1080 if ( tmpSet.size() == 1 )
1081 {
1082 if ( zypp::filesystem::unlink(location) != 0 )
1083 {
1084 // TranslatorExplanation '%s' is a filename
1085 ZYPP_THROW(zypp::repo::ServiceException( service, zypp::str::form( _("Can't delete '%s'"), location.c_str() ) ));
1086 }
1087 MIL << alias << " successfully deleted." << std::endl;
1088 }
1089 else
1090 {
1092
1093 std::ofstream file(location.c_str());
1094 if( !file )
1095 {
1096 // TranslatorExplanation '%s' is a filename
1097 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), location.c_str() )));
1098 }
1099
1100 for_(it, tmpSet.begin(), tmpSet.end())
1101 {
1102 if( it->alias() != alias )
1103 it->dumpAsIniOn(file);
1104 }
1105
1106 MIL << alias << " successfully deleted from file " << location << std::endl;
1107 }
1108
1109 // now remove all repositories added by this service
1111 getRepositoriesInService( alias,
1112 boost::make_function_output_iterator( std::bind( &RepoCollector::collect, &rcollector, std::placeholders::_1 ) ) );
1113 // cannot do this directly in getRepositoriesInService - would invalidate iterators
1114 for_(rit, rcollector.repos.begin(), rcollector.repos.end())
1115 removeRepository(*rit).unwrap();
1116
1117 return expected<void>::success();
1118
1119 } catch ( ... ) {
1120 return expected<void>::error( std::current_exception () );
1121 }
1122 }
1123
1124 template <typename ZyppContextRefType>
1126 {
1127 try {
1128
1129 MIL << "Going to modify service " << oldAlias << std::endl;
1130
1131 // we need a writable copy to link it to the file where
1132 // it is saved if we modify it
1133 ServiceInfo service(newService);
1134
1135 if ( service.type() == zypp::repo::ServiceType::PLUGIN )
1136 {
1138 }
1139
1140 const ServiceInfo & oldService = getService(oldAlias);
1141
1142 zypp::Pathname location = oldService.filepath();
1143 if( location.empty() )
1144 {
1145 ZYPP_THROW(zypp::repo::ServiceException( oldService, _("Can't figure out where the service is stored.") ));
1146 }
1147
1148 // remember: there may multiple services being defined in one file:
1151
1153 std::ofstream file(location.c_str());
1154 for_(it, tmpSet.begin(), tmpSet.end())
1155 {
1156 if( *it != oldAlias )
1157 it->dumpAsIniOn(file);
1158 }
1159 service.dumpAsIniOn(file);
1160 file.close();
1161 service.setFilepath(location);
1162
1163 _services.erase(oldAlias);
1164 _services.insert(service);
1165 // check for credentials in Urls
1166 zypp::UrlCredentialExtractor( _options.rootDir ).collect( service.url() );
1167
1168
1169 // changed properties affecting also repositories
1170 if ( oldAlias != service.alias() // changed alias
1171 || oldService.enabled() != service.enabled() ) // changed enabled status
1172 {
1173 std::vector<RepoInfo> toModify;
1174 getRepositoriesInService(oldAlias, std::back_inserter(toModify));
1175 for_( it, toModify.begin(), toModify.end() )
1176 {
1177 if ( oldService.enabled() != service.enabled() )
1178 {
1179 if ( service.enabled() )
1180 {
1181 // reset to last refreshs state
1182 const auto & last = service.repoStates().find( it->alias() );
1183 if ( last != service.repoStates().end() )
1184 it->setEnabled( last->second.enabled );
1185 }
1186 else
1187 it->setEnabled( false );
1188 }
1189
1190 if ( oldAlias != service.alias() )
1191 it->setService(service.alias());
1192
1193 modifyRepository(it->alias(), *it).unwrap();
1194 }
1195 }
1196
1197 return expected<void>::success();
1198
1199 } catch ( ... ) {
1200 return expected<void>::error( std::current_exception () );
1201 }
1202
1204 }
1205
1206
1207 template <typename ZyppContextRefType>
1209 {
1210 try {
1211
1212 zypp::filesystem::assert_dir( _options.knownServicesPath );
1213 zypp::Pathname servfile = generateNonExistingName( _options.knownServicesPath,
1214 generateFilename( service ) );
1215 service.setFilepath( servfile );
1216
1217 MIL << "saving service in " << servfile << std::endl;
1218
1219 std::ofstream file( servfile.c_str() );
1220 if ( !file )
1221 {
1222 // TranslatorExplanation '%s' is a filename
1223 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), servfile.c_str() )));
1224 }
1225 service.dumpAsIniOn( file );
1226 MIL << "done" << std::endl;
1227
1228 return expected<void>::success();
1229
1230 } catch ( ... ) {
1231 return expected<void>::error( std::current_exception () );
1232 }
1233 }
1234
1250 template <typename ZyppContextRefType>
1252 const std::string & basefilename ) const
1253 {
1254 std::string final_filename = basefilename;
1255 int counter = 1;
1256 while ( zypp::PathInfo(dir + final_filename).isExist() )
1257 {
1259 ++counter;
1260 }
1261 return dir + zypp::Pathname(final_filename);
1262 }
1263
1264 template <typename ZyppContextRefType>
1266 {
1267 try {
1269
1271 if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e )
1272 // unknown, probe the local metadata
1273 repokind = probeCache( productdatapath );
1274 // if still unknown, just return
1276 return expected<void>::success();
1277
1279 switch ( repokind.toEnum() )
1280 {
1282 p = zypp::Pathname(productdatapath + "/repodata/repomd.xml");
1283 break;
1284
1286 p = zypp::Pathname(productdatapath + "/content");
1287 break;
1288
1290 p = zypp::Pathname(productdatapath + "/cookie");
1291 break;
1292
1294 default:
1295 break;
1296 }
1297
1298 // touch the file, ignore error (they are logged anyway)
1300 } catch ( ... ) {
1302 }
1303 return expected<void>::success();
1304 }
1305
1306 template<typename ZyppContextRefType>
1308 {
1309 return joinPipeline( _zyppContext, RepoManagerWorkflow::refreshGeoIPData( _zyppContext, urls) );
1310 }
1311
1312 template <typename ZyppContextRefType>
1314 {
1315 return touchIndexFile( info, _options );
1316 }
1317
1318 template <typename ZyppContextRefType>
1320 {
1321 try {
1322 zypp::Pathname dir = _options.knownServicesPath;
1323 std::list<zypp::Pathname> entries;
1324 if (zypp::PathInfo(dir).isExist())
1325 {
1326 if ( zypp::filesystem::readdir( entries, dir, false ) != 0 )
1327 {
1328 // TranslatorExplanation '%s' is a pathname
1329 ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str())));
1330 }
1331
1332 //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
1333 for_(it, entries.begin(), entries.end() )
1334 {
1336 }
1337 }
1338
1339 zypp::repo::PluginServices(_options.pluginsPath/"services", ServiceCollector(_services));
1340
1341 return expected<void>::success();
1342
1343 } catch ( ... ) {
1344 return expected<void>::error( std::current_exception () );
1345 }
1346
1347 }
1348
1349 namespace {
1358 const std::list<std::string> & repoEscAliases_r )
1359 {
1361 return;
1362
1364 return;
1365
1366 std::list<std::string> entries;
1367 if ( zypp::filesystem::readdir( entries, cachePath_r, false ) == 0 )
1368 {
1369 entries.sort();
1370 std::set<std::string> oldfiles;
1371 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
1372 std::inserter( oldfiles, oldfiles.end() ) );
1373
1374 // bsc#1178966: Files or symlinks here have been created by the user
1375 // for whatever purpose. It's our cache, so we purge them now before
1376 // they may later conflict with directories we need.
1378 for ( const std::string & old : oldfiles )
1379 {
1380 if ( old == zypp::Repository::systemRepoAlias() ) // don't remove the @System solv file
1381 continue;
1382 pi( cachePath_r/old );
1383 if ( pi.isDir() )
1385 else
1386 zypp::filesystem::unlink( pi.path() );
1387 }
1388 }
1389 }
1390 } // namespace
1391
1392 template <typename ZyppContextRefType>
1394 {
1395 try {
1396
1397 MIL << "start construct known repos" << std::endl;
1398
1399 if ( zypp::PathInfo(_options.knownReposPath).isExist() )
1400 {
1401 std::list<std::string> repoEscAliases;
1402 std::list<RepoInfo> orphanedRepos;
1403 for ( RepoInfo & repoInfo : repositories_in_dir( _zyppContext, _options.knownReposPath ) )
1404 {
1405 // set the metadata path for the repo
1406 repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo).unwrap() );
1407 // set the downloaded packages path for the repo
1408 repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo).unwrap() );
1409 // remember it
1410 _reposX.insert( repoInfo ); // direct access via _reposX in ctor! no reposManip.
1411
1412 // detect orphaned repos belonging to a deleted service
1413 const std::string & serviceAlias( repoInfo.service() );
1414 if ( ! ( serviceAlias.empty() || hasService( serviceAlias ) ) )
1415 {
1416 WAR << "Schedule orphaned service repo for deletion: " << repoInfo << std::endl;
1417 orphanedRepos.push_back( repoInfo );
1418 continue; // don't remember it in repoEscAliases
1419 }
1420
1421 repoEscAliases.push_back(repoInfo.escaped_alias());
1422 }
1423
1424 // Cleanup orphanded service repos:
1425 if ( ! orphanedRepos.empty() )
1426 {
1427 for ( const auto & repoInfo : orphanedRepos )
1428 {
1429 MIL << "Delete orphaned service repo " << repoInfo.alias() << std::endl;
1430 // translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service.
1431 // %1% = service name
1432 // %2% = repository name
1433 JobReportHelper(_zyppContext).warning( zypp::str::Format(_("Unknown service '%1%': Removing orphaned service repository '%2%'"))
1434 % repoInfo.service()
1435 % repoInfo.alias() );
1436 try {
1437 removeRepository( repoInfo ).unwrap();
1438 }
1439 catch ( const zypp::Exception & caugth )
1440 {
1441 JobReportHelper(_zyppContext).error( caugth.asUserHistory() );
1442 }
1443 }
1444 }
1445
1446 // bsc#1210740: Don't cleanup if read-only mode was promised.
1448 // delete metadata folders without corresponding repo (e.g. old tmp directories)
1449 //
1450 // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise
1451 // we'd need somemagic file to identify zypp cache directories. Without this
1452 // we may easily remove user data (zypper --pkg-cache-dir . download ...)
1453 repoEscAliases.sort();
1454 cleanupNonRepoMetadtaFolders( _options.repoRawCachePath,
1455 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoMetadataPath() ),
1457 cleanupNonRepoMetadtaFolders( _options.repoSolvCachePath,
1458 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoSolvfilesPath() ),
1460 // bsc#1204956: Tweak to prevent auto pruning package caches
1461 if ( autoPruneInDir( _options.repoPackagesCachePath ) )
1462 cleanupNonRepoMetadtaFolders( _options.repoPackagesCachePath,
1463 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoPackagesPath() ),
1465 }
1466 }
1467 MIL << "end construct known repos" << std::endl;
1468
1469 return expected<void>::success();
1470
1471 } catch ( ... ) {
1472 return expected<void>::error( std::current_exception () );
1473 }
1474 }
1475
1476 // explicitely intantiate the template types we want to work with
1477 template class RepoManager<SyncContextRef>;
1478 template class RepoManager<ContextRef>;
1479} // namespace zyppng
#define OUTS(V)
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
AutoDispose()
Default Ctor using default constructed value and no dispose function.
static const ValueType day
Definition Date.h:44
static Date now()
Return the current time.
Definition Date.h:78
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 modifyRepository(const RepoInfo &oldrepo, const RepoInfo &newrepo)
Log certain modifications to a repository.
void addRepository(const RepoInfo &repo)
Log a newly added repository.
void removeRepository(const RepoInfo &repo)
Log recently removed repository.
What is known about a repository.
Definition RepoInfo.h:72
bool baseUrlsEmpty() const
whether repository urls are available
Definition RepoInfo.cc:659
repo::RepoType type() const
Type of repository,.
Definition RepoInfo.cc:605
void setBaseUrl(Url url)
Clears current base URL list and adds url.
Definition RepoInfo.cc:556
url_set baseUrls() const
The complete set of repository urls.
Definition RepoInfo.cc:632
bool requireStatusWithMediaFile() const
Returns true if this repository requires the media.1/media file to be included in the metadata status...
Definition RepoInfo.cc:967
std::string targetDistribution() const
Distribution for which is this repository meant.
Definition RepoInfo.cc:644
std::list< Url > url_set
Definition RepoInfo.h:108
Track changing files or directories.
Definition RepoStatus.h:41
static RepoStatus fromCookieFileUseMtime(const Pathname &path)
Reads the status from a cookie file but uses the files mtime.
bool empty() const
Whether the status is empty (empty checksum)
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition Repository.cc:38
void eraseFromPool()
Remove this Repository from its Pool.
Service data.
Definition ServiceInfo.h:37
repo::ServiceType type() const
Service type.
const RepoStates & repoStates() const
Access the remembered repository states.
Url url() const
The service url.
std::ostream & dumpAsIniOn(std::ostream &str) const override
Writes ServiceInfo to stream in ".service" format.
Extract credentials in Url authority and store them via CredentialManager.
bool collect(const Url &url_r)
Remember credentials stored in URL authority leaving the password in url_r.
Url manipulation class.
Definition Url.h:93
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:515
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition Pathname.h:175
Pathname dirname() const
Return all but the last component od this path.
Definition Pathname.h:126
const char * c_str() const
String representation.
Definition Pathname.h:112
const std::string & asString() const
String representation.
Definition Pathname.h:93
bool empty() const
Test for an empty path.
Definition Pathname.h:116
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition Pathname.cc:272
Read repository data from a .repo file.
Read service data from a .service file.
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.
void setFilepath(const Pathname &filename)
set the path to the .repo file
void setAlias(const std::string &alias)
set the repository alias
Pathname filepath() const
File where this repo was read from.
bool enabled() const
If enabled is false, then this repository must be ignored as if does not exists, except when checking...
std::string alias() const
unique identifier for this source.
thrown when it was impossible to determine one url for this repo.
The repository cache is not built yet so you can't create the repostories from the cache.
thrown when it was impossible to match a repository
Service already exists and some unique attribute can't be duplicated.
Base Exception for service handling.
Lightweight repository attribute value lookup.
Definition LookupAttr.h:265
static const SolvAttr repositoryToolVersion
Definition SolvAttr.h:181
Regular expression.
Definition Regex.h:95
bool error(std::string msg_r, UserData userData_r=UserData())
send error text
bool warning(std::string msg_r, UserData userData_r=UserData())
send warning text
The RepoManager class Provides knowledge and methods to maintain repo settings and metadata for a giv...
std::set< ServiceInfo > ServiceSet
ServiceInfo typedefs.
RepoSet::const_iterator RepoConstIterator
zypp::RepoManagerFlags::RefreshServiceOptions RefreshServiceOptions
Functor collecting ServiceInfos into a ServiceSet.
static expected success(ConsParams &&...params)
Definition expected.h:115
static expected< repo::RefreshContextRef< ZyppContextRefType > > create(ZyppContextRefType zyppContext, zypp::RepoInfo info, RepoManagerRef< ContextRefType > repoManager)
Definition refresh.cc:28
Definition Arch.h:364
String related utilities and Regular expression matching.
RefreshCheckStatus
Possibly return state of RepoManager::checkIfToRefreshMetadata function.
Namespace intended to collect all environment variables we use.
Definition Env.h:23
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition PathInfo.cc:417
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:610
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:324
int touch(const Pathname &path)
Change file's modification and access times.
Definition PathInfo.cc:1242
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
Definition String.cc:331
std::string numstring(char n, int w=0)
Definition String.h:289
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
Definition Regex.h:70
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 join(const ParamVec &pvec, const std::string &psep)
Join parameter vector to a string.
Definition UrlUtils.cc:252
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
std::string asString(const Patch::Category &obj)
Definition Patch.cc:122
AsyncOpRef< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > refreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > buildCache(repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT()
To trigger appdata refresh unconditionally.
auto incProgress(ProgressObserverRef progressObserver, double progrIncrease=1.0, std::optional< std::string > newStr={})
Exp mtry(F &&f, Args &&...args)
Definition mtry.h:28
bool isTmpRepo(const RepoInfo &info_r)
Whether repo is not under RM control and provides its own methadata paths.
Definition repomanager.h:54
expected< void > assert_urls(const RepoInfo &info)
std::list< RepoInfo > repositories_in_dir(ZContextRef zyppContext, const zypp::Pathname &dir)
List of RepoInfo's from a directory.
std::string filenameFromAlias(const std::string &alias_r, const std::string &stem_r)
Generate a related filename from a repo/service infos alias.
expected< zypp::Pathname > rawcache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw cache path for a repository, this is usually /var/cache/zypp/alias.
expected< void > assert_alias(const RepoInfo &info)
Definition repomanager.h:57
ResultType or_else(const expected< T, E > &exp, Function &&f)
Definition expected.h:463
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition expected.h:423
auto joinPipeline(ContextRef ctx, AsyncOpRef< T > res)
Definition context.h:81
expected< zypp::Pathname > solv_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the solv cache path for a repository.
expected< std::list< RepoInfo > > repositories_in_file(const zypp::Pathname &file)
Reads RepoInfo's from a repo file.
Iterator findAlias(const std::string &alias_r, Iterator begin_r, Iterator end_r)
Find alias_r in repo/service container.
Definition repomanager.h:98
std::enable_if_t<!std::is_same_v< void, T >, expected< Container< T >, E > > collect(Container< expected< T, E >, CArgs... > &&in)
Definition expected.h:501
expected< zypp::Pathname > packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
expected< zypp::Pathname > rawproductdata_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw product metadata path for a repository, this is inside the raw cache dir,...
Container< Ret > transform(Container< Msg, CArgs... > &&val, Transformation &&transformation)
Definition transform.h:31
expected< T, E > inspect(expected< T, E > exp, Function &&f)
Definition expected.h:531
bool autoPruneInDir(const zypp::Pathname &path_r)
bsc#1204956: Tweak to prevent auto pruning package caches.
ZyppContextRefType _zyppContext
zypp::RepoManager::RefreshServiceOptions _options
Repo manager settings.
creates and provides information about known sources.
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.
void addService(const std::string &alias, const Url &url)
Adds a new service by its alias and URL.
void removeService(const std::string &alias)
Removes service specified by its name.
repo::ServiceType probeService(const Url &url) const
Probe the type or the service.
void cleanCache(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
clean local cache
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.
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.
void modifyRepository(const std::string &alias, const RepoInfo &newinfo, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Modify repository attributes.
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.
RefreshCheckStatus checkIfToRefreshMetadata(const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy=RefreshIfNeeded)
Checks whether to refresh metadata for specified repository and url.
void buildCache(const RepoInfo &info, CacheBuildPolicy policy=BuildIfNeeded, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Refresh local cache.
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.
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.
repo::RepoType probe(const Url &url, const Pathname &path) const
Probe repo metadata type.
Repository type enumeration.
Definition RepoType.h:29
static const RepoType YAST2
Definition RepoType.h:31
static const RepoType RPMMD
Definition RepoType.h:30
static const RepoType NONE
Definition RepoType.h:33
static const RepoType RPMPLAINDIR
Definition RepoType.h:32
Convenient building of std::string with boost::format.
Definition String.h:253
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:212
Url::asString() view options.
Definition UrlBase.h:41
Simple callback to collect the results.
std::string targetDistro
bool collect(const RepoInfo &repo)
#define zypp_defer
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:440
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:428
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Definition Exception.h:436
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:424
#define _(MSG)
Definition Gettext.h:39
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101
#define ZYPP_PRIVATE_CONSTR_ARG
Definition zyppglobal.h:160