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"
21 #include "zypp/Pathname.h"
22 #include "zypp/ZConfig.h"
23 #include "zypp/RepoInfo.h"
24 #include "zypp/repo/RepoException.h"
25 #include "zypp/repo/RepoType.h"
26 #include "zypp/repo/ServiceType.h"
27 #include "zypp/ServiceInfo.h"
28 #include "zypp/RepoStatus.h"
29 #include "zypp/ProgressData.h"
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
36 * Parses \a repo_file and returns a list of \ref RepoInfo objects
37 * corresponding to repositories found within the file.
39 * \param repo_file Valid URL of the repo file.
40 * \return found list<RepoInfo>
42 * \throws MediaException If the access to the url fails
43 * \throws ParseException If the file parsing fails
44 * \throws Exception On other errors.
46 std::list<RepoInfo> readRepoFile(const Url & repo_file);
49 * Repo manager settings.
50 * Settings default to ZYpp global settings.
52 struct RepoManagerOptions
54 /** Default ctor following \ref ZConfig global settings.
55 * If an optional \c root_r directory is given, all paths will
56 * be prefixed accordingly.
58 * root_r\repoCachePath
61 * \repoPackagesCachePath
65 RepoManagerOptions( const Pathname & root_r = Pathname() );
67 /** Test setup adjusting all paths to be located below one \c root_r directory.
69 * root_r\ - repoCachePath
70 * \raw - repoRawCachePath
71 * \solv - repoSolvCachePath
72 * \packages - repoPackagesCachePath
73 * \repos.d - knownReposPath
76 static RepoManagerOptions makeTestSetup( const Pathname & root_r );
78 Pathname repoCachePath;
79 Pathname repoRawCachePath;
80 Pathname repoSolvCachePath;
81 Pathname repoPackagesCachePath;
82 Pathname knownReposPath;
83 Pathname knownServicesPath;
87 * Target distro ID to be used when refreshing repo index services.
88 * Repositories not maching this ID will be skipped/removed.
90 * The value is initialized upon construction to
91 * \ref Target::targetDistribution() if the Target is already initialized,
92 * otherwise the value is initially empty.
94 * If empty, no repositories contained in the index will be skipped.
96 std::string servicesTargetDistro;
98 /** remembers root_r value for later use */
105 * \short creates and provides information about known sources.
110 friend std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
113 /** Implementation */
116 /** ServiceInfo typedefs */
117 typedef std::set<ServiceInfo> ServiceSet;
118 typedef ServiceSet::const_iterator ServiceConstIterator;
119 typedef ServiceSet::size_type ServiceSizeType;
121 /** RepoInfo typedefs */
122 typedef std::set<RepoInfo> RepoSet;
123 typedef RepoSet::const_iterator RepoConstIterator;
124 typedef RepoSet::size_type RepoSizeType;
127 RepoManager( const RepoManagerOptions &options = RepoManagerOptions() );
131 enum RawMetadataRefreshPolicy
135 RefreshIfNeededIgnoreDelay
138 enum CacheBuildPolicy
144 enum RepoRemovePolicy
149 /** \name Known repositories.
151 * The known repositories are read from
152 * \ref RepoManagerOptions::knownReposPath passed on the Ctor.
153 * Which defaults to ZYpp global settings.
156 bool repoEmpty() const;
157 RepoSizeType repoSize() const;
158 RepoConstIterator repoBegin() const;
159 RepoConstIterator repoEnd() const;
161 /** List of known repositories. */
162 std::list<RepoInfo> knownRepositories() const
163 { return std::list<RepoInfo>(repoBegin(),repoEnd()); }
165 /** Find RepoInfo by alias or return \ref RepoInfo::noRepo. */
166 RepoInfo getRepo( const std::string & alias ) const;
167 /** \overload Take alias from RepoInfo. */
168 RepoInfo getRepo( const RepoInfo & info_r ) const
169 { return getRepo( info_r.alias() ); }
171 /** Return whether there is a known repository for \c alias. */
172 bool hasRepo( const std::string & alias ) const;
173 /** \overload Take alias from RepoInfo. */
174 bool hasRepo( const RepoInfo & info_r ) const
175 { return hasRepo( info_r.alias() ); }
177 /** Some stupid string but suitable as alias for your url if nothing better is available.
178 * Something like \c "http-download.opensuse.org-83df67e5"
180 static std::string makeStupidAlias( const Url & url_r = Url() );
184 * \short Status of local metadata
186 RepoStatus metadataStatus( const RepoInfo &info ) const;
189 * Possibly return state of checkIfRefreshMEtadata function
191 enum RefreshCheckStatus {
192 REFRESH_NEEDED, /**< refresh is needed */
193 REPO_UP_TO_DATE, /**< repository not changed */
194 REPO_CHECK_DELAYED /**< refresh is delayed due to settings */
198 * Checks whether to refresh metadata for specified repository and url.
200 * The need for refresh is evaluated according to the following conditions,
203 * <li>the refresh policy (refresh may be forced)
204 * <li>the repo.refresh.delay ZConfig value compared to the difference between
205 * cached index file timestamp and actual time
206 * <li>the timestamp of cached repo index file compared to the remote
207 * index file timestamp.
210 * This method checks the status against the specified url only. If more
211 * baseurls are defined for in the RepoInfo, each one must be check
212 * individually. Example:
217 * // try urls one by one
218 * for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
219 * it != info.baseUrlsEnd(); ++it )
223 * // check whether to refresh metadata
224 * // if the check fails for this url, it throws, so another url will be checked
225 * if (checkIfToRefreshMetadata(info, *it, policy)!=RepoInfo::REFRESH_NEEDED)
228 * // do the actual refresh
230 * catch (const Exception & e)
233 * ERR << *it << " doesn't look good. Trying another url." << endl;
237 * handle("No more URLs.");
244 * \return state of repository
245 * \see RefreshCheckStatus
246 * \throws RepoUnknownTypeException
247 * \throws repo::RepoNoAliasException if can't figure an alias
248 * \throws Exception on unknown error
251 RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo &info,
253 RawMetadataRefreshPolicy policy = RefreshIfNeeded);
256 * \short Path where the metadata is downloaded and kept
258 * Given a repoinfo, tells where \ref RepoManager will download
259 * and keep the raw metadata.
261 * \param info Repository information
263 * \throws repo::RepoNoAliasException if can't figure an alias
265 Pathname metadataPath( const RepoInfo &info ) const;
269 * \short Path where the rpm packages are downloaded and kept
271 * Given a repoinfo, tells where \ref RepoProvidePackage will download
272 * and keep the .rpm files.
274 * \param info Repository information
276 * \throws repo::RepoNoAliasException if can't figure an alias
278 Pathname packagesPath( const RepoInfo &info ) const;
282 * \short Refresh local raw cache
284 * Will try to download the metadata
286 * In case of falure the metadata remains
289 * \throws repo::RepoNoUrlException if no urls are available.
290 * \throws repo::RepoNoAliasException if can't figure an alias
291 * \throws repo::RepoUnknownTypeException if the metadata is unknown
292 * \throws repo::RepoException if the repository is invalid
293 * (no valid metadata found at any of baseurls)
295 void refreshMetadata( const RepoInfo &info,
296 RawMetadataRefreshPolicy policy = RefreshIfNeeded,
297 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
300 * \short Clean local metadata
302 * Empty local metadata.
304 * \throws repo::RepoNoAliasException if can't figure an alias
305 * \throws Exception on unknown error.
307 void cleanMetadata( const RepoInfo &info,
308 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
311 * \short Clean local package cache
313 * Empty local directory with downloaded packages
315 * \throws repo::RepoNoAliasException if can't figure an alias
316 * \throws Exception on unknown error.
318 void cleanPackages( const RepoInfo &info,
319 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
322 * \short Status of metadata cache
324 RepoStatus cacheStatus( const RepoInfo &info ) const;
327 * \short Refresh local cache
329 * Will try to build the cache from local metadata.
331 * If the cache exists it will be overwriten.
333 * \note the local metadata must be valid.
335 * \throws repo::RepoNoAliasException if can't figure
336 * an alias to look in cache
337 * \throws repo::RepoMetadataException if the metadata
338 * is not enough to build a cache (empty, incorrect, or
340 * \throws repo::RepoUnknownTypeException
341 * \throws parser::ParseException if parser encounters an error.
342 * \throws Exception on unknown error.
344 void buildCache( const RepoInfo &info,
345 CacheBuildPolicy policy = BuildIfNeeded,
346 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
349 * \short clean local cache
351 * Clean the cached version of the metadata
353 * \note the local metadata must be valid.
355 * \throws repo::RepoNoAliasException if can't figure an alias to look in cache
356 * \throws cache::CacheRecordNotFoundException if the cache could not be
357 * cleaned because of repository record not found.
358 * \throws Exception on unknown error.
360 void cleanCache( const RepoInfo &info,
361 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
364 * \short Whether a repository exists in cache
366 * \param RepoInfo to be checked.
368 bool isCached( const RepoInfo &info ) const;
372 * \short Load resolvables into the pool
374 * Creating from cache requires that the repository is
375 * refreshed (metadata downloaded) and cached
377 * \throws repo::RepoNoAliasException if can't figure an alias to look in cache
378 * \throw RepoNotCachedException When the source is not cached.
380 void loadFromCache( const RepoInfo &info,
381 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
384 * Remove any subdirectories of cache directories which no longer belong
385 * to any of known repositories.
387 * These can be temporary directories left by interrupted refresh,
388 * or dirs left after changing .repo files outside of libzypp.
390 void cleanCacheDirGarbage( const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
393 * \short Probe repo metadata type.
395 * The location to probe consists of the base \a url (you may think of it as
396 * a mountpoint) and the \a path to the repository on the mounted media
399 repo::RepoType probe( const Url & url, const Pathname & path ) const;
401 * \overload Using the default path \c "/".
403 repo::RepoType probe( const Url & url ) const;
407 * \short Adds a repository to the list of known repositories.
411 * \throws repo::RepoAlreadyExistsException If the repo clash some
412 * unique attribute like alias
413 * \throws RepoUnknownType
414 * If RepoManagerOptions::probe is true
415 * and repository type can't be determined.
416 * \throws RepoException
417 * If RepoManagerOptions::probe is true and access to the url fails.
418 * \throws Exception On other errors.
420 void addRepository( const RepoInfo &info,
421 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
424 * \short Adds repositores from a repo file to the list of known repositories.
425 * \param url Url of the repo file
427 * \throws repo::RepoAlreadyExistsException If the repo clash some
428 * unique attribute like alias
429 * \throws MediaException If the access to the url fails
430 * \throws ParseException If the file parsing fails
431 * \throws RepoUnknownType If repository type can't be determined
432 * \throws RepoException ON other repository related errors
433 * \throws Exception On other errors.
435 void addRepositories( const Url &url,
436 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
438 * \short Remove the best matching repository from known repos list
440 * \throws RepoNotFoundException If no repo match
442 void removeRepository( const RepoInfo & info,
443 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
446 * \short Modify repository attributes
448 * \throws RepoAlreadyExistsException if the alias specified in newinfo
449 * is already used by another repository
450 * \throws RepoNotFoundException If no repo match
451 * \throws ParseException If the file parsing fails
452 * \throws Exception On other errors.
454 void modifyRepository( const std::string &alias,
455 const RepoInfo & newinfo,
456 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
457 /** \overload Take alias from RepoInfo. */
458 void modifyRepository( const RepoInfo & newinfo,
459 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() )
460 { modifyRepository( newinfo.alias(), newinfo, progressrcv ); }
463 * \short Find a matching repository info
465 * \note if multiple repositories incorrectly share the
466 * same alias, the first one found will be returned.
468 * \param alias Repository alias
469 * \param progressrcv Progress reporting function
470 * \return RepoInfo of the found repository
471 * \throws RepoNotFoundException If no repo match the alias
472 * \throws ParseException If the file parsing fails
473 * \throws Exception On other errors.
475 RepoInfo getRepositoryInfo( const std::string &alias,
476 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
479 * \short Find repository info by URL.
481 * \param url URL to find.
482 * \param urlview url::ViewOption to influence URL matching.
483 * \param progressrcv Progress receiver function.
484 * \return RepoInfo of the found repository.
486 * \note if multpile repositories incorrectly share the
487 * same URL, the first one found will be returned.
489 * \note the string representation of the URLs are compared.
490 * The \a urlview can be used to influence which
491 parts of the URL are to be compared.
493 * \throws RepoNotFoundException If no repo match
494 * \throws ParseException If the file parsing fails
495 * \throws Exception On other errors.
497 RepoInfo getRepositoryInfo( const Url & url,
498 const url::ViewOption & urlview = url::ViewOption::DEFAULTS,
499 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
502 /** \name Known services.
504 * The known services are read from
505 * \ref RepoManagerOptions::knownServicesPath passed on the Ctor.
506 * Which defaults to ZYpp global settings.
510 * Gets true if no service is in RepoManager (so no one in specified location)
512 * \return true if any ServiceInfo is in RepoManager
514 bool serviceEmpty() const;
517 * Gets count of service in RepoManager (in specified location)
519 * \return count of service
521 ServiceSizeType serviceSize() const;
524 * Iterator to first service in internal storage.
525 * \note Iterator is immutable, so you cannot change pointed ServiceInfo
526 * \return Iterator to first service
528 ServiceConstIterator serviceBegin() const;
531 * Iterator to place behind last service in internal storage.
532 * \return iterator to end
534 ServiceConstIterator serviceEnd() const;
536 /** List of known services. */
537 std::list<ServiceInfo> knownServices() const
538 { return std::list<ServiceInfo>(serviceBegin(),serviceEnd()); }
541 * \short Finds ServiceInfo by alias or return \ref ServiceInfo::noService
543 * \param alias unique identifier of service
544 * \return information about service
546 ServiceInfo getService( const std::string & alias ) const;
548 /** Return whether there is a known service for \c alias. */
549 bool hasService( const std::string & alias ) const;
553 * \short Probe the type or the service.
555 repo::ServiceType probeService( const Url &url ) const;
558 * Adds new service by it's alias and url
560 * \param alias unique identifier of the service
561 * \param url url to service
563 * \throws FIXME RepoAlreadyExistException and as reponame is service name
565 void addService( const std::string & alias, const Url& url );
570 * \param service service info
572 * \throws FIXME RepoAlreadyExistException and as reponame is service name
574 void addService( const ServiceInfo & service );
577 * Removes service specified by its name
579 * \param alias unique indientifier of the service to remove
581 * \throws RepoException if service is not found or file with ServiceInfo cannot be deleted
582 * \throws Exception if file contain more services and rewrite file failed
584 void removeService( const std::string & alias );
585 /** \overload Take alias from ServiceInfo */
586 void removeService( const ServiceInfo & service );
590 * Refreshes all enabled services.
592 * \see refreshService(ServiceInfo)
594 void refreshServices();
597 * Refresh specific service.
599 * \param alias unique indientifier of the service to refresh
601 * \throws RepoException if service is not found.
602 * \throws MediaException If there's a problem downloading the repo index file.
604 void refreshService( const std::string & alias );
605 /** \overload Take alias from ServiceInfo */
606 void refreshService( const ServiceInfo & service );
609 * Modifies service file (rewrites it with new values) and underlying
610 * repositories if needed.
612 * Modifications of a service can lead to rewrite of all .repo files of
613 * contained repositories. Particularily, disabling a service (changing
614 * ServiceInfo::enabled() from true to false) will disable all contained
615 * repositories. Renaming of a service will modify the "service" key
616 * of all contained repositories.
618 * \param oldAlias Old alias of the service
619 * \param service ServiceInfo object containing new data
621 * \throws RepoException if sservice with oldAlias is not known
622 * \throws Exception if have problems with files
624 void modifyService( const std::string & oldAlias, const ServiceInfo & service );
625 /** \overload Take alias from ServiceInfo. */
626 void modifyService( const ServiceInfo & service )
627 { modifyService( service.alias(), service ); }
631 * Functor thats filter RepoInfo by service which it belongs to.
633 struct MatchServiceAlias
636 MatchServiceAlias( const std::string & alias_ ) : alias(alias_) {}
637 bool operator()( const RepoInfo & info ) const
638 { return info.service() == alias; }
646 * fill to output iterator repositories in service name. This output iterator can perform
647 * any action on with Repo or service Container, because it is sets and it isn't dynamic recreate.
649 * \note Don't use this function with RepoManager::removeRepository(), it will lead to segfaults
650 * due to invalidated internal iterators. FIXME can this be solved (using STL) so that this
651 * warning would not be needed?
653 * \param alias service alias
654 * \param out output iterator which get all the repositories belonging to
657 * example how set priority for each RepoInfo in this service:
660 * class ChangePriority
665 * ChangePriority(int prio) : priority(prio) {}
666 * // missing rewrite priority back via RepoManager::modifyRepo
667 * void doIt( RepoInfo info ) { info.setPriority(priority); }
670 * //somewhere in code
671 * ChangePriority changer(10);
672 * getRepositoriesInService(name,
673 * boost::make_function_output_iterator(
674 * bind(&ChangePriority::doIt, &changer, _1)));
677 template<typename OutputIterator>
678 void getRepositoriesInService( const std::string & alias,
679 OutputIterator out ) const
681 MatchServiceAlias filter(alias);
683 std::copy( boost::make_filter_iterator( filter, repoBegin(), repoEnd() ),
684 boost::make_filter_iterator( filter, repoEnd(), repoEnd() ),
689 /** Pointer to implementation */
690 RWCOW_pointer<Impl> _pimpl;
692 ///////////////////////////////////////////////////////////////////
694 /** \relates RepoManager Stream output */
695 std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
697 /////////////////////////////////////////////////////////////////
699 ///////////////////////////////////////////////////////////////////
700 #endif // ZYPP2_REPOMANAGER_H