#include <sstream>
#include "zypp/base/Logger.h"
#include "zypp/repo/ServiceRepos.h"
+#include "zypp/repo/RepoException.h"
+#include "zypp/media/MediaException.h"
#include "zypp/parser/RepoFileReader.h"
#include "zypp/media/MediaManager.h"
#include "zypp/parser/RepoindexFileReader.h"
#include "zypp/ExternalProgram.h"
using std::stringstream;
+using std::endl;
+///////////////////////////////////////////////////////////////////
namespace zypp
{
-namespace repo
-{
+ ///////////////////////////////////////////////////////////////////
+ namespace repo
+ {
+ struct ServiceRepos::Impl
+ { virtual ~Impl() {} };
-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()
+ struct RIMServiceRepos : public ServiceRepos::Impl
{
+ RIMServiceRepos( const Pathname & /*root_r*/,
+ const ServiceInfo & service,
+ const ServiceRepos::ProcessRepo & callback,
+ const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() )
+ {
+ // 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" );
+ try {
+ parser::RepoindexFileReader reader(path, callback);
+ service.setProbedTtl( reader.ttl() ); // hack! Modifying the const Service to set parsed TTL
+ mediamanager.release( mid );
+ mediamanager.close( mid );
+ } catch ( const Exception &e ) {
+ //Reader throws a bare exception, we need to translate it into something our calling
+ //code expects and handles (bnc#1116840)
+ ZYPP_CAUGHT ( e );
+ ServicePluginInformalException ex ( e.msg() );
+ ex.remember( e );
+ ZYPP_THROW( ex );
+ }
+ }
+ };
-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()
+ ///////////////////////////////////////////////////////////////////
+
+ struct PluginServiceRepos : public ServiceRepos::Impl
{
+ PluginServiceRepos( const Pathname & root_r,
+ const ServiceInfo & service,
+ const ServiceRepos::ProcessRepo & callback,
+ const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() )
+ {
+ // bsc#1080693: Service script needs to be executed chrooted to the RepoManagers rootDir.
+ // The service is not aware of the rootDir, so it's explicitly passed and needs to be
+ // stripped from the URLs path.
+ stringstream buffer;
- }
-};
+ ExternalProgram::Arguments args;
+ args.reserve( 3 );
+ args.push_back( "/bin/sh" );
+ args.push_back( "-c" );
+ args.push_back( Pathname::stripprefix( root_r, service.url().getPathName() ).asString() );
+ ExternalProgramWithStderr prog( args, root_r );
+ prog >> buffer;
-
-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()
-{
-}
-
+ if ( prog.close() != 0 )
+ {
+ // ServicePluginInformalException:
+ // Ignore this error but we'd like to report it somehow...
+ std::string errbuffer;
+ prog.stderrGetUpTo( errbuffer, '\0' );
+ ERR << "Capture plugin error:[" << endl << errbuffer << endl << ']' << endl;
+ ZYPP_THROW( repo::ServicePluginInformalException( service, errbuffer ) );
+ }
+ parser::RepoFileReader parser( buffer, callback );
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////
+
+ ServiceRepos::ServiceRepos( const Pathname & root_r,
+ const ServiceInfo & service,
+ const ServiceRepos::ProcessRepo & callback,
+ const ProgressData::ReceiverFnc &progress )
+ : _impl( ( service.type() == ServiceType::PLUGIN )
+ ? static_cast<ServiceRepos::Impl*>( new PluginServiceRepos( root_r, service, callback, progress ) )
+ : static_cast<ServiceRepos::Impl*>( new RIMServiceRepos( root_r, service, callback, progress ) ) )
+ {}
+
+ ServiceRepos::~ServiceRepos()
+ {}
-}
-}
+ } // namespace repo
+ ///////////////////////////////////////////////////////////////////
+} //namespace zypp
+///////////////////////////////////////////////////////////////////