#include "update.h"
#include "main.h"
-using namespace std;
using namespace zypp;
-using namespace boost;
+typedef std::set<PoolItem> Candidates;
extern ZYpp::Ptr God;
-typedef set<PoolItem> Candidates;
-
static void
find_updates( const ResKindSet & kinds, Candidates & candidates );
+///////////////////////////////////////////////////////////////////
+namespace
+{
+ inline bool patchIsApplicable( const PoolItem & pi ) ///< Default content for all patch lists: needed and not locked
+ { return( pi.isBroken() && ! pi.isUnwanted() ); }
+} //namespace
+///////////////////////////////////////////////////////////////////
+
// ----------------------------------------------------------------------------
//
// Updates
RuntimeData & gData = Zypper::instance()->runtimeData();
DBG << "patch check" << endl;
gData.patches_count = gData.security_patches_count = 0;
+ unsigned lockedPatches = 0;
bool updatestackOnly = Zypper::instance()->cOpts().count("updatestack-only");
for_( it, God->pool().byKindBegin(ResKind::patch), God->pool().byKindEnd(ResKind::patch) )
const PoolItem & pi( *it );
if ( pi.isBroken() )
{
- Patch::constPtr patch( pi->asKind<Patch>() );
- if ( !updatestackOnly || patch->restartSuggested() )
+ if ( pi.isUnwanted() )
+ { ++lockedPatches; }
+ else
{
- ++gData.patches_count;
- if ( patch->categoryEnum() == Patch::CAT_SECURITY )
- ++gData.security_patches_count;
+ Patch::constPtr patch( pi->asKind<Patch>() );
+ if ( !updatestackOnly || patch->restartSuggested() )
+ {
+ ++gData.patches_count;
+ if ( patch->categoryEnum() == Patch::CAT_SECURITY )
+ ++gData.security_patches_count;
+ }
}
}
}
- ostringstream s;
+ if ( lockedPatches )
+ {
+ out.info( (boost::format(_PL("%d patch locked", "%d patches locked", lockedPatches )) % lockedPatches).str(), Out::QUIET);
+ }
+ std::ostringstream s;
// translators: %d is the number of needed patches
- s << format(_PL("%d patch needed", "%d patches needed", gData.patches_count))
+ s << boost::format(_PL("%d patch needed", "%d patches needed", gData.patches_count))
% gData.patches_count
<< " ("
// translators: %d is the number of security patches
- << format(_PL("%d security patch", "%d security patches", gData.security_patches_count))
+ << boost::format(_PL("%d security patch", "%d security patches", gData.security_patches_count))
% gData.security_patches_count
<< ")";
out.info(s.str(), Out::QUIET);
return "undetermined";
}
+static void xml_print_patch( Zypper & zypper, const PoolItem & pi )
+{
+ Patch::constPtr patch = pi->asKind<Patch>();
+
+ cout << " <update ";
+ cout << "name=\"" << patch->name () << "\" ";
+ cout << "edition=\"" << patch->edition() << "\" ";
+ cout << "arch=\"" << patch->arch() << "\" ";
+ cout << "status=\"" << patchStatusAsString( pi ) << "\" ";
+ cout << "category=\"" << patch->category() << "\" ";
+ cout << "severity=\"" << patch->severity() << "\" ";
+ cout << "pkgmanager=\"" << (patch->restartSuggested() ? "true" : "false") << "\" ";
+ cout << "restart=\"" << (patch->rebootSuggested() ? "true" : "false") << "\" ";
+
+ Patch::InteractiveFlags ignoreFlags = Patch::NoFlags;
+ if (zypper.globalOpts().reboot_req_non_interactive)
+ ignoreFlags |= Patch::Reboot;
+ if ( zypper.cOpts().count("auto-agree-with-licenses") || zypper.cOpts().count("agree-to-third-party-licenses") )
+ ignoreFlags |= Patch::License;
+
+ cout << "interactive=\"" << (patch->interactiveWhenIgnoring(ignoreFlags) ? "true" : "false") << "\" ";
+ cout << "kind=\"patch\"";
+ cout << ">" << endl;
+ cout << " <summary>" << xml::escape(patch->summary()) << " </summary>" << endl;
+ cout << " <description>" << xml::escape(patch->description()) << "</description>" << endl;
+ cout << " <license>" << xml::escape(patch->licenseToConfirm()) << "</license>" << endl;
+
+ if ( !patch->repoInfo().alias().empty() )
+ {
+ cout << " <source url=\"" << xml::escape(patch->repoInfo().url().asString());
+ cout << "\" alias=\"" << xml::escape(patch->repoInfo().alias()) << "\"/>" << endl;
+ }
+
+ cout << " </update>" << endl;
+}
+
+
// returns true if restartSuggested() patches are availble
static bool xml_list_patches (Zypper & zypper)
{
const zypp::ResPool& pool = God->pool();
- unsigned int patchcount=0;
- bool pkg_mgr_available = false;
- Patch::constPtr patch;
-
// check whether there are packages affecting the update stack
+ bool pkg_mgr_available = false;
for_( it, pool.byKindBegin(ResKind::patch), pool.byKindEnd(ResKind::patch) )
{
const PoolItem & pi( *it );
- if ( pi.isBroken() && pi->asKind<Patch>()->restartSuggested())
+
+ if ( patchIsApplicable( pi ) && pi->asKind<Patch>()->restartSuggested() )
{
pkg_mgr_available = true;
break;
}
}
+ unsigned patchcount = 0;
+ bool all = zypper.cOpts().count("all");
for_( it, pool.byKindBegin(ResKind::patch), pool.byKindEnd(ResKind::patch) )
{
- if (zypper.cOpts().count("all") || it->isBroken())
+ if ( all || patchIsApplicable( *it ) )
{
- ResObject::constPtr res = it->resolvable();
- Patch::constPtr patch = asKind<Patch>(res);
+ const PoolItem & pi( *it );
+ Patch::constPtr patch = pi->asKind<Patch>();
// if updates stack patches are available, show only those
- if ((pkg_mgr_available && patch->restartSuggested()) || !pkg_mgr_available)
+ if ( all || !pkg_mgr_available || patch->restartSuggested() )
{
- cout << " <update ";
- cout << "name=\"" << res->name () << "\" ";
- cout << "edition=\"" << res->edition ().asString() << "\" ";
- cout << "arch=\"" << res->arch().asString() << "\" ";
- cout << "status=\"" << patchStatusAsString( *it ) << "\" ";
- cout << "category=\"" << patch->category() << "\" ";
- cout << "severity=\"" << patch->severity() << "\" ";
- cout << "pkgmanager=\"" << (patch->restartSuggested() ? "true" : "false") << "\" ";
- cout << "restart=\"" << (patch->rebootSuggested() ? "true" : "false") << "\" ";
-
- Patch::InteractiveFlags ignoreFlags = Patch::NoFlags;
- if (zypper.globalOpts().reboot_req_non_interactive)
- ignoreFlags |= Patch::Reboot;
- if ( zypper.cOpts().count("auto-agree-with-licenses") || zypper.cOpts().count("agree-to-third-party-licenses") )
- ignoreFlags |= Patch::License;
-
- cout << "interactive=\"" << (patch->interactiveWhenIgnoring(ignoreFlags) ? "true" : "false") << "\" ";
- cout << "kind=\"patch\"";
- cout << ">" << endl;
- cout << " <summary>" << xml::escape(patch->summary()) << " </summary>" << endl;
- cout << " <description>" << xml::escape(patch->description()) << "</description>" << endl;
- cout << " <license>" << xml::escape(patch->licenseToConfirm()) << "</license>" << endl;
-
- if ( !patch->repoInfo().alias().empty() )
- {
- cout << " <source url=\"" << xml::escape(patch->repoInfo().url().asString());
- cout << "\" alias=\"" << xml::escape(patch->repoInfo().alias()) << "\"/>" << endl;
- }
-
- cout << " </update>" << endl;
+ xml_print_patch( zypper, pi );
}
}
++patchcount;
if (patchcount == 0)
cout << "<appletinfo status=\"no-update-repositories\"/>" << endl;
+
+ if ( pkg_mgr_available )
+ {
+ // close <update-list> and write <blocked-update-list> if not all
+ cout << "</update-list>" << endl;
+ if ( ! all )
+ {
+ cout << "<blocked-update-list>" << endl;
+ for_( it, pool.byKindBegin(ResKind::patch), pool.byKindEnd(ResKind::patch) )
+ {
+ if ( patchIsApplicable( *it ) )
+ {
+ const PoolItem & pi( *it );
+ Patch::constPtr patch = pi->asKind<Patch>();
+ if ( ! patch->restartSuggested() )
+ xml_print_patch( zypper, pi );
+ }
+ }
+ cout << "</blocked-update-list>" << endl;
+ }
+ }
+
return pkg_mgr_available;
}
cout << " <update ";
cout << "name=\"" << res->name () << "\" " ;
- cout << "edition=\"" << res->edition ().asString() << "\" ";
- cout << "arch=\"" << res->arch().asString() << "\" ";
+ cout << "edition=\"" << res->edition() << "\" ";
+ cout << "arch=\"" << res->arch() << "\" ";
cout << "kind=\"" << res->kind() << "\" ";
+ // for packages show also the current installed version (bnc #466599)
+ {
+ ResObject::constPtr ires = ui::Selectable::get(*ci)->installedObj().resolvable();
+ if ( ires )
+ {
+ if ( res->edition() != ires->edition() )
+ cout << "edition-old=\"" << ires->edition() << "\" ";
+ if ( res->arch() != ires->arch() )
+ cout << "arch-old=\"" << ires->arch() << "\" ";
+ }
+ }
cout << ">" << endl;
cout << " <summary>" << xml::escape(res->summary()) << " </summary>" << endl;
cout << " <description>" << xml::escape(res->description()) << "</description>" << endl;
ResObject::constPtr res = it->resolvable();
// show only needed and wanted/unlocked (bnc #420606) patches unless --all
- if (all || (it->isBroken() && !it->isUnwanted()))
+ if ( all || patchIsApplicable( *it ) )
{
Patch::constPtr patch = asKind<Patch>(res);
if (date_limit != Date() && patch->timestamp() > date_limit ) {
else if (kind == ResKind::product)
return _("Product updates");
- return boost::str(format("%s updates") % kind);
+ return boost::str(boost::format("%s updates") % kind);
}
// ----------------------------------------------------------------------------
{
if (zypper.out().type() == Out::TYPE_XML)
{
+ // TODO: go for XmlNode
cout << "<update-status version=\"0.6\">" << endl;
cout << "<update-list>" << endl;
}
if (zypper.out().type() == Out::TYPE_XML)
{
if (!affects_pkgmgr)
+ {
xml_list_updates(localkinds);
- cout << "</update-list>" << endl;
+ cout << "</update-list>" << endl; // otherwise closed in xml_list_patches
+ }
cout << "</update-status>" << endl;
return;
}
// --bz, --cve can't be used together with --issue; this case is ruled out
// in the initial arguments validation in Zypper.cc
- typedef set<pair<string, string> > Issues;
+ typedef std::set<std::pair<std::string, std::string> > Issues;
bool only_needed = !zypper.cOpts().count("all");
bool specific = false; // whether specific issue numbers were given
if (it != zypper.cOpts().end()) \
for_(i, it->second.begin(), it->second.end()) \
{ \
- issues.insert(pair<string, string>(ID, *i)); \
+ issues.insert(std::pair<std::string, std::string>(ID, *i)); \
if (!i->empty()) \
specific = true; \
} \
for_(it, q.begin(), q.end())
{
PoolItem pi(*it);
- if (only_needed && (!pi.isBroken() || pi.isUnwanted()))
+ if ( only_needed && ! patchIsApplicable( pi ) )
continue;
Patch::constPtr patch = asKind<Patch>(pi.resolvable());
for_(it, q.begin(), q.end())
{
PoolItem pi(*it);
- if (only_needed && (!pi.isBroken() || pi.isUnwanted()))
+ if ( only_needed && ! patchIsApplicable( pi ) )
continue;
Patch::constPtr patch = asKind<Patch>(pi.resolvable());
void mark_updates_by_issue(Zypper & zypper)
{
- typedef set<pair<string, string> > Issues;
+ typedef std::set<std::pair<std::string, std::string> > Issues;
Issues issues;
parsed_opts::const_iterator it = zypper.cOpts().find("bugzilla");
if (it != zypper.cOpts().end())
for_(i, it->second.begin(), it->second.end())
- issues.insert(pair<string, string>("b", *i));
+ issues.insert(std::pair<std::string, std::string>("b", *i));
it = zypper.cOpts().find("bz");
if (it != zypper.cOpts().end())
for_(i, it->second.begin(), it->second.end())
- issues.insert(pair<string, string>("b", *i));
+ issues.insert(std::pair<std::string, std::string>("b", *i));
it = zypper.cOpts().find("cve");
if (it != zypper.cOpts().end())
for_(i, it->second.begin(), it->second.end())
- issues.insert(pair<string, string>("c", *i));
+ issues.insert(std::pair<std::string, std::string>("c", *i));
SolverRequester::Options sropts;
sropts.skip_interactive = zypper.cOpts().count("skip-interactive");