1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/RepoManager.h
12 #ifndef ZYPP_REPOMANAGER_H
13 #define ZYPP_REPOMANAGER_H
18 #include "zypp/base/PtrTypes.h"
19 #include "zypp/base/Iterator.h"
20 #include "zypp/base/Flags.h"
22 #include "zypp/Pathname.h"
23 #include "zypp/ZConfig.h"
24 #include "zypp/RepoInfo.h"
25 #include "zypp/repo/RepoException.h"
26 #include "zypp/repo/RepoType.h"
27 #include "zypp/repo/ServiceType.h"
28 #include "zypp/ServiceInfo.h"
29 #include "zypp/RepoStatus.h"
30 #include "zypp/ProgressData.h"
32 ///////////////////////////////////////////////////////////////////
34 { /////////////////////////////////////////////////////////////////
37 * Parses \a repo_file and returns a list of \ref RepoInfo objects
38 * corresponding to repositories found within the file.
40 * \param repo_file Valid URL of the repo file.
41 * \return found list<RepoInfo>
43 * \throws MediaException If the access to the url fails
44 * \throws ParseException If the file parsing fails
45 * \throws Exception On other errors.
47 std::list<RepoInfo> readRepoFile(const Url & repo_file);
50 * Repo manager settings.
51 * Settings default to ZYpp global settings.
53 struct RepoManagerOptions
55 /** Default ctor following \ref ZConfig global settings.
56 * If an optional \c root_r directory is given, all paths will
57 * be prefixed accordingly.
59 * root_r\repoCachePath
62 * \repoPackagesCachePath
66 RepoManagerOptions( const Pathname & root_r = Pathname() );
68 /** Test setup adjusting all paths to be located below one \c root_r directory.
70 * root_r\ - repoCachePath
71 * \raw - repoRawCachePath
72 * \solv - repoSolvCachePath
73 * \packages - repoPackagesCachePath
74 * \repos.d - knownReposPath
77 static RepoManagerOptions makeTestSetup( const Pathname & root_r );
79 Pathname repoCachePath;
80 Pathname repoRawCachePath;
81 Pathname repoSolvCachePath;
82 Pathname repoPackagesCachePath;
83 Pathname knownReposPath;
84 Pathname knownServicesPath;
88 * Target distro ID to be used when refreshing repo index services.
89 * Repositories not maching this ID will be skipped/removed.
91 * If empty, \ref Target::targetDistribution() will be used instead.
93 std::string servicesTargetDistro;
95 /** remembers root_r value for later use */
102 * \short creates and provides information about known sources.
107 friend std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
110 /** Implementation */
113 /** ServiceInfo typedefs */
114 typedef std::set<ServiceInfo> ServiceSet;
115 typedef ServiceSet::const_iterator ServiceConstIterator;
116 typedef ServiceSet::size_type ServiceSizeType;
118 /** RepoInfo typedefs */
119 typedef std::set<RepoInfo> RepoSet;
120 typedef RepoSet::const_iterator RepoConstIterator;
121 typedef RepoSet::size_type RepoSizeType;
124 RepoManager( const RepoManagerOptions &options = RepoManagerOptions() );
128 enum RawMetadataRefreshPolicy
132 RefreshIfNeededIgnoreDelay
135 enum CacheBuildPolicy
141 /** Flags for tuning RefreshService */
142 enum RefreshServiceBit
144 RefreshService_restoreStatus = (1<<0), ///< Force restoring repo enabled/disabled status
145 RefreshService_forceRefresh = (1<<1), ///< Force refresh even if TTL is not reached
147 ZYPP_DECLARE_FLAGS(RefreshServiceFlags,RefreshServiceBit);
149 /** Options tuning RefreshService */
150 typedef RefreshServiceFlags RefreshServiceOptions;
153 /** \name Known repositories.
155 * The known repositories are read from
156 * \ref RepoManagerOptions::knownReposPath passed on the Ctor.
157 * Which defaults to ZYpp global settings.
160 bool repoEmpty() const;
161 RepoSizeType repoSize() const;
162 RepoConstIterator repoBegin() const;
163 RepoConstIterator repoEnd() const;
164 Iterable<RepoConstIterator> repos() const;
166 /** List of known repositories. */
167 std::list<RepoInfo> knownRepositories() const
168 { return std::list<RepoInfo>(repoBegin(),repoEnd()); }
170 /** Find RepoInfo by alias or return \ref RepoInfo::noRepo. */
171 RepoInfo getRepo( const std::string & alias ) const;
172 /** \overload Take alias from RepoInfo. */
173 RepoInfo getRepo( const RepoInfo & info_r ) const
174 { return getRepo( info_r.alias() ); }
176 /** Return whether there is a known repository for \c alias. */
177 bool hasRepo( const std::string & alias ) const;
178 /** \overload Take alias from RepoInfo. */
179 bool hasRepo( const RepoInfo & info_r ) const
180 { return hasRepo( info_r.alias() ); }
182 /** Some stupid string but suitable as alias for your url if nothing better is available.
183 * Something like \c "http-download.opensuse.org-83df67e5"
185 static std::string makeStupidAlias( const Url & url_r = Url() );
189 * \short Status of local metadata
191 RepoStatus metadataStatus( const RepoInfo &info ) const;
194 * Possibly return state of checkIfRefreshMEtadata function
196 enum RefreshCheckStatus {
197 REFRESH_NEEDED, /**< refresh is needed */
198 REPO_UP_TO_DATE, /**< repository not changed */
199 REPO_CHECK_DELAYED /**< refresh is delayed due to settings */
203 * Checks whether to refresh metadata for specified repository and url.
205 * The need for refresh is evaluated according to the following conditions,
208 * <li>the refresh policy (refresh may be forced)
209 * <li>the repo.refresh.delay ZConfig value compared to the difference between
210 * cached index file timestamp and actual time
211 * <li>the timestamp of cached repo index file compared to the remote
212 * index file timestamp.
215 * This method checks the status against the specified url only. If more
216 * baseurls are defined for in the RepoInfo, each one must be check
217 * individually. Example:
222 * // try urls one by one
223 * for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
224 * it != info.baseUrlsEnd(); ++it )
228 * // check whether to refresh metadata
229 * // if the check fails for this url, it throws, so another url will be checked
230 * if (checkIfToRefreshMetadata(info, *it, policy)!=RepoInfo::REFRESH_NEEDED)
233 * // do the actual refresh
235 * catch (const Exception & e)
238 * ERR << *it << " doesn't look good. Trying another url." << endl;
242 * handle("No more URLs.");
249 * \return state of repository
250 * \see RefreshCheckStatus
251 * \throws RepoUnknownTypeException
252 * \throws repo::RepoNoAliasException if can't figure an alias
253 * \throws Exception on unknown error
256 RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo &info,
258 RawMetadataRefreshPolicy policy = RefreshIfNeeded);
261 * \short Path where the metadata is downloaded and kept
263 * Given a repoinfo, tells where \ref RepoManager will download
264 * and keep the raw metadata.
266 * \param info Repository information
268 * \throws repo::RepoNoAliasException if can't figure an alias
270 Pathname metadataPath( const RepoInfo &info ) const;
274 * \short Path where the rpm packages are downloaded and kept
276 * Given a repoinfo, tells where \ref RepoProvidePackage will download
277 * and keep the .rpm files.
279 * \param info Repository information
281 * \throws repo::RepoNoAliasException if can't figure an alias
283 Pathname packagesPath( const RepoInfo &info ) const;
287 * \short Refresh local raw cache
289 * Will try to download the metadata
291 * In case of falure the metadata remains
294 * \throws repo::RepoNoUrlException if no urls are available.
295 * \throws repo::RepoNoAliasException if can't figure an alias
296 * \throws repo::RepoUnknownTypeException if the metadata is unknown
297 * \throws repo::RepoException if the repository is invalid
298 * (no valid metadata found at any of baseurls)
300 void refreshMetadata( const RepoInfo &info,
301 RawMetadataRefreshPolicy policy = RefreshIfNeeded,
302 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
305 * \short Clean local metadata
307 * Empty local metadata.
309 * \throws repo::RepoNoAliasException if can't figure an alias
310 * \throws Exception on unknown error.
312 void cleanMetadata( const RepoInfo &info,
313 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
316 * \short Clean local package cache
318 * Empty local directory with downloaded packages
320 * \throws repo::RepoNoAliasException if can't figure an alias
321 * \throws Exception on unknown error.
323 void cleanPackages( const RepoInfo &info,
324 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
327 * \short Status of metadata cache
329 RepoStatus cacheStatus( const RepoInfo &info ) const;
332 * \short Refresh local cache
334 * Will try to build the cache from local metadata.
336 * If the cache exists it will be overwriten.
338 * \note the local metadata must be valid.
340 * \throws repo::RepoNoAliasException if can't figure
341 * an alias to look in cache
342 * \throws repo::RepoMetadataException if the metadata
343 * is not enough to build a cache (empty, incorrect, or
345 * \throws repo::RepoUnknownTypeException
346 * \throws parser::ParseException if parser encounters an error.
347 * \throws Exception on unknown error.
349 void buildCache( const RepoInfo &info,
350 CacheBuildPolicy policy = BuildIfNeeded,
351 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
354 * \short clean local cache
356 * Clean the cached version of the metadata
358 * \note the local metadata must be valid.
360 * \throws repo::RepoNoAliasException if can't figure an alias to look in cache
361 * \throws cache::CacheRecordNotFoundException if the cache could not be
362 * cleaned because of repository record not found.
363 * \throws Exception on unknown error.
365 void cleanCache( const RepoInfo &info,
366 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
369 * \short Whether a repository exists in cache
371 * \param RepoInfo to be checked.
373 bool isCached( const RepoInfo &info ) const;
377 * \short Load resolvables into the pool
379 * Creating from cache requires that the repository is
380 * refreshed (metadata downloaded) and cached
382 * \throws repo::RepoNoAliasException if can't figure an alias to look in cache
383 * \throw RepoNotCachedException When the source is not cached.
385 void loadFromCache( const RepoInfo &info,
386 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
389 * Remove any subdirectories of cache directories which no longer belong
390 * to any of known repositories.
392 * These can be temporary directories left by interrupted refresh,
393 * or dirs left after changing .repo files outside of libzypp.
395 void cleanCacheDirGarbage( const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
398 * \short Probe repo metadata type.
400 * The location to probe consists of the base \a url (you may think of it as
401 * a mountpoint) and the \a path to the repository on the mounted media
404 repo::RepoType probe( const Url & url, const Pathname & path ) const;
406 * \overload Using the default path \c "/".
408 repo::RepoType probe( const Url & url ) const;
412 * \short Adds a repository to the list of known repositories.
416 * \throws repo::RepoAlreadyExistsException If the repo clash some
417 * unique attribute like alias
418 * \throws RepoUnknownType
419 * If RepoManagerOptions::probe is true
420 * and repository type can't be determined.
421 * \throws RepoException
422 * If RepoManagerOptions::probe is true and access to the url fails.
423 * \throws Exception On other errors.
425 void addRepository( const RepoInfo &info,
426 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
429 * \short Adds repositores from a repo file to the list of known repositories.
430 * \param url Url of the repo file
432 * \throws repo::RepoAlreadyExistsException If the repo clash some
433 * unique attribute like alias
434 * \throws MediaException If the access to the url fails
435 * \throws ParseException If the file parsing fails
436 * \throws RepoUnknownType If repository type can't be determined
437 * \throws RepoException ON other repository related errors
438 * \throws Exception On other errors.
440 void addRepositories( const Url &url,
441 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
443 * \short Remove the best matching repository from known repos list
445 * \throws RepoNotFoundException If no repo match
447 void removeRepository( const RepoInfo & info,
448 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
451 * \short Modify repository attributes
453 * \throws RepoAlreadyExistsException if the alias specified in newinfo
454 * is already used by another repository
455 * \throws RepoNotFoundException If no repo match
456 * \throws ParseException If the file parsing fails
457 * \throws Exception On other errors.
459 void modifyRepository( const std::string &alias,
460 const RepoInfo & newinfo,
461 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
462 /** \overload Take alias from RepoInfo. */
463 void modifyRepository( const RepoInfo & newinfo,
464 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() )
465 { modifyRepository( newinfo.alias(), newinfo, progressrcv ); }
468 * \short Find a matching repository info
470 * \note if multiple repositories incorrectly share the
471 * same alias, the first one found will be returned.
473 * \param alias Repository alias
474 * \param progressrcv Progress reporting function
475 * \return RepoInfo of the found repository
476 * \throws RepoNotFoundException If no repo match the alias
477 * \throws ParseException If the file parsing fails
478 * \throws Exception On other errors.
480 RepoInfo getRepositoryInfo( const std::string &alias,
481 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
484 * \short Find repository info by URL.
486 * \param url URL to find.
487 * \param urlview url::ViewOption to influence URL matching.
488 * \param progressrcv Progress receiver function.
489 * \return RepoInfo of the found repository.
491 * \note if multpile repositories incorrectly share the
492 * same URL, the first one found will be returned.
494 * \note the string representation of the URLs are compared.
495 * The \a urlview can be used to influence which
496 parts of the URL are to be compared.
498 * \throws RepoNotFoundException If no repo match
499 * \throws ParseException If the file parsing fails
500 * \throws Exception On other errors.
502 RepoInfo getRepositoryInfo( const Url & url,
503 const url::ViewOption & urlview = url::ViewOption::DEFAULTS,
504 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
507 /** \name Known services.
509 * The known services are read from
510 * \ref RepoManagerOptions::knownServicesPath passed on the Ctor.
511 * Which defaults to ZYpp global settings.
515 * Gets true if no service is in RepoManager (so no one in specified location)
517 * \return true if any ServiceInfo is in RepoManager
519 bool serviceEmpty() const;
522 * Gets count of service in RepoManager (in specified location)
524 * \return count of service
526 ServiceSizeType serviceSize() const;
529 * Iterator to first service in internal storage.
530 * \note Iterator is immutable, so you cannot change pointed ServiceInfo
531 * \return Iterator to first service
533 ServiceConstIterator serviceBegin() const;
536 * Iterator to place behind last service in internal storage.
537 * \return iterator to end
539 ServiceConstIterator serviceEnd() const;
541 /** Iterate the known services. */
542 Iterable<ServiceConstIterator> services() const;
544 /** List of known services. */
545 std::list<ServiceInfo> knownServices() const
546 { return std::list<ServiceInfo>(serviceBegin(),serviceEnd()); }
549 * \short Finds ServiceInfo by alias or return \ref ServiceInfo::noService
551 * \param alias unique identifier of service
552 * \return information about service
554 ServiceInfo getService( const std::string & alias ) const;
556 /** Return whether there is a known service for \c alias. */
557 bool hasService( const std::string & alias ) const;
561 * \short Probe the type or the service.
563 repo::ServiceType probeService( const Url &url ) const;
566 * Adds new service by it's alias and url
568 * \param alias unique identifier of the service
569 * \param url url to service
571 * \throws FIXME RepoAlreadyExistException and as reponame is service name
573 void addService( const std::string & alias, const Url& url );
578 * \param service service info
580 * \throws FIXME RepoAlreadyExistException and as reponame is service name
582 void addService( const ServiceInfo & service );
585 * Removes service specified by its name
587 * \param alias unique indientifier of the service to remove
589 * \throws RepoException if service is not found or file with ServiceInfo cannot be deleted
590 * \throws Exception if file contain more services and rewrite file failed
592 void removeService( const std::string & alias );
593 /** \overload Take alias from ServiceInfo */
594 void removeService( const ServiceInfo & service );
598 * Refreshes all enabled services.
600 * \see refreshService(ServiceInfo)
602 void refreshServices( const RefreshServiceOptions & options_r = RefreshServiceOptions() );
605 * Refresh specific service.
607 * \param alias unique indientifier of the service to refresh
609 * \throws RepoException if service is not found.
610 * \throws MediaException If there's a problem downloading the repo index file.
612 void refreshService( const std::string & alias, const RefreshServiceOptions & options_r = RefreshServiceOptions() );
613 /** \overload Take alias from ServiceInfo */
614 void refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r = RefreshServiceOptions() );
617 * Modifies service file (rewrites it with new values) and underlying
618 * repositories if needed.
620 * Modifications of a service can lead to rewrite of all .repo files of
621 * contained repositories. Particularily, disabling a service (changing
622 * ServiceInfo::enabled() from true to false) will disable all contained
623 * repositories. Renaming of a service will modify the "service" key
624 * of all contained repositories.
626 * \param oldAlias Old alias of the service
627 * \param service ServiceInfo object containing new data
629 * \throws RepoException if sservice with oldAlias is not known
630 * \throws Exception if have problems with files
632 void modifyService( const std::string & oldAlias, const ServiceInfo & service );
633 /** \overload Take alias from ServiceInfo. */
634 void modifyService( const ServiceInfo & service )
635 { modifyService( service.alias(), service ); }
639 * Functor thats filter RepoInfo by service which it belongs to.
641 struct MatchServiceAlias
644 MatchServiceAlias( const std::string & alias_ ) : alias(alias_) {}
645 bool operator()( const RepoInfo & info ) const
646 { return info.service() == alias; }
654 * fill to output iterator repositories in service name. This output iterator can perform
655 * any action on with Repo or service Container, because it is sets and it isn't dynamic recreate.
657 * \note Don't use this function with RepoManager::removeRepository(), it will lead to segfaults
658 * due to invalidated internal iterators. FIXME can this be solved (using STL) so that this
659 * warning would not be needed?
661 * \param alias service alias
662 * \param out output iterator which get all the repositories belonging to
665 * example how set priority for each RepoInfo in this service:
668 * class ChangePriority
673 * ChangePriority(int prio) : priority(prio) {}
674 * // missing rewrite priority back via RepoManager::modifyRepo
675 * void doIt( RepoInfo info ) { info.setPriority(priority); }
678 * //somewhere in code
679 * ChangePriority changer(10);
680 * getRepositoriesInService(name,
681 * boost::make_function_output_iterator(
682 * bind(&ChangePriority::doIt, &changer, _1)));
685 template<typename OutputIterator>
686 void getRepositoriesInService( const std::string & alias,
687 OutputIterator out ) const
689 MatchServiceAlias filter(alias);
691 std::copy( boost::make_filter_iterator( filter, repoBegin(), repoEnd() ),
692 boost::make_filter_iterator( filter, repoEnd(), repoEnd() ),
697 /** Pointer to implementation */
698 RWCOW_pointer<Impl> _pimpl;
700 ZYPP_DECLARE_OPERATORS_FOR_FLAGS(RepoManager::RefreshServiceFlags);
701 ///////////////////////////////////////////////////////////////////
703 /** \relates RepoManager Stream output */
704 std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
706 /** Iterate the known repositories. */
707 inline Iterable<RepoManager::RepoConstIterator> RepoManager::repos() const
708 { return makeIterable( repoBegin(), repoEnd() ); }
710 /** Iterate the known services. */
711 inline Iterable<RepoManager::ServiceConstIterator> RepoManager::services() const
712 { return makeIterable( serviceBegin(), serviceEnd() ); }
714 /////////////////////////////////////////////////////////////////
716 ///////////////////////////////////////////////////////////////////
717 #endif // ZYPP2_REPOMANAGER_H