From 90dcbc247268cd644feded3c68f09a4232187e91 Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Wed, 18 Apr 2007 12:56:52 +0000 Subject: [PATCH] Support filesystem dependencies to add needed filesystem RPMs automatically (Fate 301966). --- zypp/CMakeLists.txt | 3 + zypp/CapFactory.cc | 20 +++++- zypp/CapFactory.h | 12 +++- zypp/SystemResObject.cc | 1 + zypp/capability/CapTraits.cc | 2 + zypp/capability/CapTraits.h | 1 + zypp/capability/Capabilities.h | 2 + zypp/capability/CapabilityImpl.cc | 51 +++++++++++++--- zypp/capability/CapabilityImpl.h | 124 +++++++++++++++++++++++++++----------- zypp/capability/FilesystemCap.cc | 89 +++++++++++++++++++++++++++ zypp/capability/FilesystemCap.h | 86 ++++++++++++++++++++++++++ 11 files changed, 342 insertions(+), 49 deletions(-) create mode 100644 zypp/capability/FilesystemCap.cc create mode 100644 zypp/capability/FilesystemCap.h diff --git a/zypp/CMakeLists.txt b/zypp/CMakeLists.txt index 44c6dc4..86ab0e1 100644 --- a/zypp/CMakeLists.txt +++ b/zypp/CMakeLists.txt @@ -235,6 +235,7 @@ SET( zypp_base_HEADERS base/Sysconfig.h base/UniqueString.h base/Unit.h + base/WatchFile.h ) INSTALL( FILES @@ -248,6 +249,7 @@ SET( zypp_capability_SRCS capability/FileCap.cc capability/HalCap.cc capability/ModaliasCap.cc + capability/FilesystemCap.cc capability/NamedCap.cc capability/NullCap.cc capability/SplitCap.cc @@ -262,6 +264,7 @@ SET( zypp_capability_HEADERS capability/FileCap.h capability/HalCap.h capability/ModaliasCap.h + capability/FilesystemCap.h capability/NamedCap.h capability/NullCap.h capability/OrCap.h diff --git a/zypp/CapFactory.cc b/zypp/CapFactory.cc index a4c15dd..9a61d48 100644 --- a/zypp/CapFactory.cc +++ b/zypp/CapFactory.cc @@ -148,7 +148,7 @@ namespace zypp */ struct CapFactory::Impl { - + }; /////////////////////////////////////////////////////////////////// @@ -191,7 +191,7 @@ namespace zypp ZYPP_RETHROW( excpt ); return Capability(); // not reached } - + /////////////////////////////////////////////////////////////////// // // METHOD NAME : CapFactory::parse @@ -281,6 +281,22 @@ namespace zypp /////////////////////////////////////////////////////////////////// // + // METHOD NAME : CapFactory::filesystemEvalCap + // METHOD TYPE : Capability + // + Capability CapFactory::filesystemEvalCap() const + try + { + return Capability( usetInsert( ::zypp::capability::buildFilesystem( Resolvable::Kind(), "filesystem()" ) ) ); + } + catch ( Exception & excpt ) + { + ZYPP_RETHROW( excpt ); + return Capability(); // not reached + } + + /////////////////////////////////////////////////////////////////// + // // METHOD NAME : CapFactory::encode // METHOD TYPE : std::string // diff --git a/zypp/CapFactory.h b/zypp/CapFactory.h index 947e5e9..622dc06 100644 --- a/zypp/CapFactory.h +++ b/zypp/CapFactory.h @@ -47,13 +47,13 @@ namespace zypp ~CapFactory(); public: - + /** Create capability from Implementation * \a impl is a valid \ref CapabilityImpl Ptr * \throw EXCEPTION on null capability */ Capability fromImpl( capability::CapabilityImpl::Ptr impl ) const; - + /** Parse Capability from string providing Resolvable::Kind. * \a strval_r is expected to define a valid Capability. * \throw EXCEPTION on parse error. @@ -78,6 +78,7 @@ namespace zypp Rel op_r, const Edition & edition_r ) const; + public: /** Special Capability, triggering evaluation of Hal * capabilities when matched. */ @@ -88,7 +89,12 @@ namespace zypp */ Capability modaliasEvalCap() const; - public: + /** Special Capability, triggering evaluation of filesystem + * capabilities when matched. + */ + Capability filesystemEvalCap() const; + + public: /** Provide a parsable string representation of \a cap_r. */ std::string encode( const Capability & cap_r ) const; diff --git a/zypp/SystemResObject.cc b/zypp/SystemResObject.cc index 3266352..3dba737 100644 --- a/zypp/SystemResObject.cc +++ b/zypp/SystemResObject.cc @@ -51,6 +51,7 @@ namespace zypp NVRAD dataCollect( "system" ); dataCollect[Dep::PROVIDES].insert( CapFactory().halEvalCap() ); dataCollect[Dep::PROVIDES].insert( CapFactory().modaliasEvalCap() ); + dataCollect[Dep::PROVIDES].insert( CapFactory().filesystemEvalCap() ); detail::ResImplTraits::Ptr sysImpl; _ptr = detail::makeResolvableAndImpl( dataCollect, sysImpl ); diff --git a/zypp/capability/CapTraits.cc b/zypp/capability/CapTraits.cc index abcc505..f6b3aa0 100644 --- a/zypp/capability/CapTraits.cc +++ b/zypp/capability/CapTraits.cc @@ -34,6 +34,8 @@ namespace zypp template<> const CapabilityTraits::KindType CapTraits ::kind( "ModaliasCap" ); template<> + const CapabilityTraits::KindType CapTraits ::kind( "FilesystemCap" ); + template<> const CapabilityTraits::KindType CapTraits ::kind( "OrCap" ); template<> const CapabilityTraits::KindType CapTraits::kind( "ConditionalCap" ); diff --git a/zypp/capability/CapTraits.h b/zypp/capability/CapTraits.h index 724a7c2..186df7d 100644 --- a/zypp/capability/CapTraits.h +++ b/zypp/capability/CapTraits.h @@ -38,6 +38,7 @@ namespace zypp class SplitCap; class HalCap; class ModaliasCap; + class FilesystemCap; class OrCap; class ConditionalCap; diff --git a/zypp/capability/Capabilities.h b/zypp/capability/Capabilities.h index 3d2e2cf..942324c 100644 --- a/zypp/capability/Capabilities.h +++ b/zypp/capability/Capabilities.h @@ -21,6 +21,8 @@ #include "zypp/capability/SplitCap.h" #include "zypp/capability/HalCap.h" #include "zypp/capability/ModaliasCap.h" +#include "zypp/capability/FilesystemCap.h" + //#include "zypp/capability/OrCap.h" //#include "zypp/capability/ConditionalCap.h" diff --git a/zypp/capability/CapabilityImpl.cc b/zypp/capability/CapabilityImpl.cc index f3f1a21..9ee2ae8 100644 --- a/zypp/capability/CapabilityImpl.cc +++ b/zypp/capability/CapabilityImpl.cc @@ -92,7 +92,7 @@ namespace zypp ZYPP_THROW( Exception("Unknow Operator NONE is not allowed in Capability") ); return false; // not reached } - + bool isFileSpec( const std::string & name_r ) { return *name_r.c_str() == '/'; @@ -113,6 +113,11 @@ namespace zypp return name_r.substr(0,9) == "modalias("; } + bool isFilesystemSpec( const std::string & name_r ) + { + return name_r.substr(0,11) == "filesystem("; + } + CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r, const std::string & name_r ) { @@ -145,6 +150,10 @@ namespace zypp { return new capability::FileCap( refers_r, name_r ); } + if ( isFilesystemSpec( name_r ) ) + { + return buildFilesystem( refers_r, name_r ); + } //split: name:/absolute/path static const str::regex rx( "([^/]*):(/.*)" ); @@ -224,9 +233,31 @@ namespace zypp return NULL; // make gcc happy } - CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, - const std::string & strval_r ) + /****************************************************************** + ** + ** FUNCTION NAME : buildFilesystem + ** FUNCTION TYPE : CapabilityImpl::Ptr + */ + CapabilityImpl::Ptr buildFilesystem( const Resolvable::Kind & refers_r, + const std::string & name_r ) + { + //split: filesystem(name) [op string] + static const str::regex rx( "filesystem\\(([^)]*)\\)" ); + str::smatch what; + if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) ) + { + // Filesystem always refers to 'System' kind of Resolvable + return new capability::FilesystemCap( ResTraits::kind, + what[1].str() ); + } + // otherwise + ZYPP_THROW( Exception("Unsupported kind of Filesystem Capability'" + name_r + "'") ); + return NULL; // make gcc happy + } + + CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, + const std::string & strval_r ) try { if ( isHalSpec( strval_r ) ) @@ -237,6 +268,10 @@ namespace zypp { return buildModalias( refers_r, strval_r ); } + if ( isFilesystemSpec( strval_r ) ) + { + return buildFilesystem( refers_r, strval_r ); + } if ( isFileSpec( strval_r ) ) { return buildFile( refers_r, strval_r ); @@ -287,7 +322,7 @@ namespace zypp { if ( isHalSpec( name_r ) ) { - return buildHal( refers_r, name_r, Rel(op_r), edition_r ); + return buildHal( refers_r, name_r, Rel(op_r), edition_r ); } if ( isModaliasSpec( name_r ) ) { @@ -308,9 +343,9 @@ namespace zypp // METHOD TYPE : Capability // CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, - const std::string & name_r, - Rel op_r, - const Edition & edition_r ) + const std::string & name_r, + Rel op_r, + const Edition & edition_r ) try { if ( isHalSpec( name_r ) ) @@ -328,7 +363,7 @@ namespace zypp ZYPP_RETHROW( excpt ); return NULL; // not reached } - + /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// diff --git a/zypp/capability/CapabilityImpl.h b/zypp/capability/CapabilityImpl.h index 138f0bb..531ec9d 100644 --- a/zypp/capability/CapabilityImpl.h +++ b/zypp/capability/CapabilityImpl.h @@ -27,12 +27,41 @@ namespace zypp { ///////////////////////////////////////////////////////////////// DEFINE_PTR_TYPE(CapabilityImpl) - + /////////////////////////////////////////////////////////////////// // // CLASS NAME : CapabilityImpl // /** Abstract base for Capability implementations. + * + * Example: Adding a new kind of capability: FilesystemCap + * \code + * 1) Create the implementataion files + * zypp/capability/FilesystemCap.h + * zypp/capability/FilesystemCap.cc + * for + * class FilesystemCap : public CapabilityImpl + * + * 2) Add include in zypp/capability/Capabilities.h + * #include "zypp/capability/FilesystemCap.h" + * + * 3) Add forward declaration in zypp/capability/CapTraits.h + * class FilesystemCap; + * + * 4) Define the capabilities kind in zypp/capability/CapTraits.cc + * template<> + * const CapabilityTraits::KindType CapTraits ::kind( "FilesystemCap" ); + * + * 5) If needed, define the EvalCap in zypp/CapFactory.h + * Capability filesystemEvalCap() const; + * What's this? + * Some capabilities are not evaluated by comparing 2 capabilities, but represent a query + * for some system property: 'filesystem(xfs)' -> 'xfs is listed in /etc/sysconfig/stoage'. + * The query is performed iff the capability is compared to a special EvalCap, which is usg. + * provided by a special SystemResolvable> + * : provides : filesystem() // the filesystemEvalCap + * : supplements : filesystem(xfs) // a package that supplements xfs filesystem + * \endcode */ class CapabilityImpl : public base::ReferenceCounted, private base::NonCopyable { @@ -129,7 +158,7 @@ namespace zypp virtual bool capImplOrderLess( const constPtr & rhs ) const; }; /////////////////////////////////////////////////////////////////// - + /** Check whether \a op_r and \a edition_r make a valid edition spec. * * Rel::NONE is not usefull thus forbidden. Rel::ANY can be ignored, @@ -140,22 +169,31 @@ namespace zypp * is not Rel::ANY. */ bool isEditionSpec( Rel op_r, const Edition & edition_r ); - + /** Test for a FileCap. \a name_r starts with \c "/". */ bool isFileSpec( const std::string & name_r ); - + /** Test for a SplitCap. \a name_r constains \c ":/". */ bool isSplitSpec( const std::string & name_r ); - + /** Test for a HalCap. \a name_r starts with "hal(". */ bool isHalSpec( const std::string & name_r ); - - /** Test for a ModaliasCap. \a name_r starts with "modalias(". */ + + /** Test for a ModaliasCap. \a name_r starts with "modalias(". */ bool isModaliasSpec( const std::string & name_r ); - + + /** Test for a FilesystemCap. \a name_r starts with "filesystem(". */ + bool isFilesystemSpec( const std::string & name_r ); + + /** Try to build a file cap from \a name_r . + * + * The CapabilityImpl is built here and inserted into _uset. + * The final Capability must be created by CapFactory, as it + * is a friend of Capability. Here we can't access the ctor. + */ CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r, - const std::string & name_r ); - + const std::string & name_r ); + /** Try to build a non versioned cap from \a name_r . * * The CapabilityImpl is built here and inserted into _uset. @@ -163,8 +201,8 @@ namespace zypp * is a friend of Capability. Here we can't access the ctor. */ CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r, - const std::string & name_r ); - + const std::string & name_r ); + /** Try to build a versioned cap from \a name_r . * * The CapabilityImpl is built here and inserted into _uset. @@ -174,10 +212,10 @@ namespace zypp * \todo Quick check for name not being filename or split. */ CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r, - const std::string & name_r, - Rel op_r, - const Edition & edition_r ); - + const std::string & name_r, + Rel op_r, + const Edition & edition_r ); + /** Try to build a hal cap from \a name_r . * * The CapabilityImpl is built here @@ -187,10 +225,10 @@ namespace zypp * \todo Fix incaccuracy. */ CapabilityImpl::Ptr buildHal( const Resolvable::Kind & refers_r, - const std::string & name_r, - Rel op_r = Rel::ANY, - const std::string & value_r = std::string() ); - + const std::string & name_r, + Rel op_r = Rel::ANY, + const std::string & value_r = std::string() ); + /** Try to build a modalias cap from \a name_r . * * The CapabilityImpl is built here @@ -200,22 +238,36 @@ namespace zypp * \todo Fix incaccuracy. */ CapabilityImpl::Ptr buildModalias( const Resolvable::Kind & refers_r, - const std::string & name_r, - Rel op_r = Rel::ANY, - const std::string & value_r = std::string() ); - - - CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, - const std::string & strval_r ); - CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, - const std::string & name_r, - const std::string & op_r, - const std::string & edition_r ); - CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, - const std::string & name_r, - Rel op_r, - const Edition & edition_r ); - + const std::string & name_r, + Rel op_r = Rel::ANY, + const std::string & value_r = std::string() ); + + /** Try to build a filesystem cap from \a name_r . + * + * The CapabilityImpl is built here + * The final Capability must be created by CapFactory, as it + * is a friend of Capability. Here we can't access the ctor. + * + * \todo Fix incaccuracy. + */ + CapabilityImpl::Ptr buildFilesystem( const Resolvable::Kind & refers_r, + const std::string & name_r ); + + /////////////////////////////////////////////////////////////////// + + CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, + const std::string & strval_r ); + + CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, + const std::string & name_r, + const std::string & op_r, + const std::string & edition_r ); + + CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r, + const std::string & name_r, + Rel op_r, + const Edition & edition_r ); + /** Test whether a CapabilityImpl is of a certain Kind. * \code * isKind(cap); diff --git a/zypp/capability/FilesystemCap.cc b/zypp/capability/FilesystemCap.cc new file mode 100644 index 0000000..aebe0ba --- /dev/null +++ b/zypp/capability/FilesystemCap.cc @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/capability/FilesystemCap.cc + * +*/ +#include + +#include "zypp/base/Logger.h" +#include "zypp/base/WatchFile.h" +#include "zypp/base/Sysconfig.h" + +#include "zypp/capability/FilesystemCap.h" + +using namespace std; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace capability + { ///////////////////////////////////////////////////////////////// + + /** Ctor */ + FilesystemCap::FilesystemCap( const Resolvable::Kind & refers_r, + const std::string & name_r ) + : CapabilityImpl( refers_r ) + , _name( name_r ) + {} + + const CapabilityImpl::Kind & FilesystemCap::kind() const + { return CapTraits::kind; } + + CapMatch FilesystemCap::matches( const constPtr & rhs ) const + { + if ( sameKindAndRefers( rhs ) ) + { + intrusive_ptr filesystemrhs( asKind(rhs) ); + if ( isEvalCmd() == filesystemrhs->isEvalCmd() ) + return CapMatch::irrelevant; + + return( isEvalCmd() ? filesystemrhs->evaluate() : evaluate() ); + } + return false; + } + + std::string FilesystemCap::encode() const + { + std::string ret( "filesystem(" ); + ret += _name; + ret += ")"; + return ret; + } + + std::string FilesystemCap::index() const + { + return "filesystem()"; + } + + bool FilesystemCap::isEvalCmd() const + { return _name.empty(); } + + bool FilesystemCap::evaluate() const + { + static WatchFile sysconfigFile( "/etc/sysconfig/storage", WatchFile::NO_INIT ); + static std::set fs; + + if ( sysconfigFile.hasChanged() ) + { + std::set newfs; + str::split( base::sysconfig::read( sysconfigFile.path() )["USED_FS_LIST"], + std::inserter( newfs, newfs.end() ) ); + fs.swap( newfs ); + } + + return( fs.find( _name ) != fs.end() ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace capability + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/capability/FilesystemCap.h b/zypp/capability/FilesystemCap.h new file mode 100644 index 0000000..f05f212 --- /dev/null +++ b/zypp/capability/FilesystemCap.h @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/capability/FilesystemCap.h + * +*/ +#ifndef ZYPP_CAPABILITY_FILESYSTEMCAP_H +#define ZYPP_CAPABILITY_FILESYSTEMCAP_H + +#include "zypp/capability/CapabilityImpl.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace capability + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : FilesystemCap + // + /** A Capability resolved by a query to /etc/sysconfig/storage:USED_FS_LIST + * + * \note FilesystemCap is special as it is self evaluating, and does not + * comapre to the \a rhs (or \a lhs). This is currently solved by + * treating a FilesystemCap with an empty name as evaluate command. + * + * \ref matches returns \c CapMatch::irrelevant, if either both sides + * are evaluate commands, or both are not. + * + * Otherwise the result of the query /etc/sysconfig/storage:USED_FS_LIST + * is returned. Either from \a lhs or \a rhs, dependent on which one is the + * evaluate command. + */ + class FilesystemCap : public CapabilityImpl + { + public: + typedef FilesystemCap Self; + + public: + /** Ctor */ + FilesystemCap( const Resolvable::Kind & refers_r, const std::string & name_r ); + + public: + /** */ + virtual const Kind & kind() const; + + /** Query USED_FS_LIST. */ + virtual CapMatch matches( const constPtr & rhs ) const; + + /** filesystem(name) */ + virtual std::string encode() const; + + /** filesystem() */ + virtual std::string index() const; + + public: + const std::string & name() const + { return _name; } + + private: + /** Empty FilesystemCap filesystem() */ + bool isEvalCmd() const; + + /** Query USED_FS_LIST. */ + bool evaluate() const; + + private: + /** */ + std::string _name; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace capability + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CAPABILITY_FILESYSTEMCAP_H -- 2.7.4