libzypp 17.32.5
repomanagerbase_p.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9
10#include "repomanagerbase_p.h"
11
12#include <solv/solvversion.h>
13
16#include <zypp/HistoryLog.h>
17#include <zypp/ZConfig.h>
18#include <zypp/ZYppCallbacks.h>
19#include <zypp/base/LogTools.h>
22#include <zypp/sat/Pool.h>
26
27#include <fstream>
28#include <utility>
29
30namespace zypp
31{
32
33 namespace zypp_readonly_hack {
34 bool IGotIt(); // in readonly-mode
35 }
36
37 namespace {
43 inline void cleanupNonRepoMetadataFolders( const Pathname & cachePath_r,
44 const Pathname & defaultCachePath_r,
45 const std::list<std::string> & repoEscAliases_r )
46 {
47 if ( cachePath_r != defaultCachePath_r )
48 return;
49
50 std::list<std::string> entries;
51 if ( filesystem::readdir( entries, cachePath_r, false ) == 0 )
52 {
53 entries.sort();
54 std::set<std::string> oldfiles;
55 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
56 std::inserter( oldfiles, oldfiles.end() ) );
57
58 // bsc#1178966: Files or symlinks here have been created by the user
59 // for whatever purpose. It's our cache, so we purge them now before
60 // they may later conflict with directories we need.
61 PathInfo pi;
62 for ( const std::string & old : oldfiles )
63 {
64 if ( old == Repository::systemRepoAlias() ) // don't remove the @System solv file
65 continue;
66 pi( cachePath_r/old );
67 if ( pi.isDir() )
68 filesystem::recursive_rmdir( pi.path() );
69 else
70 filesystem::unlink( pi.path() );
71 }
72 }
73 }
74 } // namespace
75
76 std::string filenameFromAlias(const std::string &alias_r, const std::string &stem_r)
77 {
78 std::string filename( alias_r );
79 // replace slashes with underscores
80 str::replaceAll( filename, "/", "_" );
81
82 filename = Pathname(filename).extend("."+stem_r).asString();
83 MIL << "generating filename for " << stem_r << " [" << alias_r << "] : '" << filename << "'" << endl;
84 return filename;
85 }
86
88 {
89 // skip repositories meant for other distros than specified
90 if (!targetDistro.empty()
91 && !repo.targetDistribution().empty()
93 {
94 MIL
95 << "Skipping repository meant for '" << repo.targetDistribution()
96 << "' distribution (current distro is '"
97 << targetDistro << "')." << endl;
98
99 return true;
100 }
101
102 repos.push_back(repo);
103 return true;
104 }
105
106 std::list<RepoInfo> repositories_in_file(const Pathname &file)
107 {
108 MIL << "repo file: " << file << endl;
109 RepoCollector collector;
110 parser::RepoFileReader parser( file, bind( &RepoCollector::collect, &collector, _1 ) );
111 return std::move(collector.repos);
112 }
113
114 std::list<RepoInfo> repositories_in_dir(const Pathname &dir)
115 {
116 MIL << "directory " << dir << endl;
117 std::list<RepoInfo> repos;
118 bool nonroot( geteuid() != 0 );
119 if ( nonroot && ! PathInfo(dir).userMayRX() )
120 {
121 JobReport::warning( str::Format(_("Cannot read repo directory '%1%': Permission denied")) % dir );
122 }
123 else
124 {
125 std::list<Pathname> entries;
126 if ( filesystem::readdir( entries, dir, false ) != 0 )
127 {
128 // TranslatorExplanation '%s' is a pathname
129 ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
130 }
131
132 str::regex allowedRepoExt("^\\.repo(_[0-9]+)?$");
133 for ( std::list<Pathname>::const_iterator it = entries.begin(); it != entries.end(); ++it )
134 {
135 if ( str::regex_match(it->extension(), allowedRepoExt) )
136 {
137 if ( nonroot && ! PathInfo(*it).userMayR() )
138 {
139 JobReport::warning( str::Format(_("Cannot read repo file '%1%': Permission denied")) % *it );
140 }
141 else
142 {
143 const std::list<RepoInfo> & tmp( repositories_in_file( *it ) );
144 repos.insert( repos.end(), tmp.begin(), tmp.end() );
145 }
146 }
147 }
148 }
149 return repos;
150 }
151
152 void assert_urls(const RepoInfo &info)
153 {
154 if ( info.baseUrlsEmpty() )
156 }
157
159 { return not zypp::PathInfo(path_r/".no_auto_prune").isExist(); }
160
161
163 : _options(std::move(opt))
164 { }
165
167 {
168 //@TODO Add Appdata refresh?
169 }
170
172 {
175
177 // If unknown, probe the local metadata
180
181 // NOTE: The calling code expects an empty RepoStatus being returned
182 // if the metadata cache is empty. So additioanl components like the
183 // RepoInfos status are joined after the switch IFF the status is not
184 // empty.
185 RepoStatus status;
186 switch ( repokind.toEnum() )
187 {
189 status = RepoStatus( productdatapath/"repodata/repomd.xml");
190 if ( info.requireStatusWithMediaFile() )
191 status = status && RepoStatus( mediarootpath/"media.1/media" );
192 break;
193
195 status = RepoStatus( productdatapath/"content" ) && RepoStatus( mediarootpath/"media.1/media" );
196 break;
197
199 // Dir status at last refresh. Plaindir uses the cookiefile as pseudo metadata index file.
200 // It gets touched if the refresh check finds the data being up-to-date. That's why we use
201 // the files mtime as timestamp (like the RepoStatus ctor in the other cases above).
203 break;
204
206 // Return default RepoStatus in case of RepoType::NONE
207 // indicating it should be created?
208 // ZYPP_THROW(RepoUnknownTypeException());
209 break;
210 }
211
212 if ( ! status.empty() )
213 status = status && RepoStatus( info );
214
215 return status;
216 }
217
219 {
220 return metadataStatus( info, _options );
221 }
222
231
233 {
234 ProgressData progress(100);
235 progress.sendTo(progressfnc);
236
237 // bsc#1204956: Tweak to prevent auto pruning package caches
239 if ( not isAutoClean || autoPruneInDir( rpc.dirname() ) )
241
242 progress.toMax();
243 }
244
251 {
252 MIL << "going to probe the cached repo at " << path_r << endl;
253
255
256 if ( PathInfo(path_r/"/repodata/repomd.xml").isFile() )
258 else if ( PathInfo(path_r/"/content").isFile() )
260 else if ( PathInfo(path_r).isDir() )
262
263 MIL << "Probed cached type " << ret << " at " << path_r << endl;
264 return ret;
265 }
266
268 {
269 MIL << "Going to clean up garbage in cache dirs" << endl;
270
271 ProgressData progress(300);
272 progress.sendTo(progressrcv);
273 progress.toMin();
274
275 std::list<Pathname> cachedirs;
279
280 for_( dir, cachedirs.begin(), cachedirs.end() )
281 {
282 if ( PathInfo(*dir).isExist() )
283 {
284 std::list<Pathname> entries;
285 if ( filesystem::readdir( entries, *dir, false ) != 0 )
286 // TranslatorExplanation '%s' is a pathname
287 ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir->c_str())));
288
289 unsigned sdircount = entries.size();
290 unsigned sdircurrent = 1;
291 for_( subdir, entries.begin(), entries.end() )
292 {
293 // if it does not belong known repo, make it disappear
294 bool found = false;
295 for_( r, repoBegin(), repoEnd() )
296 if ( subdir->basename() == r->escaped_alias() )
297 { found = true; break; }
298
299 if ( ! found && ( Date::now()-PathInfo(*subdir).mtime() > Date::day ) )
301
302 progress.set( progress.val() + sdircurrent * 100 / sdircount );
303 ++sdircurrent;
304 }
305 }
306 else
307 progress.set( progress.val() + 100 );
308 }
309 progress.toMax();
310 }
311
313 {
314 ProgressData progress(100);
315 progress.sendTo(progressrcv);
316 progress.toMin();
317
318 MIL << "Removing raw metadata cache for " << info.alias() << endl;
320
321 progress.toMax();
322 }
323
325 {
326 assert_alias(info);
328
329 if ( ! PathInfo(solvfile).isExist() )
331
332 sat::Pool::instance().reposErase( info.alias() );
333
334 Repository repo = sat::Pool::instance().addRepoSolv( solvfile, info );
335 // test toolversion in order to rebuild solv file in case
336 // it was written by a different libsolv-tool parser.
337 const std::string & toolversion( sat::LookupRepoAttr( sat::SolvAttr::repositoryToolVersion, repo ).begin().asString() );
339 repo.eraseFromPool();
340 ZYPP_THROW(Exception(str::Str() << "Solv-file was created by '"<<toolversion<<"'-parser (want "<<LIBSOLV_TOOLVERSION<<")."));
341 }
342 }
343
345 {
346
347 auto tosave = info;
348
349 // assert the directory exists
351
354 // now we have a filename that does not exists
355 MIL << "Saving repo in " << repofile << endl;
356
357 std::ofstream file(repofile.c_str());
358 if (!file)
359 {
360 // TranslatorExplanation '%s' is a filename
361 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
362 }
363
364 tosave.dumpAsIniOn(file);
365 tosave.setFilepath(repofile);
366 tosave.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ) );
368 {
369 // We should fix the API as we must inject those paths
370 // into the repoinfo in order to keep it usable.
371 RepoInfo & oinfo( const_cast<RepoInfo &>(info) );
372 oinfo.setFilepath(repofile);
373 oinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ) );
375 }
376 reposManip().insert(tosave);
377
378 // check for credentials in Urls
380
382 }
383
385 {
386 ProgressData progress;
388 progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
389 progress.name(str::form(_("Removing repository '%s'"), info.label().c_str()));
390
391 MIL << "Going to delete repo " << info.alias() << endl;
392
393 for_( it, repoBegin(), repoEnd() )
394 {
395 // they can be the same only if the provided is empty, that means
396 // the provided repo has no alias
397 // then skip
398 if ( (!info.alias().empty()) && ( info.alias() != (*it).alias() ) )
399 continue;
400
401 // TODO match by url
402
403 // we have a matching repository, now we need to know
404 // where it does come from.
406 if (todelete.filepath().empty())
407 {
408 ZYPP_THROW(repo::RepoException( todelete, _("Can't figure out where the repo is stored.") ));
409 }
410 else
411 {
412 // figure how many repos are there in the file:
413 std::list<RepoInfo> filerepos = repositories_in_file(todelete.filepath());
414 if ( filerepos.size() == 0 // bsc#984494: file may have already been deleted
415 ||(filerepos.size() == 1 && filerepos.front().alias() == todelete.alias() ) )
416 {
417 // easy: file does not exist, contains no or only the repo to delete: delete the file
418 int ret = filesystem::unlink( todelete.filepath() );
419 if ( ! ( ret == 0 || ret == ENOENT ) )
420 {
421 // TranslatorExplanation '%s' is a filename
422 ZYPP_THROW(repo::RepoException( todelete, str::form( _("Can't delete '%s'"), todelete.filepath().c_str() )));
423 }
424 MIL << todelete.alias() << " successfully deleted." << endl;
425 }
426 else
427 {
428 // there are more repos in the same file
429 // write them back except the deleted one.
430 //TmpFile tmp;
431 //std::ofstream file(tmp.path().c_str());
432
433 // assert the directory exists
434 filesystem::assert_dir(todelete.filepath().dirname());
435
436 std::ofstream file(todelete.filepath().c_str());
437 if (!file)
438 {
439 // TranslatorExplanation '%s' is a filename
440 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), todelete.filepath().c_str() )));
441 }
442 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
443 fit != filerepos.end();
444 ++fit )
445 {
446 if ( (*fit).alias() != todelete.alias() )
447 (*fit).dumpAsIniOn(file);
448 }
449 }
450
451 CombinedProgressData cSubprogrcv(progress, 20);
452 CombinedProgressData mSubprogrcv(progress, 40);
453 CombinedProgressData pSubprogrcv(progress, 40);
454 // now delete it from cache
455 if ( isCached(todelete) )
457 // now delete metadata (#301037)
459 cleanPackages( todelete, pSubprogrcv, true/*isAutoClean*/ );
460 reposManip().erase(todelete);
461 MIL << todelete.alias() << " successfully deleted." << endl;
463 return;
464 } // else filepath is empty
465
466 }
467 // should not be reached on a sucess workflow
469 }
470
472 {
474 RepoInfo newinfo( newinfo_r ); // need writable copy to upadte housekeeping data
475
476 // check if the new alias already exists when renaming the repo
477 if ( alias != newinfo.alias() && hasRepo( newinfo.alias() ) )
478 {
480 }
481
482 if (toedit.filepath().empty())
483 {
484 ZYPP_THROW(repo::RepoException( toedit, _("Can't figure out where the repo is stored.") ));
485 }
486 else
487 {
488 // figure how many repos are there in the file:
489 std::list<RepoInfo> filerepos = repositories_in_file(toedit.filepath());
490
491 // there are more repos in the same file
492 // write them back except the deleted one.
493 //TmpFile tmp;
494 //std::ofstream file(tmp.path().c_str());
495
496 // assert the directory exists
497 filesystem::assert_dir(toedit.filepath().dirname());
498
499 std::ofstream file(toedit.filepath().c_str());
500 if (!file)
501 {
502 // TranslatorExplanation '%s' is a filename
503 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), toedit.filepath().c_str() )));
504 }
505 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
506 fit != filerepos.end();
507 ++fit )
508 {
509 // if the alias is different, dump the original
510 // if it is the same, dump the provided one
511 if ( (*fit).alias() != toedit.alias() )
512 (*fit).dumpAsIniOn(file);
513 else
514 newinfo.dumpAsIniOn(file);
515 }
516
517 if ( toedit.enabled() && !newinfo.enabled() )
518 {
519 // On the fly remove solv.idx files for bash completion if a repo gets disabled.
521 if ( PathInfo(solvidx).isExist() )
523 }
524
525 newinfo.setFilepath(toedit.filepath());
526 newinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ) );
528 {
529 // We should fix the API as we must inject those paths
530 // into the repoinfo in order to keep it usable.
531 RepoInfo & oinfo( const_cast<RepoInfo &>(newinfo_r) );
532 oinfo.setFilepath(toedit.filepath());
533 oinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ) );
535 }
536 reposManip().erase(toedit);
537 reposManip().insert(newinfo);
538 // check for credentials in Urls
541 MIL << "repo " << alias << " modified" << endl;
542 }
543 }
544
546 {
547 RepoConstIterator it( findAlias( alias, repos() ) );
548 if ( it != repos().end() )
549 return *it;
550 RepoInfo info;
551 info.setAlias( alias );
553 }
554
555
557 {
558 for_( it, repoBegin(), repoEnd() )
559 {
560 for_( urlit, (*it).baseUrlsBegin(), (*it).baseUrlsEnd() )
561 {
562 if ( (*urlit).asString(urlview) == url.asString(urlview) )
563 return *it;
564 }
565 }
566 RepoInfo info;
567 info.setBaseUrl( url );
569 }
570
572 {
573 assert_alias( service );
574
575 // check if service already exists
576 if ( hasService( service.alias() ) )
578
579 // Writable ServiceInfo is needed to save the location
580 // of the .service file. Finaly insert into the service list.
581 ServiceInfo toSave( service );
583 _services.insert( toSave );
584
585 // check for credentials in Url
587
588 MIL << "added service " << toSave.alias() << endl;
589 }
590
592
593 void RepoManagerBaseImpl::removeService( const std::string & alias )
594 {
595 MIL << "Going to delete service " << alias << endl;
596
597 const ServiceInfo & service = getService( alias );
598
599 Pathname location = service.filepath();
600 if( location.empty() )
601 {
602 ZYPP_THROW(repo::ServiceException( service, _("Can't figure out where the service is stored.") ));
603 }
604
607
608 // only one service definition in the file
609 if ( tmpSet.size() == 1 )
610 {
611 if ( filesystem::unlink(location) != 0 )
612 {
613 // TranslatorExplanation '%s' is a filename
614 ZYPP_THROW(repo::ServiceException( service, str::form( _("Can't delete '%s'"), location.c_str() ) ));
615 }
616 MIL << alias << " successfully deleted." << endl;
617 }
618 else
619 {
621
622 std::ofstream file(location.c_str());
623 if( !file )
624 {
625 // TranslatorExplanation '%s' is a filename
626 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), location.c_str() )));
627 }
628
629 for_(it, tmpSet.begin(), tmpSet.end())
630 {
631 if( it->alias() != alias )
632 it->dumpAsIniOn(file);
633 }
634
635 MIL << alias << " successfully deleted from file " << location << endl;
636 }
637
638 // now remove all repositories added by this service
641 boost::make_function_output_iterator( bind( &RepoCollector::collect, &rcollector, _1 ) ) );
642 // cannot do this directly in getRepositoriesInService - would invalidate iterators
643 for_(rit, rcollector.repos.begin(), rcollector.repos.end())
645 }
646
647 void RepoManagerBaseImpl::modifyService( const std::string & oldAlias, const ServiceInfo & newService )
648 {
649 MIL << "Going to modify service " << oldAlias << endl;
650
651 // we need a writable copy to link it to the file where
652 // it is saved if we modify it
653 ServiceInfo service(newService);
654
655 if ( service.type() == repo::ServiceType::PLUGIN )
656 {
658 }
659
660 const ServiceInfo & oldService = getService(oldAlias);
661
662 Pathname location = oldService.filepath();
663 if( location.empty() )
664 {
665 ZYPP_THROW(repo::ServiceException( oldService, _("Can't figure out where the service is stored.") ));
666 }
667
668 // remember: there may multiple services being defined in one file:
671
673 std::ofstream file(location.c_str());
674 for_(it, tmpSet.begin(), tmpSet.end())
675 {
676 if( *it != oldAlias )
677 it->dumpAsIniOn(file);
678 }
679 service.dumpAsIniOn(file);
680 file.close();
681 service.setFilepath(location);
682
683 _services.erase(oldAlias);
684 _services.insert(service);
685 // check for credentials in Urls
687
688
689 // changed properties affecting also repositories
690 if ( oldAlias != service.alias() // changed alias
691 || oldService.enabled() != service.enabled() ) // changed enabled status
692 {
693 std::vector<RepoInfo> toModify;
694 getRepositoriesInService(oldAlias, std::back_inserter(toModify));
695 for_( it, toModify.begin(), toModify.end() )
696 {
697 if ( oldService.enabled() != service.enabled() )
698 {
699 if ( service.enabled() )
700 {
701 // reset to last refreshs state
702 const auto & last = service.repoStates().find( it->alias() );
703 if ( last != service.repoStates().end() )
704 it->setEnabled( last->second.enabled );
705 }
706 else
707 it->setEnabled( false );
708 }
709
710 if ( oldAlias != service.alias() )
711 it->setService(service.alias());
712
713 modifyRepository(it->alias(), *it);
714 }
715 }
716
718 }
719
720
722 {
725 generateFilename( service ) );
726 service.setFilepath( servfile );
727
728 MIL << "saving service in " << servfile << endl;
729
730 std::ofstream file( servfile.c_str() );
731 if ( !file )
732 {
733 // TranslatorExplanation '%s' is a filename
734 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), servfile.c_str() )));
735 }
736 service.dumpAsIniOn( file );
737 MIL << "done" << endl;
738 }
739
756 const std::string & basefilename ) const
757 {
758 std::string final_filename = basefilename;
759 int counter = 1;
760 while ( PathInfo(dir + final_filename).isExist() )
761 {
763 ++counter;
764 }
765 return dir + Pathname(final_filename);
766 }
767
769 {
771
773 if ( repokind.toEnum() == repo::RepoType::NONE_e )
774 // unknown, probe the local metadata
776 // if still unknown, just return
778 return;
779
780 Pathname p;
781 switch ( repokind.toEnum() )
782 {
784 p = Pathname(productdatapath + "/repodata/repomd.xml");
785 break;
786
788 p = Pathname(productdatapath + "/content");
789 break;
790
792 p = Pathname(productdatapath + "/cookie");
793 break;
794
796 default:
797 break;
798 }
799
800 // touch the file, ignore error (they are logged anyway)
802 }
803
805 {
806 return touchIndexFile( info, _options );
807 }
808
810 {
812 std::list<Pathname> entries;
813 if (PathInfo(dir).isExist())
814 {
815 if ( filesystem::readdir( entries, dir, false ) != 0 )
816 {
817 // TranslatorExplanation '%s' is a pathname
818 ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
819 }
820
821 //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
822 for_(it, entries.begin(), entries.end() )
823 {
825 }
826 }
827
829 }
830
831 namespace {
840 const std::list<std::string> & repoEscAliases_r )
841 {
843 return;
844
846 return;
847
848 std::list<std::string> entries;
849 if ( filesystem::readdir( entries, cachePath_r, false ) == 0 )
850 {
851 entries.sort();
852 std::set<std::string> oldfiles;
853 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
854 std::inserter( oldfiles, oldfiles.end() ) );
855
856 // bsc#1178966: Files or symlinks here have been created by the user
857 // for whatever purpose. It's our cache, so we purge them now before
858 // they may later conflict with directories we need.
859 PathInfo pi;
860 for ( const std::string & old : oldfiles )
861 {
862 if ( old == Repository::systemRepoAlias() ) // don't remove the @System solv file
863 continue;
864 pi( cachePath_r/old );
865 if ( pi.isDir() )
867 else
868 filesystem::unlink( pi.path() );
869 }
870 }
871 }
872 } // namespace
873
875 {
876 MIL << "start construct known repos" << endl;
877
879 {
880 std::list<std::string> repoEscAliases;
881 std::list<RepoInfo> orphanedRepos;
883 {
884 // set the metadata path for the repo
885 repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo) );
886 // set the downloaded packages path for the repo
887 repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo) );
888 // remember it
889 _reposX.insert( repoInfo ); // direct access via _reposX in ctor! no reposManip.
890
891 // detect orphaned repos belonging to a deleted service
892 const std::string & serviceAlias( repoInfo.service() );
893 if ( ! ( serviceAlias.empty() || hasService( serviceAlias ) ) )
894 {
895 WAR << "Schedule orphaned service repo for deletion: " << repoInfo << endl;
896 orphanedRepos.push_back( repoInfo );
897 continue; // don't remember it in repoEscAliases
898 }
899
900 repoEscAliases.push_back(repoInfo.escaped_alias());
901 }
902
903 // Cleanup orphanded service repos:
904 if ( ! orphanedRepos.empty() )
905 {
906 for ( const auto & repoInfo : orphanedRepos )
907 {
908 MIL << "Delete orphaned service repo " << repoInfo.alias() << endl;
909 // translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service.
910 // %1% = service name
911 // %2% = repository name
912 JobReport::warning( str::Format(_("Unknown service '%1%': Removing orphaned service repository '%2%'"))
913 % repoInfo.service()
914 % repoInfo.alias() );
915 try {
916 removeRepository( repoInfo );
917 }
918 catch ( const Exception & caugth )
919 {
920 JobReport::error( caugth.asUserHistory() );
921 }
922 }
923 }
924
925 // bsc#1210740: Don't cleanup if read-only mode was promised.
927 // delete metadata folders without corresponding repo (e.g. old tmp directories)
928 //
929 // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise
930 // we'd need somemagic file to identify zypp cache directories. Without this
931 // we may easily remove user data (zypper --pkg-cache-dir . download ...)
932 repoEscAliases.sort();
934 Pathname::assertprefix( _options.rootDir, ZConfig::instance().builtinRepoMetadataPath() ),
937 Pathname::assertprefix( _options.rootDir, ZConfig::instance().builtinRepoSolvfilesPath() ),
939 // bsc#1204956: Tweak to prevent auto pruning package caches
942 Pathname::assertprefix( _options.rootDir, ZConfig::instance().builtinRepoPackagesPath() ),
944 }
945 }
946 MIL << "end construct known repos" << endl;
947 }
948
949 void assert_alias(const RepoInfo &info)
950 {
951 if ( info.alias().empty() )
953 // bnc #473834. Maybe we can match the alias against a regex to define
954 // and check for valid aliases
955 if ( info.alias()[0] == '.')
957 info, _("Repository alias cannot start with dot.")));
958 }
959
960}
961
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
Progress callback from another progress.
static const ValueType day
Definition Date.h:44
static Date now()
Return the current time.
Definition Date.h:78
Base class for Exception.
Definition Exception.h:147
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.
Maintain [min,max] and counter (value) for progress counting.
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
bool toMax()
Set counter value to current max value (unless no range).
void name(const std::string &name_r)
Set counter name.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
bool toMin()
Set counter value to current min value.
bool set(value_type val_r)
Set new counter value.
value_type val() const
What is known about a repository.
Definition RepoInfo.h:72
bool baseUrlsEmpty() const
whether repository urls are available
Definition RepoInfo.cc:656
repo::RepoType type() const
Type of repository,.
Definition RepoInfo.cc:602
void setBaseUrl(Url url)
Clears current base URL list and adds url.
Definition RepoInfo.cc:556
bool requireStatusWithMediaFile() const
Returns true if this repository requires the media.1/media file to be included in the metadata status...
Definition RepoInfo.cc:964
std::string targetDistribution() const
Distribution for which is this repository meant.
Definition RepoInfo.cc:641
Track changing files or directories.
Definition RepoStatus.h:41
static RepoStatus fromCookieFileUseMtime(const Pathname &path)
Reads the status from a cookie file but uses the files mtime.
bool empty() const
Whether the status is empty (empty checksum)
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition Repository.cc:38
void eraseFromPool()
Remove this Repository from its Pool.
Functor collecting ServiceInfos into a ServiceSet.
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:92
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:501
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:925
Wrapper class for stat/lstat.
Definition PathInfo.h:222
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:282
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition Pathname.h:173
Pathname dirname() const
Return all but the last component od this path.
Definition Pathname.h:124
const char * c_str() const
String representation.
Definition Pathname.h:110
const std::string & asString() const
String representation.
Definition Pathname.h:91
bool empty() const
Test for an empty path.
Definition Pathname.h:114
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition Pathname.cc:272
Read repository data from a .repo file.
Read service data from a .service file.
Repository already exists and some unique attribute can't be duplicated.
Exception for repository handling.
std::string label() const
Label for use in messages for the user interface.
void setFilepath(const Pathname &filename)
set the path to the .repo file
void setAlias(const std::string &alias)
set the repository alias
Pathname filepath() const
File where this repo was read from.
bool enabled() const
If enabled is false, then this repository must be ignored as if does not exists, except when checking...
std::string alias() const
unique identifier for this source.
Thrown when the repo alias is found to be invalid.
thrown when it was impossible to determine an alias for this repo.
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:264
static Pool instance()
Singleton ctor.
Definition Pool.h:55
static const SolvAttr repositoryToolVersion
Definition SolvAttr.h:181
Regular expression.
Definition Regex.h:95
Definition Arch.h:364
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:606
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:701
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition PathInfo.cc:413
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:320
int touch(const Pathname &path)
Change file's modification and access times.
Definition PathInfo.cc:1238
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
Definition String.cc:331
std::string numstring(char n, int w=0)
Definition String.h:289
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
Definition Regex.h:70
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
Easy-to use interface to the ZYPP dependency resolver.
Pathname rawcache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw cache path for a repository, this is usually /var/cache/zypp/alias.
void assert_alias(const RepoInfo &info)
Pathname solv_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the solv cache path for a repository.
std::list< RepoInfo > repositories_in_file(const Pathname &file)
Reads RepoInfo's from a repo file.
bool autoPruneInDir(const Pathname &path_r)
bsc#1204956: Tweak to prevent auto pruning package caches.
Pathname packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
std::list< RepoInfo > repositories_in_dir(const Pathname &dir)
List of RepoInfo's from a directory.
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,...
void assert_urls(const RepoInfo &info)
std::string filenameFromAlias(const std::string &alias_r, const std::string &stem_r)
Generate a related filename from a repo/service infos alias.
Iterator findAlias(const std::string &alias_r, Iterator begin_r, Iterator end_r)
Find alias_r in repo/service container.
std::string asString(const Patch::Category &obj)
Definition Patch.cc:122
static bool warning(const std::string &msg_r, const UserData &userData_r=UserData())
send warning text
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
Simple callback to collect the results.
bool collect(const RepoInfo &repo)
RepoInfo getRepositoryInfo(const std::string &alias)
RepoSet::const_iterator RepoConstIterator
void cleanCache(const RepoInfo &info, OPT_PROGRESS)
void removeService(const std::string &alias)
void loadFromCache(const RepoInfo &info, OPT_PROGRESS)
RepoConstIterator repoEnd() const
static void touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
bool hasService(const std::string &alias) const
void removeRepositoryImpl(const RepoInfo &info, OPT_PROGRESS)
void cleanPackages(const RepoInfo &info, OPT_PROGRESS, bool isAutoClean=false)
virtual void removeRepository(const RepoInfo &info, OPT_PROGRESS)=0
bool hasRepo(const std::string &alias) const
void getRepositoriesInService(const std::string &alias, OutputIterator out) const
std::set< ServiceInfo > ServiceSet
ServiceInfo typedefs.
Pathname generateNonExistingName(const Pathname &dir, const std::string &basefilename) const
Generate a non existing filename in a directory, using a base name.
void modifyRepository(const std::string &alias, const RepoInfo &newinfo_r, OPT_PROGRESS)
static repo::RepoType probeCache(const Pathname &path_r)
Probe Metadata in a local cache directory.
void cleanMetadata(const RepoInfo &info, OPT_PROGRESS)
void modifyService(const std::string &oldAlias, const ServiceInfo &newService)
static RepoStatus metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
RepoManagerBaseImpl(RepoManagerOptions &&opt)
void saveService(ServiceInfo &service) const
ServiceInfo getService(const std::string &alias) const
RepoConstIterator repoBegin() const
void cleanCacheDirGarbage(OPT_PROGRESS)
bool isCached(const RepoInfo &info) const
void addService(const ServiceInfo &service)
void addProbedRepository(const RepoInfo &info, repo::RepoType probedType)
const RepoSet & repos() const
std::string generateFilename(const RepoInfo &info) const
Repo manager settings.
Pathname rootDir
remembers root_r value for later use
Repository type enumeration.
Definition RepoType.h:28
static const RepoType YAST2
Definition RepoType.h:30
static const RepoType RPMMD
Definition RepoType.h:29
static const RepoType NONE
Definition RepoType.h:32
static const RepoType RPMPLAINDIR
Definition RepoType.h:31
static const ServiceType PLUGIN
Plugin services are scripts installed on your system that provide the package manager with repositori...
Definition ServiceType.h:43
Convenient building of std::string with boost::format.
Definition String.h:253
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:212
Url::asString() view options.
Definition UrlBase.h:40
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:429
#define _(MSG)
Definition Gettext.h:37
#define MIL
Definition Logger.h:96
#define WAR
Definition Logger.h:97