libzypp 17.37.5
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
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
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
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
299 | and_then( [this](){ return init_knownRepositories(); } );
300 }
301
302 template<typename ZyppContextRefType>
308 template <typename ZyppContextRefType>
310 {
311 try {
312 using namespace zyppng::operators;
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.
318 zypp::Pathname mediarootpath;
319
320 return rawcache_path_for_repoinfo( options, info )
321 | and_then( [&]( zypp::Pathname mrPath ) {
322 mediarootpath = std::move(mrPath);
324 })
325 | and_then( [&]( zypp::Pathname productdatapath ) {
326 zypp::repo::RepoType repokind = info.type();
327 // If unknown, probe the local metadata
328 if ( repokind == zypp::repo::RepoType::NONE )
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() )
339 status = RepoStatus( productdatapath/"repodata/repomd.xml");
340 if ( info.requireStatusWithMediaFile() )
341 status = status && RepoStatus( mediarootpath/"media.1/media" );
342 break;
345 status = RepoStatus( productdatapath/"content" ) && RepoStatus( mediarootpath/"media.1/media" );
346 break;
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).
352 status = RepoStatus::fromCookieFileUseMtime( productdatapath/"cookie" );
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 }
371
372 template <typename ZyppContextRefType>
375 return metadataStatus( info, _options );
378 template <typename ZyppContextRefType>
379 expected<void> RepoManager<ZyppContextRefType>::cleanMetadata(const RepoInfo &info, ProgressObserverRef myProgress )
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 ( ... ) {
393 }
395 }
396
397 template <typename ZyppContextRefType>
398 expected<void> RepoManager<ZyppContextRefType>::cleanPackages(const RepoInfo &info, ProgressObserverRef myProgress, bool isAutoClean )
399 {
400 try {
401 ProgressObserver::setup( myProgress, _("Cleaning packages"), 100 );
403
404 // bsc#1204956: Tweak to prevent auto pruning package caches
406 if ( not isAutoClean || autoPruneInDir( rpc.dirname() ) )
409 ProgressObserver::finish ( myProgress );
410
411 } catch (...) {
414 }
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;
441
442 template <typename ZyppContextRefType>
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);
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 ) )
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 );
493 return expected<void>::error( ZYPP_FWD_CURRENT_EXCPT() );
497 }
499 template <typename ZyppContextRefType>
500 expected<void> RepoManager<ZyppContextRefType>::cleanCache(const RepoInfo &info, ProgressObserverRef myProgress )
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
516 }
517 }
518
519 template <typename ZyppContextRefType>
520 expected<void> RepoManager<ZyppContextRefType>::loadFromCache( const RepoInfo & info, ProgressObserverRef myProgress )
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.
543 const std::string & toolversion( zypp::sat::LookupRepoAttr( zypp::sat::SolvAttr::repositoryToolVersion, repo ).begin().asString() );
544 if ( toolversion != LIBSOLV_TOOLVERSION ) {
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]{
555 })
556 | and_then( mtry([this, info = info]{
557 _zyppContext->satPool().addRepoSolv( solv_path_for_repoinfo(_options, info).unwrap() / "solv", info );
558 }));
559 })
560 | and_then([myProgress]{
561 ProgressObserver::finish ( myProgress );
563 })
564 | or_else([myProgress]( auto ex ){
566 return expected<void>::error(ex);
567 })
568 ;
569 }
570
571 template <typename ZyppContextRefType>
573 {
574 try {
575 auto tosave = info;
576
577 // assert the directory exists
579
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.effectiveBaseUrls() );
600
601 zypp::HistoryLog(_options.rootDir).addRepository(tosave);
602
603 // return the new repoinfo
604 return expected<RepoInfo>::success( tosave );
605
606 } catch (...) {
608 }
609 }
610
611 template <typename ZyppContextRefType>
612 expected<void> RepoManager<ZyppContextRefType>::removeRepository( const RepoInfo & info, ProgressObserverRef myProgress )
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
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;
686 zypp::HistoryLog(_options.rootDir).removeRepository(todelete);
687
688 ProgressObserver::finish(myProgress);
690 } // else filepath is empty
691 }
692 // should not be reached on a sucess workflow
694 } catch (...) {
696 return expected<void>::error( std::current_exception () );
697 }
698 }
699
700 template <typename ZyppContextRefType>
701 expected<RepoInfo> RepoManager<ZyppContextRefType>::modifyRepository( const std::string & alias, const RepoInfo & newinfo_r, ProgressObserverRef myProgress )
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
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() )
760 zypp::filesystem::unlink( solvidx );
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
776 zypp::HistoryLog(_options.rootDir).modifyRepository(toedit, newinfo);
777 MIL << "repo " << alias << " modified" << std::endl;
778
779 ProgressObserver::finish ( myProgress );
780 return expected<RepoInfo>::success( newinfo );
781 }
782
783 } catch ( ... ) {
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( const auto &repourl : it->effectiveBaseUrls() )
813 {
814 if ( repourl.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;
833 | [this, info](auto) { return zyppng::repo::RefreshContext<ZyppContextRefType>::create( _zyppContext, info, shared_this<RepoManager<ZyppContextRefType>>() ); }
834 | and_then( [this, urls, policy]( zyppng::repo::RefreshContextRef<ZyppContextRefType> &&refCtx ) {
835 refCtx->setPolicy ( static_cast<zyppng::repo::RawMetadataRefreshPolicy>( policy ) );
836 return _zyppContext->provider()->prepareMedia( urls, 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
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
871 return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), myProgress );
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
915 | [sharedThis, info = info](auto) { return zyppng::repo::RefreshContext<ZyppContextRefType>::create( sharedThis->_zyppContext, info, sharedThis); }
916 | inspect( incProgress( subProgress ) )
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 })
924 | inspect( incProgress( subProgress ) )
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 })
932 | inspect( incProgress( subProgress ) )
933 | [ info = info, subProgress ]( expected<repo::RefreshContextRef<ZyppContextRefType>> result ) {
934 if ( result ) {
936 return std::make_pair(info, expected<void>::success() );
937 } else {
939 return std::make_pair(info, expected<void>::error( result.error() ) );
940 }
941 };
942 }
943 | [myProgress]( auto res ) {
945 return res;
946 }
947 );
948
949 return joinPipeline( _zyppContext, r );
950 }
951
958 template<typename ZyppContextRefType>
959 expected<zypp::repo::RepoType> RepoManager<ZyppContextRefType>::probe(const std::vector<zypp::Url> &urls, const zypp::Pathname &path) const
960 {
961 using namespace zyppng::operators;
962
965 | [this, urls=urls](auto) { return _zyppContext->provider()->prepareMedia( urls, zyppng::ProvideMediaSpec() ); }
966 | and_then( [this, path = path]( auto mediaHandle ) {
967 return RepoManagerWorkflow::probeRepoType( _zyppContext, std::forward<decltype(mediaHandle)>(mediaHandle), path );
968 }));
969 }
970
971 template<typename ZyppContextRefType>
972 expected<void> RepoManager<ZyppContextRefType>::buildCache( const RepoInfo &info, CacheBuildPolicy policy, ProgressObserverRef myProgress )
973 {
974 using namespace zyppng::operators;
977 | and_then( [policy, myProgress]( repo::RefreshContextRef<ZyppContextRefType> refCtx ) {
978 return zyppng::RepoManagerWorkflow::buildCache ( std::move(refCtx), policy, myProgress );
979 })
980 | and_then([]( auto ){ return expected<void>::success(); })
981 );
982 }
983
984 template<typename ZyppContextRefType>
989
990 template<typename ZyppContextRefType>
996
997 template <typename ZyppContextRefType>
1002
1003 template <typename ZyppContextRefType>
1005 {
1006 try {
1007
1008 assert_alias( service ).unwrap();
1009
1010 // check if service already exists
1011 if ( hasService( service.alias() ) )
1013
1014 // Writable ServiceInfo is needed to save the location
1015 // of the .service file. Finaly insert into the service list.
1016 ServiceInfo toSave( service );
1017 saveService( toSave ).unwrap();
1018 _services.insert( toSave );
1019
1020 // check for credentials in Url
1021 zypp::UrlCredentialExtractor( _options.rootDir ).collect( toSave.url() );
1022
1023 MIL << "added service " << toSave.alias() << std::endl;
1024
1025 } catch ( ... ) {
1026 return expected<void>::error( std::current_exception () );
1027 }
1028
1029 return expected<void>::success();
1030 }
1031
1032 template<typename ZyppContextRefType>
1037
1041 template<typename ZyppContextRefType>
1043 {
1044 using namespace zyppng::operators;
1045 // copy the set of services since refreshService
1046 // can eventually invalidate the iterator
1047 ServiceSet servicesCopy( serviceBegin(), serviceEnd() );
1048
1049 // convert the set into a vector, transform needs a container with push_back support
1050 std::vector<ServiceInfo> servicesVec;
1051 std::copy( std::make_move_iterator(servicesCopy.begin()), std::make_move_iterator(servicesCopy.end()), std::back_inserter(servicesVec));
1052
1053 return joinPipeline( _zyppContext,
1054 std::move(servicesVec)
1055 | transform( [options_r, this]( ServiceInfo i ){ return RepoServicesWorkflow::refreshService( shared_this<RepoManager<ZyppContextRefType>>(), i, options_r ); } )
1056 | join()
1057 | collect()
1058 );
1059 }
1060
1062
1063 template <typename ZyppContextRefType>
1065 {
1066 try {
1067 MIL << "Going to delete service " << alias << std::endl;
1068
1069 const ServiceInfo & service = getService( alias );
1070
1071 zypp::Pathname location = service.filepath();
1072 if( location.empty() )
1073 {
1074 ZYPP_THROW(zypp::repo::ServiceException( service, _("Can't figure out where the service is stored.") ));
1075 }
1076
1077 ServiceSet tmpSet;
1079
1080 // only one service definition in the file
1081 if ( tmpSet.size() == 1 )
1082 {
1083 if ( zypp::filesystem::unlink(location) != 0 )
1084 {
1085 // TranslatorExplanation '%s' is a filename
1086 ZYPP_THROW(zypp::repo::ServiceException( service, zypp::str::form( _("Can't delete '%s'"), location.c_str() ) ));
1087 }
1088 MIL << alias << " successfully deleted." << std::endl;
1089 }
1090 else
1091 {
1093
1094 std::ofstream file(location.c_str());
1095 if( !file )
1096 {
1097 // TranslatorExplanation '%s' is a filename
1098 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), location.c_str() )));
1099 }
1100
1101 for_(it, tmpSet.begin(), tmpSet.end())
1102 {
1103 if( it->alias() != alias )
1104 it->dumpAsIniOn(file);
1105 }
1106
1107 MIL << alias << " successfully deleted from file " << location << std::endl;
1108 }
1109
1110 // now remove all repositories added by this service
1111 RepoCollector rcollector;
1113 boost::make_function_output_iterator( std::bind( &RepoCollector::collect, &rcollector, std::placeholders::_1 ) ) );
1114 // cannot do this directly in getRepositoriesInService - would invalidate iterators
1115 for_(rit, rcollector.repos.begin(), rcollector.repos.end())
1116 removeRepository(*rit).unwrap();
1117
1118 return expected<void>::success();
1119
1120 } catch ( ... ) {
1121 return expected<void>::error( std::current_exception () );
1122 }
1123 }
1124
1125 template <typename ZyppContextRefType>
1126 expected<void> RepoManager<ZyppContextRefType>::modifyService( const std::string & oldAlias, const ServiceInfo & newService )
1127 {
1128 try {
1129
1130 MIL << "Going to modify service " << oldAlias << std::endl;
1131
1132 // we need a writable copy to link it to the file where
1133 // it is saved if we modify it
1134 ServiceInfo service(newService);
1135
1136 if ( service.type() == zypp::repo::ServiceType::PLUGIN )
1137 {
1139 }
1140
1141 const ServiceInfo & oldService = getService(oldAlias);
1142
1143 zypp::Pathname location = oldService.filepath();
1144 if( location.empty() )
1145 {
1146 ZYPP_THROW(zypp::repo::ServiceException( oldService, _("Can't figure out where the service is stored.") ));
1147 }
1148
1149 // remember: there may multiple services being defined in one file:
1150 ServiceSet tmpSet;
1152
1154 std::ofstream file(location.c_str());
1155 for_(it, tmpSet.begin(), tmpSet.end())
1156 {
1157 if( *it != oldAlias )
1158 it->dumpAsIniOn(file);
1159 }
1160 service.dumpAsIniOn(file);
1161 file.close();
1162 service.setFilepath(location);
1163
1164 _services.erase(oldAlias);
1165 _services.insert(service);
1166 // check for credentials in Urls
1167 zypp::UrlCredentialExtractor( _options.rootDir ).collect( service.url() );
1168
1169
1170 // changed properties affecting also repositories
1171 if ( oldAlias != service.alias() // changed alias
1172 || oldService.enabled() != service.enabled() ) // changed enabled status
1173 {
1174 std::vector<RepoInfo> toModify;
1175 getRepositoriesInService(oldAlias, std::back_inserter(toModify));
1176 for_( it, toModify.begin(), toModify.end() )
1177 {
1178 if ( oldService.enabled() != service.enabled() )
1179 {
1180 if ( service.enabled() )
1181 {
1182 // reset to last refreshs state
1183 const auto & last = service.repoStates().find( it->alias() );
1184 if ( last != service.repoStates().end() )
1185 it->setEnabled( last->second.enabled );
1186 }
1187 else
1188 it->setEnabled( false );
1189 }
1190
1191 if ( oldAlias != service.alias() )
1192 it->setService(service.alias());
1193
1194 modifyRepository(it->alias(), *it).unwrap();
1195 }
1196 }
1197
1198 return expected<void>::success();
1199
1200 } catch ( ... ) {
1201 return expected<void>::error( std::current_exception () );
1202 }
1203
1205 }
1206
1207
1208 template <typename ZyppContextRefType>
1210 {
1211 try {
1212
1213 zypp::filesystem::assert_dir( _options.knownServicesPath );
1214 zypp::Pathname servfile = generateNonExistingName( _options.knownServicesPath,
1215 generateFilename( service ) );
1216 service.setFilepath( servfile );
1217
1218 MIL << "saving service in " << servfile << std::endl;
1219
1220 std::ofstream file( servfile.c_str() );
1221 if ( !file )
1222 {
1223 // TranslatorExplanation '%s' is a filename
1224 ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), servfile.c_str() )));
1225 }
1226 service.dumpAsIniOn( file );
1227 MIL << "done" << std::endl;
1228
1229 return expected<void>::success();
1230
1231 } catch ( ... ) {
1232 return expected<void>::error( std::current_exception () );
1233 }
1234 }
1235
1251 template <typename ZyppContextRefType>
1253 const std::string & basefilename ) const
1254 {
1255 std::string final_filename = basefilename;
1256 int counter = 1;
1257 while ( zypp::PathInfo(dir + final_filename).isExist() )
1258 {
1259 final_filename = basefilename + "_" + zypp::str::numstring(counter);
1260 ++counter;
1261 }
1262 return dir + zypp::Pathname(final_filename);
1263 }
1264
1265 template <typename ZyppContextRefType>
1267 {
1268 try {
1269 zypp::Pathname productdatapath = rawproductdata_path_for_repoinfo( options, info ).unwrap();
1270
1271 zypp::repo::RepoType repokind = info.type();
1272 if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e )
1273 // unknown, probe the local metadata
1274 repokind = probeCache( productdatapath );
1275 // if still unknown, just return
1276 if (repokind == zypp::repo::RepoType::NONE_e)
1277 return expected<void>::success();
1278
1280 switch ( repokind.toEnum() )
1281 {
1283 p = zypp::Pathname(productdatapath + "/repodata/repomd.xml");
1284 break;
1285
1287 p = zypp::Pathname(productdatapath + "/content");
1288 break;
1289
1291 p = zypp::Pathname(productdatapath + "/cookie");
1292 break;
1293
1295 default:
1296 break;
1297 }
1298
1299 // touch the file, ignore error (they are logged anyway)
1301 } catch ( ... ) {
1303 }
1304 return expected<void>::success();
1305 }
1306
1307 template<typename ZyppContextRefType>
1312
1313 template <typename ZyppContextRefType>
1318
1319 template <typename ZyppContextRefType>
1321 {
1322 try {
1323 zypp::Pathname dir = _options.knownServicesPath;
1324 std::list<zypp::Pathname> entries;
1325 if (zypp::PathInfo(dir).isExist())
1326 {
1327 if ( zypp::filesystem::readdir( entries, dir, false ) != 0 )
1328 {
1329 // TranslatorExplanation '%s' is a pathname
1330 ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str())));
1331 }
1332
1333 //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
1334 for_(it, entries.begin(), entries.end() )
1335 {
1337 }
1338 }
1339
1341
1342 return expected<void>::success();
1343
1344 } catch ( ... ) {
1345 return expected<void>::error( std::current_exception () );
1346 }
1347
1348 }
1349
1350 namespace {
1357 inline void cleanupNonRepoMetadtaFolders( const zypp::Pathname & cachePath_r,
1358 const zypp::Pathname & defaultCachePath_r,
1359 const std::list<std::string> & repoEscAliases_r )
1360 {
1362 return;
1363
1364 if ( cachePath_r != defaultCachePath_r )
1365 return;
1366
1367 std::list<std::string> entries;
1368 if ( zypp::filesystem::readdir( entries, cachePath_r, false ) == 0 )
1369 {
1370 entries.sort();
1371 std::set<std::string> oldfiles;
1372 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
1373 std::inserter( oldfiles, oldfiles.end() ) );
1374
1375 // bsc#1178966: Files or symlinks here have been created by the user
1376 // for whatever purpose. It's our cache, so we purge them now before
1377 // they may later conflict with directories we need.
1378 zypp::PathInfo pi;
1379 for ( const std::string & old : oldfiles )
1380 {
1381 if ( old == zypp::Repository::systemRepoAlias() ) // don't remove the @System solv file
1382 continue;
1383 pi( cachePath_r/old );
1384 if ( pi.isDir() )
1386 else
1388 }
1389 }
1390 }
1391 } // namespace
1392
1393 template <typename ZyppContextRefType>
1395 {
1396 try {
1397
1398 MIL << "start construct known repos" << std::endl;
1399
1400 if ( zypp::PathInfo(_options.knownReposPath).isExist() )
1401 {
1402 std::list<std::string> repoEscAliases;
1403 std::list<RepoInfo> orphanedRepos;
1404 for ( RepoInfo & repoInfo : repositories_in_dir( _zyppContext, _options.knownReposPath ) )
1405 {
1406 // set the metadata path for the repo
1407 repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo).unwrap() );
1408 // set the downloaded packages path for the repo
1409 repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo).unwrap() );
1410 // remember it
1411 _reposX.insert( repoInfo ); // direct access via _reposX in ctor! no reposManip.
1412
1413 // detect orphaned repos belonging to a deleted service
1414 const std::string & serviceAlias( repoInfo.service() );
1415 if ( ! ( serviceAlias.empty() || hasService( serviceAlias ) ) )
1416 {
1417 WAR << "Schedule orphaned service repo for deletion: " << repoInfo << std::endl;
1418 orphanedRepos.push_back( repoInfo );
1419 continue; // don't remember it in repoEscAliases
1420 }
1421
1422 repoEscAliases.push_back(repoInfo.escaped_alias());
1423 }
1424
1425 // Cleanup orphanded service repos:
1426 if ( ! orphanedRepos.empty() )
1427 {
1428 for ( const auto & repoInfo : orphanedRepos )
1429 {
1430 MIL << "Delete orphaned service repo " << repoInfo.alias() << std::endl;
1431 // translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service.
1432 // %1% = service name
1433 // %2% = repository name
1434 JobReportHelper(_zyppContext).warning( zypp::str::Format(_("Unknown service '%1%': Removing orphaned service repository '%2%'"))
1435 % repoInfo.service()
1436 % repoInfo.alias() );
1437 try {
1438 removeRepository( repoInfo ).unwrap();
1439 }
1440 catch ( const zypp::Exception & caugth )
1441 {
1443 }
1444 }
1445 }
1446
1447 // bsc#1210740: Don't cleanup if read-only mode was promised.
1449 // delete metadata folders without corresponding repo (e.g. old tmp directories)
1450 //
1451 // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise
1452 // we'd need somemagic file to identify zypp cache directories. Without this
1453 // we may easily remove user data (zypper --pkg-cache-dir . download ...)
1454 repoEscAliases.sort();
1455 cleanupNonRepoMetadtaFolders( _options.repoRawCachePath,
1456 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoMetadataPath() ),
1457 repoEscAliases );
1458 cleanupNonRepoMetadtaFolders( _options.repoSolvCachePath,
1459 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoSolvfilesPath() ),
1460 repoEscAliases );
1461 // bsc#1204956: Tweak to prevent auto pruning package caches
1462 if ( autoPruneInDir( _options.repoPackagesCachePath ) )
1463 cleanupNonRepoMetadtaFolders( _options.repoPackagesCachePath,
1464 zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoPackagesPath() ),
1465 repoEscAliases );
1466 }
1467 }
1468 MIL << "end construct known repos" << std::endl;
1469
1470 return expected<void>::success();
1471
1472 } catch ( ... ) {
1473 return expected<void>::error( std::current_exception () );
1474 }
1475 }
1476
1477 // explicitely intantiate the template types we want to work with
1478 template class RepoManager<SyncContextRef>;
1479 template class RepoManager<ContextRef>;
1480} // namespace zyppng
#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.
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
repo::RepoType type() const
Type of repository,.
Definition RepoInfo.cc:759
url_set effectiveBaseUrls() const
The complete set of effective repository urls.
Definition RepoInfo.cc:711
void setBaseUrl(Url url)
Clears current base URL list and adds url.
Definition RepoInfo.cc:693
void setPackagesPath(const Pathname &path)
set the path where the local packages are stored
Definition RepoInfo.cc:729
bool requireStatusWithMediaFile() const
Returns true if this repository requires the media.1/media file to be included in the metadata status...
Definition RepoInfo.cc:1143
std::ostream & dumpAsIniOn(std::ostream &str) const override
Write this RepoInfo object into str in a .repo file format.
Definition RepoInfo.cc:1015
void setMetadataPath(const Pathname &path)
Set the path where the local metadata is stored.
Definition RepoInfo.cc:726
void setType(const repo::RepoType &t)
set the repository type
Definition RepoInfo.cc:719
std::list< Url > url_set
Definition RepoInfo.h:108
bool effectiveBaseUrlsEmpty() const
whether effective repository urls are available
Definition RepoInfo.cc:706
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.
RepoManager(RepoManagerOptions options=RepoManagerOptions())
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.
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
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: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
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)
The RepoManager class Provides knowledge and methods to maintain repo settings and metadata for a giv...
ServiceInfo getService(const std::string &alias) const
std::set< ServiceInfo > ServiceSet
ServiceInfo typedefs.
ServiceConstIterator serviceBegin() const
expected< void > cleanPackages(const RepoInfo &info, ProgressObserverRef myProgress=nullptr, bool isAutoClean=false)
static expected< void > touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
expected< RepoInfo > getRepositoryInfo(const std::string &alias)
expected< RepoInfo > modifyRepository(const std::string &alias, const RepoInfo &newinfo_r, ProgressObserverRef myProgress=nullptr)
void getRepositoriesInService(const std::string &alias, OutputIterator out) const
zypp::RepoManagerFlags::RawMetadataRefreshPolicy RawMetadataRefreshPolicy
ServiceConstIterator serviceEnd() const
static zypp::repo::RepoType probeCache(const zypp::Pathname &path_r)
Probe Metadata in a local cache directory.
expected< void > init_knownServices()
expected< RepoInfo > addProbedRepository(RepoInfo info, zypp::repo::RepoType probedType)
const RepoSet & repos() const
expected< bool > isCached(const RepoInfo &info) const
expected< void > initialize()
zypp::Pathname generateNonExistingName(const zypp::Pathname &dir, const std::string &basefilename) const
Generate a non existing filename in a directory, using a base name.
expected< void > buildCache(const RepoInfo &info, CacheBuildPolicy policy, ProgressObserverRef myProgress=nullptr)
RepoSet::const_iterator RepoConstIterator
RepoManagerOptions _options
expected< void > init_knownRepositories()
expected< void > cleanCache(const RepoInfo &info, ProgressObserverRef myProgress=nullptr)
zypp::DefaultIntegral< bool, false > _reposDirty
expected< void > cleanMetadata(const RepoInfo &info, ProgressObserverRef myProgress=nullptr)
static expected< RepoStatus > metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
expected< void > removeRepository(const RepoInfo &info, ProgressObserverRef myProgress=nullptr)
bool hasService(const std::string &alias) const
RepoConstIterator repoBegin() const
expected< void > saveService(ServiceInfo &service) const
bool hasRepo(const std::string &alias) const
std::string generateFilename(const RepoInfo &info) const
RepoConstIterator repoEnd() const
zypp::RepoManagerFlags::RefreshServiceOptions RefreshServiceOptions
const RepoManagerOptions & options() const
zypp::RepoManagerFlags::CacheBuildPolicy CacheBuildPolicy
RepoSet & reposManip()
Functor collecting ServiceInfos into a ServiceSet.
static expected success(ConsParams &&...params)
Definition expected.h:115
static expected error(ConsParams &&...params)
Definition expected.h:126
static expected< repo::RefreshContextRef< ZyppContextRefType > > create(ZyppContextRefType zyppContext, zypp::RepoInfo info, RepoManagerRef< ContextRefType > repoManager)
Definition refresh.cc:32
SignalProxy< void(zypp::repo::RepoType)> sigProbedTypeChanged()
Definition refresh.cc:158
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:25
bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT()
To trigger appdata refresh unconditionally.
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: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
AsyncOpRef< expected< zypp::repo::RepoType > > probeRepoType(ContextRef ctx, AsyncLazyMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath)
AsyncOpRef< expected< RepoInfo > > addRepository(AsyncRepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress)
AsyncOpRef< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< void > > refreshGeoIPData(ContextRef ctx, RepoInfo::url_set urls)
AsyncOpRef< expected< void > > addRepositories(AsyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress)
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)
AsyncOpRef< expected< void > > refreshService(AsyncRepoManagerRef repoMgr, ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options)
AsyncOpRef< 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
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:55
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.
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition expected.h:397
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:58
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:99
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.
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_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 ZYPP_PRIVATE_CONSTR_ARG
Definition zyppglobal.h:160