From 8acdb609ee823887db0e31b84dc0d501d51bbd82 Mon Sep 17 00:00:00 2001 From: Duncan Mac-Vicar P Date: Wed, 6 Jun 2007 14:45:35 +0000 Subject: [PATCH] zypper port starts. zypp2 to zypp --- zypp/RepoInfo.cc | 189 +++++++++++++++++ zypp/RepoInfo.h | 199 ++++++++++++++++++ zypp/RepoManager.cc | 402 +++++++++++++++++++++++++++++++++++++ zypp/RepoManager.h | 177 ++++++++++++++++ zypp/RepoStatus.cc | 110 ++++++++++ zypp/RepoStatus.h | 93 +++++++++ zypp/Repository.cc | 50 +++++ zypp/Repository.h | 81 ++++++++ zypp/RepositoryFactory.cc | 23 +++ zypp/RepositoryFactory.h | 30 +++ zypp/dummy.cc | 0 zypp/parser/RepoFileReader.cc | 100 +++++++++ zypp/parser/RepoFileReader.h | 93 +++++++++ zypp/parser/susetags/RepoParser.cc | 283 ++++++++++++++++++++++++++ zypp/parser/susetags/RepoParser.h | 103 ++++++++++ 15 files changed, 1933 insertions(+) create mode 100644 zypp/RepoInfo.cc create mode 100644 zypp/RepoInfo.h create mode 100644 zypp/RepoManager.cc create mode 100644 zypp/RepoManager.h create mode 100644 zypp/RepoStatus.cc create mode 100644 zypp/RepoStatus.h create mode 100644 zypp/Repository.cc create mode 100644 zypp/Repository.h create mode 100644 zypp/RepositoryFactory.cc create mode 100644 zypp/RepositoryFactory.h create mode 100644 zypp/dummy.cc create mode 100644 zypp/parser/RepoFileReader.cc create mode 100644 zypp/parser/RepoFileReader.h create mode 100644 zypp/parser/susetags/RepoParser.cc create mode 100644 zypp/parser/susetags/RepoParser.h diff --git a/zypp/RepoInfo.cc b/zypp/RepoInfo.cc new file mode 100644 index 0000000..a26bbb8 --- /dev/null +++ b/zypp/RepoInfo.cc @@ -0,0 +1,189 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoInfo.cc + * +*/ +#include +#include "zypp/base/Logger.h" + +#include "zypp2/RepoInfo.h" + +using namespace std; +using namespace boost; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfo::Impl + // + /** RepoInfo implementation. */ + struct RepoInfo::Impl + { + + Impl() + : enabled (indeterminate), + autorefresh(indeterminate), + type(repo::RepoType::NONE_e) + {} + + ~Impl() + { + //MIL << std::endl; + } + public: + boost::tribool enabled; + boost::tribool autorefresh; + repo::RepoType type; + Url mirrorlist_url; + std::set urls; + std::string alias; + std::string name; + + public: + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoInfo::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RepoInfo::Impl & obj ) + { + return str << "RepoInfo::Impl"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfo + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoInfo::RepoInfo + // METHOD TYPE : Ctor + // + RepoInfo::RepoInfo() + : _pimpl( new Impl() ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoInfo::~RepoInfo + // METHOD TYPE : Dtor + // + RepoInfo::~RepoInfo() + { + //MIL << std::endl; + } + + + + RepoInfo & RepoInfo::setEnabled( boost::tribool enabled ) + { + _pimpl->enabled = enabled; + return *this; + } + + RepoInfo & RepoInfo::setAutorefresh( boost::tribool autorefresh ) + { + _pimpl->autorefresh = autorefresh; + return *this; + } + + RepoInfo & RepoInfo::setMirrorListUrl( const Url &url ) + { + _pimpl->mirrorlist_url = url; + return *this; + } + + RepoInfo & RepoInfo::addBaseUrl( const Url &url ) + { + _pimpl->urls.insert(url); + return *this; + } + + RepoInfo & RepoInfo::setAlias( const std::string &alias ) + { + _pimpl->alias = alias; + return *this; + } + + RepoInfo & RepoInfo::setType( const repo::RepoType &t ) + { + _pimpl->type = t; + return *this; + } + + RepoInfo & RepoInfo::setName( const std::string &name ) + { + _pimpl->name = name; + return *this; + } + + tribool RepoInfo::enabled() const + { return _pimpl->enabled; } + + tribool RepoInfo::autorefresh() const + { return _pimpl->autorefresh; } + + std::string RepoInfo::alias() const + { return _pimpl->alias; } + + std::string RepoInfo::name() const + { return _pimpl->name; } + + repo::RepoType RepoInfo::type() const + { return _pimpl->type; } + + Url RepoInfo::mirrorListUrl() const + { return _pimpl->mirrorlist_url; } + + std::set RepoInfo::urls() const + { return _pimpl->urls; } + + RepoInfo::urls_const_iterator RepoInfo::urlsBegin() const + { return _pimpl->urls.begin(); } + + RepoInfo::urls_const_iterator RepoInfo::urlsEnd() const + { return _pimpl->urls.end(); } + + std::ostream & RepoInfo::dumpOn( std::ostream & str ) const + { + str << "--------------------------------------" << std::endl; + str << "- alias : " << alias() << std::endl; + std::set url_set(urls()); + for ( std::set::const_iterator it = url_set.begin(); + it != url_set.end(); + ++it ) + { + str << "- url : " << *it << std::endl; + } + + str << "- type : " << type() << std::endl; + str << "- enabled : " << enabled() << std::endl; + str << "- autorefresh : " << autorefresh() << std::endl; + //str << "- path : " << path() << std::endl; + return str; + } + + std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ) + { + return obj.dumpOn(str); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp2 +/////////////////////////////////////////////////////////////////// diff --git a/zypp/RepoInfo.h b/zypp/RepoInfo.h new file mode 100644 index 0000000..b1a7b27 --- /dev/null +++ b/zypp/RepoInfo.h @@ -0,0 +1,199 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp2/RepoInfo.h + * +*/ +#ifndef ZYPP2_REPOSITORYINFO_H +#define ZYPP2_REPOSITORYINFO_H + +#include +#include +#include +#include "zypp/base/PtrTypes.h" + +#include +#include "zypp/Pathname.h" +#include "zypp/Url.h" +#include "zypp2/repo/RepoType.h" + + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfo + // + /** + * \short What is known about a repository + * + * The class RepoInfo represents everything that + * is known about a software repository. + * + * It can be used to store information about known + * sources. + * + * This class tries to be compatible with the + * concept of a .repo file used by YUM and + * also available in the openSUSE build service. + * + * Example file + * + * \code + * [ruby] + * name=Ruby repository (openSUSE_10.2) + * type=rpm-md + * baseurl=http://software.opensuse.org/download/ruby/openSUSE_10.2/ + * gpgcheck=1 + * gpgkey=http://software.opensuse.org/openSUSE-Build-Service.asc + * enabled=1 + * \endcode + * + * \note A Repository info is a hint about how + * to create a repository. + */ + class RepoInfo + { + friend std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ); + + public: + RepoInfo(); + ~RepoInfo(); + //RepoInfo( const Url & url, const Pathname & path, const std::string & alias = "", boost::tribool autorefresh = boost::indeterminate ); + + /** + * unique identifier for this source. If not specified + * It should be generated from the base url. + * + * Normally, in a .repo file the section name is used + * ( [somerepo] ) + */ + std::string alias() const; + + /** + * The base Url is the Url of the repository that generates + * the authoritative metadata this repository provides. + * + * For example for the url http://updates.novell.com/10.2 + * the base url is http://updates.novell.com/10.2. + * For the url http://host.com/mirror/update.novell.com/10.2 + * the base url is http://updates.novell.com/10.2 + * + * This can't be empty in order the repository to be valid + * unless the download of the mirror list succeeds and it + * contains a valid url. + */ + std::set urls() const; + + /** + * Url of a file which contains a list of Urls + * If empty, the base url will be used. + */ + Url mirrorListUrl() const; + + typedef std::set::const_iterator urls_const_iterator; + + /** + * iterator that points at begin of repository urls + */ + urls_const_iterator urlsBegin() const; + + /** + * iterator that points at end of repository urls + */ + urls_const_iterator urlsEnd() const; + + /** + * If enabled is false, then this repository must be ignored as if does + * not exists, except when checking for duplicate alias. + */ + boost::tribool enabled() const; + + /** + * If true, the repostory must be refreshed before creating resolvables + * from it + */ + boost::tribool autorefresh() const; + + /** + * Type of repository, + * + */ + repo::RepoType type() const; + + /** + * \short Repository short label + * + * Short label or description of the repository, to be used on + * the user interface. + * ie: "SUSE Linux 10.2 updates" + */ + std::string name() const; + + /** + * Add a base url. \see baseUrl + * \param url The base url for the repository. + */ + RepoInfo & addBaseUrl( const Url &url ); + + /** + * Set mirror list url. \see mirrorListUrl + * \param url The base url for the list + */ + RepoInfo & setMirrorListUrl( const Url &url ); + + /** + * enable or disable the repository \see enabled + * \param enabled + */ + RepoInfo & setEnabled( boost::tribool enabled ); + + /** + * enable or disable autorefresh \see autorefresh + * \param enabled + */ + RepoInfo & setAutorefresh( boost::tribool autorefresh ); + + /** + * set the repository alias \see alias + * \param alias + */ + RepoInfo & setAlias( const std::string &alias ); + + /** + * set the repository type \see type + * \param t + */ + RepoInfo & setType( const repo::RepoType &t ); + + /** + * set the repository name \see name + * \param name + */ + RepoInfo & setName( const std::string &name ); + + std::ostream & dumpOn( std::ostream & str ) const; + + class Impl; + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoInfo Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ); + + typedef std::list RepoInfoList; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp2 +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_REPOSITORYINFO_H diff --git a/zypp/RepoManager.cc b/zypp/RepoManager.cc new file mode 100644 index 0000000..b3b1a79 --- /dev/null +++ b/zypp/RepoManager.cc @@ -0,0 +1,402 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManager.cc + * +*/ + +#include +#include +#include +#include "zypp/base/InputStream.h" +#include "zypp/base/Logger.h" +#include "zypp/base/Function.h" +#include "zypp/PathInfo.h" +#include "zypp/TmpPath.h" + +#include "zypp/repo/RepoException.h" +#include "zypp/RepoManager.h" + +#include "zypp/cache/CacheStore.h" +#include "zypp/repo/cached/RepoImpl.h" +#include "zypp/MediaSetAccess.h" + +#include "zypp/parser/RepoFileReader.h" +#include "zypp/source/yum/YUMDownloader.h" +#include "zypp/parser/yum/RepoParser.h" + +#include "zypp/source/susetags/SUSETagsDownloader.h" +#include "zypp/parser/susetags/RepoParser.h" + +using namespace std; +using namespace zypp; +using namespace zypp::repo; +using namespace zypp::filesystem; + +using zypp::source::yum::YUMDownloader; +using zypp::source::susetags::SUSETagsDownloader; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoManagerOptions + // + /////////////////////////////////////////////////////////////////// + + RepoManagerOptions::RepoManagerOptions() + { + ZConfig globalConfig; + repoCachePath = globalConfig.defaultRepoCachePath(); + repoRawCachePath = globalConfig.defaultRepoRawCachePath(); + knownReposPath = globalConfig.defaultKnownReposPath(); + } + + /** + * \short Simple callback to collect the results + */ + struct RepoCollector + { + RepoCollector() + { + MIL << endl; + } + + ~RepoCollector() + { + MIL << endl; + } + + bool collect( const RepoInfo &repo ) + { + //MIL << "here in collector: " << repo.alias() << endl; + repos.push_back(repo); + //MIL << "added: " << repo.alias() << endl; + return true; + } + + RepoInfoList repos; + }; + + //////////////////////////////////////////////////////////////////////////// + + /** + * \short List of RepoInfo's from a directory + * + * Goes trough every file in a directory and adds all + * RepoInfo's contained in that file. + * + * \param file pathname of the file to read. + */ + static std::list repositories_in_path( const Pathname &dir ) + { + MIL << " " << dir << endl; + RepoCollector collector; + std::list repos; + list entries; + if ( filesystem::readdir( entries, Pathname(dir), false ) != 0 ) + ZYPP_THROW(Exception("failed to read directory")); + + for ( list::const_iterator it = entries.begin(); it != entries.end(); ++it ) + { + Pathname file = *it; + parser::RepoFileReader parser( file, bind( &RepoCollector::collect, &collector, _1 ) ); + + //std::copy( collector.repos.begin(), collector.repos.end(), std::back_inserter(repos)); + //MIL << "ok" << endl; + } + return collector.repos; + } + + //////////////////////////////////////////////////////////////////////////// + + static void assert_alias( const RepoInfo &info ) + { + if (info.alias().empty()) + ZYPP_THROW(RepoNoAliasException()); + } + + //////////////////////////////////////////////////////////////////////////// + + static void assert_urls( const RepoInfo &info ) + { + if (info.urls().empty()) + ZYPP_THROW(RepoNoUrlException()); + } + + //////////////////////////////////////////////////////////////////////////// + + /** + * \short Calculates the raw cache path for a repository + */ + static Pathname rawcache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info ) + { + assert_alias(info); + return opt.repoRawCachePath + info.alias(); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoManager::Impl + // + /////////////////////////////////////////////////////////////////// + + /** + * \short RepoManager implementation. + */ + struct RepoManager::Impl + { + Impl( const RepoManagerOptions &opt ) + : options(opt) + { + + } + + Impl() + { + + } + + RepoManagerOptions options; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoManager::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RepoManager::Impl & obj ) + { + return str << "RepoManager::Impl"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoManager + // + /////////////////////////////////////////////////////////////////// + + RepoManager::RepoManager( const RepoManagerOptions &opt ) + : _pimpl( new Impl(opt) ) + {} + + //////////////////////////////////////////////////////////////////////////// + + RepoManager::~RepoManager() + {} + + //////////////////////////////////////////////////////////////////////////// + + std::list RepoManager::knownRepositories() const + { + MIL << endl; + return repositories_in_path("/etc/zypp/repos.d"); + MIL << endl; + } + + //////////////////////////////////////////////////////////////////////////// + + void RepoManager::refreshMetadata( const RepoInfo &info ) + { + assert_alias(info); + assert_urls(info); + + // try urls one by one + for ( RepoInfo::urls_const_iterator it = info.urlsBegin(); it != info.urlsEnd(); ++it ) + { + Url url(*it); + filesystem::TmpDir tmpdir; + + repo::RepoType repokind = info.type(); + + // if the type is unknown, try probing. + switch ( repokind.toEnum() ) + { + case RepoType::NONE_e: + // unknown, probe it + repokind = probe(*it); + break; + default: + break; + } + + switch ( repokind.toEnum() ) + { + case RepoType::RPMMD_e : + { + YUMDownloader downloader( url, "/" ); + downloader.download(tmpdir.path()); + // no error + } + break; + case RepoType::YAST2_e : + { + SUSETagsDownloader downloader( url, "/" ); + downloader.download(tmpdir.path()); + // no error + } + break; + default: + ZYPP_THROW(RepoUnknownTypeException()); + } + + // ok we have the metadata, now exchange + // the contents + Pathname rawpath = rawcache_path_for_repoinfo(_pimpl->options, info); + TmpDir oldmetadata; + filesystem::assert_dir(rawpath); + filesystem::rename( rawpath, oldmetadata.path() ); + // move the just downloaded there + filesystem::rename( tmpdir.path(), rawpath ); + + // we are done. + } + } + + //////////////////////////////////////////////////////////////////////////// + + void RepoManager::cleanMetadata( const RepoInfo &info ) + { + filesystem::recursive_rmdir(rawcache_path_for_repoinfo(_pimpl->options, info)); + } + + //////////////////////////////////////////////////////////////////////////// + + void RepoManager::buildCache( const RepoInfo &info ) + { + assert_alias(info); + Pathname rawpath = rawcache_path_for_repoinfo(_pimpl->options, info); + + cache::CacheStore store(_pimpl->options.repoCachePath); + + if ( store.isCached( info.alias() ) ) + { + MIL << info.alias() << " is already cached, cleaning..." << endl; + data::RecordId id = store.lookupRepository(info.alias()); + store.cleanRepository(id); + } + + data::RecordId id = store.lookupOrAppendRepository(info.alias()); + + // do we have type? + repo::RepoType repokind = info.type(); + + // if the type is unknown, try probing. + switch ( repokind.toEnum() ) + { + case RepoType::NONE_e: + // unknown, probe the local metadata + repokind = probe(Url(rawpath.asString())); + break; + default: + break; + } + + switch ( repokind.toEnum() ) + { + case RepoType::RPMMD_e : + { + parser::yum::RepoParser parser(id, store); + parser.parse(rawpath); + // no error + } + break; + case RepoType::YAST2_e : + { + parser::susetags::RepoParser parser(id, store); + parser.parse(rawpath); + // no error + } + break; + default: + ZYPP_THROW(RepoUnknownTypeException()); + } + + MIL << "Commit cache.." << endl; + store.commit(); + } + + //////////////////////////////////////////////////////////////////////////// + + repo::RepoType RepoManager::probe( const Url &url ) + { + MediaSetAccess access(url); + if ( access.doesFileExist("/repodata/repomd.xml") ) + return repo::RepoType::RPMMD; + if ( access.doesFileExist("/content") ) + return repo::RepoType::YAST2; + + return repo::RepoType("UNKNOWN"); + } + + //////////////////////////////////////////////////////////////////////////// + + void RepoManager::cleanCache( const RepoInfo &info ) + { + cache::CacheStore store(_pimpl->options.repoCachePath); + + data::RecordId id = store.lookupRepository(info.alias()); + store.cleanRepository(id); + store.commit(); + } + + //////////////////////////////////////////////////////////////////////////// + + bool RepoManager::isCached( const RepoInfo &info ) const + { + cache::CacheStore store(_pimpl->options.repoCachePath); + return store.isCached(info.alias()); + } + + Repository RepoManager::createFromCache( const RepoInfo &info ) + { + cache::CacheStore store(_pimpl->options.repoCachePath); + + if ( ! store.isCached( info.alias() ) ) + ZYPP_THROW(RepoNotCachedException()); + + MIL << "Repository " << info.alias() << " is cached" << endl; + + data::RecordId id = store.lookupRepository(info.alias()); + repo::cached::RepoImpl::Ptr repoimpl = + new repo::cached::RepoImpl( info, _pimpl->options.repoCachePath, id ); + // read the resolvables from cache + repoimpl->createResolvables(); + return Repository(repoimpl); + } + + //////////////////////////////////////////////////////////////////////////// + + void RepoManager::addRepository( const RepoInfo &info ) + { + + } + + //////////////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const RepoManager & obj ) + { + return str << *obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/RepoManager.h b/zypp/RepoManager.h new file mode 100644 index 0000000..fb00242 --- /dev/null +++ b/zypp/RepoManager.h @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManager.h + * +*/ +#ifndef ZYPP_REPOMANAGER_H +#define ZYPP_REPOMANAGER_H + +#include +#include + +#include "zypp/base/PtrTypes.h" +//#include "zypp/base/ReferenceCounted.h" +//#include "zypp/base/NonCopyable.h" +#include "zypp/Pathname.h" +#include "zypp/ZConfig.h" +#include "zypp/Repository.h" +#include "zypp/RepoInfo.h" +#include "zypp/repo/RepoException.h" +#include "zypp/repo/RepoType.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** + * Repo manager settings. + * Settings default to ZYpp global settings. + */ + struct RepoManagerOptions + { + RepoManagerOptions(); + + Pathname repoCachePath; + Pathname repoRawCachePath; + Pathname knownReposPath; + }; + + /** + * \short creates and provides information about known sources. + * + */ + class RepoManager + { + friend std::ostream & operator<<( std::ostream & str, const RepoManager & obj ); + + public: + /** Implementation */ + class Impl; + + public: + RepoManager( const RepoManagerOptions &options = RepoManagerOptions() ); + /** Dtor */ + ~RepoManager(); + + /** + * \short List known repositories. + * + * The known repositories are read from + * \ref RepoManagerOptions::knownReposPath passed on the Ctor. + * Which defaults to ZYpp global settings. + * + */ + std::list knownRepositories() const; + + /** + * \short Refresh local cache + * + * Will try to download the metadata + * + * In case of falure the metadata remains + * as it was before. + * + * \throws RepoNoUrlException if no urls are available. + * \throws RepoNoAliasException if can't figure an alias + * \throws RepoUnknownTypeException if the metadata is unknown + * \throws Exception on unknown error. + */ + void refreshMetadata( const RepoInfo &info ); + + /** + * \short Clean local metadata + * + * Empty local metadata. + * + * \throws RepoNoAlias if can't figure an alias + * \throws Exception on unknown error. + */ + void cleanMetadata( const RepoInfo &info ); + + /** + * \short Refresh local cache + * + * Will try to build the cache from + * local metadata. + * + * If the cache exists it will be overwriten. + * + * \note the local metadata must be valid. + * + * \throws RepoNoAlias if can't figure an alias to look in cache + * \throws Exception on unknown error. + */ + void buildCache( const RepoInfo &info ); + + /** + * \short clean local cache + * + * Clean the cached version of the metadata + * + * \note the local metadata must be valid. + * + * \throws RepoNoAlias if can't figure an alias to look in cache + * \throws Exception on unknown error. + */ + void cleanCache( const RepoInfo &info ); + + /** + * \short Wether a repository exists in cache + * + * \param RepoInfo to be checked. + */ + bool isCached( const RepoInfo &info ) const; + + /** + * \short Create a repository object from the cache data + * + * \throw RepoNotCachedException When the source is not cached. + */ + Repository createFromCache( const RepoInfo &info ); + + /** + * \short Probe repo metadata type. + * + * \todo FIXME Should this be private? + */ + repo::RepoType probe( const Url &url ); + + + /** + * \short Adds a repository to the list of known repositories. + * + * + * + * \throws RepoAlreadyExistsException If the repo clash some + * unique attribute like alias + */ + void addRepository( const RepoInfo &info ); + + /** + * Adds a .repo file directly, which can contain + * one or more repositories. + */ + //void addRepositories( const Url &url ); + + + public: + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoManager Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoManager & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_REPOMANAGER_H diff --git a/zypp/RepoStatus.cc b/zypp/RepoStatus.cc new file mode 100644 index 0000000..3d54d6d --- /dev/null +++ b/zypp/RepoStatus.cc @@ -0,0 +1,110 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoStatus.cc + * +*/ +#include +//#include "zypp/base/Logger.h" +#include "zypp/RepoStatus.h" + + +using namespace std; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoStatus::Impl + // + /** RepoStatus implementation. */ + struct RepoStatus::Impl + { + + public: + + string checksum; + Date timestamp; + + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoStatus::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RepoStatus::Impl & obj ) + { + return str << "RepoStatus::Impl"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoStatus + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoStatus::RepoStatus + // METHOD TYPE : Ctor + // + RepoStatus::RepoStatus() + : _pimpl( Impl::nullimpl() ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoStatus::~RepoStatus + // METHOD TYPE : Dtor + // + RepoStatus::~RepoStatus() + {} + + RepoStatus & RepoStatus::setChecksum( const string &checksum ) + { + _pimpl->checksum = checksum; + return *this; + } + + RepoStatus & RepoStatus::setTimestamp( const Date ×tamp ) + { + _pimpl->timestamp = timestamp; + return *this; + } + + string RepoStatus::checksum() const + { return _pimpl->checksum; } + + Date RepoStatus::timestamp() const + { return _pimpl->timestamp; } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const RepoStatus & obj ) + { + return str << *obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/RepoStatus.h b/zypp/RepoStatus.h new file mode 100644 index 0000000..a4faffe --- /dev/null +++ b/zypp/RepoStatus.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoStatus.h + * +*/ +#ifndef ZYPP2_REPOSTATUS_H +#define ZYPP2_REPOSTATUS_H + +#include +#include "zypp/base/PtrTypes.h" +#include "zypp/CheckSum.h" +#include "zypp/Date.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoStatus + // + /** + * \short Local facts about a repository + * This class represents the status of a + * repository on the system. + * + * Anything that is not provided on the metadata + * files, like the timestamp of the downloaded + * metadata, and its checksum. + */ + class RepoStatus + { + friend std::ostream & operator<<( std::ostream & str, const RepoStatus & obj ); + + public: + + /** + * Checksum of the repository. + * Usually the checksum of the index, but any + * checksum that changes when the repository changes + * in any way is sufficient. + */ + std::string checksum() const; + + /** + * timestamp of the repository. If the repository + * changes, it has to be updated as well with the + * new timestamp. + */ + Date timestamp() const; + + /** + * set the repository checksum \see checksum + * \param checksum + */ + RepoStatus & setChecksum( const std::string &checksum ); + + /** + * set the repository timestamp \see timestamp + * \param timestamp + */ + RepoStatus & setTimestamp( const Date ×tamp ); + + /** Implementation */ + class Impl; + + public: + /** Default ctor */ + RepoStatus(); + /** Dtor */ + ~RepoStatus(); + + public: + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoStatus Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoStatus & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_REPOSTATUS_H diff --git a/zypp/Repository.cc b/zypp/Repository.cc new file mode 100644 index 0000000..2a61085 --- /dev/null +++ b/zypp/Repository.cc @@ -0,0 +1,50 @@ +#include +#include + +#include "zypp/Repository.h" +#include "zypp/repo/RepositoryImpl.h" + +using namespace std; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const Repository Repository::noRepository; + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Repository::Repository + // METHOD TYPE : Ctor + // + Repository::Repository() + : _pimpl( Impl::nullimpl() ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Repository::Repository + // METHOD TYPE : Ctor + // + Repository::Repository( const Impl_Ptr & impl_r ) + : _pimpl( impl_r ) + { + assert( impl_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // Forward to RepositoryImpl: + // + /////////////////////////////////////////////////////////////////// + + Repository::NumericId Repository::numericId() const + { return _pimpl->numericId(); } + + const ResStore & Repository::resolvables() + { + return _pimpl->resolvables(); + } + +} + diff --git a/zypp/Repository.h b/zypp/Repository.h new file mode 100644 index 0000000..c9b1a13 --- /dev/null +++ b/zypp/Repository.h @@ -0,0 +1,81 @@ + +#ifndef ZYPP_REPOSITORY_H +#define ZYPP_REPOSITORY_H + +#include +#include + +#include "zypp/base/PtrTypes.h" +#include "zypp/base/SafeBool.h" +#include "zypp/ResStore.h" + +namespace zypp +{ + namespace repo + { + DEFINE_PTR_TYPE(RepositoryImpl); + class RepositoryImpl; + } + + class Repository : protected base::SafeBool /* private, but gcc refuses */ + { + public: + friend std::ostream & operator<<( std::ostream & str, const Repository & obj ); + friend bool operator==( const Repository & lhs, const Repository & rhs ); + friend bool operator<( const Repository & lhs, const Repository & rhs ); + + public: + typedef repo::RepositoryImpl Impl; + typedef repo::RepositoryImpl_Ptr Impl_Ptr; + + public: + + /** Default ctor: noRepository. + * Real Repositorys are to be created via RepositoryFactory. + */ + Repository(); + + /** A dummy Repository (Id \c 0) providing nothing, doing nothing. + * \todo provide a _constRef + */ + static const Repository noRepository; + + /** Validate Repository in a boolean context. + * \c FALSE iff == noRepository. + */ + using base::SafeBool::operator bool_type; + + public: + typedef unsigned long NumericId; + + /** Runtime unique numeric Repository Id. */ + NumericId numericId() const; + + const ResStore & resolvables(); + + private: + friend base::SafeBool::operator bool_type() const; + /** \ref SafeBool test. */ + bool boolTest() const + { return _pimpl != noRepository._pimpl; } + + private: + /** Factory */ + friend class RepoManager; + friend class repo::RepositoryImpl; + + private: + /** Factory ctor */ + explicit + Repository( const Impl_Ptr & impl_r ); + + private: + /** Pointer to implementation */ + Impl_Ptr _pimpl; + }; + +} + +#endif + + diff --git a/zypp/RepositoryFactory.cc b/zypp/RepositoryFactory.cc new file mode 100644 index 0000000..44518cd --- /dev/null +++ b/zypp/RepositoryFactory.cc @@ -0,0 +1,23 @@ + +#include "zypp/RepositoryFactory.h" + +namespace zypp { + +RepositoryFactory::RepositoryFactory() +{ +} + +RepositoryFactory::~RepositoryFactory() +{ + +} + + +Repository RepositoryFactory::createFrom( const RepoInfo & context ) +{ + +} + +} // ns zypp + + diff --git a/zypp/RepositoryFactory.h b/zypp/RepositoryFactory.h new file mode 100644 index 0000000..b5338e3 --- /dev/null +++ b/zypp/RepositoryFactory.h @@ -0,0 +1,30 @@ + +#ifndef ZYPP_REPOSITORY_FACTORY_H +#define ZYPP_REPOSITORY_FACTORY_H + +#include "zypp/Repository.h" +#include "zypp/RepoInfo.h" + +namespace zypp +{ + class RepositoryFactory + { + friend std::ostream & operator<<( std::ostream & str, const RepositoryFactory & obj ); + + public: + /** Default ctor */ + RepositoryFactory(); + /** Dtor */ + ~RepositoryFactory(); + + public: + /** Construct source. + * \throw EXCEPTION on fail + */ + Repository createFrom( const RepoInfo & context ); + }; +} + +#endif + + diff --git a/zypp/dummy.cc b/zypp/dummy.cc new file mode 100644 index 0000000..e69de29 diff --git a/zypp/parser/RepoFileReader.cc b/zypp/parser/RepoFileReader.cc new file mode 100644 index 0000000..3a59ec4 --- /dev/null +++ b/zypp/parser/RepoFileReader.cc @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoFileReader.cc + * +*/ +#include +#include "zypp/base/Logger.h" +#include "zypp/base/InputStream.h" +#include "zypp/base/UserRequestException.h" + +#include "zypp/parser/IniDict.h" +#include "zypp/parser/RepoFileReader.h" + +using std::endl; +using zypp::parser::IniDict; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + /** + * \short List of RepoInfo's from a file. + * \param file pathname of the file to read. + */ + static void repositories_in_file( const Pathname &file, + const RepoFileReader::ProcessRepo &callback, + const ProgressData::ReceiverFnc &progress ) + { + InputStream is(file); + parser::IniDict dict(is); + for ( parser::IniDict::section_const_iterator its = dict.sectionsBegin(); + its != dict.sectionsEnd(); + ++its ) + { + MIL << (*its) << endl; + + RepoInfo info; + info.setAlias(*its); + + for ( IniDict::entry_const_iterator it = dict.entriesBegin(*its); + it != dict.entriesEnd(*its); + ++it ) + { + + //MIL << (*it).first << endl; + if (it->first == "name" ) + info.setName(it-> second); + else if ( it->first == "enabled" ) + info.setEnabled( it->second == "1" ); + else if ( it->first == "baseurl" ) + info.addBaseUrl( Url(it->second) ); + else if ( it->first == "type" ) + info.setType(repo::RepoType(it->second)); + } + + // add it to the list. + callback(info); + //if (!progress.tick()) + // ZYPP_THROW(AbortRequestException()); + } + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoFileReader + // + /////////////////////////////////////////////////////////////////// + + RepoFileReader::RepoFileReader( const Pathname & repo_file, + const ProcessRepo & callback, + const ProgressData::ReceiverFnc &progress ) + : _callback(callback) + { + repositories_in_file(repo_file, _callback, progress); + //MIL << "Done" << endl; + } + + RepoFileReader::~RepoFileReader() + {} + + std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj ) + { + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/RepoFileReader.h b/zypp/parser/RepoFileReader.h new file mode 100644 index 0000000..d7ab7a9 --- /dev/null +++ b/zypp/parser/RepoFileReader.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoFileReader.h + * +*/ +#ifndef ZYPP_REPO_REPOFILEREADER_H +#define ZYPP_REPO_REPOFILEREADER_H + +#include + +#include "zypp/base/PtrTypes.h" +#include "zypp/RepoInfo.h" +#include "zypp/ProgressData.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + /** + * \short Read repository data from a .repo file + * + * After each repo is read, a \ref RepoInfo is prepared and \ref _callback + * is called with the object passed in. + * + * The \ref _callback is provided on construction. + * + * \code + * RepoFileReader reader(repo_file, + * bind( &SomeClass::callbackfunc, &SomeClassInstance, _1, _2 ) ); + * \endcode + */ + class RepoFileReader + { + friend std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj ); + public: + + /** + * Callback definition. + * First parameter is a \ref RepoInfo object with the resource + * second parameter is the resource type. + * + * Return false from the callback to get a \ref AbortRequestException + * to be thrown and the processing to be cancelled. + */ + typedef function< bool( const RepoInfo & )> ProcessRepo; + + /** Implementation */ + class Impl; + + public: + /** + * \short Constructor. Creates the reader and start reading. + * + * \param repo_file A valid .repo file + * \param callback Callback that will be called for each repository. + * \param progress Optional progress function. \see ProgressData + * + * \throws AbortRequestException If the callback returns false + * \throws Exception If a error occurs at reading / parsing + * + */ + RepoFileReader( const Pathname & repo_file, + const ProcessRepo & callback, + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() ); + + /** + * Dtor + */ + ~RepoFileReader(); + private: + ProcessRepo _callback; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoFileReader Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_REPOFILEREADER_H diff --git a/zypp/parser/susetags/RepoParser.cc b/zypp/parser/susetags/RepoParser.cc new file mode 100644 index 0000000..fd9cb7d --- /dev/null +++ b/zypp/parser/susetags/RepoParser.cc @@ -0,0 +1,283 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/susetags/RepoParser.cc + * +*/ +#include +#include "zypp/base/Logger.h" +#include "zypp/base/Iterator.h" +#include "zypp/base/String.h" + +#include "zypp/parser/susetags/RepoParser.h" +#include "zypp/parser/susetags/ContentFileReader.h" +#include "zypp/parser/susetags/PackagesFileReader.h" +#include "zypp/parser/susetags/PackagesLangFileReader.h" +#include "zypp/parser/susetags/PatternFileReader.h" +#include "zypp/parser/susetags/RepoIndex.h" +#include "zypp/parser/ParseException.h" + +#include "zypp/ZConfig.h" + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace susetags + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoParser::Impl + // + /** RepoParser implementation. + * \todo Clean data on exeption. + */ + class RepoParser::Impl + { + public: + Impl( const data::RecordId & repositoryId_r, + data::ResolvableDataConsumer & consumer_r, + const ProgressData::ReceiverFnc & fnc_r ) + : _repositoryId( repositoryId_r ) + , _consumer( consumer_r ) + { + _ticks.sendTo( fnc_r ); + } + + /** Main entry to parser. */ + void parse( const Pathname & reporoot_r ); + + /** \name FileReader callbacks delivering data. */ + //@{ + void consumeIndex( const RepoIndex_Ptr & data_r ) + { + SEC << "[Index]" << data_r << endl; + _repoIndex = data_r; + } + + void consumeProd( const data::Product_Ptr & data_r ) + { + SEC << "[Prod]" << data_r << endl; + _prodData = data_r; + _consumer.consumeProduct( _repositoryId, data_r ); + } + + void consumePkg( const data::Package_Ptr & data_r ) + { + SEC << "[Package]" << data_r << endl; + _consumer.consumePackage( _repositoryId, data_r ); + } + + void consumeSrcPkg( const data::SrcPackage_Ptr & data_r ) + { + SEC << "[SrcPackage]" << data_r << endl; + _consumer.consumeSourcePackage( _repositoryId, data_r ); + } + + void consumePat( const data::Pattern_Ptr & data_r ) + { + SEC << "[Pattern]" << data_r << endl; + _consumer.consumePattern( _repositoryId, data_r ); + } + //@} + + public: + + bool isPatternFile( const std::string & name_r ) const + { + return( name_r.size() > 4 && name_r.substr( name_r.size() - 4 ) == ".pat" ); + } + + /** Test for \c packages.lang in \ref _repoIndex.*/ + bool haveLocale( const Locale & locale_r ) const + { + std::string searchFor( "packages." + locale_r.code() ); + for ( RepoIndex::FileChecksumMap::const_iterator it = _repoIndex->metaFileChecksums.begin(); + it != _repoIndex->metaFileChecksums.end(); ++it ) + { + if ( it->first == searchFor ) + return true; // got it + } + return false; // not found + } + + /** Take care translations for \a locale_r or an appropriate + * fallback were parsed. + */ + void parseLocaleIf( const Locale & locale_r ) + { + Locale toParse( locale_r ); + bool alreadyParsed = false; + + while ( toParse != Locale::noCode ) + { + alreadyParsed = ( _parsedLocales.find( toParse ) != _parsedLocales.end() ); + if ( alreadyParsed || haveLocale( toParse ) ) + break; // no return because we want to log in case of a fallback + toParse = toParse.fallback(); + } + + if ( toParse != locale_r ) + { + WAR << "Using fallback locale " << toParse << " for " << locale_r << endl; + } + + if ( alreadyParsed ) + { + return; // now return... + } + + // ...or parse + _parsedLocales.insert( toParse ); // don't try again. + + PackagesLangFileReader reader; + reader.setLocale( toParse ); + reader.setPkgConsumer( bind( &Impl::consumePkg, this, _1 ) ); + reader.setSrcPkgConsumer( bind( &Impl::consumeSrcPkg, this, _1 ) ); + reader.parse( _descrdir / ("packages." + toParse.code()) ); + + if ( ! _ticks.incr() ) + ZYPP_THROW( AbortRequestException() ); + } + + private: + data::RecordId _repositoryId; + data::ResolvableDataConsumer & _consumer; + ProgressData _ticks; + + private: // these (and _ticks) are actually scoped per parse() run. + RepoIndex_Ptr _repoIndex; + data::Product_Ptr _prodData; + Pathname _descrdir; // full path + Pathname _datadir; // full path + + /** Translations processed by \ref parseLocaleIf so far.*/ + std::set _parsedLocales; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoParser::Impl::parse + // METHOD TYPE : void + // + void RepoParser::Impl::parse( const Pathname & reporoot_r ) + { + _prodData = 0; + _repoIndex = 0; + _descrdir = _datadir = Pathname(); + _parsedLocales.clear(); + + // Content file first to get the repoindex + { + ContentFileReader content; + content.setProductConsumer( bind( &Impl::consumeProd, this, _1 ) ); + content.setRepoIndexConsumer( bind( &Impl::consumeIndex, this, _1 ) ); + content.parse( reporoot_r / "content" ); + } + if ( ! _repoIndex ) + { + ZYPP_THROW( ParseException( reporoot_r.asString() + ": " + "No reository index in content file." ) ); + } + DBG << _repoIndex << endl; + + // Prepare parsing + _descrdir = reporoot_r / _repoIndex->descrdir; + _datadir = reporoot_r / _repoIndex->datadir; + + _ticks.name( "Parsing susetags repo at " + reporoot_r.asString() ); + _ticks.range( _repoIndex->metaFileChecksums.size() ); + if ( ! _ticks.toMin() ) + ZYPP_THROW( AbortRequestException() ); + + // Start with packages + { + PackagesFileReader reader; + reader.setPkgConsumer( bind( &Impl::consumePkg, this, _1 ) ); + reader.setSrcPkgConsumer( bind( &Impl::consumeSrcPkg, this, _1 ) ); + reader.parse( _descrdir / "packages" ); + } + if ( ! _ticks.incr() ) + ZYPP_THROW( AbortRequestException() ); + + // Now process packages.lang + // Always parse 'en'. For each wanted locale at least + // some fallback, if locale is not present. + parseLocaleIf( Locale("en") ); + parseLocaleIf( Locale("de_DE") ); + parseLocaleIf( ZConfig().defaultTextLocale() ); + + // Now process the rest of RepoIndex + for ( RepoIndex::FileChecksumMap::const_iterator it = _repoIndex->metaFileChecksums.begin(); + it != _repoIndex->metaFileChecksums.end(); ++it ) + { + if ( isPatternFile( it->first ) ) + { + PatternFileReader reader; + reader.setConsumer( bind( &Impl::consumePat, this, _1 ) ); + reader.parse( _descrdir / it->first ); + } + + if ( ! _ticks.incr() ) + ZYPP_THROW( AbortRequestException() ); + } + + // Done + if ( ! _ticks.toMax() ) + ZYPP_THROW( AbortRequestException() ); + } + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoParser + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoParser::RepoParser + // METHOD TYPE : Ctor + // + RepoParser::RepoParser( const data::RecordId & repositoryId_r, + data::ResolvableDataConsumer & consumer_r, + const ProgressData::ReceiverFnc & fnc_r ) + : _pimpl( new Impl( repositoryId_r, consumer_r, fnc_r ) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoParser::~RepoParser + // METHOD TYPE : Dtor + // + RepoParser::~RepoParser() + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : RepoParser::parse + // METHOD TYPE : void + // + void RepoParser::parse( const Pathname & reporoot_r ) + { + _pimpl->parse( reporoot_r ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace susetags + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/susetags/RepoParser.h b/zypp/parser/susetags/RepoParser.h new file mode 100644 index 0000000..39ec351 --- /dev/null +++ b/zypp/parser/susetags/RepoParser.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/susetags/RepoParser.h + * +*/ +#ifndef ZYPP2_PARSER_SUSETAGS_REPOPARSER_H +#define ZYPP2_PARSER_SUSETAGS_REPOPARSER_H + +#include + +#include "zypp/base/PtrTypes.h" +#include "zypp/base/NonCopyable.h" + +#include "zypp/data/RecordId.h" +#include "zypp/data/ResolvableDataConsumer.h" + +#include "zypp/ProgressData.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace susetags + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoParser + // + /** SuseTags metadata parser. + * + * Reads a \c content file to get the \ref data::Product and a \Ref RepoIndex. + * Then parses the remaining files and feeds them to a \ref data::ResolvableDataConsumer + * (typically to store them in a database). + * + * \see \ref ContentFileReader and \ref FileReaderBase + * + * \code + * Pathname dbdir( "store" ); + * Pathname reporoot( "lmd" ); + * + * cache::CacheStore store( dbdir ); + * data::RecordId catalogId = store.lookupOrAppendRepository( Url("dir:///somewhere"), "/" ); + * + * parser::susetags::RepoParser repo( catalogId, store ); + * repo.parse( reporoot ); + * + * store.commit(); + * \endcode + * + * \todo Improve selection of Languages to parse + * \todo Improve feeding of translations into Cachestore. Add specialized consumer, for Du too. + * \todo DiskUsage filereader and parsing + * \todo more doc and Exception specification + */ + class RepoParser : private base::NonCopyable + { + public: + /** Ctor. + * + * \param repositoryId_r repository identifier + * \param consumer_r consumer of parsed data + * \param fnc_r progress reporting function + */ + RepoParser( const data::RecordId & repositoryId_r, + data::ResolvableDataConsumer & consumer_r, + const ProgressData::ReceiverFnc & fnc_r = ProgressData::ReceiverFnc() ); + /** Dtor */ + ~RepoParser(); + + /** Parse a local repository located at \a reporoot_r. + * + * \param reporoot_r The local repositories root directory. + * \throw Exception on errors. + */ + void parse( const Pathname & reporoot_r ); + + public: + class Impl; + private: + RW_pointer > _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace susetags + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_PARSER_SUSETAGS_REPOPARSER_H -- 2.7.4