From 8e2bf29b47a9f00f8fd0679d416f0f8b13ad1a76 Mon Sep 17 00:00:00 2001 From: Jiri Srain Date: Thu, 19 Jan 2006 10:07:50 +0000 Subject: [PATCH] source factory now produces source from URL and directory, adapted both YUM and SuSEtags sources --- devel/devel.jsrain/SourceRead.cc | 30 +++++++----- zypp/SourceFactory.cc | 94 ++++++++++++++++++++++++++++++++++++ zypp/SourceFactory.h | 30 ++++++++++++ zypp/base/String.cc | 69 ++++++++++++++++++++++++++ zypp/base/String.h | 6 +++ zypp/media/MediaAccess.h | 1 + zypp/parser/yum/YUMParserData.h | 1 + zypp/parser/yum/YUMPatternParser.h | 4 +- zypp/source/SourceImpl.cc | 11 ++++- zypp/source/SourceImpl.h | 16 +++++- zypp/source/susetags/SuseTagsImpl.cc | 12 +++-- zypp/source/susetags/SuseTagsImpl.h | 2 +- zypp/source/yum/YUMSourceImpl.cc | 47 +++++++++--------- zypp/source/yum/YUMSourceImpl.h | 7 +-- 14 files changed, 281 insertions(+), 49 deletions(-) diff --git a/devel/devel.jsrain/SourceRead.cc b/devel/devel.jsrain/SourceRead.cc index 2424ec7..25c6f52 100644 --- a/devel/devel.jsrain/SourceRead.cc +++ b/devel/devel.jsrain/SourceRead.cc @@ -1,18 +1,13 @@ #include #include -#include -#include -#include -#include -#include #include -#include "zypp/source/yum/YUMSource.h" - +#include "zypp/base/Logger.h" +#include "zypp/SourceFactory.h" +#include "zypp/Source.h" +#include "zypp/source/SourceImpl.h" using namespace std; using namespace zypp; -using namespace zypp::source::yum; - /****************************************************************** ** @@ -25,10 +20,19 @@ using namespace zypp::source::yum; int main( int argc, char * argv[] ) { INT << "===[START]==========================================" << endl; - YUMSource src; - - src.parseSourceMetadata("repodata"); - + SourceFactory _f; + Pathname p = "/"; + Url url = Url("ftp://cml.suse.cz/netboot/find/SUSE-10.1-CD-OSS-i386-Alpha4-CD1"); +// Url url = Url("http://lide.suse.cz/~~jsrain/devel.jsrain"); +// Url url = Url("dir:/local/zypp/libzypp/devel/devel.jsrain"); + Source s = _f.createFrom( url, p ); + ResStore store = s.resolvables(); + for (ResStore::const_iterator it = store.begin(); + it != store.end(); it++) + { + ERR << **it << endl; + } + ERR << store << endl; INT << "===[END]============================================" << endl; return 0; } diff --git a/zypp/SourceFactory.cc b/zypp/SourceFactory.cc index d968def..c614478 100644 --- a/zypp/SourceFactory.cc +++ b/zypp/SourceFactory.cc @@ -10,13 +10,17 @@ * */ #include +#include #include "zypp/base/Logger.h" #include "zypp/base/Exception.h" +#include "zypp/base/String.h" #include "zypp/SourceFactory.h" #include "zypp/source/Builtin.h" +#include "zypp/media/MediaAccess.h" using std::endl; +using namespace zypp::source; /////////////////////////////////////////////////////////////////// namespace zypp @@ -73,6 +77,73 @@ namespace zypp return Source( impl_r ); } + + void SourceFactory::listProducts( const Url & url_r, ProductSet & products_r ) + { + if (! url_r.isValid()) + ZYPP_THROW( Exception("Empty URL passed to SourceFactory") ); + + // open the media + media::MediaAccess::Ptr media = new media::MediaAccess(); + media->open( url_r ); + media->attach(); + Pathname products_file = Pathname("media.1/products"); + media->provideFile (products_file); + products_file = media->localPath (products_file); + scanProductsFile (products_file, products_r); + media->release(); + media->close(); + } + + Source SourceFactory::createFrom( const Url & url_r, const Pathname & path_r ) + { + if (! url_r.isValid()) + ZYPP_THROW( Exception("Empty URL passed to SourceFactory") ); + + // open the media + media::MediaAccess::Ptr media; + try { + media = new media::MediaAccess(); + media->open( url_r ); + media->attach(); + try + { + MIL << "Trying the YUM source" << endl; + Source::Impl_Ptr impl = new yum::YUMSourceImpl(media, path_r); +ERR << "Impl created" << endl; + return Source(impl); + } + catch (const Exception & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + WAR << "Not YUM source, trying next type" << endl; + } + catch (...) + { + INT << "Unknown exception" << endl; + } + try + { + MIL << "Trying the SUSE tags source" << endl; + Source::Impl_Ptr impl = new susetags::SuseTagsImpl(media, path_r); + return Source(impl); + } + catch (const Exception & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + WAR << "Not SUSE tags source, trying next type" << endl; + } + } + catch (const media::MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + catch (const Exception & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW(Exception("Cannot create the installatino source")); + } /****************************************************************** ** @@ -84,6 +155,29 @@ namespace zypp return str << "SourceFactory"; } + void SourceFactory::scanProductsFile( const Pathname & file_r, ProductSet & pset_r ) const + { + std::ifstream pfile( file_r.asString().c_str() ); + while ( pfile.good() ) { + + std::string value = str::getline( pfile, str::TRIM ); + if ( pfile.bad() ) { + ERR << "Error parsing " << file_r << endl; + ZYPP_THROW(Exception("Error parsing " + file_r.asString())); + } + if ( pfile.fail() ) { + break; // no data on last line + } + std::string tag = str::stripFirstWord( value, true ); + + if ( tag.size() ) { + pset_r.insert( ProductEntry( tag, value ) ); + } + } + } + + + ///////////////////////////////////////////////////////////////// } // namespace zypp /////////////////////////////////////////////////////////////////// diff --git a/zypp/SourceFactory.h b/zypp/SourceFactory.h index 798c88c..9d6dd16 100644 --- a/zypp/SourceFactory.h +++ b/zypp/SourceFactory.h @@ -17,6 +17,8 @@ #include "zypp/base/PtrTypes.h" #include "zypp/Source.h" +#include "zypp/Url.h" +#include "zypp/Pathname.h" /////////////////////////////////////////////////////////////////// namespace zypp @@ -46,11 +48,39 @@ namespace zypp */ Source createFrom( const Source::Impl_Ptr & impl_r ); + /** Construct source from an implementation. + * \throw EXCEPTION on fail + */ + Source createFrom( const Url & url_r, const Pathname & path_r = "/" ); + private: /** Implementation */ class Impl; /** Pointer to implementation */ RW_pointer _pimpl; + + public: + struct ProductEntry { + Pathname _dir; + std::string _name; + ProductEntry( const Pathname & dir_r = "/", const std::string & name_r = std::string() ){ + _dir = dir_r; + _name = name_r; + } + bool operator<( const ProductEntry & rhs ) const { + return( _dir.asString() < rhs._dir.asString() ); + } + }; + + typedef std::set ProductSet; + + /** Check which products are available on the media + * \throw Exception or MediaException on fail + */ + void listProducts( const Url & url_r, ProductSet & products_r ); + + private: + void scanProductsFile( const Pathname & file_r, ProductSet & pset_r ) const; }; /////////////////////////////////////////////////////////////////// diff --git a/zypp/base/String.cc b/zypp/base/String.cc index 8f20996..6cdefde 100644 --- a/zypp/base/String.cc +++ b/zypp/base/String.cc @@ -120,6 +120,75 @@ namespace zypp return ret; } + /****************************************************************** + ** + ** FUNCTION NAME : stripFirstWord + ** FUNCTION TYPE : std::string + ** + ** DESCRIPTION : + */ + std::string stripFirstWord( std::string & line, const bool ltrim_first ) + { + if ( ltrim_first ) + line = ltrim( line ); + + if ( line.empty() ) + return line; + + std::string ret; + std::string::size_type p = line.find_first_of( " \t" ); + + if ( p == std::string::npos ) { + // no ws on line + ret = line; + line.erase(); + } else if ( p == 0 ) { + // starts with ws + // ret remains empty + line = ltrim( line ); + } + else { + // strip word and ltim line + ret = line.substr( 0, p ); + line = ltrim( line.erase( 0, p ) ); + } + return ret; + } + + /****************************************************************** + ** + ** + ** FUNCTION NAME : getline + ** FUNCTION TYPE : std::string + ** + ** DESCRIPTION : + */ + static inline std::string _getline( std::istream & str, const Trim trim_r ) + { + const unsigned tmpBuffLen = 1024; + char tmpBuff[tmpBuffLen]; + + std::string ret; + do { + str.clear(); + str.getline( tmpBuff, tmpBuffLen ); // always writes '\0' terminated + ret += tmpBuff; + } while( str.rdstate() == std::ios::failbit ); + + return trim( ret, trim_r ); + } + + std::string getline( std::istream & str, const Trim trim_r ) + { + return _getline(str, trim_r); + } + + std::string getline( std::istream & str, bool trim ) + { + return _getline(str, trim?TRIM:NO_TRIM); + } + + ///////////////////////////////////////////////////////////////// } // namespace str diff --git a/zypp/base/String.h b/zypp/base/String.h index 088e0a3..e8022ec 100644 --- a/zypp/base/String.h +++ b/zypp/base/String.h @@ -301,6 +301,12 @@ namespace zypp { return trim( s, R_TRIM ); } //@} + std::string stripFirstWord( std::string & line, const bool ltrim_first ); + + std::string getline( std::istream & str, bool trim = false ); + + std::string getline( std::istream & str, const Trim trim_r ); + ///////////////////////////////////////////////////////////////// } // namespace str /////////////////////////////////////////////////////////////////// diff --git a/zypp/media/MediaAccess.h b/zypp/media/MediaAccess.h index 604ff5c..1aaed4e 100644 --- a/zypp/media/MediaAccess.h +++ b/zypp/media/MediaAccess.h @@ -26,6 +26,7 @@ #include "zypp/media/MediaException.h" #include "zypp/Url.h" +#include "zypp/base/Logger.h" namespace zypp { namespace media { diff --git a/zypp/parser/yum/YUMParserData.h b/zypp/parser/yum/YUMParserData.h index 92deba4..84cf927 100644 --- a/zypp/parser/yum/YUMParserData.h +++ b/zypp/parser/yum/YUMParserData.h @@ -453,6 +453,7 @@ namespace zypp { std::ostream& operator<<(std::ostream &out, const YUMRepomdData& data); std::ostream& operator<<(std::ostream &out, const YUMPrimaryData& data); std::ostream& operator<<(std::ostream &out, const YUMGroupData& data); + std::ostream& operator<<(std::ostream &out, const YUMPatternData& data); std::ostream& operator<<(std::ostream &out, const YUMFileListData& data); std::ostream& operator<<(std::ostream& out, const YUMOtherData& data); std::ostream& operator<<(std::ostream& out, const YUMPatchData& data); diff --git a/zypp/parser/yum/YUMPatternParser.h b/zypp/parser/yum/YUMPatternParser.h index 3b62e1e..b76629c 100644 --- a/zypp/parser/yum/YUMPatternParser.h +++ b/zypp/parser/yum/YUMPatternParser.h @@ -26,10 +26,10 @@ namespace zypp { /** * - * @short Parser for YUM group files. + * @short Parser for YUM pattern files. * * Use this class as an iterator that produces, one after one, - * YUMPatternData_Ptr(s) for the XML group elements. + * YUMPatternData_Ptr(s) for the XML pattern elements. * Here's an example: * * for (YUMPatternParser iter(anIstream, baseUrl), diff --git a/zypp/source/SourceImpl.cc b/zypp/source/SourceImpl.cc index 04a85f5..220906a 100644 --- a/zypp/source/SourceImpl.cc +++ b/zypp/source/SourceImpl.cc @@ -30,7 +30,10 @@ namespace zypp // METHOD NAME : SourceImpl::SourceImpl // METHOD TYPE : Ctor // - SourceImpl::SourceImpl() + SourceImpl::SourceImpl(media::MediaAccess::Ptr & media_r, + const Pathname & path_r) + : _media (media_r) + , _path(path_r) {} /////////////////////////////////////////////////////////////////// @@ -41,6 +44,12 @@ namespace zypp SourceImpl::~SourceImpl() {} + const Pathname SourceImpl::provideFile(const Pathname & file_r) + { + _media->provideFile (file_r); + return _media->localPath (file_r); + } + ///////////////////////////////////////////////////////////////// } // namespace source /////////////////////////////////////////////////////////////////// diff --git a/zypp/source/SourceImpl.h b/zypp/source/SourceImpl.h index 375d5e0..f4e43fd 100644 --- a/zypp/source/SourceImpl.h +++ b/zypp/source/SourceImpl.h @@ -19,6 +19,9 @@ #include "zypp/base/PtrTypes.h" #include "zypp/ResStore.h" +#include "zypp/Pathname.h" +#include "zypp/media/MediaAccess.h" + /////////////////////////////////////////////////////////////////// namespace zypp { ///////////////////////////////////////////////////////////////// @@ -42,8 +45,12 @@ namespace zypp friend std::ostream & operator<<( std::ostream & str, const SourceImpl & obj ); public: + /** Ctor, FIXME it is here only because of target storage */ + SourceImpl() + {} /** Ctor. */ - SourceImpl(); + SourceImpl(media::MediaAccess::Ptr & media_r, + const Pathname & path_r = "/"); /** Dtor. */ virtual ~SourceImpl(); @@ -53,6 +60,9 @@ namespace zypp const ResStore & resolvables() const { return _store; } + /** Provide a file to local filesystem */ + const Pathname provideFile(const Pathname & file); + /** Overload to realize stream output. */ virtual std::ostream & dumpOn( std::ostream & str ) const { return str << "SourceImpl"; } @@ -60,6 +70,10 @@ namespace zypp protected: /** All resolvables provided by this source. */ ResStore _store; + /** Handle to media which contains this source */ + media::MediaAccess::Ptr _media; + /** Path to the source on the media */ + Pathname _path; }; /////////////////////////////////////////////////////////////////// diff --git a/zypp/source/susetags/SuseTagsImpl.cc b/zypp/source/susetags/SuseTagsImpl.cc index 54a24f8..790cff8 100644 --- a/zypp/source/susetags/SuseTagsImpl.cc +++ b/zypp/source/susetags/SuseTagsImpl.cc @@ -35,20 +35,22 @@ namespace zypp // METHOD NAME : SuseTagsImpl::SuseTagsImpl // METHOD TYPE : Ctor // - SuseTagsImpl::SuseTagsImpl( const Pathname & localDir_r ) + SuseTagsImpl::SuseTagsImpl( media::MediaAccess::Ptr & media_r, const Pathname & path_r ) + : SourceImpl(media_r, path_r) { - PathInfo p( localDir_r ); + Pathname p = provideFile(path_r + "suse/setup/descr/packages"); +/* PathInfo p( localDir_r ); if ( p.isDir() ) p( localDir_r + "packages" ); if ( ! p.isFile() ) ZYPP_THROW( Exception( p.asString()+" is not a file" ) ); if ( ! p.userMayR() ) ZYPP_THROW( Exception( p.asString()+" no permission to read" ) ); - +*/ DBG << "Going to parse " << p << endl; - std::list content( parsePackages( p.path() ) ); + std::list content( parsePackages( p ) ); _store.insert( content.begin(), content.end() ); - DBG << "SuseTagsImpl (fake) from " << p.path() << ": " + DBG << "SuseTagsImpl (fake) from " << p << ": " << content.size() << " packages" << endl; } diff --git a/zypp/source/susetags/SuseTagsImpl.h b/zypp/source/susetags/SuseTagsImpl.h index 7fee0c4..39e596b 100644 --- a/zypp/source/susetags/SuseTagsImpl.h +++ b/zypp/source/susetags/SuseTagsImpl.h @@ -38,7 +38,7 @@ namespace zypp /** \deprecated Interim ctor * \throw EXCEPTION on parse error */ - SuseTagsImpl( const Pathname & localDir_r ); + SuseTagsImpl( media::MediaAccess::Ptr & media_r, const Pathname & path_r = "/" ); /** Dtor */ ~SuseTagsImpl(); diff --git a/zypp/source/yum/YUMSourceImpl.cc b/zypp/source/yum/YUMSourceImpl.cc index 9e38775..b553476 100644 --- a/zypp/source/yum/YUMSourceImpl.cc +++ b/zypp/source/yum/YUMSourceImpl.cc @@ -47,10 +47,9 @@ namespace zypp /** Default ctor */ - YUMSourceImpl::YUMSourceImpl() - {} - - void YUMSourceImpl::parseSourceMetadata(std::string path) + YUMSourceImpl::YUMSourceImpl(media::MediaAccess::Ptr & media_r, + const Pathname & path_r) + : SourceImpl(media_r, path_r) { std::list repo_primary; std::list repo_files; @@ -62,9 +61,9 @@ namespace zypp try { // first read list of all files in the reposotory - std::string filename = path + "/repmod.xml"; + Pathname filename = provideFile(path_r + "/repomd.xml"); DBG << "Reading file " << filename << endl; - ifstream repo_st(filename.c_str()); + ifstream repo_st(filename.asString().c_str()); YUMRepomdParser repomd(repo_st, ""); for(; @@ -79,6 +78,8 @@ namespace zypp repo_other.push_back(*repomd); else if ((*repomd)->type == "group") repo_group.push_back(*repomd); + else if ((*repomd)->type == "pattern") + repo_pattern.push_back(*repomd); else if ((*repomd)->type == "product") repo_product.push_back(*repomd); else if ((*repomd)->type == "patches") @@ -90,7 +91,7 @@ namespace zypp catch (...) { ERR << "Cannot read repomd file, cannot initialize source" << endl; -// ZYPP_THROW( Exception("Cannot read repomd file, cannot initialize source") ); + ZYPP_THROW( Exception("Cannot read repomd file, cannot initialize source") ); } try { // now put other and filelist data to structures for easier find @@ -102,9 +103,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMFileListParser filelist(st, ""); for (; ! filelist.atEnd(); @@ -126,9 +127,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMOtherParser other(st, ""); for (; ! other.atEnd(); @@ -151,9 +152,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMPrimaryParser prim(st, ""); for (; !prim.atEnd(); @@ -196,9 +197,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMGroupParser group(st, ""); for (; !group.atEnd(); @@ -222,9 +223,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMPatternParser pattern(st, ""); for (; !pattern.atEnd(); @@ -248,9 +249,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMProductParser product(st, ""); for (; !product.atEnd(); @@ -275,9 +276,9 @@ namespace zypp it++) { // TODO check checksum - string filename = (*it)->location; + Pathname filename = provideFile(path_r + (*it)->location); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMPatchesParser patch(st, ""); for (; !patch.atEnd(); @@ -295,9 +296,9 @@ namespace zypp it != patch_files.end(); it++) { - std::string filename = *it; + Pathname filename = provideFile(path_r + *it); DBG << "Reading file " << filename << endl; - ifstream st(filename.c_str()); + ifstream st(filename.asString().c_str()); YUMPatchParser ptch(st, ""); for(; !ptch.atEnd(); diff --git a/zypp/source/yum/YUMSourceImpl.h b/zypp/source/yum/YUMSourceImpl.h index e024dfc..04abaa9 100644 --- a/zypp/source/yum/YUMSourceImpl.h +++ b/zypp/source/yum/YUMSourceImpl.h @@ -42,10 +42,11 @@ namespace zypp class YUMSourceImpl : public SourceImpl { public: + /** Ctor, FIXME it is here only because of target storage */ + YUMSourceImpl() + {} /** Default ctor */ - YUMSourceImpl(); - - void parseSourceMetadata(std::string path); + YUMSourceImpl(media::MediaAccess::Ptr & media_r, const Pathname & path_r = "/"); Package::Ptr createPackage( const zypp::parser::yum::YUMPrimaryData & parsed, -- 2.7.4