/** \file zypp/Patch.cc
*
*/
-extern "C"
-{
-#include <satsolver/repo.h>
-}
+#include <iostream>
-#include "zypp/base/Logger.h"
+#include "zypp/base/LogTools.h"
+#include "zypp/base/String.h"
#include "zypp/Patch.h"
#include "zypp/sat/WhatProvides.h"
{}
///////////////////////////////////////////////////////////////////
- //
- // Patch interface forwarded to implementation
- //
- ///////////////////////////////////////////////////////////////////
+
+ std::string Patch::category() const
+ { return lookupStrAttribute( sat::SolvAttr::patchcategory ); }
Patch::Category Patch::categoryEnum() const
- {
- static const IdString cat_yast( "yast" );
- static const IdString cat_security( "security" );
- static const IdString cat_recommended( "recommended" );
- static const IdString cat_optional( "optional" );
- static const IdString cat_document( "document" );
-
- IdString cat( sat::LookupAttr( sat::SolvAttr::patchcategory ).begin().idStr() );
-
- if ( cat == cat_yast )
- return CAT_YAST;
- if ( cat == cat_security )
- return CAT_SECURITY;
- if ( cat == cat_recommended )
- return CAT_RECOMMENDED;
- if ( cat == cat_optional )
- return CAT_OPTIONAL;
- if ( cat == cat_document )
- return CAT_DOCUMENT;
+ { return categoryEnum( category() ); }
+ bool Patch::isCategory( const std::string & category_r ) const
+ { return( str::compareCI( category_r, category() ) == 0 ); }
+
+ Patch::Category Patch::categoryEnum( const std::string & category_r )
+ {
+ switch ( category_r[0] )
+ {
+ // CAT_YAST
+ case 'y':
+ case 'Y':
+ if ( str::compareCI( category_r, "yast" ) == 0 )
+ return CAT_YAST;
+ break;
+
+ // CAT_SECURITY
+ case 's':
+ case 'S':
+ if ( str::compareCI( category_r, "security" ) == 0 )
+ return CAT_SECURITY;
+ break;
+
+ // CAT_RECOMMENDED
+ case 'r':
+ case 'R':
+ if ( str::compareCI( category_r, "recommended" ) == 0 )
+ return CAT_RECOMMENDED;
+ break;
+ case 'b':
+ case 'B':
+ if ( str::compareCI( category_r, "bugfix" ) == 0 ) // rhn
+ return CAT_RECOMMENDED;
+ break;
+
+ // CAT_OPTIONAL
+ case 'o':
+ case 'O':
+ if ( str::compareCI( category_r, "optional" ) == 0 )
+ return CAT_OPTIONAL;
+ break;
+ case 'f':
+ case 'F':
+ if ( str::compareCI( category_r, "feature" ) == 0 )
+ return CAT_OPTIONAL;
+ break;
+ case 'e':
+ case 'E':
+ if ( str::compareCI( category_r, "enhancement" ) == 0 ) // rhn
+ return CAT_OPTIONAL;
+ break;
+
+ // CAT_DOCUMENT
+ case 'd':
+ case 'D':
+ if ( str::compareCI( category_r, "document" ) == 0 )
+ return CAT_DOCUMENT;
+ break;
+ }
+ // default:
return CAT_OTHER;
}
+ ///////////////////////////////////////////////////////////////////
+
+ std::string Patch::severity() const
+ { return lookupStrAttribute( sat::SolvAttr::severity ); }
+
+ Patch::SeverityFlag Patch::severityFlag() const
+ { return severityFlag( severity() ); }
+
+ bool Patch::isSeverity( const std::string & severity_r ) const
+ { return( str::compareCI( severity_r, severity() ) == 0 ); }
+
+ Patch::SeverityFlag Patch::severityFlag( const std::string & severity_r )
+ {
+ switch ( severity_r[0] )
+ {
+ case 'l':
+ case 'L':
+ if ( str::compareCI( severity_r, "low" ) == 0 )
+ return SEV_LOW;
+ break;
+
+ case 'm':
+ case 'M':
+ if ( str::compareCI( severity_r, "moderate" ) == 0 )
+ return SEV_MODERATE;
+ break;
+
+ case 'i':
+ case 'I':
+ if ( str::compareCI( severity_r, "important" ) == 0 )
+ return SEV_IMPORTANT;
+ break;
+
+ case 'c':
+ case 'C':
+ if ( str::compareCI( severity_r, "critical" ) == 0 )
+ return SEV_CRITICAL;
+ break;
+
+ case 'u':
+ case 'U':
+ if ( str::compareCI( severity_r, "unspecified" ) == 0 )
+ return SEV_NONE;
+ break;
+
+ case '\0':
+ return SEV_NONE;
+ break;
+ }
+ // default:
+ return SEV_OTHER;
+ }
+
+ std::string asString( const Patch::SeverityFlag & obj )
+ {
+ switch ( obj )
+ {
+ case Patch::SEV_NONE: return std::string( "unspecified" ); break;
+ case Patch::SEV_OTHER: return std::string( "unknown" ); break;
+ case Patch::SEV_LOW: return std::string( "low" ); break;
+ case Patch::SEV_MODERATE: return std::string( "moderate" ); break;
+ case Patch::SEV_IMPORTANT:return std::string( "important" ); break;
+ case Patch::SEV_CRITICAL: return std::string( "critical" ); break;
+ }
+ // make gcc happy:
+ return std::string( "unknown" );
+ }
+
+ ///////////////////////////////////////////////////////////////////
+
std::string Patch::message( const Locale & lang_r ) const
{ return lookupStrAttribute( sat::SolvAttr::message, lang_r ); }
- std::string Patch::category() const
- { return lookupStrAttribute( sat::SolvAttr::patchcategory ); }
-
bool Patch::rebootSuggested() const
{ return lookupBoolAttribute( sat::SolvAttr::rebootSuggested ); }
bool Patch::reloginSuggested() const
{ return lookupBoolAttribute( sat::SolvAttr::reloginSuggested ); }
-
- bool Patch::interactive() const
+ Patch::InteractiveFlags Patch::interactiveFlags() const
{
- if ( rebootSuggested()
- || ! message().empty()
- || ! licenseToConfirm().empty() )
- {
- return true;
- }
+ InteractiveFlags patchFlags (NoFlags);
+ if ( rebootSuggested() )
+ patchFlags |= Reboot;
+
+ if ( ! message().empty() )
+ patchFlags |= Message;
+
+ if ( ! licenseToConfirm().empty() )
+ patchFlags |= License;
Patch::Contents c( contents() );
for_( it, c.begin(), c.end() )
{
- if ( ! licenseToConfirm().empty() )
+ if ( ! makeResObject(*it)->licenseToConfirm().empty() )
{
- return true;
+ patchFlags |= License;
+ break;
}
}
+ return patchFlags;
+ }
- return false;
+ bool Patch::interactiveWhenIgnoring( InteractiveFlags flags_r ) const
+ {
+ if ( interactiveFlags() & ( ~flags_r ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
+ bool Patch::interactive() const
+ {
+ return interactiveWhenIgnoring();
+ }
Patch::Contents Patch::contents() const
{
- Contents result;
+ Contents result;
+ // DBG << *this << endl;
+ sat::LookupAttr updateCollection( sat::SolvAttr::updateCollection, satSolvable() );
+ for_( entry, updateCollection.begin(), updateCollection.end() )
+ {
+ IdString name ( entry.subFind( sat::SolvAttr::updateCollectionName ).idStr() );
+ Edition edition ( entry.subFind( sat::SolvAttr::updateCollectionEvr ).idStr() );
+ Arch arch ( entry.subFind( sat::SolvAttr::updateCollectionArch ).idStr() );
+ if ( name.empty() )
+ {
+ WAR << "Ignore malformed updateCollection entry: " << name << "-" << edition << "." << arch << endl;
+ continue;
+ }
- ::Dataiterator di;
- ::dataiterator_init(&di
- , sat::Pool::instance().get()
- , repository().get() // in this repo
- , sat::Solvable::id() // in metadata
- , UPDATE_COLLECTION, 0, 0 );
+ // The entry is relevant if there is an installed
+ // package with the same name and arch.
+ bool relevant = false;
+ sat::WhatProvides providers( (Capability( name.id() )) );
+ for_( it, providers.begin(), providers.end() )
+ {
+ if ( it->isSystem() && it->ident() == name && it->arch() == arch )
+ {
+ relevant = true;
+ break;
+ }
+ }
+ if ( ! relevant )
+ {
+ // DBG << "Not relevant: " << name << "-" << edition << "." << arch << endl;
+ continue;
+ }
- while (::dataiterator_step(&di))
+ /* find exact providers first (this matches the _real_ 'collection content' of the patch */
+ providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::EQ, edition, ResKind::package ) );
+ if ( providers.empty() )
{
- ::dataiterator_setpos( &di );
- ::Dataiterator di2;
- ::dataiterator_init(&di2
- , sat::Pool::instance().get()
- , repository().get() // in this repo
- , SOLVID_POS // in metadata
- ,0,0,0 );
-
- IdString nameid;
- Edition evr;
- Arch arch;
-
- while (::dataiterator_step(&di2))
- {
- switch ( di2.key->name )
- {
- case UPDATE_COLLECTION_NAME:
- nameid = IdString(di2.kv.id);
- break;
- case UPDATE_COLLECTION_EVR:
- evr = Edition(di2.kv.id);
- break;
- case UPDATE_COLLECTION_ARCH:
- arch = Arch(di2.kv.id);
- break;
- }
- }
-
- if ( nameid.empty() )
- continue;
-
- /* search providers of name */
- sat::WhatProvides providers( Capability( nameid.c_str() ) );
- MIL << *this << " providers: " << endl;
- MIL << providers << endl;
-
- if (providers.empty())
- {
- WAR << *this << " misses provider for '" << nameid << "'" << endl;
- continue;
- }
-
- bool is_relevant = false;
- for_( it, providers.begin(), providers.end() )
- {
- if (it->ident() != nameid) /* package _name_ must match */
- continue;
-
- if (it->isSystem() /* only look at installed providers with same arch */
- && it->arch() == arch)
- {
- is_relevant = true;
- }
- }
- if (!is_relevant)
- {
- MIL << *this << " is not relevant to the system" << endl;
-
- continue; /* skip if name.arch is not installed */
- }
-
-
- /* find exact providers first (this matches the _real_ 'collection content' of the patch */
- sat::WhatProvides exact_providers( Capability( nameid.c_str(), Rel::EQ, evr, ResKind::package ) );
- if (exact_providers.empty())
- {
- /* no exact providers: find 'best' providers: those with a larger evr */
- sat::WhatProvides best_providers( Capability( nameid.c_str(), Rel::GT, evr, ResKind::package ) );
- if (best_providers.empty())
- {
- // Hmm, this patch is not installable, noone is providing the package in the collection
- // FIXME: raise execption ? fake a solvable ?
- }
- else
- {
- // FIXME ?! loop over providers and try to find installed ones ?
- result.get().insert( *(best_providers.begin()) );
- }
- }
- else
- {
- // FIXME ?! loop over providers and try to find installed ones ?
- result.get().insert( *(exact_providers.begin()) );
- }
- } /* while (attribute array) */
-
- return result;
- }
+ /* no exact providers: find 'best' providers: those with a larger evr */
+ providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::GT, edition, ResKind::package ) );
+ if ( providers.empty() )
+ {
+ // Hmm, this patch is not installable, no one is providing the package in the collection
+ // FIXME: raise execption ? fake a solvable ?
+ WAR << "Missing provider: " << name << "-" << edition << "." << arch << endl;
+ continue;
+ }
+ }
+
+ // FIXME ?! loop over providers and try to find installed ones ?
+ // DBG << "Found " << name << "-" << edition << "." << arch << ": " << *(providers.begin()) << endl;
+ result.get().insert( *(providers.begin()) );
+ }
+ return result;
+ }
///////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////
Patch::ReferenceIterator::ReferenceIterator( const sat::Solvable & val_r )
- {
- base_reference() = sat::LookupAttr( sat::SolvAttr::updateReferenceId,
- val_r ).begin();
- _hrefit = sat::LookupAttr( sat::SolvAttr::updateReferenceHref,
- val_r ).begin();
- _titleit = sat::LookupAttr( sat::SolvAttr::updateReferenceTitle,
- val_r ).begin();
- _typeit = sat::LookupAttr( sat::SolvAttr::updateReferenceType,
- val_r ).begin();
- }
-
+ { base_reference() = sat::LookupAttr( sat::SolvAttr::updateReference, val_r ).begin(); }
std::string Patch::ReferenceIterator::id() const
- { return base_reference().asString(); }
+ { return base_reference().subFind( sat::SolvAttr::updateReferenceId ).asString(); }
std::string Patch::ReferenceIterator::href() const
- { return _hrefit.asString(); }
+ { return base_reference().subFind( sat::SolvAttr::updateReferenceHref ).asString(); }
std::string Patch::ReferenceIterator::title() const
- { return _titleit.asString(); }
+ { return base_reference().subFind( sat::SolvAttr::updateReferenceTitle ).asString(); }
std::string Patch::ReferenceIterator::type() const
- { return _typeit.asString(); }
-
-
- void Patch::ReferenceIterator::increment()
- {
- ++base_reference();
- ++_hrefit;
- ++_titleit;
- ++_typeit;
- }
+ { return base_reference().subFind( sat::SolvAttr::updateReferenceType ).asString(); }
/////////////////////////////////////////////////////////////////
} // namespace zypp