# See './mkChangelog -h' for help.
#
SET(LIBZYPP_MAJOR "14")
-SET(LIBZYPP_COMPATMINOR "27")
-SET(LIBZYPP_MINOR "27")
-SET(LIBZYPP_PATCH "2")
+SET(LIBZYPP_COMPATMINOR "28")
+SET(LIBZYPP_MINOR "28")
+SET(LIBZYPP_PATCH "0")
#
-# LAST RELEASED: 14.27.2 (27)
+# LAST RELEASED: 14.28.0 (28)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
-------------------------------------------------------------------
+Fri Sep 5 12:46:57 CEST 2014 - ma@suse.de
+
+- Make Repository::isUpdateRepo also check for being referenced
+ by products (bnc#892579)
+- Report repositories skipped as nonroot due to insufficient
+ permission (bnc#893260)
+- version 14.28.0 (28)
+
+-------------------------------------------------------------------
+Thu Sep 4 01:14:34 CEST 2014 - ma@suse.de
+
+- Update zypp-po.tar.bz2
+
+-------------------------------------------------------------------
Fri Aug 29 14:46:25 CEST 2014 - ma@suse.de
- PackageProvider: consider toplevel cache if --root or --pkg-cachedir
CpeId( "", CpeId::noThrow );
BOOST_CHECK_EQUAL( CpeId::NoThrowType::lastMalformed, "" );
- for ( const auto & c : { CpeId(), CpeId( nullptr ), CpeId( "" ), CpeId( std::string() ) } )
+ for ( const auto & c : { CpeId(), CpeId( nullptr ), CpeId( "" ), CpeId( std::string() ), CpeId( "cpe:2.3:" ), CpeId( "cpe:/" ) } )
{
BOOST_CHECK( ! c ); // evaluate false in boolean context
BOOST_CHECK_EQUAL( c.asString(), c.asFs() );
field.reserve( Attribute::numAttributes );
if ( str::splitFields( cpe_r.c_str()+8/* skip magic 'cpe:2.3:' */, std::back_inserter(field), ":" ) > Attribute::numAttributes )
throw std::invalid_argument( str::Str() << "CpeId:Fs: too many fields (" << field.size() << "); expected 11" /*<< Attribute::numAttributes but g++ currently can't resoolve this as constexpr*/ );
- if ( field.back().empty() ) // A trailing ':' leads to an empty (illegal) field, but we fillup missing fields with ANY|"*"
+ if ( !field.empty() && field.back().empty() ) // A trailing ':' leads to an empty (illegal) field, but we fillup missing fields with ANY|"*"
field.back() = "*";
field.resize( Attribute::numAttributes, "*" ); // fillup with ANY|"*"
Date Product::endOfLife() const
{ return Date( lookupNumAttribute( sat::SolvAttr::productEndOfLife ) );}
- unsigned Product::updateContentIdentifierSize( std::list<Repository::ContentIdentifier> & ret_r ) const
+ std::vector<Repository::ContentIdentifier> Product::updateContentIdentifier() const
+ {
+ std::vector<Repository::ContentIdentifier> ret;
+ sat::LookupAttr q( sat::SolvAttr::productUpdatesRepoid, sat::SolvAttr::productUpdates, *this );
+ if ( ! q.empty() )
+ {
+ ret.reserve( 2 );
+ for_( it, q.begin(), q.end() )
+ ret.push_back( it.asString() );
+ }
+ return ret;
+ }
+
+ bool Product::hasUpdateContentIdentifier( const Repository::ContentIdentifier & cident_r ) const
{
sat::LookupAttr q( sat::SolvAttr::productUpdatesRepoid, sat::SolvAttr::productUpdates, *this );
for_( it, q.begin(), q.end() )
{
- ret_r.push_back( it.asString() );
+ if ( it.asString() == cident_r )
+ return true;
}
- return q.size();
+ return false;
}
bool Product::isTargetDistribution() const
/** The date when this Product goes out of support as indicated by it's medadata. */
Date endOfLife() const;
- /** ContentIdentifier of required update repositories.
- * \todo remove and provide iterator.
- */
- unsigned updateContentIdentifierSize( std::list<Repository::ContentIdentifier> & ret_r ) const;
+ /** ContentIdentifier of required update repositories. */
+ std::vector<Repository::ContentIdentifier> updateContentIdentifier() const;
+
+ /** Whether \a cident_r is listed as required update repository. */
+ bool hasUpdateContentIdentifier( const Repository::ContentIdentifier & cident_r ) const;
+
+ /** Whether one of the ContentIdentifier is listed as required update repository. */
+ template <class _Iterator>
+ bool hasUpdateContentIdentifier( _Iterator begin, _Iterator end ) const
+ {
+ for_( it, begin, end )
+ if ( hasUpdateContentIdentifier( *it ) )
+ return true;
+ return false;
+ }
public:
/** This is the \b installed product that is also targeted by the
MIL << "repo file: " << file << endl;
RepoCollector collector;
parser::RepoFileReader parser( file, bind( &RepoCollector::collect, &collector, _1 ) );
- return collector.repos;
+ return std::move(collector.repos);
}
////////////////////////////////////////////////////////////////////////////
{
MIL << "directory " << dir << endl;
std::list<RepoInfo> repos;
- std::list<Pathname> entries;
- if ( filesystem::readdir( entries, dir, false ) != 0 )
+ bool nonroot( geteuid() != 0 );
+ if ( nonroot && ! PathInfo(dir).userMayRX() )
{
- // TranslatorExplanation '%s' is a pathname
- ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
+ JobReport::warning( formatNAC(_("Cannot read repo directory ‘%1%’: Permission denied")) % dir );
}
-
- str::regex allowedRepoExt("^\\.repo(_[0-9]+)?$");
- for ( std::list<Pathname>::const_iterator it = entries.begin(); it != entries.end(); ++it )
+ else
{
- if (str::regex_match(it->extension(), allowedRepoExt))
+ std::list<Pathname> entries;
+ if ( filesystem::readdir( entries, dir, false ) != 0 )
{
- std::list<RepoInfo> tmp = repositories_in_file( *it );
- repos.insert( repos.end(), tmp.begin(), tmp.end() );
+ // TranslatorExplanation '%s' is a pathname
+ ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
+ }
- //std::copy( collector.repos.begin(), collector.repos.end(), std::back_inserter(repos));
- //MIL << "ok" << endl;
+ str::regex allowedRepoExt("^\\.repo(_[0-9]+)?$");
+ for ( std::list<Pathname>::const_iterator it = entries.begin(); it != entries.end(); ++it )
+ {
+ if ( str::regex_match(it->extension(), allowedRepoExt) )
+ {
+ if ( nonroot && ! PathInfo(*it).userMayR() )
+ {
+ JobReport::warning( formatNAC(_("Cannot read repo file ‘%1%’: Permission denied")) % *it );
+ }
+ else
+ {
+ const std::list<RepoInfo> & tmp( repositories_in_file( *it ) );
+ repos.insert( repos.end(), tmp.begin(), tmp.end() );
+ }
+ }
}
}
return repos;
#include "zypp/sat/detail/PoolImpl.h"
#include "zypp/Repository.h"
+#include "zypp/ResPool.h"
+#include "zypp/Product.h"
#include "zypp/sat/Pool.h"
using std::endl;
bool Repository::providesUpdatesFor( const CpeId & cpeid_r ) const
{
NO_REPOSITORY_RETURN( false );
+ if ( ! cpeid_r )
+ return false; // filter queries/products without CpeId, as an empty CpeId matches ANYthing.
+
+ // check in repository metadata
for_( it, updatesProductBegin(), updatesProductEnd() )
{
if ( compare( cpeid_r, it.cpeId(), SetRelation::subset ) )
return true;
}
+
+ // check whether known products refer to this as update repo
+ sat::LookupRepoAttr myIds( sat::SolvAttr::repositoryRepoid, *this ); // usually just one, but...
+ if ( ! myIds.empty() )
+ {
+ const ResPool & pool( ResPool::instance() );
+ for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() )
+ {
+ Product::constPtr prod( (*it)->asKind<Product>() );
+ if ( compare( cpeid_r, prod->cpeId(), SetRelation::superset ) )
+ {
+ for_( myId, myIds.begin(), myIds.end() )
+ {
+ if ( prod->hasUpdateContentIdentifier( myId.asString() ) )
+ return true;
+ }
+ }
+ }
+ }
return false;
}
bool Repository::isUpdateRepo() const
{
NO_REPOSITORY_RETURN( false );
- return ( updatesProductBegin() != updatesProductEnd() );
+
+ // check in repository metadata
+ if ( updatesProductBegin() != updatesProductEnd() )
+ return true;
+
+ // check whether known products refer to this as update repo
+ sat::LookupRepoAttr myIds( sat::SolvAttr::repositoryRepoid, *this ); // usually just one, but...
+ if ( ! myIds.empty() )
+ {
+ const ResPool & pool( ResPool::instance() );
+ for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() )
+ {
+ for_( myId, myIds.begin(), myIds.end() )
+ {
+ if ( (*it)->asKind<Product>()->hasUpdateContentIdentifier( myId.asString() ) )
+ return true;
+ }
+ }
+ }
+ return false;
}
bool Repository::solvablesEmpty() const
*/
bool maybeOutdated() const;
- /**
- * if the repository claims to update something then
- * it is an update repository
- *
- * This is implemented by looking at the repository updates
- * tag.
- * \see http://en.opensuse.org/Standards/Rpm_Metadata#SUSE_repository_info_.28suseinfo.xml.29.2C_extensions_to_repomd.xml
+ /** Hint whether the Repo may provide updates for a product.
+ *
+ * Either the repository claims to update a product via a repository updates
+ * tag in it's metadata or a known product lists the repositories ContentIdentifier
+ * as required update repo.
*/
bool isUpdateRepo() const;
- /** Whether the repository claims to provide updates for product identified by it's \ref CpeId */
+ /** Hint whether the Repo may provide updates for a product identified by it's \ref CpeId
+ *
+ * Either the repository claims to update a product via a repository updates
+ * tag in it's metadata or a known product lists the repositories ContentIdentifier
+ * as required update repo.
+ */
bool providesUpdatesFor( const CpeId & cpeid_r ) const;
/** Whether \ref Repository contains solvables. */
public:
- /** Query class for Repository */
+ /** Query class for Repository related products */
class ProductInfoIterator;
/**
ProductInfoIterator compatibleWithProductEnd() const;
/**
- * Get an iterator to the beginning of the repository
- * compatible distros.
+ * Get an iterator to the beginning of distos the repository
+ * provides upadates for.
+ * \note This is only a hint within the repositories metadata.
+ * The same realation might be expressed by a product listing
+ * this repositories ContentIdentifier as required update repo.
* \see Repository::ProductInfoIterator
*/
ProductInfoIterator updatesProductBegin() const;
/**
- * Get an iterator to the end of the repository
- * compatible distros.
+ * Get an iterator to the end of distos the repository
+ * provides upadates for.
* \see Repository::ProductInfoIterator
*/
ProductInfoIterator updatesProductEnd() const;
/**
* Query class for Repository related products
*
+ * Products are identified by CpeIds within the repositories metadata.
+ * \see http://en.opensuse.org/Standards/Rpm_Metadata#SUSE_repository_info_.28suseinfo.xml.29.2C_extensions_to_repomd.xml
+ *
* The iterator does not provide a dereference
* operator so you can do * on it, but you can
* access the attributes of each related product
* \code
* for_( it, repo.compatibleWithProductBegin(), repo.compatibleWithProductEnd() )
* {
- * cout << it.cpeid() << endl;
+ * cout << it.label() << ": " << it.cpeid() << endl;
* }
* \endcode
*
public:
Impl()
: _trans( ::transaction_create( nullptr ) )
- { memset( _trans, 0, sizeof(_trans) ); }
+ { memset( _trans, 0, sizeof(*_trans) ); }
Impl( LoadFromPoolType )
: _watcher( myPool().serial() )