libzypp 17.38.3
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/ng/pipelines/MTry>
19#include <zypp-core/ng/pipelines/Transform>
21#include <zypp-core/ng/ui/ProgressObserver>
23#include <zypp/HistoryLog.h>
24#include <zypp/ZConfig.h>
25#include <zypp/ZYppCallbacks.h>
29#include <zypp/sat/Pool.h>
33
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
113 std::ostream & operator<<( std::ostream & str, zypp::RepoManagerFlags::RefreshCheckStatus obj )
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
125 std::ostream & operator<<( std::ostream & str, zypp::RepoManagerFlags::CacheBuildPolicy obj )
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
233
234 bool autoPruneInDir(const zypp::Pathname &path_r)
235 { return not zypp::PathInfo(path_r/".no_auto_prune").isExist(); }
236
237
239 : _zyppContext( std::move(zyppCtx) )
240 , _options( std::move(opt) )
241 , _pluginRepoverification( _options.pluginsPath / "repoverification",
242 _options.rootDir)
243 {
244
245 }
246
248 {
249 // trigger appdata refresh if some repos change
251 && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) )
252 {
253 try {
254 std::list<zypp::Pathname> entries;
255 zypp::filesystem::readdir( entries, _options.pluginsPath/"appdata", false );
256 if ( ! entries.empty() )
257 {
259 cmd.push_back( "<" ); // discard stdin
260 cmd.push_back( ">" ); // discard stdout
261 cmd.push_back( "PROGRAM" ); // [2] - fix index below if changing!
262 for ( const auto & rinfo : repos() )
263 {
264 if ( ! rinfo.enabled() )
265 continue;
266 cmd.push_back( "-R" );
267 cmd.push_back( rinfo.alias() );
268 cmd.push_back( "-t" );
269 cmd.push_back( rinfo.type().asString() );
270 cmd.push_back( "-p" );
271 cmd.push_back( (rinfo.metadataPath()/rinfo.path()).asString() ); // bsc#1197684: path to the repodata/ directory inside the cache
272 }
273
274 for_( it, entries.begin(), entries.end() )
275 {
276 zypp::PathInfo pi( *it );
277 //DBG << "/tmp/xx ->" << pi << endl;
278 if ( pi.isFile() && pi.userMayRX() )
279 {
280 // trigger plugin
281 cmd[2] = pi.asString(); // [2] - PROGRAM
283 }
284 }
285 }
286 }
287 catch (...) {} // no throw in dtor
288 }
289 }
290
291
293 {
294 using namespace zyppng::operators;
295 return
297 | and_then( [this](){ return init_knownRepositories(); } );
298 }
299
300
302 {
303 return _options;
304 }
305
306
308 {
309 try {
310 using namespace zyppng::operators;
311
312 // ATTENTION when making this pipeline async
313 // consider moving it into a workflow object
314 // this var is caputured by ref to modify it from
315 // inside the pipeline, which would break.
316 zypp::Pathname mediarootpath;
317
318 return rawcache_path_for_repoinfo( options, info )
319 | and_then( [&]( zypp::Pathname mrPath ) {
320 mediarootpath = std::move(mrPath);
322 })
323 | and_then( [&]( zypp::Pathname productdatapath ) {
324 zypp::repo::RepoType repokind = info.type();
325 // If unknown, probe the local metadata
326 if ( repokind == zypp::repo::RepoType::NONE )
327 repokind = probeCache( productdatapath );
328
329 // NOTE: The calling code expects an empty RepoStatus being returned
330 // if the metadata cache is empty. So additional components like the
331 // RepoInfos status are joined after the switch IFF the status is not
332 // empty.huhu
333 RepoStatus status;
334 switch ( repokind.toEnum() )
335 {
337 status = RepoStatus( productdatapath/"repodata/repomd.xml");
338 if ( info.requireStatusWithMediaFile() )
339 status = status && RepoStatus( mediarootpath/"media.1/media" );
340 break;
341
343 status = RepoStatus( productdatapath/"content" ) && RepoStatus( mediarootpath/"media.1/media" );
344 break;
345
347 // Dir status at last refresh. Plaindir uses the cookiefile as pseudo metadata index file.
348 // It gets touched if the refresh check finds the data being up-to-date. That's why we use
349 // the files mtime as timestamp (like the RepoStatus ctor in the other cases above).
350 status = RepoStatus::fromCookieFileUseMtime( productdatapath/"cookie" );
351 break;
352
354 // Return default RepoStatus in case of RepoType::NONE
355 // indicating it should be created?
356 // ZYPP_THROW(RepoUnknownTypeException());
357 break;
358 }
359
360 if ( ! status.empty() )
361 status = status && RepoStatus( info );
362
363 return expected<RepoStatus>::success(status);
364 });
365 } catch (...) {
367 }
368 }
369
370
372 {
373 return metadataStatus( info, _options );
374 }
375
376
377 expected<void> RepoManager::cleanMetadata(const RepoInfo &info, ProgressObserverRef myProgress )
378 {
379 try {
380
381 ProgressObserver::setup( myProgress, _("Cleaning metadata"), 100 );
382 ProgressObserver::start( myProgress );
383 zypp::filesystem::recursive_rmdir( _zyppContext->config().geoipCachePath() );
384 ProgressObserver::setCurrent ( myProgress, 50 );
386 ProgressObserver::finish ( myProgress );
387
388 } catch ( ... ) {
391 }
393 }
394
395
396 expected<void> RepoManager::cleanPackages(const RepoInfo &info, ProgressObserverRef myProgress, bool isAutoClean )
397 {
398 try {
399 ProgressObserver::setup( myProgress, _("Cleaning packages"), 100 );
400 ProgressObserver::start( myProgress );
401
402 // bsc#1204956: Tweak to prevent auto pruning package caches
404 if ( not isAutoClean || autoPruneInDir( rpc.dirname() ) )
406
407 ProgressObserver::finish ( myProgress );
408
409 } catch (...) {
412 }
413
415 }
416
422
424 {
425 MIL << "going to probe the cached repo at " << path_r << std::endl;
426
428
429 if ( zypp::PathInfo(path_r/"/repodata/repomd.xml").isFile() )
431 else if ( zypp::PathInfo(path_r/"/content").isFile() )
433 else if ( zypp::PathInfo(path_r/"/cookie").isFile() )
435
436 MIL << "Probed cached type " << ret << " at " << path_r << std::endl;
437 return ret;
438 }
439
440
441 expected<void> RepoManager::cleanCacheDirGarbage( ProgressObserverRef myProgress )
442 {
443 try {
444 MIL << "Going to clean up garbage in cache dirs" << std::endl;
445
446 std::list<zypp::Pathname> cachedirs;
447 cachedirs.push_back(_options.repoRawCachePath);
448 cachedirs.push_back(_options.repoPackagesCachePath);
449 cachedirs.push_back(_options.repoSolvCachePath);
450
451 ProgressObserver::setup( myProgress, _("Cleaning up cache dirs"), cachedirs.size() );
452 ProgressObserver::start( myProgress );
453
454 for( const auto &dir : cachedirs )
455 {
456 // increase progress on end of every iteration
457 zypp_defer {
458 ProgressObserver::increase( myProgress );
459 };
460
461 if ( zypp::PathInfo(dir).isExist() )
462 {
463 std::list<zypp::Pathname> entries;
464 if ( zypp::filesystem::readdir( entries, dir, false ) != 0 )
465 // TranslatorExplanation '%s' is a pathname
466 ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str())));
467
468 if ( !entries.size() )
469 continue;
470
471 auto dirProgress = ProgressObserver::makeSubTask( myProgress, 1.0, zypp::str::Format( _("Cleaning up directory: %1%") ) % dir, entries.size() );
472 for( const auto &subdir : entries )
473 {
474 // if it does not belong known repo, make it disappear
475 bool found = false;
476 for_( r, repoBegin(), repoEnd() )
477 if ( subdir.basename() == r->escaped_alias() )
478 { found = true; break; }
479
480 if ( ! found && ( zypp::Date::now()-zypp::PathInfo(subdir).mtime() > zypp::Date::day ) )
482
483 ProgressObserver::increase( dirProgress );
484 }
485 ProgressObserver::finish( dirProgress );
486 }
487 }
488 } catch (...) {
489 // will finish all subprogress children
492 }
493 ProgressObserver::finish ( myProgress );
495 }
496
497
498 expected<void> RepoManager::cleanCache(const RepoInfo &info, ProgressObserverRef myProgress )
499 {
500 try {
501 ProgressObserver::setup( myProgress, _("Cleaning cache"), 100 );
502 ProgressObserver::start( myProgress );
503
504 MIL << "Removing raw metadata cache for " << info.alias() << std::endl;
506
507 ProgressObserver::finish( myProgress );
509
510 } catch (...) {
511 // will finish all subprogress children
514 }
515 }
516
517
518 expected<void> RepoManager::loadFromCache( const RepoInfo & info, ProgressObserverRef myProgress )
519 {
520 using namespace zyppng::operators;
521 return zyppng::mtry( [this, info, myProgress](){
522 ProgressObserver::setup( myProgress, _("Loading from cache"), 3 );
523 ProgressObserver::start( myProgress );
524
525 assert_alias(info).unwrap();
526 zypp::Pathname solvfile = solv_path_for_repoinfo(_options, info).unwrap() / "solv";
527
528 if ( ! zypp::PathInfo(solvfile).isExist() )
530
531 _zyppContext->satPool().reposErase( info.alias() );
532
533 ProgressObserver::increase ( myProgress );
534
535 zypp::Repository repo = _zyppContext->satPool().addRepoSolv( solvfile, info );
536
537 ProgressObserver::increase ( myProgress );
538
539 // test toolversion in order to rebuild solv file in case
540 // it was written by a different libsolv-tool parser.
541 const std::string & toolversion( zypp::sat::LookupRepoAttr( zypp::sat::SolvAttr::repositoryToolVersion, repo ).begin().asString() );
542 if ( toolversion != LIBSOLV_TOOLVERSION ) {
543 repo.eraseFromPool();
544 ZYPP_THROW(zypp::Exception(zypp::str::Str() << "Solv-file was created by '"<<toolversion<<"'-parser (want "<<LIBSOLV_TOOLVERSION<<")."));
545 }
546 })
547 | or_else( [this, info, myProgress]( std::exception_ptr exp ) {
548 ZYPP_CAUGHT( exp );
549 MIL << "Try to handle exception by rebuilding the solv-file" << std::endl;
550 return cleanCache( info, ProgressObserver::makeSubTask( myProgress ) )
551 | and_then([this, info, myProgress]{
553 })
554 | and_then( mtry([this, info = info]{
555 _zyppContext->satPool().addRepoSolv( solv_path_for_repoinfo(_options, info).unwrap() / "solv", info );
556 }));
557 })
558 | and_then([myProgress]{
559 ProgressObserver::finish ( myProgress );
561 })
562 | or_else([myProgress]( auto ex ){
564 return expected<void>::error(ex);
565 })
566 ;
567 }
568
569
571 {
572 try {
573 auto tosave = info;
574
575 // assert the directory exists
577
579 _options.knownReposPath, generateFilename(tosave));
580 // now we have a filename that does not exists
581 MIL << "Saving repo in " << repofile << std::endl;
582
583 std::ofstream file(repofile.c_str());
584 if (!file)
585 {
586 // TranslatorExplanation '%s' is a filename
587 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
588 }
589
590 tosave.dumpAsIniOn(file);
591 tosave.setFilepath(repofile);
592 tosave.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ).unwrap() );
593 tosave.setPackagesPath( packagescache_path_for_repoinfo( _options, tosave ).unwrap() );
594 reposManip().insert(tosave);
595
596 // check for credentials in base Urls
597 zypp::UrlCredentialExtractor( _options.rootDir ).collect( tosave.baseUrls() );
598
599 zypp::HistoryLog(_options.rootDir).addRepository(tosave);
600
601 // return the new repoinfo
602 return expected<RepoInfo>::success( tosave );
603
604 } catch (...) {
606 }
607 }
608
609
610 expected<void> RepoManager::removeRepository( const RepoInfo & info, ProgressObserverRef myProgress )
611 {
612 try {
613 ProgressObserver::setup( myProgress, zypp::str::form(_("Removing repository '%s'"), info.label().c_str()), 1 );
614 ProgressObserver::start( myProgress );
615
616 MIL << "Going to delete repo " << info.alias() << std::endl;
617
618 for( const auto &repo : repos() )
619 {
620 // they can be the same only if the provided is empty, that means
621 // the provided repo has no alias
622 // then skip
623 if ( (!info.alias().empty()) && ( info.alias() != repo.alias() ) )
624 continue;
625
626 // TODO match by url
627
628 // we have a matching repository, now we need to know
629 // where it does come from.
630 RepoInfo todelete = repo;
631 if (todelete.filepath().empty())
632 {
633 ZYPP_THROW(zypp::repo::RepoException( todelete, _("Can't figure out where the repo is stored.") ));
634 }
635 else
636 {
637 // figure how many repos are there in the file:
638 std::list<RepoInfo> filerepos = repositories_in_file(todelete.filepath()).unwrap();
639 if ( filerepos.size() == 0 // bsc#984494: file may have already been deleted
640 ||(filerepos.size() == 1 && filerepos.front().alias() == todelete.alias() ) )
641 {
642 // easy: file does not exist, contains no or only the repo to delete: delete the file
643 int ret = zypp::filesystem::unlink( todelete.filepath() );
644 if ( ! ( ret == 0 || ret == ENOENT ) )
645 {
646 // TranslatorExplanation '%s' is a filename
647 ZYPP_THROW(zypp::repo::RepoException( todelete, zypp::str::form( _("Can't delete '%s'"), todelete.filepath().c_str() )));
648 }
649 MIL << todelete.alias() << " successfully deleted." << std::endl;
650 }
651 else
652 {
653 // there are more repos in the same file
654 // write them back except the deleted one.
655 //TmpFile tmp;
656 //std::ofstream file(tmp.path().c_str());
657
658 // assert the directory exists
660
661 std::ofstream file(todelete.filepath().c_str());
662 if (!file)
663 {
664 // TranslatorExplanation '%s' is a filename
665 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), todelete.filepath().c_str() )));
666 }
667 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
668 fit != filerepos.end();
669 ++fit )
670 {
671 if ( (*fit).alias() != todelete.alias() )
672 (*fit).dumpAsIniOn(file);
673 }
674 }
675
676 // now delete it from cache
677 if ( isCached(todelete) )
678 cleanCache( todelete, ProgressObserver::makeSubTask( myProgress, 0.2 )).unwrap();
679 // now delete metadata (#301037)
680 cleanMetadata( todelete, ProgressObserver::makeSubTask( myProgress, 0.4 )).unwrap();
681 cleanPackages( todelete, ProgressObserver::makeSubTask( myProgress, 0.4 ), true/*isAutoClean*/ ).unwrap();
682 reposManip().erase(todelete);
683 MIL << todelete.alias() << " successfully deleted." << std::endl;
684 zypp::HistoryLog(_options.rootDir).removeRepository(todelete);
685
686 ProgressObserver::finish(myProgress);
688 } // else filepath is empty
689 }
690 // should not be reached on a sucess workflow
692 } catch (...) {
694 return expected<void>::error( std::current_exception () );
695 }
696 }
697
698
699 expected<RepoInfo> RepoManager::modifyRepository( const std::string & alias, const RepoInfo & newinfo_r, ProgressObserverRef myProgress )
700 {
701 try {
702
703 ProgressObserver::setup( myProgress, _("Modifying repository"), 5 );
704 ProgressObserver::start( myProgress );
705
706 RepoInfo toedit = getRepositoryInfo(alias).unwrap();
707 RepoInfo newinfo( newinfo_r ); // need writable copy to upadte housekeeping data
708
709 // check if the new alias already exists when renaming the repo
710 if ( alias != newinfo.alias() && hasRepo( newinfo.alias() ) )
711 {
713 }
714
715 if (toedit.filepath().empty())
716 {
717 ZYPP_THROW(zypp::repo::RepoException( toedit, _("Can't figure out where the repo is stored.") ));
718 }
719 else
720 {
721 ProgressObserver::increase( myProgress );
722 // figure how many repos are there in the file:
723 std::list<RepoInfo> filerepos = repositories_in_file(toedit.filepath()).unwrap();
724
725 // there are more repos in the same file
726 // write them back except the deleted one.
727 //TmpFile tmp;
728 //std::ofstream file(tmp.path().c_str());
729
730 // assert the directory exists
732
733 std::ofstream file(toedit.filepath().c_str());
734 if (!file)
735 {
736 // TranslatorExplanation '%s' is a filename
737 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), toedit.filepath().c_str() )));
738 }
739 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
740 fit != filerepos.end();
741 ++fit )
742 {
743 // if the alias is different, dump the original
744 // if it is the same, dump the provided one
745 if ( (*fit).alias() != toedit.alias() )
746 (*fit).dumpAsIniOn(file);
747 else
748 newinfo.dumpAsIniOn(file);
749 }
750
751 ProgressObserver::increase( myProgress );
752
753 if ( toedit.enabled() && !newinfo.enabled() )
754 {
755 // On the fly remove solv.idx files for bash completion if a repo gets disabled.
756 const zypp::Pathname solvidx = solv_path_for_repoinfo(_options, newinfo).unwrap()/"solv.idx";
757 if ( zypp::PathInfo(solvidx).isExist() )
758 zypp::filesystem::unlink( solvidx );
759 }
760
761 newinfo.setFilepath(toedit.filepath());
762 newinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ).unwrap() );
763 newinfo.setPackagesPath( packagescache_path_for_repoinfo( _options, newinfo ).unwrap() );
764
765 ProgressObserver::increase( myProgress );
766
767 reposManip().erase(toedit);
768 reposManip().insert(newinfo);
769
770 ProgressObserver::increase( myProgress );
771
772 // check for credentials in Urls
774 zypp::HistoryLog(_options.rootDir).modifyRepository(toedit, newinfo);
775 MIL << "repo " << alias << " modified" << std::endl;
776
777 ProgressObserver::finish ( myProgress );
778 return expected<RepoInfo>::success( newinfo );
779 }
780
781 } catch ( ... ) {
784 }
785 }
786
787
789 {
790 try {
791 RepoConstIterator it( findAlias( alias, repos() ) );
792 if ( it != repos().end() )
793 return make_expected_success(*it);
794 RepoInfo info;
795 info.setAlias( alias );
797 } catch ( ... ) {
798 return expected<RepoInfo>::error( std::current_exception () );
799 }
800 }
801
802
803
805 {
806 try {
807
808 for_( it, repoBegin(), repoEnd() )
809 {
810 for( const auto &origin : it->repoOrigins() )
811 {
812 if ( std::any_of( origin.begin(), origin.end(), [&url, &urlview]( const zypp::OriginEndpoint &ep ){ return (ep.url().asString(urlview) == url.asString(urlview)); }) )
813 return make_expected_success(*it);
814 }
815 }
816 RepoInfo info;
817 info.setBaseUrl( url );
819
820 } catch ( ... ) {
821 return expected<RepoInfo>::error( std::current_exception () );
822 }
823 }
824
825
827 {
828 using namespace zyppng::operators;
831 | [this, info](auto) { return zyppng::repo::RefreshContext::create( _zyppContext, info, shared_this<RepoManager>() ); }
832 | and_then( [this, origin, policy]( zyppng::repo::RefreshContextRef &&refCtx ) {
833 refCtx->setPolicy ( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
834
835 return _zyppContext->provider()->prepareMedia( origin, zyppng::ProvideMediaSpec() )
836 | and_then( [ r = std::move(refCtx) ]( auto mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::checkIfToRefreshMetadata ( std::move(r), std::move(mediaHandle), nullptr ); } );
837 })
838 );
839 }
840
841
842 expected<void> RepoManager::refreshMetadata( const RepoInfo &info, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress )
843 {
844 using namespace zyppng::operators;
845 // helper callback in case the repo type changes on the remote
846 // do NOT capture by reference here, since this is possibly executed async
847 const auto &updateProbedType = [this, info = info]( zypp::repo::RepoType repokind ) {
848 // update probed type only for repos in system
849 for( const auto &repo : repos() ) {
850 if ( info.alias() == repo.alias() )
851 {
852 RepoInfo modifiedrepo = repo;
853 modifiedrepo.setType( repokind );
854 // don't modify .repo in refresh.
855 // modifyRepository( info.alias(), modifiedrepo );
856 break;
857 }
858 }
859 };
860
861 // the list of URLs we want to have geo ip redirects for
862 auto urls = info.baseUrls ();
863 if ( info.mirrorListUrl ().isValid () )
864 urls.push_back ( info.mirrorListUrl () );
865
867 // make sure geoIP data is up 2 date, but ignore errors
869 | [this, info = info](auto) { return zyppng::repo::RefreshContext::create( _zyppContext, info, shared_this<RepoManager>()); }
870 | and_then( [policy, myProgress, cb = updateProbedType]( repo::RefreshContextRef refCtx ) {
871 refCtx->setPolicy( static_cast<repo::RawMetadataRefreshPolicy>( policy ) );
872 // in case probe detects a different repokind, update our internal repos
873 refCtx->connectFunc( &repo::RefreshContext::sigProbedTypeChanged, cb );
874
875 return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), myProgress );
876 })
877 | and_then([rMgr = shared_this<RepoManager>()]( repo::RefreshContextRef ctx ) {
878
879 if ( ! isTmpRepo( ctx->repoInfo() ) )
880 rMgr->reposManip(); // remember to trigger appdata refresh
881
882 return expected<void>::success ();
883 }));
884 }
885
886
887 std::vector<std::pair<RepoInfo, expected<void>>> RepoManager::refreshMetadata( std::vector<RepoInfo> infos, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress )
888 {
889 using namespace zyppng::operators;
890
891 ProgressObserver::setup( myProgress, "Refreshing repositories" , 1 );
892
893 auto r = std::move(infos)
894 | transform( [this, policy, myProgress]( const RepoInfo &info ) {
895
896 auto subProgress = ProgressObserver::makeSubTask( myProgress, 1.0, zypp::str::Str() << _("Refreshing Repository: ") << info.alias(), 3 );
897
898 // helper callback in case the repo type changes on the remote
899 // do NOT capture by reference here, since this is possibly executed async
900 const auto &updateProbedType = [this, info = info]( zypp::repo::RepoType repokind ) {
901 // update probed type only for repos in system
902 for( const auto &repo : repos() ) {
903 if ( info.alias() == repo.alias() )
904 {
905 RepoInfo modifiedrepo = repo;
906 modifiedrepo.setType( repokind );
907 // don't modify .repo in refresh.
908 // modifyRepository( info.alias(), modifiedrepo );
909 break;
910 }
911 }
912 };
913
914 auto sharedThis = shared_this<RepoManager>();
915
916 return
917 // make sure geoIP data is up 2 date, but ignore errors
919 | [sharedThis, info = info](auto) { return zyppng::repo::RefreshContext::create( sharedThis->_zyppContext, info, sharedThis); }
920 | inspect( incProgress( subProgress ) )
921 | and_then( [policy, subProgress, cb = updateProbedType]( repo::RefreshContextRef refCtx ) {
922 refCtx->setPolicy( static_cast<repo::RawMetadataRefreshPolicy>( policy ) );
923 // in case probe detects a different repokind, update our internal repos
924 refCtx->connectFunc( &repo::RefreshContext::sigProbedTypeChanged, cb );
925
926 return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), ProgressObserver::makeSubTask( subProgress ) );
927 })
928 | inspect( incProgress( subProgress ) )
929 | and_then([subProgress]( repo::RefreshContextRef ctx ) {
930
931 if ( ! isTmpRepo( ctx->repoInfo() ) )
932 ctx->repoManager()->reposManip(); // remember to trigger appdata refresh
933
934 return zyppng::RepoManagerWorkflow::buildCache ( std::move(ctx), CacheBuildPolicy::BuildIfNeeded, ProgressObserver::makeSubTask( subProgress ) );
935 })
936 | inspect( incProgress( subProgress ) )
937 | [ info = info, subProgress ]( expected<repo::RefreshContextRef> result ) {
938 if ( result ) {
940 return std::make_pair(info, expected<void>::success() );
941 } else {
943 return std::make_pair(info, expected<void>::error( result.error() ) );
944 }
945 };
946 }
947 | [myProgress]( auto res ) {
949 return res;
950 }
951 );
952
953 return joinPipeline( _zyppContext, r );
954 }
955
962
964 {
965 using namespace zyppng::operators;
966
967 RepoInfo::url_set allUrls;
968 std::transform( origin.begin (), origin.end(), std::back_inserter(allUrls), []( const zypp::OriginEndpoint &ep ){ return ep.url(); } );
969
972 | [this, origin=origin](auto) { return _zyppContext->provider()->prepareMedia( origin, zyppng::ProvideMediaSpec() ); }
973 | and_then( [this, path = path]( auto mediaHandle ) {
974 return RepoManagerWorkflow::probeRepoType( _zyppContext, std::move(mediaHandle), path );
975 }));
976 }
977
978
979 expected<void> RepoManager::buildCache( const RepoInfo &info, CacheBuildPolicy policy, ProgressObserverRef myProgress )
980 {
981 using namespace zyppng::operators;
984 | and_then( [policy, myProgress]( repo::RefreshContextRef refCtx ) {
985 return zyppng::RepoManagerWorkflow::buildCache ( std::move(refCtx), policy, myProgress );
986 })
987 | and_then([]( auto ){ return expected<void>::success(); })
988 );
989 }
990
991
992 expected<RepoInfo> RepoManager::addRepository(const RepoInfo &info, ProgressObserverRef myProgress, const zypp::TriBool & forcedProbe )
993 {
994 return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepository( shared_this<RepoManager>(), info, std::move(myProgress), forcedProbe ) );
995 }
996
997
998 expected<void> RepoManager::addRepositories(const zypp::Url &url, ProgressObserverRef myProgress)
999 {
1000 using namespace zyppng::operators;
1002 }
1003
1004
1009
1010
1012 {
1013 try {
1014
1015 assert_alias( service ).unwrap();
1016
1017 // check if service already exists
1018 if ( hasService( service.alias() ) )
1020
1021 // Writable ServiceInfo is needed to save the location
1022 // of the .service file. Finaly insert into the service list.
1023 ServiceInfo toSave( service );
1024 saveService( toSave ).unwrap();
1025 _services.insert( toSave );
1026
1027 // check for credentials in Url
1028 zypp::UrlCredentialExtractor( _options.rootDir ).collect( toSave.url() );
1029
1030 MIL << "added service " << toSave.alias() << std::endl;
1031
1032 } catch ( ... ) {
1033 return expected<void>::error( std::current_exception () );
1034 }
1035
1036 return expected<void>::success();
1037 }
1038
1039
1040 expected<void> RepoManager::refreshService( const std::string &alias, const RefreshServiceOptions &options_r )
1041 {
1043 }
1044
1048
1050 {
1051 using namespace zyppng::operators;
1052 // copy the set of services since refreshService
1053 // can eventually invalidate the iterator
1054 ServiceSet servicesCopy( serviceBegin(), serviceEnd() );
1055
1056 // convert the set into a vector, transform needs a container with push_back support
1057 std::vector<ServiceInfo> servicesVec;
1058 std::copy( std::make_move_iterator(servicesCopy.begin()), std::make_move_iterator(servicesCopy.end()), std::back_inserter(servicesVec));
1059
1060 return joinPipeline( _zyppContext,
1061 std::move(servicesVec)
1062 | transform( [options_r, this]( ServiceInfo i ){ return RepoServicesWorkflow::refreshService( shared_this<RepoManager>(), i, options_r ); } )
1063 | join()
1064 | collect()
1065 );
1066 }
1067
1069
1070
1071 expected<void> RepoManager::removeService( const std::string & alias )
1072 {
1073 try {
1074 MIL << "Going to delete service " << alias << std::endl;
1075
1076 const ServiceInfo & service = getService( alias );
1077
1078 zypp::Pathname location = service.filepath();
1079 if( location.empty() )
1080 {
1081 ZYPP_THROW(zypp::repo::ServiceException( service, _("Can't figure out where the service is stored.") ));
1082 }
1083
1084 ServiceSet tmpSet;
1086
1087 // only one service definition in the file
1088 if ( tmpSet.size() == 1 )
1089 {
1090 if ( zypp::filesystem::unlink(location) != 0 )
1091 {
1092 // TranslatorExplanation '%s' is a filename
1093 ZYPP_THROW(zypp::repo::ServiceException( service, zypp::str::form( _("Can't delete '%s'"), location.c_str() ) ));
1094 }
1095 MIL << alias << " successfully deleted." << std::endl;
1096 }
1097 else
1098 {
1100
1101 std::ofstream file(location.c_str());
1102 if( !file )
1103 {
1104 // TranslatorExplanation '%s' is a filename
1105 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), location.c_str() )));
1106 }
1107
1108 for_(it, tmpSet.begin(), tmpSet.end())
1109 {
1110 if( it->alias() != alias )
1111 it->dumpAsIniOn(file);
1112 }
1113
1114 MIL << alias << " successfully deleted from file " << location << std::endl;
1115 }
1116
1117 // now remove all repositories added by this service
1118 RepoCollector rcollector;
1120 boost::make_function_output_iterator( std::bind( &RepoCollector::collect, &rcollector, std::placeholders::_1 ) ) );
1121 // cannot do this directly in getRepositoriesInService - would invalidate iterators
1122 for_(rit, rcollector.repos.begin(), rcollector.repos.end())
1123 removeRepository(*rit).unwrap();
1124
1125 return expected<void>::success();
1126
1127 } catch ( ... ) {
1128 return expected<void>::error( std::current_exception () );
1129 }
1130 }
1131
1132
1133 expected<void> RepoManager::modifyService( const std::string & oldAlias, const ServiceInfo & newService )
1134 {
1135 try {
1136
1137 MIL << "Going to modify service " << oldAlias << std::endl;
1138
1139 // we need a writable copy to link it to the file where
1140 // it is saved if we modify it
1141 ServiceInfo service(newService);
1142
1143 if ( service.type() == zypp::repo::ServiceType::PLUGIN )
1144 {
1146 }
1147
1148 const ServiceInfo & oldService = getService(oldAlias);
1149
1150 zypp::Pathname location = oldService.filepath();
1151 if( location.empty() )
1152 {
1153 ZYPP_THROW(zypp::repo::ServiceException( oldService, _("Can't figure out where the service is stored.") ));
1154 }
1155
1156 // remember: there may multiple services being defined in one file:
1157 ServiceSet tmpSet;
1159
1161 std::ofstream file(location.c_str());
1162 for_(it, tmpSet.begin(), tmpSet.end())
1163 {
1164 if( *it != oldAlias )
1165 it->dumpAsIniOn(file);
1166 }
1167 service.dumpAsIniOn(file);
1168 file.close();
1169 service.setFilepath(location);
1170
1171 _services.erase(oldAlias);
1172 _services.insert(service);
1173 // check for credentials in Urls
1174 zypp::UrlCredentialExtractor( _options.rootDir ).collect( service.url() );
1175
1176
1177 // changed properties affecting also repositories
1178 if ( oldAlias != service.alias() // changed alias
1179 || oldService.enabled() != service.enabled() ) // changed enabled status
1180 {
1181 std::vector<RepoInfo> toModify;
1182 getRepositoriesInService(oldAlias, std::back_inserter(toModify));
1183 for_( it, toModify.begin(), toModify.end() )
1184 {
1185 if ( oldService.enabled() != service.enabled() )
1186 {
1187 if ( service.enabled() )
1188 {
1189 // reset to last refreshs state
1190 const auto & last = service.repoStates().find( it->alias() );
1191 if ( last != service.repoStates().end() )
1192 it->setEnabled( last->second.enabled );
1193 }
1194 else
1195 it->setEnabled( false );
1196 }
1197
1198 if ( oldAlias != service.alias() )
1199 it->setService(service.alias());
1200
1201 modifyRepository(it->alias(), *it).unwrap();
1202 }
1203 }
1204
1205 return expected<void>::success();
1206
1207 } catch ( ... ) {
1208 return expected<void>::error( std::current_exception () );
1209 }
1210
1212 }
1213
1214
1215
1217 {
1218 try {
1219
1220 zypp::filesystem::assert_dir( _options.knownServicesPath );
1221 zypp::Pathname servfile = generateNonExistingName( _options.knownServicesPath,
1222 generateFilename( service ) );
1223 service.setFilepath( servfile );
1224
1225 MIL << "saving service in " << servfile << std::endl;
1226
1227 std::ofstream file( servfile.c_str() );
1228 if ( !file )
1229 {
1230 // TranslatorExplanation '%s' is a filename
1231 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), servfile.c_str() )));
1232 }
1233 service.dumpAsIniOn( file );
1234 MIL << "done" << std::endl;
1235
1236 return expected<void>::success();
1237
1238 } catch ( ... ) {
1239 return expected<void>::error( std::current_exception () );
1240 }
1241 }
1242
1258
1260 const std::string & basefilename ) const
1261 {
1262 std::string final_filename = basefilename;
1263 int counter = 1;
1264 while ( zypp::PathInfo(dir + final_filename).isExist() )
1265 {
1266 final_filename = basefilename + "_" + zypp::str::numstring(counter);
1267 ++counter;
1268 }
1269 return dir + zypp::Pathname(final_filename);
1270 }
1271
1272
1273 expected<void> RepoManager::touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
1274 {
1275 try {
1276 zypp::Pathname productdatapath = rawproductdata_path_for_repoinfo( options, info ).unwrap();
1277
1278 zypp::repo::RepoType repokind = info.type();
1279 if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e )
1280 // unknown, probe the local metadata
1281 repokind = probeCache( productdatapath );
1282 // if still unknown, just return
1283 if (repokind == zypp::repo::RepoType::NONE_e)
1284 return expected<void>::success();
1285
1286 zypp::Pathname p;
1287 switch ( repokind.toEnum() )
1288 {
1290 p = zypp::Pathname(productdatapath + "/repodata/repomd.xml");
1291 break;
1292
1294 p = zypp::Pathname(productdatapath + "/content");
1295 break;
1296
1298 p = zypp::Pathname(productdatapath + "/cookie");
1299 break;
1300
1302 default:
1303 break;
1304 }
1305
1306 // touch the file, ignore error (they are logged anyway)
1308 } catch ( ... ) {
1309 return expected<void>::error( ZYPP_FWD_CURRENT_EXCPT() );
1310 }
1311 return expected<void>::success();
1312 }
1313
1314 expected<void> RepoManager::refreshGeoIp( const RepoInfo::url_set &urls )
1315 {
1316 return joinPipeline( _zyppContext, RepoManagerWorkflow::refreshGeoIPData( _zyppContext, urls) );
1317 }
1318
1319 expected<void> RepoManager::touchIndexFile( const RepoInfo & info )
1320 {
1321 return touchIndexFile( info, _options );
1322 }
1323
1324
1325 expected<void> RepoManager::init_knownServices()
1326 {
1327 try {
1328 zypp::Pathname dir = _options.knownServicesPath;
1329 std::list<zypp::Pathname> entries;
1330 if (zypp::PathInfo(dir).isExist())
1331 {
1332 if ( zypp::filesystem::readdir( entries, dir, false ) != 0 )
1333 {
1334 // TranslatorExplanation '%s' is a pathname
1335 ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str())));
1336 }
1337
1338 //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
1339 for_(it, entries.begin(), entries.end() )
1340 {
1341 zypp::parser::ServiceFileReader(*it, ServiceCollector(_services));
1342 }
1343 }
1344
1345 zypp::repo::PluginServices(_options.pluginsPath/"services", ServiceCollector(_services));
1346
1347 return expected<void>::success();
1348
1349 } catch ( ... ) {
1350 return expected<void>::error( std::current_exception () );
1351 }
1352
1353 }
1354
1355 namespace {
1362 inline void cleanupNonRepoMetadtaFolders( const zypp::Pathname & cachePath_r,
1363 const zypp::Pathname & defaultCachePath_r,
1364 const std::list<std::string> & repoEscAliases_r )
1365 {
1367 return;
1368
1369 if ( cachePath_r != defaultCachePath_r )
1370 return;
1371
1372 std::list<std::string> entries;
1373 if ( zypp::filesystem::readdir( entries, cachePath_r, false ) == 0 )
1374 {
1375 entries.sort();
1376 std::set<std::string> oldfiles;
1377 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
1378 std::inserter( oldfiles, oldfiles.end() ) );
1379
1380 // bsc#1178966: Files or symlinks here have been created by the user
1381 // for whatever purpose. It's our cache, so we purge them now before
1382 // they may later conflict with directories we need.
1383 zypp::PathInfo pi;
1384 for ( const std::string & old : oldfiles )
1385 {
1386 if ( old == zypp::Repository::systemRepoAlias() ) // don't remove the @System solv file
1387 continue;
1388 pi( cachePath_r/old );
1389 if ( pi.isDir() )
1391 else
1393 }
1394 }
1395 }
1396 } // namespace
1397
1398
1400 {
1401 try {
1402
1403 MIL << "start construct known repos" << std::endl;
1404
1405 if ( zypp::PathInfo(_options.knownReposPath).isExist() )
1406 {
1407 std::list<std::string> repoEscAliases;
1408 std::list<RepoInfo> orphanedRepos;
1409 for ( RepoInfo & repoInfo : repositories_in_dir( _zyppContext, _options.knownReposPath ) )
1410 {
1411 // set the metadata path for the repo
1412 repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo).unwrap() );
1413 // set the downloaded packages path for the repo
1414 repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo).unwrap() );
1415 // remember it
1416 _reposX.insert( repoInfo ); // direct access via _reposX in ctor! no reposManip.
1417
1418 // detect orphaned repos belonging to a deleted service
1419 const std::string & serviceAlias( repoInfo.service() );
1420 if ( ! ( serviceAlias.empty() || hasService( serviceAlias ) ) )
1421 {
1422 WAR << "Schedule orphaned service repo for deletion: " << repoInfo << std::endl;
1423 orphanedRepos.push_back( repoInfo );
1424 continue; // don't remember it in repoEscAliases
1425 }
1426
1427 repoEscAliases.push_back(repoInfo.escaped_alias());
1428 }
1429
1430 // Cleanup orphanded service repos:
1431 if ( ! orphanedRepos.empty() )
1432 {
1433 for ( const auto & repoInfo : orphanedRepos )
1434 {
1435 MIL << "Delete orphaned service repo " << repoInfo.alias() << std::endl;
1436 // translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service.
1437 // %1% = service name
1438 // %2% = repository name
1439 JobReportHelper(_zyppContext).warning( zypp::str::Format(_("Unknown service '%1%': Removing orphaned service repository '%2%'"))
1440 % repoInfo.service()
1441 % repoInfo.alias() );
1442 try {
1443 removeRepository( repoInfo ).unwrap();
1444 }
1445 catch ( const zypp::Exception & caugth )
1446 {
1448 }
1449 }
1450 }
1451
1452 // bsc#1210740: Don't cleanup if read-only mode was promised.
1454 // delete metadata folders without corresponding repo (e.g. old tmp directories)
1455 //
1456 // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise
1457 // we'd need somemagic file to identify zypp cache directories. Without this
1458 // we may easily remove user data (zypper --pkg-cache-dir . download ...)
1459 repoEscAliases.sort();
1460 cleanupNonRepoMetadtaFolders( _options.repoRawCachePath,
1461 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoMetadataPath() ),
1462 repoEscAliases );
1463 cleanupNonRepoMetadtaFolders( _options.repoSolvCachePath,
1464 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoSolvfilesPath() ),
1465 repoEscAliases );
1466 // bsc#1204956: Tweak to prevent auto pruning package caches
1467 if ( autoPruneInDir( _options.repoPackagesCachePath ) )
1468 cleanupNonRepoMetadtaFolders( _options.repoPackagesCachePath,
1469 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoPackagesPath() ),
1470 repoEscAliases );
1471 }
1472 }
1473 MIL << "end construct known repos" << std::endl;
1474
1475 return expected<void>::success();
1476
1477 } catch ( ... ) {
1478 return expected<void>::error( std::current_exception () );
1479 }
1480 }
1481} // namespace zyppng
#define zypp_defer
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:463
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Definition Exception.h:471
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define _(MSG)
Definition Gettext.h:39
#define MIL
Definition Logger.h:100
#define WAR
Definition Logger.h:101
#define OUTS(V)
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:153
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition Exception.cc:140
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.
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
endpoint_iterator end()
endpoint_iterator begin()
Represents a single, configurable network endpoint, combining a URL with specific access settings.
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
What is known about a repository.
Definition RepoInfo.h:72
MirroredOriginSet repoOrigins() const
The repodata origins.
Definition RepoInfo.cc:733
repo::RepoType type() const
Type of repository,.
Definition RepoInfo.cc:789
void setBaseUrl(Url url)
Clears current base URL list and adds url.
Definition RepoInfo.cc:720
void setPackagesPath(const Pathname &path)
set the path where the local packages are stored
Definition RepoInfo.cc:756
url_set baseUrls() const
The complete set of repository urls as configured.
Definition RepoInfo.cc:816
bool requireStatusWithMediaFile() const
Returns true if this repository requires the media.1/media file to be included in the metadata status...
Definition RepoInfo.cc:1170
Url mirrorListUrl() const
Url of a file which contains a list of repository urls.
Definition RepoInfo.cc:792
std::ostream & dumpAsIniOn(std::ostream &str) const override
Write this RepoInfo object into str in a .repo file format.
Definition RepoInfo.cc:1042
void setMetadataPath(const Pathname &path)
Set the path where the local metadata is stored.
Definition RepoInfo.cc:753
void setType(const repo::RepoType &t)
set the repository type
Definition RepoInfo.cc:746
std::list< Url > url_set
Definition RepoInfo.h:108
bool repoOriginsEmpty() const
whether repo origins are available
Definition RepoInfo.cc:738
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 hasService(const std::string &alias) const
Return whether there is a known service for alias.
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.
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.
ServiceConstIterator serviceEnd() const
Iterator to place behind last service in internal storage.
ServiceConstIterator serviceBegin() const
Iterator to first service in internal storage.
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.
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.
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.
repo::RepoType probe(const Url &url, const Pathname &path) const
Probe repo metadata type.
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
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
bool isValid() const
Verifies the Url.
Definition Url.cc:516
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
const std::string & asString() const
Return current Pathname as String.
Definition PathInfo.h:253
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition Pathname.h:182
Pathname dirname() const
Return all but the last component od this path.
Definition Pathname.h:133
const char * c_str() const
String representation.
Definition Pathname.h:113
const std::string & asString() const
String representation.
Definition Pathname.h:94
bool empty() const
Test for an empty path.
Definition Pathname.h:117
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:193
Regular expression.
Definition Regex.h:95
std::shared_ptr< T > shared_this() const
Definition base.h:113
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
static void increase(ProgressObserverRef progress, double inc=1.0, const std::optional< std::string > &newLabel={})
static ProgressObserverRef makeSubTask(ProgressObserverRef parentProgress, float weight=1.0, const std::string &label=std::string(), int steps=100)
static void setup(ProgressObserverRef progress, const std::string &label=std::string(), int steps=100)
static void finish(ProgressObserverRef progress, ProgressObserver::FinishResult result=ProgressObserver::Success)
RepoSet::const_iterator RepoConstIterator
expected< RepoInfo > addProbedRepository(RepoInfo info, zypp::repo::RepoType probedType)
std::string generateFilename(const RepoInfo &info) const
expected< void > init_knownServices()
zypp::RepoManagerFlags::RefreshServiceOptions RefreshServiceOptions
zypp::DefaultIntegral< bool, false > _reposDirty
bool hasRepo(const std::string &alias) const
expected< void > saveService(ServiceInfo &service) const
zypp::RepoManagerFlags::RawMetadataRefreshPolicy RawMetadataRefreshPolicy
static zypp::repo::RepoType probeCache(const zypp::Pathname &path_r)
Probe Metadata in a local cache directory.
zypp::Pathname generateNonExistingName(const zypp::Pathname &dir, const std::string &basefilename) const
ContextRefType _zyppContext
expected< void > initialize()
std::set< ServiceInfo > ServiceSet
ServiceInfo typedefs.
RepoSet & reposManip()
RepoManagerOptions _options
expected< void > init_knownRepositories()
bool hasService(const std::string &alias) const
const RepoManagerOptions & options() const
zypp::RepoManagerFlags::CacheBuildPolicy CacheBuildPolicy
Functor collecting ServiceInfos into a ServiceSet.
static expected success(ConsParams &&...params)
Definition expected.h:178
static expected error(ConsParams &&...params)
Definition expected.h:189
SignalProxy< void(zypp::repo::RepoType)> sigProbedTypeChanged()
Definition refresh.cc:157
static expected< repo::RefreshContextRef > create(ContextRef zyppContext, zypp::RepoInfo info, RepoManagerRef repoManager)
Definition refresh.cc:31
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:31
Definition ansi.h:855
String related utilities and Regular expression matching.
RefreshCheckStatus
Possibly return state of RepoManager::checkIfToRefreshMetadata function.
Namespace intended to collect all environment variables we use.
bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT()
To trigger appdata refresh unconditionally.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition PathInfo.cc:431
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:719
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:624
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:338
int touch(const Pathname &path)
Change file's modification and access times.
Definition PathInfo.cc:1256
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:333
std::string numstring(char n, int w=0)
Definition String.h:290
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:39
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:500
Url details namespace.
Definition UrlBase.cc:58
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
MaybeAwaitable< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::RefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
MaybeAwaitable< expected< void > > addRepositories(RepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress)
MaybeAwaitable< expected< zypp::repo::RepoType > > probeRepoType(ContextRef ctx, Provide::LazyMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath)
MaybeAwaitable< expected< RepoInfo > > addRepository(RepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress, const zypp::TriBool &forcedProbe)
MaybeAwaitable< expected< repo::RefreshContextRef > > refreshMetadata(repo::RefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
MaybeAwaitable< expected< repo::RefreshContextRef > > buildCache(repo::RefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
MaybeAwaitable< expected< void > > refreshGeoIPData(ContextRef ctx, RepoInfo::url_set urls)
MaybeAwaitable< expected< void > > refreshService(RepoManagerRef repoMgr, ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options)
MaybeAwaitable< expected< zypp::repo::ServiceType > > probeServiceType(ContextRef ctx, const zypp::Url &url)
auto incProgress(ProgressObserverRef progressObserver, double progrIncrease=1.0, std::optional< std::string > newStr={})
zypp::RepoManagerFlags::RawMetadataRefreshPolicy RawMetadataRefreshPolicy
Definition refresh.h:33
bool isTmpRepo(const RepoInfo &info_r)
Whether repo is not under RM control and provides its own methadata paths.
Definition repomanager.h:49
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.
void cleanupNonRepoMetadtaFolders(const zypp::Pathname &cachePath_r, const zypp::Pathname &defaultCachePath_r, const std::list< std::string > &repoEscAliases_r)
Generate a non existing filename in a directory, using a base name.
std::string filenameFromAlias(const std::string &alias_r, const std::string &stem_r)
Generate a related filename from a repo/service infos alias.
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition expected.h:470
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:52
ResultType or_else(const expected< T, E > &exp, Function &&f)
Definition expected.h:554
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition expected.h:520
auto transform(Container< Msg, CArgs... > &&val, Transformation &&transformation)
Definition transform.h:64
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:93
std::enable_if_t<!std::is_same_v< void, T >, expected< Container< T >, E > > collect(Container< expected< T, E >, CArgs... > &&in)
Definition expected.h:586
expected< zypp::Pathname > packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
auto joinPipeline(ContextRef ctx, T &&val)
Definition context.h:52
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,...
expected< T, E > inspect(expected< T, E > exp, Function &&f)
Definition expected.h:616
bool autoPruneInDir(const zypp::Pathname &path_r)
bsc#1204956: Tweak to prevent auto pruning package caches.
auto mtry(F &&f, Args &&...args)
Definition mtry.h:50
Repo manager settings.
Repository type enumeration.
Definition RepoType.h:29
static const RepoType YAST2
Definition RepoType.h:31
Type toEnum() const
Definition RepoType.h:49
static const RepoType RPMMD
Definition RepoType.h:30
static const RepoType NONE
Definition RepoType.h:33
static const RepoType RPMPLAINDIR
Definition RepoType.h:32
Convenient building of std::string with boost::format.
Definition String.h:254
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:213
Url::asString() view options.
Definition UrlBase.h:41
Simple callback to collect the results.
std::string targetDistro
bool collect(const RepoInfo &repo)
#define ZYPP_PRIVATE_CONSTR_ARG
Definition zyppglobal.h:160