First working version of a local service. Still some design and
authorDuncan Mac-Vicar P <dmacvicar@suse.de>
Fri, 17 Sep 2010 15:21:27 +0000 (17:21 +0200)
committerDuncan Mac-Vicar P <dmacvicar@suse.de>
Fri, 17 Sep 2010 15:21:27 +0000 (17:21 +0200)
discussion needed:
- is local the right name?
- do we want just a different format? just the repo index?
- why not exec all local file:/ with chmod +x as scripts?

15 files changed:
tests/zypp/RepoManager_test.cc
tests/zypp/data/RepoManager/local-service-lib-1/service [new file with mode: 0755]
tests/zypp/data/RepoManager/local-service-lib-2/service [new file with mode: 0755]
zypp/CMakeLists.txt
zypp/RepoManager.cc
zypp/RepoManager.h
zypp/ZConfig.cc
zypp/ZConfig.h
zypp/parser/RepoFileReader.cc
zypp/parser/RepoFileReader.h
zypp/repo/LocalServices.cc
zypp/repo/ServiceRepos.cc [new file with mode: 0644]
zypp/repo/ServiceRepos.h [new file with mode: 0644]
zypp/repo/ServiceType.cc
zypp/repo/ServiceType.h

index 63400ac..1e53336 100644 (file)
@@ -62,6 +62,50 @@ BOOST_AUTO_TEST_CASE(refresh_addon_in_subdir)
     BOOST_CHECK( r.info().hasLicense() );
 }
 
