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