From: Josef Reidinger Date: Thu, 19 Jun 2008 13:50:48 +0000 (+0000) Subject: initial Service implementation. Also little refactor of RepoManager. X-Git-Tag: BASE-SuSE-Code-11-Branch~684 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8f7d94eea1ef91c9aacd10563c762e60040b18cc;p=platform%2Fupstream%2Flibzypp.git initial Service implementation. Also little refactor of RepoManager. --- diff --git a/zypp.conf b/zypp.conf index 8c09b0f..4f6b3bf 100644 --- a/zypp.conf +++ b/zypp.conf @@ -76,6 +76,16 @@ ## # reposdir = /etc/zypp/repos.d +## +## Path where the known services .service files are kept +## +## Valid values: A directory +## Default value: {configdir}/services.d +## +## Changing this invalidates all known services +## +# reposdir = /etc/zypp/service.d + ## ## Whether repository urls should be probed when added diff --git a/zypp/CMakeLists.txt b/zypp/CMakeLists.txt index a151df9..fbdd2d5 100644 --- a/zypp/CMakeLists.txt +++ b/zypp/CMakeLists.txt @@ -64,6 +64,7 @@ SET( zypp_SRCS ResPoolProxy.cc ResStatus.cc Script.cc + Service.cc Signature.cc SrcPackage.cc SysContent.cc @@ -162,6 +163,7 @@ SET( zypp_HEADERS ResStatus.h ResTraits.h Script.h + Service.h Signature.h SrcPackage.h SysContent.h @@ -338,7 +340,9 @@ SET( zypp_parser_SRCS parser/LibXMLHelper.cc parser/XMLNodeIterator.cc parser/RepoFileReader.cc + parser/RepoindexFileReader.cc parser/ProductConfReader.cc + parser/ServiceFileReader.cc parser/xml_escape_parser.cpp ) @@ -354,6 +358,8 @@ SET( zypp_parser_HEADERS parser/RepoFileReader.h parser/ProductConfReader.h parser/xml_escape_parser.hpp + parser/RepoindexFileReader.h + parser/ServiceFileReader.h ) INSTALL( FILES diff --git a/zypp/RepoManager.cc b/zypp/RepoManager.cc index 557d452..77ede0a 100644 --- a/zypp/RepoManager.cc +++ b/zypp/RepoManager.cc @@ -24,6 +24,7 @@ #include "zypp/base/Regex.h" #include "zypp/PathInfo.h" #include "zypp/TmpPath.h" +#include "zypp/Service.h" #include "zypp/repo/RepoException.h" #include "zypp/RepoManager.h" @@ -34,6 +35,7 @@ #include "zypp/ManagedFile.h" #include "zypp/parser/RepoFileReader.h" +#include "zypp/parser/ServiceFileReader.h" #include "zypp/repo/yum/Downloader.h" #include "zypp/parser/yum/RepoParser.h" #include "zypp/repo/susetags/Downloader.h" @@ -71,6 +73,7 @@ namespace zypp repoSolvCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoSolvfilesPath() ); repoPackagesCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoPackagesPath() ); knownReposPath = Pathname::assertprefix( root_r, ZConfig::instance().knownReposPath() ); + knownServicesPath = Pathname::assertprefix( root_r, ZConfig::instance().knownServicesPath() ); probe = ZConfig::instance().repo_add_probe(); } @@ -82,6 +85,7 @@ namespace zypp ret.repoSolvCachePath = root_r/"solv"; ret.repoPackagesCachePath = root_r/"packages"; ret.knownReposPath = root_r/"repos.d"; + ret.knownServicesPath = root_r/"services.d"; return ret; } @@ -246,6 +250,8 @@ namespace zypp RepoManagerOptions options; map _repoinfos; + + ServiceSet services; public: /** Offer default Impl. */ @@ -255,6 +261,23 @@ namespace zypp return _nullimpl; } + void saveService( const Service& service ); + + Pathname generateNonExistingName( const Pathname &dir, + const std::string &basefilename ) const; + + std::string generateFilename( const RepoInfo &info ) const; + std::string generateFilename( const Service &info ) const; + + struct ServiceCollector { + ServiceCollector(ServiceSet& services_) : services(services_) {} + bool collect(Service service) { services.insert(service); return true; } + private: + ServiceSet& services; + }; + + void knownServices(); + private: friend Impl * rwcowClone( const Impl * rhs ); /** clone for RWCOW_pointer */ @@ -976,8 +999,8 @@ namespace zypp * \param dir Directory where the file needs to be unique * \param basefilename string to base the filename on. */ - static Pathname generate_non_existing_name( const Pathname &dir, - const std::string &basefilename ) + Pathname RepoManager::Impl::generateNonExistingName( const Pathname &dir, + const std::string &basefilename ) const { string final_filename = basefilename; int counter = 1; @@ -998,23 +1021,27 @@ namespace zypp * escaping it if necessary. Other fallbacks can be added to * this function in case there is no way to use the alias */ - static std::string generate_filename( const RepoInfo &info ) + std::string RepoManager::Impl::generateFilename( const RepoInfo &info ) const { - std::string fnd="/"; - std::string rep="_"; std::string filename = info.alias(); // replace slashes with underscores - size_t pos = filename.find(fnd); - while(pos!=string::npos) - { - filename.replace(pos,fnd.length(),rep); - pos = filename.find(fnd,pos+rep.length()); - } + str::replaceAll( filename, "/", "_" ); + filename = Pathname(filename).extend(".repo").asString(); MIL << "generating filename for repo [" << info.alias() << "] : '" << filename << "'" << endl; return filename; } + std::string RepoManager::Impl::generateFilename( const Service &info ) const + { + std::string filename = info.name(); + // replace slashes with underscores + str::replaceAll( filename, "/", "_" ); + + filename = Pathname(filename).extend(".service").asString(); + MIL << "generating filename for service [" << info.name() << "] : '" << filename << "'" << endl; + return filename; + } //////////////////////////////////////////////////////////////////////////// @@ -1061,8 +1088,8 @@ namespace zypp // assert the directory exists filesystem::assert_dir(_pimpl->options.knownReposPath); - Pathname repofile = generate_non_existing_name(_pimpl->options.knownReposPath, - generate_filename(tosave)); + Pathname repofile = _pimpl->generateNonExistingName( + _pimpl->options.knownReposPath, _pimpl->generateFilename(tosave)); // now we have a filename that does not exists MIL << "Saving repo in " << repofile << endl; @@ -1106,7 +1133,7 @@ namespace zypp // assert the directory exists filesystem::assert_dir(_pimpl->options.knownReposPath); - Pathname repofile = generate_non_existing_name(_pimpl->options.knownReposPath, filename); + Pathname repofile = _pimpl->generateNonExistingName(_pimpl->options.knownReposPath, filename); // now we have a filename that does not exists MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << endl; @@ -1310,6 +1337,140 @@ namespace zypp ZYPP_THROW(RepoNotFoundException(info)); } + void RepoManager::addService( const std::string& name, const Url& url ) + { + Service service(name, url); + + //check if service isn't already exist + if( _pimpl->services.find(service)!= _pimpl->services.end() ) + return; //TODO throw exception + + _pimpl->services.insert( service ); + + _pimpl->saveService( service ); + } + + void RepoManager::removeService( const string& name) + { + MIL << "Going to delete repo " << name << endl; + + const Service& service = getService( name ); + + Pathname location = service.location(); + if( location.empty() ) + { + ZYPP_THROW(RepoException("Can't figure where the service is stored")); + } + + ServiceSet tmpSet; + Impl::ServiceCollector collector(tmpSet); + + parser::ServiceFileReader reader( location, + bind(&Impl::ServiceCollector::collect,collector,_1) ); + + if ( tmpSet.size() == 1 ) //only one record + { + if ( filesystem::unlink(location) != 0 ) + { + ZYPP_THROW(RepoException("Can't delete " + location.asString())); + } + MIL << name << " sucessfully deleted." << endl; + } + else + { + filesystem::assert_dir(location.dirname()); + + std::ofstream file(location.c_str()); + + for_(it, tmpSet.begin(), tmpSet.end()) + { + if( it->name() != name ) + it->dumpServiceOn(file); + } + } + + //now remove all repositories added by this service + for_( it, service.begin(), service.end() ) + removeRepository(getRepositoryInfo(*it)); + } + + + void RepoManager::Impl::saveService( const Service& service ) + { + filesystem::assert_dir( options.knownServicesPath ); + + Pathname servfile = generateNonExistingName( options.knownServicesPath, + generateFilename( service ) ); + + MIL << "saving service in " << servfile << endl; + + std::ofstream file(servfile.c_str()); + if (!file) { + ZYPP_THROW (Exception( "Can't open " + servfile.asString() ) ); + } + + service.dumpServiceOn( file ); + + service.setLocation( servfile ); + MIL << "done" << endl; + } + + const Service& RepoManager::getService( const std::string& name ) const + { + //little trick for Set, because it is sorted by Service name + Service tmpServ(name); + + ServiceConstIterator it = _pimpl->services.find(name); + if ( it == serviceEnd() ) + return Service::noService; + else + return *it; + } + + bool RepoManager::serviceEmpty() const { return _pimpl->services.empty(); } + + RepoManager::ServiceSizeType RepoManager::serviceSize() const + { + return _pimpl->services.size(); + } + + RepoManager::ServiceConstIterator RepoManager::serviceBegin() const + { + return _pimpl->services.begin(); + } + + RepoManager::ServiceConstIterator RepoManager::serviceEnd() const + { + return _pimpl->services.end(); + } + + void RepoManager::refreshServices() + { + //cannot user for_, because it uses const version + for (std::set::iterator it = _pimpl->services.begin(); + it != _pimpl->services.end(); ++it) + { + it->refresh(*this); + } + } + + void RepoManager::Impl::knownServices() + { + ServiceCollector collector(services); + Pathname dir = options.knownServicesPath; + list entries; + + if ( filesystem::readdir( entries, Pathname(dir), false ) != 0 ) + ZYPP_THROW(Exception("failed to read directory")); + + str::regex allowedServiceExt("^\\.service(_[0-9]+)?$"); + for_(it, entries.begin(), entries.end() ) + { + parser::ServiceFileReader reader(*it, + bind(&ServiceCollector::collect, collector, _1) ); + } + } + //////////////////////////////////////////////////////////////////////////// std::ostream & operator<<( std::ostream & str, const RepoManager & obj ) diff --git a/zypp/RepoManager.h b/zypp/RepoManager.h index d361a20..c91d2a2 100644 --- a/zypp/RepoManager.h +++ b/zypp/RepoManager.h @@ -27,6 +27,7 @@ /////////////////////////////////////////////////////////////////// namespace zypp { ///////////////////////////////////////////////////////////////// + class Service; //predef /** * Parses \a repo_file and returns a list of \ref RepoInfo objects @@ -76,6 +77,7 @@ namespace zypp Pathname repoSolvCachePath; Pathname repoPackagesCachePath; Pathname knownReposPath; + Pathname knownServicesPath; bool probe; }; @@ -93,6 +95,11 @@ namespace zypp /** Implementation */ class Impl; + /** service typedefs */ + typedef std::set ServiceSet; + typedef ServiceSet::const_iterator ServiceConstIterator; + typedef ServiceSet::size_type ServiceSizeType; + public: RepoManager( const RepoManagerOptions &options = RepoManagerOptions() ); /** Dtor */ @@ -423,6 +430,22 @@ namespace zypp const url::ViewOption & urlview = url::ViewOption::DEFAULTS, const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + void addService( const std::string& name, const Url& url ); + + void removeService( const std::string& name ); + + bool serviceEmpty() const; + + ServiceSizeType serviceSize() const; + + ServiceConstIterator serviceBegin() const; + + ServiceConstIterator serviceEnd() const; + + const Service& getService( const std::string& name ) const; + + void refreshServices(); + protected: RepoStatus rawMetadataStatus( const RepoInfo &info ); void setCacheStatus( const RepoInfo &info, const RepoStatus &status ); diff --git a/zypp/Service.cc b/zypp/Service.cc new file mode 100644 index 0000000..5292dec --- /dev/null +++ b/zypp/Service.cc @@ -0,0 +1,156 @@ +#include "zypp/Service.h" + +#include + +#include "zypp/Url.h" +#include "zypp/RepoInfo.h" +#include "zypp/media/MediaManager.h" +#include "zypp/parser/RepoindexFileReader.h" + +using namespace std; +/////////////////////////////////////////////////////////////////////////////// +namespace zypp +{////////////////////////////////////////////////////////////////////////////// + + struct RepoInfoCollector { + std::vector repos; + bool collect(const RepoInfo& info) + { + repos.push_back(info); + return true; + } + + }; + + class Service::Impl{ + public: + RepoContainer repos; + string name; + Url url; + Pathname loc; + Impl() : name("") {}; + Impl(const string& name_) : name(name_) {}; + Impl(const string& name_, const Url& url_) : name(name_), url(url_) {}; + }; + + Service::Service() : _pimpl( new Impl() ) {}; + + Service::Service(const string& name) : _pimpl( new Impl(name) ) {}; + Service::Service(const string& name, const Url& url) + : _pimpl( new Impl(name,url) ) {}; + + const Service Service::noService; + + string Service::name() const { return _pimpl->name; } + Url Service::url() const { return _pimpl->url; } + + void Service::setUrl( const Url& url ) { _pimpl->url = url; } + + bool Service::empty() const { return _pimpl->repos.empty(); } + Service::size_type Service::size() const { return _pimpl->repos.size(); } + Service::const_iterator Service::begin() const { return _pimpl->repos.begin(); } + Service::const_iterator Service::end() const { return _pimpl->repos.end(); } + + void Service::addRepo( const std::string& alias ) + { + _pimpl->repos.push_back(alias); + } + + void Service::dumpServiceOn( std::ostream& str ) const + { + str << endl; + str << "[" << name() << "]" << endl; + str << "url = " << url() << endl; + for_( it, begin(), end() ) + { + str << "alias = " << *it << endl; + } + str << endl; + } + + void Service::refresh( RepoManager& repomanager ) const + { + //download index file + media::MediaManager mediamanager; + media::MediaAccessId mid = mediamanager.open( url() ); + mediamanager.provideFile( mid, "repo/repoindex.xml" ); + Pathname path = mediamanager.localPath(mid, "repo/repoindex.xml" ); + + //parse it + RepoInfoCollector collector; + parser::RepoindexFileReader reader( path, + bind( &RepoInfoCollector::collect, &collector, _1 ) ); + + // set base url for all collected repositories + for_( it, collector.repos.begin(), collector.repos.end()) + { + it->setBaseUrl( url() ); + } + + //compare old and new repositories (hope not to much, if it change + // then construct set and use set operation on it) + + std::list krepos = repomanager.knownRepositories(); + + //find old to remove + for_( it, begin(), end() ) + { + bool found = false; + + for_( it2, collector.repos.begin(), collector.repos.end() ) + if ( *it == it2->alias() ) + { + found = true; + break; + } + + if( !found ) + repomanager.removeRepository( repomanager.getRepositoryInfo( *it ) ); + } + + //find new to add + for_( it, collector.repos.begin(), collector.repos.end() ) + { + bool found = false; + + for_( it2, begin(), end() ) + if( it->alias() == *it2 ) + { + found = true; + break; + } + + if (!found) + repomanager.addRepository( *it ); + } + + //update internal alias storage + _pimpl->repos.clear(); + for_( it, collector.repos.begin(), collector.repos.end() ) + { + _pimpl->repos.push_back(it->alias()); + } + + mediamanager.close( mid ); + } + + Pathname Service::location() const + { + return _pimpl->loc; + } + + void Service::setLocation( const Pathname& location ) const + { + _pimpl->loc = location; + } + + std::ostream & operator<<( std::ostream& str, const Service &obj ) + { + obj.dumpServiceOn(str); + return str; + } + + +/////////////////////////////////////////////////////////////////////////////// +} //namespace zypp +/////////////////////////////////////////////////////////////////////////////// diff --git a/zypp/Service.h b/zypp/Service.h new file mode 100644 index 0000000..ced5093 --- /dev/null +++ b/zypp/Service.h @@ -0,0 +1,132 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Service.h + * +*/ +#ifndef ZYPP_SERVICE_H +#define ZYPP_SERVICE_H + +#include +#include "zypp/Url.h" +#include "zypp/RepoManager.h" + + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Service + // + /** */ + class Service + { + public: + typedef std::vector RepoContainer; + typedef RepoContainer::const_iterator const_iterator; + typedef RepoContainer::size_type size_type; + + public: + /** Default ctor creates \ref noService.*/ + Service(); + + /** + * Service with this name. + */ + Service( const std::string& name ); + + /** + * Creates service with name and it's url. + * Used for adding new services. + * \note internal, do not used outside libzypp + */ + Service( const std::string& name, const Url& url ); + + public: + /** Represents no \ref Service. */ + static const Service noService; + + public: + std::string name() const; + + Url url() const; + + Pathname location() const; + + void setLocation( const Pathname& location ) const; + + void setUrl( const Url& url ); + + public: + + /** Whether \ref Service contains solvables. */ + bool empty() const; + + /** Number of solvables in \ref Service. */ + size_type size() const; + + /** Iterator to the first \ref Solvable. */ + const_iterator begin() const; + + /** Iterator behind the last \ref Solvable. */ + const_iterator end() const; + + public: + /** + * Refreshes local information about service. + * It can addi, remove or modify repositories. + * it is const due to use Service in set or map and name doesn't change + */ + void refresh( RepoManager& repomanager) const; + + /** + * Writes Service to stream in ".service" format + */ + void dumpServiceOn( std::ostream & str ) const; + + /** + * set repositories by alias. + * Used only during local loading, for update repository use refresh + */ + template + void setRepos(InputIterator begin, InputIterator end) + { + for_(it,begin,end) + addRepo(*it); + } + + void addRepo(const std::string& alias); + + class Impl; + + private: + mutable RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Service Stream output */ + std::ostream & operator<<( std::ostream & str, const Service & obj ); + + /** \relates Service */ + inline bool operator==( const Service & lhs, const Service & rhs ) + { return lhs.name() == rhs.name(); } + + /** \relates Service */ + inline bool operator!=( const Service & lhs, const Service & rhs ) + { return lhs.name() != rhs.name(); } + + /** \relates Service */ + inline bool operator<( const Service & lhs, const Service & rhs ) + { return lhs.name() < rhs.name(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_REPOSITORY_H diff --git a/zypp/ZConfig.cc b/zypp/ZConfig.cc index 52cec69..52ec469 100644 --- a/zypp/ZConfig.cc +++ b/zypp/ZConfig.cc @@ -310,6 +310,7 @@ namespace zypp Pathname cfg_config_path; Pathname cfg_known_repos_path; + Pathname cfg_known_services_path; Pathname cfg_vendor_path; Pathname cfg_products_path; Pathname locks_file; @@ -454,6 +455,13 @@ namespace zypp return ( _pimpl->cfg_known_repos_path.empty() ? (configPath()/"repos.d") : _pimpl->cfg_known_repos_path ); } + + Pathname ZConfig::knownServicesPath() const + { + return ( _pimpl->cfg_known_services_path.empty() + ? (configPath()/"services.d") : _pimpl->cfg_known_repos_path ); + } + Pathname ZConfig::vendorPath() const { return ( _pimpl->cfg_vendor_path.empty() diff --git a/zypp/ZConfig.h b/zypp/ZConfig.h index ad623e7..6a45494 100644 --- a/zypp/ZConfig.h +++ b/zypp/ZConfig.h @@ -129,6 +129,12 @@ namespace zypp Pathname knownReposPath() const; /** + * Path where the known services .service files are kept (configPath()/services.d). + * \ingroup g_ZC_CONFIGFILES + */ + Pathname knownServicesPath() const; + + /** * Separator string for storing/reading sets of strings to/from * metadata cache DB. */ diff --git a/zypp/parser/RepoindexFileReader.cc b/zypp/parser/RepoindexFileReader.cc new file mode 100644 index 0000000..538c8c2 --- /dev/null +++ b/zypp/parser/RepoindexFileReader.cc @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/yum/RepoindexFileReader.cc + * Implementation of repoindex.xml file reader. + */ +#include + +#include "zypp/base/String.h" +#include "zypp/base/Logger.h" + +#include "zypp/Pathname.h" +#include "zypp/parser/xml/Reader.h" + +#include "zypp/parser/RepoindexFileReader.h" + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "parser" + +using namespace std; +using namespace zypp::xml; + +namespace zypp +{ + namespace parser + { + + + /////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoindexFileReader::Impl + // + class RepoindexFileReader::Impl : private base::NonCopyable + { + public: + /** + * CTOR + * + * \see RepoindexFileReader::RepoindexFileReader(Pathname,ProcessResource) + */ + Impl(const Pathname &repoindex_file, const ProcessResource & callback); + + /** + * Callback provided to the XML parser. + */ + bool consumeNode( Reader & reader_r ); + + + private: + /** Function for processing collected data. Passed-in through constructor. */ + ProcessResource _callback; + }; + /////////////////////////////////////////////////////////////////////// + + RepoindexFileReader::Impl::Impl( + const Pathname &repoindex_file, const ProcessResource & callback) + : _callback(callback) + { + Reader reader( repoindex_file ); + MIL << "Reading " << repoindex_file << endl; + reader.foreachNode( bind( &RepoindexFileReader::Impl::consumeNode, this, _1 ) ); + } + + // -------------------------------------------------------------------------- + + /* + * xpath and multiplicity of processed nodes are included in the code + * for convenience: + * + * // xpath: (?|*|+) + * + * if multiplicity is ommited, then the node has multiplicity 'one'. + */ + + // -------------------------------------------------------------------------- + + bool RepoindexFileReader::Impl::consumeNode( Reader & reader_r ) + { + if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT ) + { + // xpath: /repoindex + if ( reader_r->name() == "repoindex" ) + { + return true; + } + + // xpath: /repoindex/data (+) + if ( reader_r->name() == "repo" ) + { + RepoInfo info; + info.setPath(Pathname(string("/repo/")+reader_r->getAttribute("path").asString())); + info.setAlias(reader_r->getAttribute("alias").asString()); + info.setType(repo::RepoType::RPMMD_e); //TODO hardwired rpmmd??? + XmlString s = reader_r->getAttribute("name"); + if (s.get()) //name setted so also set it + info.setName(s.asString()); + //ignore rest + _callback(info); + return true; + } + } + + return true; + } + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoindexFileReader + // + /////////////////////////////////////////////////////////////////// + + RepoindexFileReader::RepoindexFileReader( + const Pathname & repoindex_file, const ProcessResource & callback) + : + _pimpl(new Impl(repoindex_file, callback)) + {} + + RepoindexFileReader::~RepoindexFileReader() + {} + + + } // ns parser +} // ns zypp + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/parser/RepoindexFileReader.h b/zypp/parser/RepoindexFileReader.h new file mode 100644 index 0000000..fd18461 --- /dev/null +++ b/zypp/parser/RepoindexFileReader.h @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/yum/RepoindexFileReader.h + * Interface of repoindex.xml file reader. + */ +#ifndef zypp_source_yum_RepoindexFileReader_H +#define zypp_source_yum_RepoindexFileReader_H + +#include "zypp/base/PtrTypes.h" +#include "zypp/base/NonCopyable.h" +#include "zypp/base/Function.h" + +#include "zypp/RepoInfo.h" + +namespace zypp +{ + namespace parser + { + + /** + * Reads through a repoindex.xml file and collects repositories. + * + * After each repository is read, a \ref RepoInfo + * is prepared and \ref _callback + * is called with these two objects passed in. + * + * The \ref _callback is provided on construction. + * + * + * \code + * RepoindexFileReader reader(repoindex_file, + * bind( &SomeClass::callbackfunc, &SomeClassInstance, _1) ); + * \endcode + */ + class RepoindexFileReader : private base::NonCopyable + { + public: + /** + * Callback definition. + * First parameter is a \ref RepoInfo object with the resource + * second parameter is the resource type. + */ + typedef function< bool( + const RepoInfo & )> + ProcessResource; + + /** + * CTOR. Creates also \ref xml::Reader and starts reading. + * + * \param repoindex_file is the repoindex.xml file you want to read + * \param callback is a function. + * + * \see RepoindexFileReader::ProcessResource + */ + RepoindexFileReader( + const Pathname & repoindex_file, const ProcessResource & callback); + + /** + * DTOR + */ + ~RepoindexFileReader(); + + private: + class Impl; + RW_pointer > _pimpl; + }; + + + } // ns parser +} // ns zypp + +#endif /*zypp_source_yum_RepoindexFileReader_H*/ + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/parser/ServiceFileReader.cc b/zypp/parser/ServiceFileReader.cc new file mode 100644 index 0000000..d1d249f --- /dev/null +++ b/zypp/parser/ServiceFileReader.cc @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoFileReader.cc + * +*/ +#include +#include "zypp/base/Logger.h" +#include "zypp/base/String.h" +#include "zypp/base/InputStream.h" +#include "zypp/base/UserRequestException.h" + +#include "zypp/parser/IniDict.h" +#include "zypp/parser/ServiceFileReader.h" +#include "zypp/Service.h" + +using std::endl; +using zypp::parser::IniDict; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + class ServiceFileReader::Impl { + public: + static void parseServices( const Pathname &file, + const ServiceFileReader::ProcessService& callback ); + }; + + void ServiceFileReader::Impl::parseServices( const Pathname &file, + const ServiceFileReader::ProcessService &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; + + Service service(*its); + + for ( IniDict::entry_const_iterator it = dict.entriesBegin(*its); + it != dict.entriesEnd(*its); + ++it ) + { + //MIL << (*it).first << endl; + if (it->first == "url" ) + service.setUrl( Url (it->second) ); + else if ( it->first == "alias" ) + service.addRepo( it->second ); + else + ERR << "Unknown attribute " << it->second << " ignored" << endl; + } + MIL << "Linking repo info with file " << file << endl; + service.setLocation(file); + // add it to the list. + if ( !callback(service) ) + break; + } + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoFileReader + // + /////////////////////////////////////////////////////////////////// + + ServiceFileReader::ServiceFileReader( const Pathname & repo_file, + const ProcessService & callback/*, + const ProgressData::ReceiverFnc &progress */) + { + Impl::parseServices(repo_file, callback/*, progress*/); + //MIL << "Done" << endl; + } + + ServiceFileReader::~ServiceFileReader() + {} + + std::ostream & operator<<( std::ostream & str, const ServiceFileReader & obj ) + { + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/ServiceFileReader.h b/zypp/parser/ServiceFileReader.h new file mode 100644 index 0000000..137c0fd --- /dev/null +++ b/zypp/parser/ServiceFileReader.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/ServiceFileReader.h + * +*/ +#ifndef ZYPP_REPO_SERVICEFILEREADER_H +#define ZYPP_REPO_SERVICEFILEREADER_H + +#include + +#include "zypp/base/PtrTypes.h" +#include "zypp/ProgressData.h" +#include "zypp/Pathname.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class Service; + /////////////////////////////////////////////////////////////////// + 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 + * ServiceFileReader reader(repo_file, + * bind( &SomeClass::callbackfunc, &SomeClassInstance, _1, _2 ) ); + * \endcode + */ + class ServiceFileReader + { + friend std::ostream & operator<<( std::ostream & str, const ServiceFileReader & 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 Service & )> ProcessService; + + /** 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 + * + */ + ServiceFileReader( const Pathname & repo_file, + const ProcessService & callback/*, + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc()*/); + + /** + * Dtor + */ + ~ServiceFileReader(); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ServiceFileReader Stream output */ + std::ostream & operator<<( std::ostream & str, const ServiceFileReader & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_SERVICEFILEREADER_H diff --git a/zypp/parser/yum/schema/patch.rng b/zypp/parser/yum/schema/patch.rng index fd32f03..78b48f6 100644 --- a/zypp/parser/yum/schema/patch.rng +++ b/zypp/parser/yum/schema/patch.rng @@ -1,5 +1,5 @@ - + diff --git a/zypp/parser/yum/schema/primary.rng b/zypp/parser/yum/schema/primary.rng index d38f13b..1eb2d5f 100644 --- a/zypp/parser/yum/schema/primary.rng +++ b/zypp/parser/yum/schema/primary.rng @@ -1,5 +1,5 @@ - + diff --git a/zypp/parser/yum/schema/products.rng b/zypp/parser/yum/schema/products.rng index 6fc53f7..8248552 100644 --- a/zypp/parser/yum/schema/products.rng +++ b/zypp/parser/yum/schema/products.rng @@ -33,11 +33,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/repoindex.rnc b/zypp/parser/yum/schema/repoindex.rnc new file mode 100644 index 0000000..bc32693 --- /dev/null +++ b/zypp/parser/yum/schema/repoindex.rnc @@ -0,0 +1,28 @@ +# NU service index file schema. +# +# Elements: +# +# repoindex +# Root element. Contains only repo elements. +# repo element contains only attributes - +# name - name of repository +# alias - unique alias of repository +# description - description of repository +# distro_target - target distribution +# priority - priority of repository +# pub - ??? +# path - relative path to repository +# + +element repoindex { + element repo { + attribute name { xsd:string }?, + attribute alias { xsd:string }, + attribute description { xsd:string }?, + attribute distro_target { xsd:string }, + attribute priority { xsd:integer }?, + attribute pub { xsd:integer }?, + attribute path { xsd:string } + }+, + empty +} diff --git a/zypp/parser/yum/schema/repoindex.rng b/zypp/parser/yum/schema/repoindex.rng new file mode 100644 index 0000000..5b7ae26 --- /dev/null +++ b/zypp/parser/yum/schema/repoindex.rng @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/rpm-ns.rng b/zypp/parser/yum/schema/rpm-ns.rng index 09b488f..9451201 100644 --- a/zypp/parser/yum/schema/rpm-ns.rng +++ b/zypp/parser/yum/schema/rpm-ns.rng @@ -1,5 +1,5 @@ - + @@ -251,6 +251,7 @@ + diff --git a/zypp/parser/yum/schema/suse-primary.rng b/zypp/parser/yum/schema/suse-primary.rng index aa69bbc..f3029b8 100644 --- a/zypp/parser/yum/schema/suse-primary.rng +++ b/zypp/parser/yum/schema/suse-primary.rng @@ -1,5 +1,5 @@ - + diff --git a/zypp/parser/yum/schemanames.h b/zypp/parser/yum/schemanames.h index 47c90f6..54629c6 100644 --- a/zypp/parser/yum/schemanames.h +++ b/zypp/parser/yum/schemanames.h @@ -31,6 +31,7 @@ namespace yum #define PATCHSCHEMA (SCHEMABASE "patch.rng") #define PATCHESSCHEMA (SCHEMABASE "patches.rng") #define PRODUCTSCHEMA (SCHEMABASE "product.rng") +#define REPOINDEXSCHEMA (SCHEMABASE "product.rng") } // namespace yum } // namespace parser } // namespace zypp