+BOOST_AUTO_TEST_CASE(localservices_test)
+{
+  TmpDir tmpCachePath;
+  RepoManagerOptions opts( RepoManagerOptions::makeTestSetup( tmpCachePath ) ) ;
+
+  filesystem::mkdir( opts.knownReposPath );
+  filesystem::mkdir( opts.knownServicesPath );
+
+  opts.localServicesPath = DATADIR + "/local-service-lib-1";
+  BOOST_CHECK(PathInfo(opts.localServicesPath / "service").isExist());
+
+  {
+    RepoManager manager(opts);
+    BOOST_CHECK_EQUAL(1, manager.serviceSize());
+    BOOST_CHECK(manager.repoEmpty());
+
+    ServiceInfo service(*manager.serviceBegin());
+    BOOST_CHECK_EQUAL("service", service.alias());
+    BOOST_CHECK_EQUAL( "file:" + DATADIR.asString() + "/local-service-lib-1/service", service.url().asString());
+
+    // now refresh the service
+    manager.refreshServices();
+    BOOST_CHECK_EQUAL((unsigned) 2, manager.repoSize());
+
+    //std::list<RepoInfo> infos;
+    //manager.getRepositoriesInService("test",
+    //  insert_iterator<std::list<RepoInfo> >(infos,infos.begin()));
+    //BOOST_CHECK_EQUAL(infos.size(), 2); // 2 from new repoindex
+  }
+  
+  // Now simulate the service changed
+  opts.localServicesPath = DATADIR + "/local-service-lib-2";
+  {
+    RepoManager manager(opts);
+    BOOST_CHECK_EQUAL(1, manager.serviceSize());
+
+    ServiceInfo service(*manager.serviceBegin());
+    BOOST_CHECK_EQUAL("service", service.alias());
+    BOOST_CHECK_EQUAL( "file:" + DATADIR.asString() + "/local-service-lib-2/service", service.url().asString());
+    // now refresh the service
+    manager.refreshServices();
+    BOOST_CHECK_EQUAL((unsigned) 1, manager.repoSize());
+  }
+}
 
 BOOST_AUTO_TEST_CASE(repomanager_test)
 {
diff --git a/tests/zypp/data/RepoManager/local-service-lib-1/service b/tests/zypp/data/RepoManager/local-service-lib-1/service
new file mode 100755 (executable)
index 0000000..a5bb647
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+echo "
+[repo1]
+name=Repository1
+baseurl=http://somehost.com/repo1
+type=rpmmd
+
+[repo12]
+name=Repository2
+baseurl=http://somehost.com/repo2
+type=rpmmd
+"
+
diff --git a/tests/zypp/data/RepoManager/local-service-lib-2/service b/tests/zypp/data/RepoManager/local-service-lib-2/service
new file mode 100755 (executable)
index 0000000..97db399
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+echo "
+[repo3]
+name=Repository3
+baseurl=http://somehost.com/repo3
+type=rpmmd
+"
+
index 4001908..488bc7c 100644 (file)
@@ -702,6 +702,7 @@ SET( zypp_repo_SRCS
   repo/RepoVariables.cc
   repo/RepoInfoBase.cc
   repo/LocalServices.cc
+  repo/ServiceRepos.cc
 )
 
 SET( zypp_repo_HEADERS
@@ -721,6 +722,7 @@ SET( zypp_repo_HEADERS
   repo/RepoInfoBase.h
   repo/RepoInfoBaseImpl.h
   repo/LocalServices.h
+  repo/ServiceRepos.h
 )
 
 INSTALL( FILES
index 0be20be..d02a58e 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "zypp/parser/RepoFileReader.h"
 #include "zypp/parser/ServiceFileReader.h"
-#include "zypp/parser/RepoindexFileReader.h"
+#include "zypp/repo/ServiceRepos.h"
 #include "zypp/repo/yum/Downloader.h"
 #include "zypp/repo/susetags/Downloader.h"
 #include "zypp/parser/plaindir/RepoParser.h"
@@ -145,6 +145,7 @@ namespace zypp
     repoPackagesCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoPackagesPath() );
     knownReposPath        = Pathname::assertprefix( root_r, ZConfig::instance().knownReposPath() );
     knownServicesPath     = Pathname::assertprefix( root_r, ZConfig::instance().knownServicesPath() );
+    localServicesPath     = Pathname::assertprefix( root_r, ZConfig::instance().localServicesPath() );
     probe                 = ZConfig::instance().repo_add_probe();
 
     rootDir = root_r;
@@ -159,6 +160,7 @@ namespace zypp
     ret.repoPackagesCachePath = root_r/"packages";
     ret.knownReposPath        = root_r/"repos.d";
     ret.knownServicesPath     = root_r/"services.d";
+    ret.localServicesPath     = root_r/"services-lib";
     ret.rootDir = root_r;
     return ret;
   }
@@ -405,6 +407,7 @@ namespace zypp
       init_knownRepositories();
     }
 
+    
     RepoManagerOptions options;
 
     RepoSet repos;
@@ -541,7 +544,7 @@ namespace zypp
       }
     }
 
-    repo::LocalServices("/space/tmp/services", ServiceCollector(services));    
+    repo::LocalServices(options.localServicesPath, ServiceCollector(services));    
   }
 
   void RepoManager::Impl::init_knownRepositories()
@@ -1559,7 +1562,7 @@ namespace zypp
         continue;
 
       // TODO match by url
-
       // we have a matcing repository, now we need to know
       // where it does come from.
       RepoInfo todelete = *it;
@@ -1888,17 +1891,6 @@ namespace zypp
       }
     }
 
-    // repoindex.xml must be fetched always without using cookies (bnc #573897)
-    Url serviceUrl( service.url() );
-    serviceUrl.setQueryParam( "cookies", "0" );
-
-    // download the repo index file
-    media::MediaManager mediamanager;
-    media::MediaAccessId mid = mediamanager.open( serviceUrl );
-    mediamanager.attach( mid );
-    mediamanager.provideFile( mid, "repo/repoindex.xml" );
-    Pathname path = mediamanager.localPath(mid, "repo/repoindex.xml" );
-
     // get target distro identifier
     std::string servicesTargetDistro = _pimpl->options.servicesTargetDistro;
     if ( servicesTargetDistro.empty() && getZYpp()->getTarget() )
