#include <zypp/CapSet.h>
/////////////////////////////////////////////////////////////////////////
-namespace zypp
+namespace zypp
{ ///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
namespace solver
/////////////////////////////////////////////////////////////////////
namespace detail
{ ///////////////////////////////////////////////////////////////////
-
+
using namespace std;
-
+
IMPL_DERIVED_POINTER(QueueItemInstall,QueueItem);
-
+
//---------------------------------------------------------------------------
-
+
string
QueueItemInstall::asString ( void ) const
{
- return toString (*this);
+ return toString (*this);
}
-
-
+
+
string
QueueItemInstall::toString ( const QueueItemInstall & item)
{
- string ret = "[Install: ";
- ret += item._resItem->asString();
- if (item._upgrades != NULL) {
- ret += ", Upgrades ";
- ret += item._upgrades->asString();
- }
- if (!item._deps_satisfied_by_this_install.empty()) {
- ret += ", Satisfies [";
- for (CapSet::const_iterator iter = item._deps_satisfied_by_this_install.begin();
- iter != item._deps_satisfied_by_this_install.end(); iter++) {
- if (iter != item._deps_satisfied_by_this_install.begin()) ret += ", ";
- ret += (*iter).asString();
- }
- ret += "]";
- }
- if (!item._needed_by.empty()) {
- ret += ", Needed by ";
- ret += ResItem::toString(item._needed_by);
- }
- if (item._explicitly_requested) ret += ", Explicit !";
- ret += "]";
- return ret;
+ string ret = "[Install: ";
+ ret += item._resItem->asString();
+ if (item._upgrades != NULL) {
+ ret += ", Upgrades ";
+ ret += item._upgrades->asString();
+ }
+ if (!item._deps_satisfied_by_this_install.empty()) {
+ ret += ", Satisfies [";
+ for (CapSet::const_iterator iter = item._deps_satisfied_by_this_install.begin();
+ iter != item._deps_satisfied_by_this_install.end(); iter++) {
+ if (iter != item._deps_satisfied_by_this_install.begin()) ret += ", ";
+ ret += (*iter).asString();
+ }
+ ret += "]";
+ }
+ if (!item._needed_by.empty()) {
+ ret += ", Needed by ";
+ ret += ResItem::toString(item._needed_by);
+ }
+ if (item._explicitly_requested) ret += ", Explicit !";
+ ret += "]";
+ return ret;
}
-
-
+
+
ostream &
QueueItemInstall::dumpOn( ostream & str ) const
{
- str << asString();
- return str;
+ str << asString();
+ return str;
}
-
-
+
+
ostream&
operator<<( ostream& os, const QueueItemInstall & item)
{
- return os << item.asString();
+ return os << item.asString();
}
-
+
//---------------------------------------------------------------------------
-
+
QueueItemInstall::QueueItemInstall (WorldPtr world, constResItemPtr resItem)
- : QueueItem (QUEUE_ITEM_TYPE_INSTALL, world)
- , _resItem (resItem)
- , _channel_priority (0)
- , _other_penalty (0)
- , _explicitly_requested (false)
+ : QueueItem (QUEUE_ITEM_TYPE_INSTALL, world)
+ , _resItem (resItem)
+ , _channel_priority (0)
+ , _other_penalty (0)
+ , _explicitly_requested (false)
{
- constResItemPtr upgrades = world->findInstalledResItem (resItem);
- if (getenv("RC_SPEW")) fprintf (stderr, "QueueItemInstall::QueueItemInstall(%s) upgrades %s\n", resItem->asString().c_str(), upgrades!=NULL?upgrades->asString().c_str():"nothing");
- if (upgrades
- && ! (upgrades->equals (resItem))) {
- setUpgrades(upgrades);
- }
+ constResItemPtr upgrades = world->findInstalledResItem (resItem);
+ if (getenv("RC_SPEW")) fprintf (stderr, "QueueItemInstall::QueueItemInstall(%s) upgrades %s\n", resItem->asString().c_str(), upgrades!=NULL?upgrades->asString().c_str():"nothing");
+ if (upgrades
+ && ! (upgrades->equals (resItem))) {
+ setUpgrades(upgrades);
+ }
}
-
-
+
+
QueueItemInstall::~QueueItemInstall()
{
}
-
+
//---------------------------------------------------------------------------
-
+
bool
QueueItemInstall::isSatisfied (ResolverContextPtr context) const
{
- return context->resItemIsPresent (_resItem);
+ return context->resItemIsPresent (_resItem);
}
-
-
+
+
//---------------------------------------------------------------------------
-
+
// Handle system resItem's that conflict with us -> uninstall them
-
+
static bool
build_conflict_list (constResItemPtr resItem, const Capability & dep, void *data)
{
- CResItemList *rl = (CResItemList *)data;
- rl->push_front (resItem);
- return true;
+ CResItemList *rl = (CResItemList *)data;
+ rl->push_front (resItem);
+ return true;
}
-
+
bool
QueueItemInstall::process (ResolverContextPtr context, QueueItemList & qil)
{
- if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemInstall::process(%s)\n", this->asString().c_str());
-
- constResItemPtr resItem = _resItem;
- string pkg_name = resItem->asString();
- string msg;
- ResItemStatus status = context->getStatus (resItem);
-
- CapSet deps;
- CResItemList conflicts;
-
- /* If we are trying to upgrade resItem A with resItem B and they both have the
- same version number, do nothing. This shouldn't happen in general with
- red-carpet, but can come up with the installer & autopull. */
-
- if (_upgrades
- && _resItem->equals (_upgrades)) {
- ResolverInfoPtr info;
-
- if (getenv ("RC_SPEW")) fprintf (stderr, "upgrades equal resItem, skipping\n");
-
- msg = string("Skipping ") + pkg_name + (": already installed");
- info = new ResolverInfoMisc (_resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg);
- context->addInfo (info);
- goto finished;
- }
-
- if (!_needed_by.empty()) {
- bool still_needed = false;
-
- if (getenv ("RC_SPEW")) fprintf (stderr, "still needed ");
-
- for (CResItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end() && !still_needed; iter++) {
- ResItemStatus status = context->getStatus (*iter);
- if (getenv ("RC_SPEW")) fprintf (stderr, "by: [status: %s] %s\n", ResolverContext::toString(status).c_str(), (*iter)->asString().c_str());
- if (! resItem_status_is_to_be_uninstalled (status)) {
- still_needed = true;
- }
- }
-
- if (! still_needed)
- goto finished;
- }
-
- /* If we are in verify mode and this install is about to fail, don't let it happen...
- instead, we try to back out of the install by removing whatever it was that
- needed this. */
-
- if (context->verifying()
- && resItem_status_is_to_be_uninstalled (context->getStatus (resItem))
- && !_needed_by.empty()) {
-
- QueueItemUninstallPtr uninstall_item;
-
- for (CResItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end(); iter++) {
- uninstall_item = new QueueItemUninstall (world(), *iter, "uninstallable resolvable");
- qil.push_front (uninstall_item);
- }
-
- goto finished;
- }
-
- if (_upgrades == NULL) {
-
- if (getenv ("RC_SPEW")) fprintf (stderr, "simple install of %s\n", resItem->asString(true).c_str());
-
- context->installResItem (resItem, context->verifying(), /* is_soft */ _other_penalty);
-
- } else {
-
- QueueItemUninstallPtr uninstall_item;
-
- if (getenv ("RC_SPEW")) fprintf (stderr, "upgrade install of %s\n", resItem->asString().c_str());
-
- context->upgradeResItem (resItem, _upgrades, context->verifying(), /* is_soft */ _other_penalty);
-
- uninstall_item = new QueueItemUninstall (world(), _upgrades, "upgrade");
- uninstall_item->setUpgradedTo (resItem);
-
- if (_explicitly_requested)
- uninstall_item->setExplicitlyRequested ();
-
- qil.push_front (uninstall_item);
- }
-
- /* Log which resItem need this install */
-
- if (!_needed_by.empty()) {
- ResolverInfoNeededByPtr info;
-
- info = new ResolverInfoNeededBy (resItem);
- info->addRelatedResItemList (_needed_by);
- context->addInfo (info);
- }
-
- if (! (status == RESOLVABLE_STATUS_UNINSTALLED
- || status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK)) {
- goto finished;
- }
-
- if (_upgrades != NULL) {
- msg = string ("Upgrading ") + _upgrades->asString() + " => " + pkg_name;
- } else {
- msg = string ("Installing ") + pkg_name;
- }
-
- context->addInfoString (resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg);
-
- logInfo (context);
-
- /* Construct require items for each of the resItem's requires that is still unsatisfied. */
-
- deps = resItem->requires();
- for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
- const Capability dep = *iter;
- if (!context->requirementIsMet (dep, false)) {
- if (getenv("RC_SPEW")) fprintf (stderr, "this requires %s\n", dep.asString().c_str());
- QueueItemRequirePtr req_item = new QueueItemRequire (world(), dep);
- req_item->addResItem (resItem);
- qil.push_front (req_item);
- }
- }
-
- /* Construct conflict items for each of the resItem's conflicts. */
-
- deps = resItem->conflicts();
- for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
- const Capability dep = *iter;
- if (getenv("RC_SPEW")) fprintf (stderr, "this conflicts with '%s'\n", dep.asString().c_str());
- QueueItemConflictPtr conflict_item = new QueueItemConflict (world(), dep, resItem);
- qil.push_front (conflict_item);
- }
-
- /* Construct conflict items for each of the resItem's obsoletes. */
-
- deps = resItem->obsoletes();
- for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
- const Capability dep = *iter;
- if (getenv("RC_SPEW")) fprintf (stderr, "this obsoletes %s\n", dep.asString().c_str());
- QueueItemConflictPtr conflict_item = new QueueItemConflict (world(), dep, resItem);
- conflict_item->setActuallyAnObsolete();
- qil.push_front (conflict_item);
- }
-
- /* Construct uninstall items for system resItem's that conflict with us. */
-
- deps = resItem->provides();
- for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
- const Capability dep = *iter;
- world()->foreachConflictingResItem (dep, build_conflict_list, &conflicts);
- }
-
- for (CResItemList::const_iterator iter = conflicts.begin(); iter != conflicts.end(); iter++) {
- constResItemPtr conflicting_resItem = *iter;
- ResolverInfoPtr log_info;
- QueueItemUninstallPtr uninstall_item;
-
- /* Check to see if we conflict with ourself and don't create
- * an uninstall item for it if we do. This is Debian's way of
- * saying that one and only one resItem with this provide may
- * exist on the system at a time.
- */
- if (conflicting_resItem->equals (resItem)) {
- continue;
- }
-
- if (getenv("RC_SPEW")) fprintf (stderr, "because: '%s'\n", conflicting_resItem->asString(true).c_str());
-
- uninstall_item = new QueueItemUninstall (world(), conflicting_resItem, "conflict");
- uninstall_item->setDueToConflict ();
- log_info = new ResolverInfoConflictsWith (conflicting_resItem, resItem);
- uninstall_item->addInfo (log_info);
- qil.push_front (uninstall_item);
- }
-
+ if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemInstall::process(%s)\n", this->asString().c_str());
+
+ constResItemPtr resItem = _resItem;
+ string res_name = resItem->asString();
+ string msg;
+ ResItemStatus status = context->getStatus (resItem);
+
+ /* If we are trying to upgrade resItem A with resItem B and they both have the
+ same version number, do nothing. This shouldn't happen in general with
+ red-carpet, but can come up with the installer & autopull. */
+
+ if (_upgrades
+ && _resItem->equals (_upgrades)) {
+ ResolverInfoPtr info;
+
+ if (getenv ("RC_SPEW")) fprintf (stderr, "upgrades equal resItem, skipping\n");
+
+ msg = string("Skipping ") + res_name + (": already installed");
+ info = new ResolverInfoMisc (_resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg);
+ context->addInfo (info);
+ goto finished;
+ }
+
+ // check if this install is still needed
+ // (maybe other resolver processing made this install obsolete
+
+ if (!_needed_by.empty()) {
+ bool still_needed = false;
+
+ if (getenv ("RC_SPEW")) fprintf (stderr, "still needed ");
+
+ for (CResItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end() && !still_needed; iter++) {
+ ResItemStatus status = context->getStatus (*iter);
+ if (getenv ("RC_SPEW")) fprintf (stderr, "by: [status: %s] %s\n", ResolverContext::toString(status).c_str(), (*iter)->asString().c_str());
+ if (! resItem_status_is_to_be_uninstalled (status)) {
+ still_needed = true;
+ }
+ }
+
+ if (! still_needed)
+ goto finished;
+ }
+
+ /* If we are in verify mode and this install is about to fail, don't let it happen...
+ instead, we try to back out of the install by removing whatever it was that
+ needed this. */
+
+ if (context->verifying()
+ && resItem_status_is_to_be_uninstalled (context->getStatus (resItem))
+ && !_needed_by.empty()) {
+
+ QueueItemUninstallPtr uninstall_item;
+
+ for (CResItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end(); iter++) {
+ uninstall_item = new QueueItemUninstall (world(), *iter, "uninstallable resolvable");
+ qil.push_front (uninstall_item);
+ }
+
+ goto finished;
+ }
+
+ // if this install upgrades an installed resolvable, explicitly uninstall this one
+ // in order to ensure that all dependencies are still met after the upgrade
+
+ if (_upgrades == NULL) {
+
+ if (getenv ("RC_SPEW")) fprintf (stderr, "simple install of %s\n", resItem->asString(true).c_str());
+
+ context->installResItem (resItem, context->verifying(), /* is_soft */ _other_penalty);
+
+ } else {
+
+ QueueItemUninstallPtr uninstall_item;
+
+ if (getenv ("RC_SPEW")) fprintf (stderr, "upgrade install of %s\n", resItem->asString().c_str());
+
+ context->upgradeResItem (resItem, _upgrades, context->verifying(), /* is_soft */ _other_penalty);
+
+ uninstall_item = new QueueItemUninstall (world(), _upgrades, "upgrade");
+ uninstall_item->setUpgradedTo (resItem);
+
+ if (_explicitly_requested)
+ uninstall_item->setExplicitlyRequested ();
+
+ qil.push_front (uninstall_item);
+ }
+
+ /* Log which resItem need this install */
+
+ if (!_needed_by.empty()) {
+ ResolverInfoNeededByPtr info;
+
+ info = new ResolverInfoNeededBy (resItem);
+ info->addRelatedResItemList (_needed_by);
+ context->addInfo (info);
+ }
+
+ // we're done if this isn't currently uninstalled
+
+ if (! (status == RESOLVABLE_STATUS_UNINSTALLED
+ || status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK)) {
+ goto finished;
+ }
+
+ if (_upgrades != NULL) {
+ msg = string ("Upgrading ") + _upgrades->asString() + " => " + res_name;
+ } else {
+ msg = string ("Installing ") + res_name;
+ }
+
+ context->addInfoString (resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg);
+
+ logInfo (context);
+
+ /* Construct require items for each of the resItem's requires that is still unsatisfied. */
+
+ CapSet deps;
+
+ deps = resItem->requires();
+ for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
+ const Capability dep = *iter;
+ if (!context->requirementIsMet (dep, false)) {
+ if (getenv("RC_SPEW")) fprintf (stderr, "this requires %s\n", dep.asString().c_str());
+ QueueItemRequirePtr req_item = new QueueItemRequire (world(), dep);
+ req_item->addResItem (resItem);
+ qil.push_front (req_item);
+ }
+ }
+
+ /* Construct conflict items for each of the resItem's conflicts. */
+
+ deps = resItem->conflicts();
+ for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
+ const Capability dep = *iter;
+ if (getenv("RC_SPEW")) fprintf (stderr, "this conflicts with '%s'\n", dep.asString().c_str());
+ QueueItemConflictPtr conflict_item = new QueueItemConflict (world(), dep, resItem);
+ qil.push_front (conflict_item);
+ }
+
+ /* Construct conflict items for each of the resItem's obsoletes. */
+
+ deps = resItem->obsoletes();
+ for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
+ const Capability dep = *iter;
+ if (getenv("RC_SPEW")) fprintf (stderr, "this obsoletes %s\n", dep.asString().c_str());
+ QueueItemConflictPtr conflict_item = new QueueItemConflict (world(), dep, resItem);
+ conflict_item->setActuallyAnObsolete();
+ qil.push_front (conflict_item);
+ }
+
+ /* Construct uninstall items for system resItem's that conflict with us. */
+
+ CResItemList conflicts;
+ deps = resItem->provides();
+ for (CapSet::const_iterator iter = deps.begin(); iter != deps.end(); iter++) {
+ const Capability dep = *iter;
+ world()->foreachConflictingResItem (dep, build_conflict_list, &conflicts);
+ }
+
+ for (CResItemList::const_iterator iter = conflicts.begin(); iter != conflicts.end(); iter++) {
+ constResItemPtr conflicting_resItem = *iter;
+ ResolverInfoPtr log_info;
+ QueueItemUninstallPtr uninstall_item;
+
+ /* Check to see if we conflict with ourself and don't create
+ * an uninstall item for it if we do. This is Debian's way of
+ * saying that one and only one resItem with this provide may
+ * exist on the system at a time.
+ */
+ if (conflicting_resItem->equals (resItem)) {
+ continue;
+ }
+
+ if (getenv("RC_SPEW")) fprintf (stderr, "because: '%s'\n", conflicting_resItem->asString(true).c_str());
+
+ uninstall_item = new QueueItemUninstall (world(), conflicting_resItem, "conflict");
+ uninstall_item->setDueToConflict ();
+ log_info = new ResolverInfoConflictsWith (conflicting_resItem, resItem);
+ uninstall_item->addInfo (log_info);
+ qil.push_front (uninstall_item);
+ }
+
finished:
- //FIXME rc_queue_item_free (item);
-
- return true;
+
+ return true;
}
-
-
+
+
QueueItemPtr
QueueItemInstall::copy (void) const
{
- QueueItemInstallPtr new_install = new QueueItemInstall (world(), _resItem);
- ((QueueItemPtr)new_install)->copy((constQueueItemPtr)this);
-
- new_install->_upgrades = _upgrades;
- new_install->_deps_satisfied_by_this_install = CapSet(_deps_satisfied_by_this_install.begin(), _deps_satisfied_by_this_install.end());
- new_install->_needed_by = CResItemList (_needed_by.begin(), _needed_by.end());
- new_install->_channel_priority = _channel_priority;
- new_install->_other_penalty = _other_penalty;
- new_install->_explicitly_requested = _explicitly_requested;
-
- return new_install;
+ QueueItemInstallPtr new_install = new QueueItemInstall (world(), _resItem);
+ ((QueueItemPtr)new_install)->copy((constQueueItemPtr)this);
+
+ new_install->_upgrades = _upgrades;
+ new_install->_deps_satisfied_by_this_install = CapSet(_deps_satisfied_by_this_install.begin(), _deps_satisfied_by_this_install.end());
+ new_install->_needed_by = CResItemList (_needed_by.begin(), _needed_by.end());
+ new_install->_channel_priority = _channel_priority;
+ new_install->_other_penalty = _other_penalty;
+ new_install->_explicitly_requested = _explicitly_requested;
+
+ return new_install;
}
-
-
+
+
int
QueueItemInstall::cmp (constQueueItemPtr item) const
{
- int cmp = this->compare (item);
- if (cmp != 0)
- return cmp;
- constQueueItemInstallPtr install = item;
- return ResItem::compare (_resItem, install->_resItem);
+ int cmp = this->compare (item);
+ if (cmp != 0)
+ return cmp;
+ constQueueItemInstallPtr install = item;
+ return ResItem::compare (_resItem, install->_resItem);
}
-
+
//---------------------------------------------------------------------------
-
- void
+
+ void
QueueItemInstall::addDependency (const Capability & dep)
{
- _deps_satisfied_by_this_install.insert (dep);
+ _deps_satisfied_by_this_install.insert (dep);
}
-
-
- void
+
+
+ void
QueueItemInstall::addNeededBy (constResItemPtr resItem)
{
- _needed_by.push_front (resItem);
+ _needed_by.push_front (resItem);
}
-
+
///////////////////////////////////////////////////////////////////
};// namespace detail
/////////////////////////////////////////////////////////////////////