- Service -> ServiceInfo derived from RepoInfoBase
[platform/upstream/libzypp.git] / zypp / RepoManager.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/RepoManager.h
10  *
11 */
12 #ifndef ZYPP_REPOMANAGER_H
13 #define ZYPP_REPOMANAGER_H
14
15 #include <iosfwd>
16 #include <list>
17
18 #include <boost/iterator.hpp>
19
20 #include "zypp/base/PtrTypes.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/RepoStatus.h"
27 #include "zypp/ProgressData.h"
28
29 ///////////////////////////////////////////////////////////////////
30 namespace zypp
31 { /////////////////////////////////////////////////////////////////
32   class ServiceInfo; //predef
33
34    /**
35     * Parses \a repo_file and returns a list of \ref RepoInfo objects
36     * corresponding to repositories found within the file.
37     *
38     * \param repo_file Valid URL of the repo file.
39     * \return found list<RepoInfo>
40     *
41     * \throws MediaException If the access to the url fails
42     * \throws ParseException If the file parsing fails
43     * \throws Exception On other errors.
44     */
45    std::list<RepoInfo> readRepoFile(const Url & repo_file);
46
47   /**
48    * Repo manager settings.
49    * Settings default to ZYpp global settings.
50    */
51   struct RepoManagerOptions
52   {
53     /** Default ctor following \ref ZConfig global settings.
54      * If an optional \c root_r directory is given, all paths  will
55      * be prefixed accordingly.
56      * \code
57      *    root_r\repoCachePath
58      *          \repoRawCachePath
59      *          \repoSolvCachePath
60      *          \repoPackagesCachePath
61      *          \knownReposPath
62      * \endcode
63      */
64     RepoManagerOptions( const Pathname & root_r = Pathname() );
65
66     /** Test setup adjusting all paths to be located below one \c root_r directory.
67      * \code
68      *    root_r\          - repoCachePath
69      *          \raw       - repoRawCachePath
70      *          \solv      - repoSolvCachePath
71      *          \packages  - repoPackagesCachePath
72      *          \repos.d   - knownReposPath
73      * \endcode
74      */
75     static RepoManagerOptions makeTestSetup( const Pathname & root_r );
76
77     Pathname repoCachePath;
78     Pathname repoRawCachePath;
79     Pathname repoSolvCachePath;
80     Pathname repoPackagesCachePath;
81     Pathname knownReposPath;
82     Pathname knownServicesPath;
83     bool probe;
84   };
85
86
87
88   /**
89    * \short creates and provides information about known sources.
90    *
91    */
92   class RepoManager
93   {
94     friend std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
95
96   public:
97     /** Implementation  */
98     class Impl;
99
100     /** service typedefs */
101     typedef std::set<ServiceInfo> ServiceSet;
102     typedef ServiceSet::const_iterator ServiceConstIterator;
103     typedef ServiceSet::size_type ServiceSizeType;
104
105     /** RepoInfo typedefs */
106     typedef std::set<RepoInfo> RepoSet;
107     typedef RepoSet::const_iterator RepoConstIterator;
108     typedef RepoSet::size_type RepoSizeType;
109
110   public:
111    RepoManager( const RepoManagerOptions &options = RepoManagerOptions() );
112    /** Dtor */
113     ~RepoManager();
114
115     enum RawMetadataRefreshPolicy
116     {
117       RefreshIfNeeded,
118       RefreshForced,
119       RefreshIfNeededIgnoreDelay
120     };
121
122     enum CacheBuildPolicy
123     {
124       BuildIfNeeded,
125       BuildForced
126     };
127
128     enum RepoRemovePolicy
129     {
130
131     };
132
133    /**
134     * \short List known repositories.
135     *
136     * The known repositories are read from
137     * \ref RepoManagerOptions::knownReposPath passed on the Ctor.
138     * Which defaults to ZYpp global settings.
139     * \deprecated use iterator instead which read only one time directory
140     * \return found list<RepoInfo>
141     */
142    ZYPP_DEPRECATED std::list<RepoInfo> knownRepositories() const;
143
144    bool repoEmpty() const;
145    RepoSizeType repoSize() const;
146    RepoConstIterator repoBegin() const;
147    RepoConstIterator repoEnd() const;
148
149
150    /**
151     * \short Status of local metadata
152     */
153     RepoStatus metadataStatus( const RepoInfo &info ) const;
154
155     /**
156      * Possibly return state of checkIfRefreshMEtadata function
157      */
158     enum RefreshCheckStatus {
159       REFRESH_NEEDED,  /**< refresh is needed */
160       REPO_UP_TO_DATE, /**< repository not changed */
161       REPO_CHECK_DELAYED     /**< refresh is delayed due to settings */
162     };
163
164     /**
165      * Checks whether to refresh metadata for specified repository and url.
166      * <p>
167      * The need for refresh is evaluated according to the following conditions,
168      * in that order:
169      * <ul>
170      * <li>the refresh policy (refresh may be forced)
171      * <li>the repo.refresh.delay ZConfig value compared to the difference between
172      *   cached index file timestamp and actual time
173      * <li>the timestamp of cached repo index file compared to the remote
174      *   index file timestamp.
175      * </ul>
176      * <p>
177      * This method checks the status against the specified url only. If more
178      * baseurls are defined for in the RepoInfo, each one must be check
179      * individually. Example:
180      *
181      * <code>
182      *
183      * RepoInfo info;
184      * // try urls one by one
185      * for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
186      *       it != info.baseUrlsEnd(); ++it )
187      * {
188      *   try
189      *   {
190      *     // check whether to refresh metadata
191      *     // if the check fails for this url, it throws, so another url will be checked
192      *     if (checkIfToRefreshMetadata(info, *it, policy)!=RepoInfo::REFRESH_NEEDED)
193      *       return;
194      *
195      *     // do the actual refresh
196      *   }
197      *   catch (const Exception & e)
198      *   {
199      *     ZYPP_CAUGHT(e);
200      *     ERR << *it << " doesn't look good. Trying another url." << endl;
201      *   }
202      * } // for all urls
203      *
204      * handle("No more URLs.");
205      *
206      * </code>
207      *
208      * \param info
209      * \param url
210      * \param policy
211      * \return state of repository
212      * \see RefreshCheckStatus
213      * \throws RepoUnknownTypeException
214      * \throws repo::RepoNoAliasException if can't figure an alias
215      * \throws Exception on unknown error
216      *
217      */
218     RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo &info,
219                                    const Url &url,
220                                    RawMetadataRefreshPolicy policy = RefreshIfNeeded);
221
222     /**
223      * \short Path where the metadata is downloaded and kept
224      *
225      * Given a repoinfo, tells where \ref RepoManager will download
226      * and keep the raw metadata.
227      *
228      * \param info Repository information
229      *
230      * \throws repo::RepoNoAliasException if can't figure an alias
231      */
232     Pathname metadataPath( const RepoInfo &info ) const;
233
234
235     /**
236      * \short Path where the rpm packages are downloaded and kept
237      *
238      * Given a repoinfo, tells where \ref RepoProvidePackage will download
239      * and keep the .rpm files.
240      *
241      * \param info Repository information
242      *
243      * \throws repo::RepoNoAliasException if can't figure an alias
244      */
245     Pathname packagesPath( const RepoInfo &info ) const;
246
247
248    /**
249     * \short Refresh local raw cache
250     *
251     * Will try to download the metadata
252     *
253     * In case of falure the metadata remains
254     * as it was before.
255     *
256     * \throws repo::RepoNoUrlException if no urls are available.
257     * \throws repo::RepoNoAliasException if can't figure an alias
258     * \throws repo::RepoUnknownTypeException if the metadata is unknown
259     * \throws repo::RepoException if the repository is invalid
260     *         (no valid metadata found at any of baseurls)
261     */
262    void refreshMetadata( const RepoInfo &info,
263                          RawMetadataRefreshPolicy policy = RefreshIfNeeded,
264                          const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
265
266    /**
267     * \short Clean local metadata
268     *
269     * Empty local metadata.
270     *
271     * \throws repo::RepoNoAliasException if can't figure an alias
272     * \throws Exception on unknown error.
273     */
274    void cleanMetadata( const RepoInfo &info,
275                        const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
276
277    /**
278     * \short Clean local package cache
279     *
280     * Empty local directory with downloaded packages
281     *
282     * \throws repo::RepoNoAliasException if can't figure an alias
283     * \throws Exception on unknown error.
284     */
285    void cleanPackages( const RepoInfo &info,
286                        const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
287
288    /**
289     * \short Status of metadata cache
290     */
291     RepoStatus cacheStatus( const RepoInfo &info ) const;
292
293    /**
294     * \short Refresh local cache
295     *
296     * Will try to build the cache from local metadata.
297     *
298     * If the cache exists it will be overwriten.
299     *
300     * \note the local metadata must be valid.
301     *
302     * \throws repo::RepoNoAliasException if can't figure
303     *     an alias to look in cache
304     * \throws repo::RepoMetadataException if the metadata
305     *     is not enough to build a cache (empty, incorrect, or
306     *     refresh needed)
307     * \throws repo::RepoUnknownTypeException
308     * \throws parser::ParseException if parser encounters an error.
309     * \throws Exception on unknown error.
310     */
311    void buildCache( const RepoInfo &info,
312                     CacheBuildPolicy policy = BuildIfNeeded,
313                     const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
314
315    /**
316     * \short clean local cache
317     *
318     * Clean the cached version of the metadata
319     *
320     * \note the local metadata must be valid.
321     *
322     * \throws repo::RepoNoAliasException if can't figure an alias to look in cache
323     * \throws cache::CacheRecordNotFoundException if the cache could not be
324     *     cleaned because of repository record not found.
325     * \throws Exception on unknown error.
326     */
327    void cleanCache( const RepoInfo &info,
328                     const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
329
330    /**
331     * \short Whether a repository exists in cache
332     *
333     * \param RepoInfo to be checked.
334     */
335     bool isCached( const RepoInfo &info ) const;
336
337
338     /**
339     * \short Load resolvables into the pool
340     *
341     * Creating from cache requires that the repository is
342     * refreshed (metadata downloaded) and cached
343     *
344     * \throws repo::RepoNoAliasException if can't figure an alias to look in cache
345     * \throw RepoNotCachedException When the source is not cached.
346     */
347    void loadFromCache( const RepoInfo &info,
348                        const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
349    /**
350     * \short Probe repo metadata type.
351     *
352     * \todo FIXME Should this be private?
353     */
354    repo::RepoType probe( const Url &url ) const;
355
356
357    /**
358     * \short Adds a repository to the list of known repositories.
359     *
360     *
361     *
362     * \throws repo::RepoAlreadyExistsException If the repo clash some
363     *         unique attribute like alias
364     * \throws RepoUnknownType
365     *         If RepoManagerOptions::probe is true
366     *         and repository type can't be determined.
367     * \throws RepoException
368     *         If RepoManagerOptions::probe is true and access to the url fails.
369     * \throws Exception On other errors.
370     */
371    void addRepository( const RepoInfo &info,
372                        const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
373
374    /**
375     * \short Adds repositores from a repo file to the list of known repositories.
376     * \param url Url of the repo file
377     *
378     * \throws repo::RepoAlreadyExistsException If the repo clash some
379     *         unique attribute like alias
380     * \throws MediaException If the access to the url fails
381     * \throws ParseException If the file parsing fails
382     * \throws RepoUnknownType If repository type can't be determined
383     * \throws RepoException ON other repository related errors
384     * \throws Exception On other errors.
385     */
386     void addRepositories( const Url &url,
387                          const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
388     /**
389      * \short Remove the best matching repository from known repos list
390      *
391      * \throws RepoNotFoundException If no repo match
392      */
393     void removeRepository( const RepoInfo & info,
394                            const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
395
396     /**
397      * \short Modify repository attributes
398      *
399      * \throws RepoAlreadyExistsException if the alias specified in newinfo
400      *         is already used by another repository
401      * \throws RepoNotFoundException If no repo match
402      * \throws ParseException If the file parsing fails
403      * \throws Exception On other errors.
404      */
405     void modifyRepository( const std::string &alias,
406                            const RepoInfo & newinfo,
407                            const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
408
409     /**
410      * \short Find a matching repository info
411      *
412      * \note if multiple repositories incorrectly share the
413      * same alias, the first one found will be returned.
414      *
415      * \param alias Repository alias
416      * \param progressrcv Progress reporting function
417      * \return RepoInfo of the found repository
418      * \throws RepoNotFoundException If no repo match the alias
419      * \throws ParseException If the file parsing fails
420      * \throws Exception On other errors.
421      */
422     RepoInfo getRepositoryInfo( const std::string &alias,
423                                 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
424
425     /**
426      * \short Find repository info by URL.
427      *
428      * \param url URL to find.
429      * \param urlview url::ViewOption to influence URL matching.
430      * \param progressrcv Progress receiver function.
431      * \return RepoInfo of the found repository.
432      *
433      * \note if multpile repositories incorrectly share the
434      * same URL, the first one found will be returned.
435      *
436      * \note the string representation of the URLs are compared.
437      *       The \a urlview can be used to influence which
438              parts of the URL are to be compared.
439      *
440      * \throws RepoNotFoundException If no repo match
441      * \throws ParseException If the file parsing fails
442      * \throws Exception On other errors.
443      */
444     RepoInfo getRepositoryInfo( const Url & url,
445                                 const url::ViewOption & urlview = url::ViewOption::DEFAULTS,
446                                 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
447
448     /**
449      * Adds new service by it's alias and url
450      *
451      * \param alias unique identifier of the service
452      * \param url url to service
453      *
454      * \throws FIXME RepoAlreadyExistException and as reponame is service name
455      */
456     void addService( const std::string & alias, const Url& url );
457
458     /**
459      * Adds new service
460      *
461      * \param service service info
462      *
463      * \throws FIXME RepoAlreadyExistException and as reponame is service name
464      */
465     void addService( const ServiceInfo & service );
466
467     /**
468      * Removes service specified by its name
469      *
470      * \param alias unique indientifier of the service to remove
471      *
472      * \throws RepoException if service is not found or file with ServiceInfo cannot be deleted
473      * \throws Exception if file contain more services and rewrite file failed
474      */
475     void removeService( const std::string & alias );
476
477     void removeService( const ServiceInfo & service );
478
479     /**
480      * Gets true if no service is in RepoManager (so no one in specified location)
481      *
482      * \return true if any ServiceInfo is in RepoManager
483      */
484     bool serviceEmpty() const;
485
486     /**
487      * Gets count of service in RepoManager (in specified location)
488      *
489      * \return count of service
490      */
491     ServiceSizeType serviceSize() const;
492
493     /**
494      * Iterator to first service in internal storage.
495      * \note Iterator is immutable, so you cannot change pointed ServiceInfo
496      * \return Iterator to first service
497      */
498     ServiceConstIterator serviceBegin() const;
499
500     /**
501      * Iterator to place behind last service in internal storage.
502      * \return iterator to end
503      */
504     ServiceConstIterator serviceEnd() const;
505
506     /**
507      * Finds ServiceInfo by alias or return noService
508      *
509      * \param alias unique identifier of service
510      * \return information about service
511      */
512     ServiceInfo getService( const std::string & alias ) const;
513
514     /**
515      * Refreshes all enabled services.
516      * 
517      * \see refreshService(ServiceInfo)
518      */
519     void refreshServices();
520
521     /**
522      * Refresh specific service.
523      * 
524      * \param name service structure
525      * \throws MediaException If there's a problem downloading the repo index file.
526      */
527     void refreshService( const ServiceInfo & service );
528
529     /**
530      * Modifies service file (rewrites it with new values) and underlying
531      * repositories if needed.
532      * 
533      * Modifications of a service can lead to rewrite of all .repo files of
534      * contained repositories. Particularily, disabling a service (changing
535      * ServiceInfo::enabled() from true to false) will disable all contained
536      * repositories. Renaming of a service will modify the "service" key
537      * of all contained repositories.
538      *
539      * \param oldAlias Old alias of the service
540      * \param service ServiceInfo object containing new data
541      *
542      * \throws RepoException if sservice with oldAlias is not known
543      * \throws Exception if have problems with files
544      */
545     void modifyService(const std::string & oldAlias, const ServiceInfo & service);
546
547   private:
548     /**
549      * Functor thats filter RepoInfo by service which belongs to.
550      */
551     struct MatchServiceAlias
552     {
553       private:
554         std::string alias;
555       public:
556         MatchServiceAlias( const std::string & alias_ ) : alias(alias_) {}
557         bool match( const RepoInfo & info ) { return info.service() == alias; }
558     };
559
560   public:
561
562     /**
563      * fill to output iterator repositories in service name. This output iterator can perform
564      * any action on with Repo or service Container, because it is sets and it isn't dynamic recreate.
565      *
566      * \note Don't use this function with RepoManager::removeRepository(), it will lead to segfaults
567      *       due to invalidated internal iterators. FIXME can this be solved (using STL) so that this
568      *       warning would not be needed?
569      *
570      * \param alias service alias
571      * \param out output iterator which get all the repositories belonging to
572      *   specified service
573      *
574      * example how set priority for each RepoInfo in this service:
575      * \code
576      * //functor
577      * class ChangePriority
578      * {
579      * private:
580      *   int priority;
581      * public:
582      *   ChangePriority(int prio) : priority(prio) {}
583      *   // missing rewrite priority back via RepoManager::modifyRepo
584      *   void doIt( RepoInfo info ) { info.setPriority(priority); } 
585      * }
586      *
587      * //somewhere in code
588      * ChangePriority changer(10);
589      * getRepositoriesInService(name,
590      *   boost::make_function_output_iterator(
591      *     bind(&ChangePriority::doIt, &changer, _1)));
592      * \endcode
593      */
594     template<typename OutputIterator>
595     void getRepositoriesInService( const std::string & alias,
596                                    OutputIterator out ) const
597     {
598       MatchServiceAlias filter(alias);
599
600       std::copy(
601         boost::make_filter_iterator(
602           bind(&MatchServiceAlias::match, filter, _1), repoBegin(), repoEnd()),
603         boost::make_filter_iterator(
604           bind(&MatchServiceAlias::match, filter, _1), repoEnd(), repoEnd()),
605         out);
606     }
607
608   protected:
609     RepoStatus rawMetadataStatus( const RepoInfo &info );
610     void setCacheStatus( const RepoInfo &info, const RepoStatus &status );
611
612     /**
613      * Update timestamp of repository index file for the specified repository \a info.
614      * Used in \ref checkIfToRefreshMetadata() for repo.refresh.delay feature.
615      */
616     void touchIndexFile(const RepoInfo & info);
617
618   public:
619
620   private:
621     /** Pointer to implementation */
622     RWCOW_pointer<Impl> _pimpl;
623   };
624   ///////////////////////////////////////////////////////////////////
625
626   /** \relates RepoManager Stream output */
627   std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
628
629   /////////////////////////////////////////////////////////////////
630 } // namespace zypp
631 ///////////////////////////////////////////////////////////////////
632 #endif // ZYPP2_REPOMANAGER_H