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