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