add comment to missing modifyRepo
[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 Service; //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<Service> 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 If repository type can't be determined
365     * \throws RepoException If the access to the url fails (while probing).
366     * \throws Exception On other errors.
367     */
368    void addRepository( const RepoInfo &info,
369                        const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
370
371    /**
372     * \short Adds repositores from a repo file to the list of known repositories.
373     * \param url Url of the repo file
374     *
375     * \throws repo::RepoAlreadyExistsException If the repo clash some
376     * unique attribute like alias
377     *
378     * \throws RepoAlreadyExistsException
379     * \throws MediaException If the access to the url fails
380     * \throws ParseException If the file parsing fails
381     * \throws RepoUnknownType If repository type can't be determined
382     * \throws RepoException ON other repository related errors
383     * \throws Exception On other errors.
384     */
385     void addRepositories( const Url &url,
386                          const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
387     /**
388      * \short Remove the best matching repository from known repos list
389      *
390      * \throws RepoNotFoundException If no repo match
391      */
392     void removeRepository( const RepoInfo & info,
393                            const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
394
395     /**
396      * \short Modify repository attributes
397      *
398      * \throws RepoAlreadyExistsException if the alias specified in newinfo
399      *         is already used by another repository
400      * \throws RepoNotFoundException If no repo match
401      * \throws ParseException If the file parsing fails
402      * \throws Exception On other errors.
403      */
404     void modifyRepository( const std::string &alias,
405                            const RepoInfo & newinfo,
406                            const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
407
408     /**
409      * \short Find a matching repository info
410      *
411      * \note if multiple repositories incorrectly share the
412      * same alias, the first one found will be returned.
413      *
414      * \param alias Repository alias
415      * \param progressrcv Progress reporting function
416      * \return RepoInfo of the found repository
417      * \throws RepoNotFoundException If no repo match the alias
418      * \throws ParseException If the file parsing fails
419      * \throws Exception On other errors.
420      */
421     RepoInfo getRepositoryInfo( const std::string &alias,
422                                 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
423
424     /**
425      * \short Find repository info by URL.
426      *
427      * \param url URL to find.
428      * \param urlview url::ViewOption to influence URL matching.
429      * \param progressrcv Progress receiver function.
430      * \return RepoInfo of the found repository.
431      *
432      * \note if multpile repositories incorrectly share the
433      * same URL, the first one found will be returned.
434      *
435      * \note the string representation of the URLs are compared.
436      *       The \a urlview can be used to influence which
437              parts of the URL are to be compared.
438      *
439      * \throws RepoNotFoundException If no repo match
440      * \throws ParseException If the file parsing fails
441      * \throws Exception On other errors.
442      */
443     RepoInfo getRepositoryInfo( const Url & url,
444                                 const url::ViewOption & urlview = url::ViewOption::DEFAULTS,
445                                 const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() );
446
447     /**
448      * Adds new service by it's name and url
449      *
450      * \param name unique name of service
451      * \param url url to service
452      *
453      * \throws FIXME RepoAlreadyExistException and as reponame is service name
454      */
455     void addService( const std::string& name, const Url& url );
456
457     /**
458      * Adds new service
459      *
460      * \param name service info 
461      *
462      * \throws FIXME RepoAlreadyExistException and as reponame is service name
463      */
464     void addService( const Service& name );
465
466     /**
467      * Removes service specified by its name
468      *
469      * \param name name of service to remove
470      *
471      * \throws RepoException if service is not found or file with Service cannot be deleted
472      * \throws Exception if file contain more services and rewrite file failed
473      */
474     void removeService( const std::string& name );
475
476     /**
477      * Gets true if no service is in RepoManager (so no one in specified location)
478      *
479      * \return true if any Service is in RepoManager
480      */
481     bool serviceEmpty() const;
482
483     /**
484      * Gets count of service in RepoManager (in specified location)
485      *
486      * \return count of service
487      */
488     ServiceSizeType serviceSize() const;
489
490     /**
491      * Iterator to first service in internal storage.
492      * \note Iterator is immutable, so you cannot change pointed Service
493      * \return Iterator to first service
494      */
495     ServiceConstIterator serviceBegin() const;
496
497     /**
498      * Iterator to place behind last service in internal storage.
499      * \return iterator to end
500      */
501     ServiceConstIterator serviceEnd() const;
502
503     /**
504      * Finds Service by name or return noService
505      *
506      * \param name unique name of service
507      * \return information about Service
508      */
509     Service getService( const std::string& name ) const;
510
511     /**
512      * Refreshs all services
513      * \see refreshService
514      */
515     void refreshServices();
516
517     /**
518      * Refresh specific service. 
519      * \throws Exception if cannot download file
520      * \param name service structure
521      */
522     void refreshService( const Service& name );
523
524     /**
525      * modify service, rewrite Service to filesystem.
526      * If change Service name, then can escalate to rewrite all repositories which it contain.
527      * 
528      * \param oldName oldName of service
529      * \param service Structure containing new datas
530      *
531      * \throws RepoException if sservice with oldName is not known
532      * \throws Exception if have problems with files
533      */
534     void modifyService(const std::string& oldName, const Service& service);
535
536     /**
537      * Functor thats filter RepoInfo by service which belongs to.
538      */
539     struct MatchServiceName {
540       private:
541         std::string name;
542       public:
543         MatchServiceName( const std::string& name_ ) : name(name_) {}
544         bool match( const RepoInfo& info ) { return info.service()==name; }
545     };
546
547     /**
548      * fill to output iterator repositories in service name. This output iterator can perform
549      * any action on with Repo or service Container, because it is sets and it isn't dynamic recreate.
550      * \param name service name
551      * \param out output iterator which get all repositories in Service
552      *
553      * example how set priority for each RepoInfo in this service:
554      * \code
555      * //functor
556      * class ChangePriority{
557      *   private:
558      *     int priority;
559      *   public:
560      *     ChangePriority(int prio) : priority(prio) {}
561      *     void doIt( RepoInfo info ) { info.setPriority(priority); } //missing rewrite priority back via RepoManager::modifyRepo
562      * }
563      *
564      * //somewhere in code
565      * ChangePriority changer(10);
566      * getRepositoriesInService(name,getRepositoriesInService( name, boost::make_function_output_iterator(bind(&ChangePriority::doIt, &changer, _1))));
567      * \endcode
568      */ 
569
570     template<typename OutputIterator>
571     void getRepositoriesInService( const std::string& name, OutputIterator out ) const
572     {
573       MatchServiceName filter(name);
574
575       std::copy(boost::make_filter_iterator(bind(&MatchServiceName::match, 
576           filter, _1),repoBegin(),repoEnd()), boost::make_filter_iterator(
577           bind(&MatchServiceName::match, filter, _1),repoEnd(),repoEnd()),
578           out );
579     }
580
581   protected:
582     RepoStatus rawMetadataStatus( const RepoInfo &info );
583     void setCacheStatus( const RepoInfo &info, const RepoStatus &status );
584
585     /**
586      * Update timestamp of repository index file for the specified repository \a info.
587      * Used in \ref checkIfToRefreshMetadata() for repo.refresh.delay feature.
588      */
589     void touchIndexFile(const RepoInfo & info);
590
591   public:
592
593   private:
594     /** Pointer to implementation */
595     RWCOW_pointer<Impl> _pimpl;
596   };
597   ///////////////////////////////////////////////////////////////////
598
599   /** \relates RepoManager Stream output */
600   std::ostream & operator<<( std::ostream & str, const RepoManager & obj );
601
602   /////////////////////////////////////////////////////////////////
603 } // namespace zypp
604 ///////////////////////////////////////////////////////////////////
605 #endif // ZYPP2_REPOMANAGER_H