@@ -1907,11 +1899,8 @@ namespace zypp
 
     // parse it
     RepoCollector collector(servicesTargetDistro);
-    parser::RepoindexFileReader reader( path, bind( &RepoCollector::collect, &collector, _1 ) );
-    mediamanager.release( mid );
-    mediamanager.close( mid );
-
-
+    ServiceRepos repos(service, bind( &RepoCollector::collect, &collector, _1 ));
+    
     // set service alias and base url for all collected repositories
     for_( it, collector.repos.begin(), collector.repos.end() )
     {
index c69c77c..f77c12a 100644 (file)
@@ -81,6 +81,7 @@ namespace zypp
     Pathname repoPackagesCachePath;
     Pathname knownReposPath;
     Pathname knownServicesPath;
+    Pathname localServicesPath;
     bool probe;
     /**
      * Target distro ID to be used when refreshing repo index services.
index cd77cef..1ff2008 100644 (file)
@@ -339,6 +339,10 @@ namespace zypp
                 {
                   cfg_known_services_path = Pathname(value);
                 }
+                else if ( entry == "localservicesdir" )
+                {
+                  cfg_local_services_path = Pathname(value);
+                }
                 else if ( entry == "repo.add.probe" )
                 {
                   repo_add_probe = str::strToBool( value, repo_add_probe );
@@ -493,6 +497,8 @@ namespace zypp
     Pathname cfg_config_path;
     Pathname cfg_known_repos_path;
     Pathname cfg_known_services_path;
+    Pathname cfg_local_services_path;
+    
     Pathname cfg_vendor_path;
     Pathname locks_file;
 
@@ -676,6 +682,12 @@ namespace zypp
         ? (configPath()/"services.d") : _pimpl->cfg_known_repos_path );
   }
 
+  Pathname ZConfig::localServicesPath() const
+  {
+    return ( _pimpl->cfg_local_services_path.empty()
+        ? ("/space/tmp/services") : _pimpl->cfg_local_services_path );
+  }
+
   Pathname ZConfig::vendorPath() const
   {
     return ( _pimpl->cfg_vendor_path.empty()
index 76722c2..87ec47d 100644 (file)
@@ -151,6 +151,14 @@ namespace zypp
       Pathname knownServicesPath() const;
 
       /**
+       * Path where local services are installed
+       * local services are scripts returning a repository
+       * list
+       * \ingroup g_ZC_CONFIGFILES
+       */
+      Pathname localServicesPath() const;
+
+      /**
        * Whether repository urls should be probed.
        / config option
        * repo.add.probe
index 7a41431..9196baf 100644 (file)
@@ -32,11 +32,10 @@ namespace zypp
    * \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 )
+    static void repositories_in_stream( const InputStream &is,
+                                        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();
@@ -77,7 +76,7 @@ namespace zypp
           else
             ERR << "Unknown attribute in [" << *its << "]: " << it->second << " ignored" << endl;
         }
-        info.setFilepath(file);
+        info.setFilepath(is.path());
         MIL << info << endl;
         // add it to the list.
         callback(info);
@@ -97,13 +96,21 @@ namespace zypp
                                     const ProgressData::ReceiverFnc &progress )
       : _callback(callback)
     {
-      repositories_in_file(repo_file, _callback, progress);
-      //MIL << "Done" << endl;
+      repositories_in_stream(InputStream(repo_file), _callback, progress);
+    }
+
+    RepoFileReader::RepoFileReader( const InputStream &is,
+                                    const ProcessRepo & callback,
+                                    const ProgressData::ReceiverFnc &progress )
+      : _callback(callback)
+    {
+      repositories_in_stream(is, _callback, progress);
     }
 
     RepoFileReader::~RepoFileReader()
     {}
 
+
     std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
     {
       return str;
index d7ab7a9..e326b56 100644 (file)
@@ -15,6 +15,7 @@
 #include <iosfwd>
 
 #include "zypp/base/PtrTypes.h"
+#include "zypp/base/InputStream.h"
 #include "zypp/RepoInfo.h"
 #include "zypp/ProgressData.h"
 
@@ -71,6 +72,21 @@ namespace zypp
       RepoFileReader( const Pathname & repo_file,
                       const ProcessRepo & callback,
                       const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() );
+
+     /**
+      * \short Constructor. Creates the reader and start reading.
+      *
+      * \param is A valid input stream
+      * \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 InputStream &is,
+                      const ProcessRepo & callback,
+                      const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() );
      
       /**
        * Dtor
index d76eb2f..34e66cb 100644 (file)
@@ -7,20 +7,20 @@
 |                                                                      |
 \---------------------------------------------------------------------*/
 #include <iostream>
+#include <sstream>
 #include "zypp/base/Logger.h"
 #include "zypp/base/Gettext.h"
 #include "zypp/base/String.h"
 #include "zypp/base/InputStream.h"
 #include "zypp/base/UserRequestException.h"
 
-#include "zypp/parser/IniDict.h"
 #include "zypp/repo/LocalServices.h"
 #include "zypp/ServiceInfo.h"
+#include "zypp/RepoInfo.h"
 #include "zypp/PathInfo.h"
-#include "zypp/ExternalProgram.h"
 
 using std::endl;
-using zypp::parser::IniDict;
+using std::stringstream;
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
@@ -52,18 +52,16 @@ namespace zypp
         //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
         for_(it, entries.begin(), entries.end() )
         {
-          const char* argv[] = {
-            (*it).c_str(),
-            NULL
-          };
-          ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
-          std::string line;
-          for(line = prog.receiveLine(); !line.empty(); line = prog.receiveLine())
-          {
-            std::cout << line << endl;
-          }
-          prog.close();
+          ServiceInfo service_info;
+          service_info.setAlias((*it).basename());
+          Url url;
+          url.setPathName((*it).asString());
+          url.setScheme("file");
+          service_info.setUrl(url);
+          service_info.setType(ServiceType::LOCAL);
+          callback(service_info);
         }
+
       }
     }
 
