libzypp 17.32.2
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
14#include <zypp-core/base/Regex.h>
15#include <zypp-core/fs/PathInfo.h>
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 status = RepoStatus::fromCookieFile( productdatapath/"cookie" ); // dir status at last refresh
200 break;
201
203 // Return default RepoStatus in case of RepoType::NONE
204 // indicating it should be created?
205 // ZYPP_THROW(RepoUnknownTypeException());
206 break;
207 }
208
209 if ( ! status.empty() )
210 status = status && RepoStatus( info );
211
212 return status;
213 }
214
216 {
217 return metadataStatus( info, _options );
218 }
219
228
230 {
231 ProgressData progress(100);
232 progress.sendTo(progressfnc);
233
234 // bsc#1204956: Tweak to prevent auto pruning package caches
236 if ( not isAutoClean || autoPruneInDir( rpc.dirname() ) )
238
239 progress.toMax();
240 }
241
248 {
249 MIL << "going to probe the cached repo at " << path_r << endl;
250
252
253 if ( PathInfo(path_r/"/repodata/repomd.xml").isFile() )
255 else if ( PathInfo(path_r/"/content").isFile() )
257 else if ( PathInfo(path_r).isDir() )
259
260 MIL << "Probed cached type " << ret << " at " << path_r << endl;
261 return ret;
262 }
263
265 {
266 MIL << "Going to clean up garbage in cache dirs" << endl;
267
268 ProgressData progress(300);
269 progress.sendTo(progressrcv);
270 progress.toMin();
271
272 std::list<Pathname> cachedirs;
276
277 for_( dir, cachedirs.begin(), cachedirs.end() )
278 {
279 if ( PathInfo(*dir).isExist() )
280 {
281 std::list<Pathname> entries;
282 if ( filesystem::readdir( entries, *dir, false ) != 0 )
283 // TranslatorExplanation '%s' is a pathname
284 ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir->c_str())));
285
286 unsigned sdircount = entries.size();
287 unsigned sdircurrent = 1;
288 for_( subdir, entries.begin(), entries.end() )
289 {
290 // if it does not belong known repo, make it disappear
291 bool found = false;
292 for_( r, repoBegin(), repoEnd() )
293 if ( subdir->basename() == r->escaped_alias() )
294 { found = true; break; }
295
296 if ( ! found && ( Date::now()-PathInfo(*subdir).mtime() > Date::day ) )
298
299 progress.set( progress.val() + sdircurrent * 100 / sdircount );
300 ++sdircurrent;
301 }
302 }
303 else
304 progress.set( progress.val() + 100 );
305 }
306 progress.toMax();
307 }
308
310 {
311 ProgressData progress(100);
312 progress.sendTo(progressrcv);
313 progress.toMin();
314
315 MIL << "Removing raw metadata cache for " << info.alias() << endl;
317
318 progress.toMax();
319 }
320
322 {
323 assert_alias(info);
325
326 if ( ! PathInfo(solvfile).isExist() )
328
329 sat::Pool::instance().reposErase( info.alias() );
330
331 Repository repo = sat::Pool::instance().addRepoSolv( solvfile, info );
332 // test toolversion in order to rebuild solv file in case
333 // it was written by a different libsolv-tool parser.
334 const std::string & toolversion( sat::LookupRepoAttr( sat::SolvAttr::repositoryToolVersion, repo ).begin().asString() );
336 repo.eraseFromPool();
337 ZYPP_THROW(Exception(str::Str() << "Solv-file was created by '"<<toolversion<<"'-parser (want "<<LIBSOLV_TOOLVERSION<<")."));
338 }
339 }
340
342 {
343
344 auto tosave = info;
345
346 // assert the directory exists
348
351 // now we have a filename that does not exists
352 MIL << "Saving repo in " << repofile << endl;
353
354 std::ofstream file(repofile.c_str());
355 if (!file)
356 {
357 // TranslatorExplanation '%s' is a filename
358 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
359 }
360
361 tosave.dumpAsIniOn(file);
362 tosave.setFilepath(repofile);
363 tosave.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ) );
365 {
366 // We should fix the API as we must inject those paths
367 // into the repoinfo in order to keep it usable.
368 RepoInfo & oinfo( const_cast<RepoInfo &>(info) );
369 oinfo.setFilepath(repofile);
370 oinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ) );
372 }
373 reposManip().insert(tosave);
374
375 // check for credentials in Urls
377
379 }
380
382 {
383 ProgressData progress;
385 progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
386 progress.name(str::form(_("Removing repository '%s'"), info.label().c_str()));
387
388 MIL << "Going to delete repo " << info.alias() << endl;
389
390 for_( it, repoBegin(), repoEnd() )
391 {
392 // they can be the same only if the provided is empty, that means
393 // the provided repo has no alias
394 // then skip
395 if ( (!info.alias().empty()) && ( info.alias() != (*it).alias() ) )
396 continue;
397
398 // TODO match by url
399
400 // we have a matching repository, now we need to know
401 // where it does come from.
403 if (todelete.filepath().empty())
404 {
405 ZYPP_THROW(repo::RepoException( todelete, _("Can't figure out where the repo is stored.") ));
406 }
407 else
408 {
409 // figure how many repos are there in the file:
410 std::list<RepoInfo> filerepos = repositories_in_file(todelete.filepath());
411 if ( filerepos.size() == 0 // bsc#984494: file may have already been deleted
412 ||(filerepos.size() == 1 && filerepos.front().alias() == todelete.alias() ) )
413 {
414 // easy: file does not exist, contains no or only the repo to delete: delete the file
415 int ret = filesystem::unlink( todelete.filepath() );
416 if ( ! ( ret == 0 || ret == ENOENT ) )
417 {
418 // TranslatorExplanation '%s' is a filename
419 ZYPP_THROW(repo::RepoException( todelete, str::form( _("Can't delete '%s'"), todelete.filepath().c_str() )));
420 }
421 MIL << todelete.alias() << " successfully deleted." << endl;
422 }
423 else
424 {
425 // there are more repos in the same file
426 // write them back except the deleted one.
427 //TmpFile tmp;
428 //std::ofstream file(tmp.path().c_str());
429
430 // assert the directory exists
431 filesystem::assert_dir(todelete.filepath().dirname());
432
433 std::ofstream file(todelete.filepath().c_str());
434 if (!file)
435 {
436 // TranslatorExplanation '%s' is a filename
437 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), todelete.filepath().c_str() )));
438 }
439 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
440 fit != filerepos.end();
441 ++fit )
442 {
443 if ( (*fit).alias() != todelete.alias() )
444 (*fit).dumpAsIniOn(file);
445 }
446 }
447
448 CombinedProgressData cSubprogrcv(progress, 20);
449 CombinedProgressData mSubprogrcv(progress, 40);
450 CombinedProgressData pSubprogrcv(progress, 40);
451 // now delete it from cache
452 if ( isCached(todelete) )
454 // now delete metadata (#301037)
456 cleanPackages( todelete, pSubprogrcv, true/*isAutoClean*/ );
457 reposManip().erase(todelete);
458 MIL << todelete.alias() << " successfully deleted." << endl;
460 return;
461 } // else filepath is empty
462
463 }
464 // should not be reached on a sucess workflow
466 }
467
469 {
471 RepoInfo newinfo( newinfo_r ); // need writable copy to upadte housekeeping data
472
473 // check if the new alias already exists when renaming the repo
474 if ( alias != newinfo.alias() && hasRepo( newinfo.alias() ) )
475 {
477 }
478
479 if (toedit.filepath().empty())
480 {
481 ZYPP_THROW(repo::RepoException( toedit, _("Can't figure out where the repo is stored.") ));
482 }
483 else
484 {
485 // figure how many repos are there in the file:
486 std::list<RepoInfo> filerepos = repositories_in_file(toedit.filepath());
487
488 // there are more repos in the same file
489 // write them back except the deleted one.
490 //TmpFile tmp;
491 //std::ofstream file(tmp.path().c_str());
492
493 // assert the directory exists
494 filesystem::assert_dir(toedit.filepath().dirname());
495
496 std::ofstream file(toedit.filepath().c_str());
497 if (!file)
498 {
499 // TranslatorExplanation '%s' is a filename
500 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), toedit.filepath().c_str() )));
501 }
502 for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
503 fit != filerepos.end();
504 ++fit )
505 {
506 // if the alias is different, dump the original
507 // if it is the same, dump the provided one
508 if ( (*fit).alias() != toedit.alias() )
509 (*fit).dumpAsIniOn(file);
510 else
511 newinfo.dumpAsIniOn(file);
512 }
513
514 if ( toedit.enabled() && !newinfo.enabled() )
515 {
516 // On the fly remove solv.idx files for bash completion if a repo gets disabled.
518 if ( PathInfo(solvidx).isExist() )
520 }
521
522 newinfo.setFilepath(toedit.filepath());
523 newinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ) );
525 {
526 // We should fix the API as we must inject those paths
527 // into the repoinfo in order to keep it usable.
528 RepoInfo & oinfo( const_cast<RepoInfo &>(newinfo_r) );
529 oinfo.setFilepath(toedit.filepath());
530 oinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ) );
532 }
533 reposManip().erase(toedit);
534 reposManip().insert(newinfo);
535 // check for credentials in Urls
538 MIL << "repo " << alias << " modified" << endl;
539 }
540 }
541
543 {
544 RepoConstIterator it( findAlias( alias, repos() ) );
545 if ( it != repos().end() )
546 return *it;
547 RepoInfo info;
548 info.setAlias( alias );
550 }
551
552
554 {
555 for_( it, repoBegin(), repoEnd() )
556 {
557 for_( urlit, (*it).baseUrlsBegin(), (*it).baseUrlsEnd() )
558 {
559 if ( (*urlit).asString(urlview) == url.asString(urlview) )
560 return *it;
561 }
562 }
563 RepoInfo info;
564 info.setBaseUrl( url );
566 }
567
569 {
570 assert_alias( service );
571
572 // check if service already exists
573 if ( hasService( service.alias() ) )
575
576 // Writable ServiceInfo is needed to save the location
577 // of the .service file. Finaly insert into the service list.
578 ServiceInfo toSave( service );
580 _services.insert( toSave );
581
582 // check for credentials in Url
584
585 MIL << "added service " << toSave.alias() << endl;
586 }
587
589
590 void RepoManagerBaseImpl::removeService( const std::string & alias )
591 {
592 MIL << "Going to delete service " << alias << endl;
593
594 const ServiceInfo & service = getService( alias );
595
596 Pathname location = service.filepath();
597 if( location.empty() )
598 {
599 ZYPP_THROW(repo::ServiceException( service, _("Can't figure out where the service is stored.") ));
600 }
601
604
605 // only one service definition in the file
606 if ( tmpSet.size() == 1 )
607 {
608 if ( filesystem::unlink(location) != 0 )
609 {
610 // TranslatorExplanation '%s' is a filename
611 ZYPP_THROW(repo::ServiceException( service, str::form( _("Can't delete '%s'"), location.c_str() ) ));
612 }
613 MIL << alias << " successfully deleted." << endl;
614 }
615 else
616 {
618
619 std::ofstream file(location.c_str());
620 if( !file )
621 {
622 // TranslatorExplanation '%s' is a filename
623 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), location.c_str() )));
624 }
625
626 for_(it, tmpSet.begin(), tmpSet.end())
627 {
628 if( it->alias() != alias )
629 it->dumpAsIniOn(file);
630 }
631
632 MIL << alias << " successfully deleted from file " << location << endl;
633 }
634
635 // now remove all repositories added by this service
638 boost::make_function_output_iterator( bind( &RepoCollector::collect, &rcollector, _1 ) ) );
639 // cannot do this directly in getRepositoriesInService - would invalidate iterators
640 for_(rit, rcollector.repos.begin(), rcollector.repos.end())
642 }
643
644 void RepoManagerBaseImpl::modifyService( const std::string & oldAlias, const ServiceInfo & newService )
645 {
646 MIL << "Going to modify service " << oldAlias << endl;
647
648 // we need a writable copy to link it to the file where
649 // it is saved if we modify it
650 ServiceInfo service(newService);
651
652 if ( service.type() == repo::ServiceType::PLUGIN )
653 {
655 }
656
657 const ServiceInfo & oldService = getService(oldAlias);
658
659 Pathname location = oldService.filepath();
660 if( location.empty() )
661 {
662 ZYPP_THROW(repo::ServiceException( oldService, _("Can't figure out where the service is stored.") ));
663 }
664
665 // remember: there may multiple services being defined in one file:
668
670 std::ofstream file(location.c_str());
671 for_(it, tmpSet.begin(), tmpSet.end())
672 {
673 if( *it != oldAlias )
674 it->dumpAsIniOn(file);
675 }
676 service.dumpAsIniOn(file);
677 file.close();
678 service.setFilepath(location);
679
680 _services.erase(oldAlias);
681 _services.insert(service);
682 // check for credentials in Urls
684
685
686 // changed properties affecting also repositories
687 if ( oldAlias != service.alias() // changed alias
688 || oldService.enabled() != service.enabled() ) // changed enabled status
689 {
690 std::vector<RepoInfo> toModify;
691 getRepositoriesInService(oldAlias, std::back_inserter(toModify));
692 for_( it, toModify.begin(), toModify.end() )
693 {
694 if ( oldService.enabled() != service.enabled() )
695 {
696 if ( service.enabled() )
697 {
698 // reset to last refreshs state
699 const auto & last = service.repoStates().find( it->alias() );
700 if ( last != service.repoStates().end() )
701 it->setEnabled( last->second.enabled );
702 }
703 else
704 it->setEnabled( false );
705 }
706
707 if ( oldAlias != service.alias() )
708 it->setService(service.alias());
709
710 modifyRepository(it->alias(), *it);
711 }
712 }
713
715 }
716
717
719 {
722 generateFilename( service ) );
723 service.setFilepath( servfile );
724
725 MIL << "saving service in " << servfile << endl;
726
727 std::ofstream file( servfile.c_str() );
728 if ( !file )
729 {
730 // TranslatorExplanation '%s' is a filename
731 ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), servfile.c_str() )));
732 }
733 service.dumpAsIniOn( file );
734 MIL << "done" << endl;
735 }
736
753 const std::string & basefilename ) const
754 {
755 std::string final_filename = basefilename;
756 int counter = 1;
757 while ( PathInfo(dir + final_filename).isExist() )
758 {
760 ++counter;
761 }
762 return dir + Pathname(final_filename);
763 }
764
766 {
768
770 if ( repokind.toEnum() == repo::RepoType::NONE_e )
771 // unknown, probe the local metadata
773 // if still unknown, just return
775 return;
776
777 Pathname p;
778 switch ( repokind.toEnum() )
779 {
781 p = Pathname(productdatapath + "/repodata/repomd.xml");
782 break;
783
785 p = Pathname(productdatapath + "/content");
786 break;
787
789 p = Pathname(productdatapath + "/cookie");
790 break;
791
793 default:
794 break;
795 }
796
797 // touch the file, ignore error (they are logged anyway)
799 }
800
802 {
803 return touchIndexFile( info, _options );
804 }
805
807 {
809 std::list<Pathname> entries;
810 if (PathInfo(dir).isExist())
811 {
812 if ( filesystem::readdir( entries, dir, false ) != 0 )
813 {
814 // TranslatorExplanation '%s' is a pathname
815 ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
816 }
817
818 //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
819 for_(it, entries.begin(), entries.end() )
820 {
822 }
823 }
824
826 }
827
828 namespace {
837 const std::list<std::string> & repoEscAliases_r )
838 {
840 return;
841
843 return;
844
845 std::list<std::string> entries;
846 if ( filesystem::readdir( entries, cachePath_r, false ) == 0 )
847 {
848 entries.sort();
849 std::set<std::string> oldfiles;
850 set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
851 std::inserter( oldfiles, oldfiles.end() ) );
852
853 // bsc#1178966: Files or symlinks here have been created by the user
854 // for whatever purpose. It's our cache, so we purge them now before
855 // they may later conflict with directories we need.
856 PathInfo pi;
857 for ( const std::string & old : oldfiles )
858 {
859 if ( old == Repository::systemRepoAlias() ) // don't remove the @System solv file
860 continue;
861 pi( cachePath_r/old );
862 if ( pi.isDir() )
864 else
865 filesystem::unlink( pi.path() );
866 }
867 }
868 }
869 } // namespace
870
872 {
873 MIL << "start construct known repos" << endl;
874
876 {
877 std::list<std::string> repoEscAliases;
878 std::list<RepoInfo> orphanedRepos;
880 {
881 // set the metadata path for the repo
882 repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo) );
883 // set the downloaded packages path for the repo
884 repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo) );
885 // remember it
886 _reposX.insert( repoInfo ); // direct access via _reposX in ctor! no reposManip.
887
888 // detect orphaned repos belonging to a deleted service
889 const std::string & serviceAlias( repoInfo.service() );
890 if ( ! ( serviceAlias.empty() || hasService( serviceAlias ) ) )
891 {
892 WAR << "Schedule orphaned service repo for deletion: " << repoInfo << endl;
893 orphanedRepos.push_back( repoInfo );
894 continue; // don't remember it in repoEscAliases
895 }
896
897 repoEscAliases.push_back(repoInfo.escaped_alias());
898 }
899
900 // Cleanup orphanded service repos:
901 if ( ! orphanedRepos.empty() )
902 {
903 for ( const auto & repoInfo : orphanedRepos )
904 {
905 MIL << "Delete orphaned service repo " << repoInfo.alias() << endl;
906 // translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service.
907 // %1% = service name
908 // %2% = repository name
909 JobReport::warning( str::Format(_("Unknown service '%1%': Removing orphaned service repository '%2%'"))
910 % repoInfo.service()
911 % repoInfo.alias() );
912 try {
913 removeRepository( repoInfo );
914 }
915 catch ( const Exception & caugth )
916 {
917 JobReport::error( caugth.asUserHistory() );
918 }
919 }
920 }
921
922 // bsc#1210740: Don't cleanup if read-only mode was promised.
924 // delete metadata folders without corresponding repo (e.g. old tmp directories)
925 //
926 // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise
927 // we'd need somemagic file to identify zypp cache directories. Without this
928 // we may easily remove user data (zypper --pkg-cache-dir . download ...)
929 repoEscAliases.sort();
931 Pathname::assertprefix( _options.rootDir, ZConfig::instance().builtinRepoMetadataPath() ),
934 Pathname::assertprefix( _options.rootDir, ZConfig::instance().builtinRepoSolvfilesPath() ),
936 // bsc#1204956: Tweak to prevent auto pruning package caches
939 Pathname::assertprefix( _options.rootDir, ZConfig::instance().builtinRepoPackagesPath() ),
941 }
942 }
943 MIL << "end construct known repos" << endl;
944 }
945
946 void assert_alias(const RepoInfo &info)
947 {
948 if ( info.alias().empty() )
950 // bnc #473834. Maybe we can match the alias against a regex to define
951 // and check for valid aliases
952 if ( info.alias()[0] == '.')
954 info, _("Repository alias cannot start with dot.")));
955 }
956
957}
958
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 fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
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:1235
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