zypper port starts. zypp2 to zypp
authorDuncan Mac-Vicar P <dmacvicar@suse.de>
Wed, 6 Jun 2007 14:45:35 +0000 (14:45 +0000)
committerDuncan Mac-Vicar P <dmacvicar@suse.de>
Wed, 6 Jun 2007 14:45:35 +0000 (14:45 +0000)
15 files changed:
zypp/RepoInfo.cc [new file with mode: 0644]
zypp/RepoInfo.h [new file with mode: 0644]
zypp/RepoManager.cc [new file with mode: 0644]
zypp/RepoManager.h [new file with mode: 0644]
zypp/RepoStatus.cc [new file with mode: 0644]
zypp/RepoStatus.h [new file with mode: 0644]
zypp/Repository.cc [new file with mode: 0644]
zypp/Repository.h [new file with mode: 0644]
zypp/RepositoryFactory.cc [new file with mode: 0644]
zypp/RepositoryFactory.h [new file with mode: 0644]
zypp/dummy.cc [new file with mode: 0644]
zypp/parser/RepoFileReader.cc [new file with mode: 0644]
zypp/parser/RepoFileReader.h [new file with mode: 0644]
zypp/parser/susetags/RepoParser.cc [new file with mode: 0644]
zypp/parser/susetags/RepoParser.h [new file with mode: 0644]

diff --git a/zypp/RepoInfo.cc b/zypp/RepoInfo.cc
new file mode 100644 (file)
index 0000000..a26bbb8
--- /dev/null
@@ -0,0 +1,189 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/RepoInfo.cc
+ *
+*/
+#include <iostream>
+#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<Url> urls;
+    std::string alias;
+    std::string name;
+
+  public:
+
+  private:
+    friend Impl * rwcowClone<Impl>( 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<Url> 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> url_set(urls());
+    for ( std::set<Url>::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 (file)
index 0000000..b1a7b27
--- /dev/null
@@ -0,0 +1,199 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp2/RepoInfo.h
+ *
+*/
+#ifndef ZYPP2_REPOSITORYINFO_H
+#define ZYPP2_REPOSITORYINFO_H
+
+#include <iosfwd>
+#include <list>
+#include <set>
+#include "zypp/base/PtrTypes.h"
+
+#include <boost/logic/tribool.hpp>
+#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<Url> 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<Url>::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<Impl> _pimpl;
+  };
+  ///////////////////////////////////////////////////////////////////
+
+  /** \relates RepoInfo Stream output */
+  std::ostream & operator<<( std::ostream & str, const RepoInfo & obj );
+
+  typedef std::list<RepoInfo> RepoInfoList;
+  
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp2
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP2_REPOSITORYINFO_H
diff --git a/zypp/RepoManager.cc b/zypp/RepoManager.cc
new file mode 100644 (file)
index 0000000..b3b1a79
--- /dev/null
@@ -0,0 +1,402 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/RepoManager.cc
+ *
+*/
+
+#include <iostream>
+#include <list>
+#include <algorithm>
+#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<RepoInfo> repositories_in_path( const Pathname &dir )
+  {
+    MIL << " " << dir << endl;
+    RepoCollector collector;
+    std::list<RepoInfo> repos;
+    list<Pathname> entries;
+    if ( filesystem::readdir( entries, Pathname(dir), false ) != 0 )
+      ZYPP_THROW(Exception("failed to read directory"));
+    
+    for ( list<Pathname>::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<Impl> nullimpl()
+    {
+      static shared_ptr<Impl> _nullimpl( new Impl );
+      return _nullimpl;
+    }
+
+  private:
+    friend Impl * rwcowClone<Impl>( 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<RepoInfo> 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 (file)
index 0000000..fb00242
--- /dev/null
@@ -0,0 +1,177 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/RepoManager.h
+ *
+*/
+#ifndef ZYPP_REPOMANAGER_H
+#define ZYPP_REPOMANAGER_H
+
+#include <iosfwd>
+#include <list>
+
+#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<RepoInfo> 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<Impl> _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 (file)
index 0000000..3d54d6d
--- /dev/null
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/RepoStatus.cc
+ *
+*/
+#include <iostream>
+//#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<Impl> nullimpl()
+    {
+      static shared_ptr<Impl> _nullimpl( new Impl );
+      return _nullimpl;
+    }
+
+  private:
+    friend Impl * rwcowClone<Impl>( 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 &timestamp )
+  {
+    _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 (file)
index 0000000..a4faffe
--- /dev/null
@@ -0,0 +1,93 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/RepoStatus.h
+ *
+*/
+#ifndef ZYPP2_REPOSTATUS_H
+#define ZYPP2_REPOSTATUS_H
+
+#include <iosfwd>
+#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 &timestamp );
+
+    /** Implementation  */
+    class Impl;
+
+  public:
+    /** Default ctor */
+    RepoStatus();
+    /** Dtor */
+    ~RepoStatus();
+
+  public:
+
+  private:
+    /** Pointer to implementation */
+    RWCOW_pointer<Impl> _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 (file)
index 0000000..2a61085
--- /dev/null
@@ -0,0 +1,50 @@
+#include <cassert>
+#include <iostream>
+
+#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 (file)
index 0000000..c9b1a13
--- /dev/null
@@ -0,0 +1,81 @@
+
+#ifndef ZYPP_REPOSITORY_H
+#define ZYPP_REPOSITORY_H
+
+#include <iosfwd>
+#include <string>
+
+#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<Repository> /* 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<Repository>::operator bool_type;
+
+  public:
+    typedef unsigned long NumericId;
+
+    /** Runtime unique numeric Repository Id. */
+    NumericId numericId() const;
+    
+    const ResStore & resolvables();
+    
+  private:
+    friend base::SafeBool<Repository>::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 (file)
index 0000000..44518cd
--- /dev/null
@@ -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 (file)
index 0000000..b5338e3
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/zypp/parser/RepoFileReader.cc b/zypp/parser/RepoFileReader.cc
new file mode 100644 (file)
index 0000000..3a59ec4
--- /dev/null
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/repo/RepoFileReader.cc
+ *
+*/
+#include <iostream>
+#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 (file)
index 0000000..d7ab7a9
--- /dev/null
@@ -0,0 +1,93 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/repo/RepoFileReader.h
+ *
+*/
+#ifndef ZYPP_REPO_REPOFILEREADER_H
+#define ZYPP_REPO_REPOFILEREADER_H
+
+#include <iosfwd>
+
+#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 (file)
index 0000000..fd9cb7d
--- /dev/null
@@ -0,0 +1,283 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/parser/susetags/RepoParser.cc
+ *
+*/
+#include <iostream>
+#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<Locale>  _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 (file)
index 0000000..39ec351
--- /dev/null
@@ -0,0 +1,103 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/parser/susetags/RepoParser.h
+ *
+*/
+#ifndef ZYPP2_PARSER_SUSETAGS_REPOPARSER_H
+#define ZYPP2_PARSER_SUSETAGS_REPOPARSER_H
+
+#include <iosfwd>
+
+#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<Impl,rw_pointer::Scoped<Impl> > _pimpl;
+      };
+      ///////////////////////////////////////////////////////////////////
+
+      /////////////////////////////////////////////////////////////////
+    } // namespace susetags
+    ///////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////
+  } // namespace parser
+  ///////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP2_PARSER_SUSETAGS_REPOPARSER_H