diff --git a/zypp/repo/ServiceRepos.cc b/zypp/repo/ServiceRepos.cc
new file mode 100644 (file)
index 0000000..59c846c
--- /dev/null
@@ -0,0 +1,101 @@
+#include <iostream>
+#include <sstream>
+#include "zypp/base/Logger.h"
+#include "zypp/repo/ServiceRepos.h"
+#include "zypp/parser/RepoFileReader.h"
+#include "zypp/media/MediaManager.h"
+#include "zypp/parser/RepoindexFileReader.h"
+#include "zypp/ExternalProgram.h"
+
+using std::stringstream;
+
+namespace zypp
+{
+namespace repo
+{
+
+class ServiceRepos::Impl
+{
+public:
+    Impl()
+    {
+    }
+    
+    virtual ~Impl()
+    {
+    }
+};
+
+class RIMServiceRepos : public ServiceRepos::Impl
+{
+public:
+    ServiceRepos::ProcessRepo _callback;
+    
+    RIMServiceRepos(const ServiceInfo &service,
+                    const ServiceRepos::ProcessRepo & callback,
+                    const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() )
+        : _callback(callback)
+    {
+      // repoindex.xml must be fetched always without using cookies (bnc #573897)
+      Url serviceUrl( service.url() );
+      serviceUrl.setQueryParam( "cookies", "0" );
+      
+      // download the repo index file
+      media::MediaManager mediamanager;
+      media::MediaAccessId mid = mediamanager.open( serviceUrl );
+      mediamanager.attach( mid );
+      mediamanager.provideFile( mid, "repo/repoindex.xml" );
+      Pathname path = mediamanager.localPath(mid, "repo/repoindex.xml" );
+      parser::RepoindexFileReader reader(path, _callback);
+      mediamanager.release( mid );
+      mediamanager.close( mid );
+    }
+    
+    ~RIMServiceRepos()
+    {
+
+    }
+};
+
+class LocalServiceRepos : public ServiceRepos::Impl
+{
+public:
+    ServiceRepos::ProcessRepo _callback;
+    
+    LocalServiceRepos(const ServiceInfo &service,
+                      const ServiceRepos::ProcessRepo & callback,
+                      const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() )
+        : _callback(callback)
+    {
+      Url serviceUrl( service.url() );
+      stringstream buffer;
+     
+      ExternalProgram prog(serviceUrl.getPathName(), ExternalProgram::Discard_Stderr, false, -1, true);
+      std::string line;
+      for(line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
+          buffer << line;
+      prog.close();
+      parser::RepoFileReader parser(buffer, _callback);
+    }
+    
+    ~LocalServiceRepos()
+    {
+
+    }
+};
+
+    
+ServiceRepos::ServiceRepos(const ServiceInfo &service,
+                           const ServiceRepos::ProcessRepo & callback,
+                           const ProgressData::ReceiverFnc &progress)
+    : _impl( (service.type() == ServiceType::LOCAL) ? (ServiceRepos::Impl *)(new LocalServiceRepos(service, callback, progress)) : (ServiceRepos::Impl *)(new RIMServiceRepos(service, callback, progress)))
+{
+}
+    
+ServiceRepos::~ServiceRepos()
+{
+}
+    
+
+}
+}
diff --git a/zypp/repo/ServiceRepos.h b/zypp/repo/ServiceRepos.h
new file mode 100644 (file)
index 0000000..66bef82
--- /dev/null
@@ -0,0 +1,53 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+
+#ifndef ZYPP_REPO_SERVICE_REPOS
+#define ZYPP_REPO_SERVICE_REPOS
+
+#include "zypp/base/NonCopyable.h"
+#include "zypp/ProgressData.h"
+#include "zypp/ServiceInfo.h"
+#include "zypp/RepoInfo.h"
+
+namespace zypp
+{
+  namespace repo
+  {
+    /**
+     * Retrieval of repository list for
+     * a service
+     */
+    class ServiceRepos : private base::NonCopyable
+    {
+    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;
+
+      ServiceRepos(const ServiceInfo &service,
+                   const ProcessRepo & callback,
+                   const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() );
+      ~ServiceRepos();
+
+      /** Implementation  */
+      class Impl;
+    private:
+      RW_pointer<Impl> _impl;
+    };
+  } // ns repo
+} // ns zypp
+
+#endif
index 80a217b..33077d5 100644 (file)
@@ -22,6 +22,7 @@ namespace zypp
 
   const ServiceType ServiceType::RIS(ServiceType::RIS_e);
   const ServiceType ServiceType::NONE(ServiceType::NONE_e);
+  const ServiceType ServiceType::LOCAL(ServiceType::LOCAL_e);
 
   ServiceType::ServiceType(const std::string & strval_r)
     : _type(parse(strval_r))
@@ -36,6 +37,8 @@ namespace zypp
       _table["RIS"] = ServiceType::RIS_e;
       _table["nu"] = ServiceType::RIS_e;
       _table["NU"] = ServiceType::RIS_e;
+      _table["local"] = ServiceType::LOCAL_e;
+      _table["LOCAL"] = ServiceType::LOCAL_e;
       _table["NONE"] = _table["none"] = ServiceType::NONE_e;
     }
 
@@ -57,6 +60,7 @@ namespace zypp
     {
       // initialize it
       _table[RIS_e]  = "ris";
+      _table[LOCAL_e]  = "local";
       _table[NONE_e] = "NONE";
     }
     return _table[_type];
index ad347c4..94fb404 100644 (file)
@@ -32,11 +32,13 @@ namespace zypp
     static const ServiceType RIS;
     /** No service set. */
     static const ServiceType NONE;
+    static const ServiceType LOCAL;
 
     enum Type
     {
       NONE_e,
       RIS_e,
+      LOCAL_e,
     };
 
     ServiceType() : _type(NONE_e) {}