From: Stefan Schubert Date: Thu, 15 Dec 2005 14:03:13 +0000 (+0000) Subject: added namespace solver::detail X-Git-Tag: BASE-SuSE-SLE-10-SP2-Branch~3554 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8ebaf9e7e3f40006330b9f3405b628073eeed6fe;p=platform%2Fupstream%2Flibzypp.git added namespace solver::detail --- diff --git a/zypp/solver/detail/Arch.cc b/zypp/solver/detail/Arch.cc index 29666ec..e938645 100644 --- a/zypp/solver/detail/Arch.cc +++ b/zypp/solver/detail/Arch.cc @@ -41,209 +41,221 @@ static char *known_archs[] = { }; #endif -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -static const string system_arch (void); -static const string canonical_arch (const string & arch); - -//--------------------------------------------------------------------------- - -const Arch * Arch::Unknown = Arch::create ("unknown"); -const Arch * Arch::Any = Arch::create ("any"); -const Arch * Arch::Noarch = Arch::create ("noarch"); -const Arch * Arch::System = Arch::create (system_arch ()); - -//--------------------------------------------------------------------------- -// architecture stuff - -static const string -canonical_arch (const string & arch) -{ - typedef struct { char *from; char *to; } canonical; - // convert machine string to known_arch -static canonical canonical_archs[] = { - { "noarch", "noarch" }, - { "unknown", "unknown" }, - { "any", "any" }, - { "all", "any" }, - { "i386", "i386" }, - { "ix86", "i386" }, /* OpenPKG uses this */ - { "i486", "i486" }, - { "i586", "i586" }, - { "i686", "i686" }, - { "x86_64", "x86_64" }, - { "ia32e", "ia32e" }, - { "athlon", "athlon" }, - { "ppc", "ppc" }, - { "ppc64", "ppc64" }, - { "s390", "s390" }, - { "s390x", "s390x" }, - { "ia64", "ia64" }, - { "sparc", "sparc" }, - { "sun4c", "sparc" }, - { "sun4d", "sparc" }, - { "sun4m", "sparc" }, - { "sparc64", "sparc64" }, - { "sun4u", "sparc64" }, - { "sparcv9", "sparc64" }, - { 0 } -}; - - for (canonical *ptr = canonical_archs; ptr->from; ptr++) { - if (arch == ptr->from) { - return ptr->to; - } - } - - return "canonical"; -} - - -static const string -system_arch (void) -{ - static struct utsname buf; - static bool checked = false; - - if (!checked) { - if (uname (&buf) < 0) { - return NULL; - } - checked = true; - } - - return string (buf.machine); -} - - -//--------------------------------------------------------------------------- - -const string -Arch::asString ( void ) const -{ - return toString (*this); -} - - -const string -Arch::toString ( const Arch & arch ) -{ - return arch._arch; -} - - -ostream & -Arch::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream & os, const Arch & arch) -{ - return os << arch.asString(); -} - -//--------------------------------------------------------------------------- - -Arch::Arch( const string & a) - : _arch (a) -{ -} - - -const Arch * -Arch::create (const string & arch) -{ -typedef std::map ArchTable; - - static ArchTable table; - ArchTable::iterator pos = table.find (arch); - if (pos != table.end()) { - return pos->second; - } - const Arch *new_arch = new Arch(canonical_arch (arch)); - table.insert (ArchTable::value_type (arch, new_arch)); - - return new_arch; -} - - -ArchList -Arch::getCompatList () const -{ - typedef struct { - const char *arch; - const char *compat_arch; - } ArchAndCompatArch; - - /* _NOARCH should never be listed in this table (other than as the - * terminator), as it will automatically be added. Every architecture - * is implicitly compatible with itself. Compatible architectures - * should be listed in most-preferred to least-preferred order. */ - - static ArchAndCompatArch compat_table[] = { - { "i486", "i386" }, - { "i586", "i486" }, - { "i586", "i386" }, - { "i686", "i586" }, - { "i686", "i486" }, - { "i686", "i386" }, - { "athlon", "i686" }, - { "athlon", "i586" }, - { "athlon", "i486" }, - { "athlon", "i386" }, - { "x86_64", "i686" }, - { "x86_64", "i586" }, - { "x86_64", "i486" }, - { "x86_64", "i386" }, - { "x86_64", "athlon" }, - { "x86_64", "ia32e" }, - { "ppc64", "ppc" }, - { "s390x", "s390" }, - { "sparc64", "sparc" }, - { 0 } - }; - - - ArchAndCompatArch *iter; - ArchList ret; - - ret.push_back (this); // be compatible with yourself - - iter = compat_table; - while (iter->arch != NULL) { - if (_arch == iter->arch) { - ret.push_back (create (iter->compat_arch)); - } - iter++; - } - - return ret; -} - - -int -Arch::getCompatScore (const ArchList & archlist) const -{ - int score = 0; - - for (ArchList::const_iterator iter = archlist.begin(); iter != archlist.end(); iter++) { - if (*iter == this) { - return score; - } - score++; - } - return -1; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + static const string system_arch (void); + static const string canonical_arch (const string & arch); + + //--------------------------------------------------------------------------- + + const Arch * Arch::Unknown = Arch::create ("unknown"); + const Arch * Arch::Any = Arch::create ("any"); + const Arch * Arch::Noarch = Arch::create ("noarch"); + const Arch * Arch::System = Arch::create (system_arch ()); + + //--------------------------------------------------------------------------- + // architecture stuff + + static const string + canonical_arch (const string & arch) + { + typedef struct { char *from; char *to; } canonical; + // convert machine string to known_arch + static canonical canonical_archs[] = { + { "noarch", "noarch" }, + { "unknown", "unknown" }, + { "any", "any" }, + { "all", "any" }, + { "i386", "i386" }, + { "ix86", "i386" }, /* OpenPKG uses this */ + { "i486", "i486" }, + { "i586", "i586" }, + { "i686", "i686" }, + { "x86_64", "x86_64" }, + { "ia32e", "ia32e" }, + { "athlon", "athlon" }, + { "ppc", "ppc" }, + { "ppc64", "ppc64" }, + { "s390", "s390" }, + { "s390x", "s390x" }, + { "ia64", "ia64" }, + { "sparc", "sparc" }, + { "sun4c", "sparc" }, + { "sun4d", "sparc" }, + { "sun4m", "sparc" }, + { "sparc64", "sparc64" }, + { "sun4u", "sparc64" }, + { "sparcv9", "sparc64" }, + { 0 } + }; + + for (canonical *ptr = canonical_archs; ptr->from; ptr++) { + if (arch == ptr->from) { + return ptr->to; + } + } + + return "canonical"; + } + + + static const string + system_arch (void) + { + static struct utsname buf; + static bool checked = false; + + if (!checked) { + if (uname (&buf) < 0) { + return NULL; + } + checked = true; + } + + return string (buf.machine); + } + + + //--------------------------------------------------------------------------- + + const string + Arch::asString ( void ) const + { + return toString (*this); + } + + + const string + Arch::toString ( const Arch & arch ) + { + return arch._arch; + } + + + ostream & + Arch::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream & os, const Arch & arch) + { + return os << arch.asString(); + } + + //--------------------------------------------------------------------------- + + Arch::Arch( const string & a) + : _arch (a) + { + } + + + const Arch * + Arch::create (const string & arch) + { + typedef std::map ArchTable; + + static ArchTable table; + ArchTable::iterator pos = table.find (arch); + if (pos != table.end()) { + return pos->second; + } + const Arch *new_arch = new Arch(canonical_arch (arch)); + table.insert (ArchTable::value_type (arch, new_arch)); + + return new_arch; + } + + + ArchList + Arch::getCompatList () const + { + typedef struct { + const char *arch; + const char *compat_arch; + } ArchAndCompatArch; + + /* _NOARCH should never be listed in this table (other than as the + * terminator), as it will automatically be added. Every architecture + * is implicitly compatible with itself. Compatible architectures + * should be listed in most-preferred to least-preferred order. */ + + static ArchAndCompatArch compat_table[] = { + { "i486", "i386" }, + { "i586", "i486" }, + { "i586", "i386" }, + { "i686", "i586" }, + { "i686", "i486" }, + { "i686", "i386" }, + { "athlon", "i686" }, + { "athlon", "i586" }, + { "athlon", "i486" }, + { "athlon", "i386" }, + { "x86_64", "i686" }, + { "x86_64", "i586" }, + { "x86_64", "i486" }, + { "x86_64", "i386" }, + { "x86_64", "athlon" }, + { "x86_64", "ia32e" }, + { "ppc64", "ppc" }, + { "s390x", "s390" }, + { "sparc64", "sparc" }, + { 0 } + }; + + + ArchAndCompatArch *iter; + ArchList ret; + + ret.push_back (this); // be compatible with yourself + + iter = compat_table; + while (iter->arch != NULL) { + if (_arch == iter->arch) { + ret.push_back (create (iter->compat_arch)); + } + iter++; + } + + return ret; + } + + + int + Arch::getCompatScore (const ArchList & archlist) const + { + int score = 0; + + for (ArchList::const_iterator iter = archlist.begin(); iter != archlist.end(); iter++) { + if (*iter == this) { + return score; + } + score++; + } + return -1; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Arch.h b/zypp/solver/detail/Arch.h index 00e1ba2..656f227 100644 --- a/zypp/solver/detail/Arch.h +++ b/zypp/solver/detail/Arch.h @@ -31,61 +31,72 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -class Arch; -typedef std::list ArchList; - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Arch -/** - * - **/ -class Arch { - - private: - - std::string _arch; - - explicit Arch( const std::string & a = "" ); - - public: - static const Arch *Any; - static const Arch *Unknown; - static const Arch *Noarch; - static const Arch *System; - - static const Arch *create ( const std::string & arch ); // factory - virtual ~Arch() {}; - - // ---------------------------------- I/O - - static const std::string toString ( const Arch & arch ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<< ( std::ostream &, const Arch & arch); - - const std::string asString ( void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - bool isAny (void) const { return this == Any; } - bool isUnknown (void) const { return this == Unknown; } - bool isNoarch (void) const { return this == Noarch; } - - ArchList getCompatList () const; - int getCompatScore (const ArchList & archlist) const; - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + class Arch; + typedef std::list ArchList; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Arch + /** + * + **/ + class Arch { + + private: + + std::string _arch; + + explicit Arch( const std::string & a = "" ); + + public: + static const Arch *Any; + static const Arch *Unknown; + static const Arch *Noarch; + static const Arch *System; + + static const Arch *create ( const std::string & arch ); // factory + virtual ~Arch() {}; + + // ---------------------------------- I/O + + static const std::string toString ( const Arch & arch ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<< ( std::ostream &, const Arch & arch); + + const std::string asString ( void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + bool isAny (void) const { return this == Any; } + bool isUnknown (void) const { return this == Unknown; } + bool isNoarch (void) const { return this == Noarch; } + + ArchList getCompatList () const; + int getCompatScore (const ArchList & archlist) const; + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Arch_h diff --git a/zypp/solver/detail/Channel.cc b/zypp/solver/detail/Channel.cc index 2776f44..0735924 100644 --- a/zypp/solver/detail/Channel.cc +++ b/zypp/solver/detail/Channel.cc @@ -26,396 +26,407 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Channel); - -//--------------------------------------------------------------------------- - -int Channel::_fake_id = 1; - -//--------------------------------------------------------------------------- - -string -Channel::asString ( void ) const -{ - if (this == NULL) fprintf (stderr, "Channel::asString NULL\n"); - return toString (*this); -} - - -string -Channel::toString ( const Channel & channel ) -{ - string res (" *_distro_targets; /* List of targets (char *) for this channel */ - - res += ", LastUpdate: "; - res += stringutil::numstring(channel.lastUpdate()); - - if (channel.system()) res += ", System! "; - if (channel.hidden()) res += ", Hidden! "; - if (channel.immutable()) res += ", Immutable! "; - - return res + "'>"; -} - - -ostream & -Channel::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Channel& channel) -{ - return os << channel.asString(); -} - -//--------------------------------------------------------------------------- - -Channel::Channel(const string & id, const string & name, const string & alias, const string & description) - : _world (NULL) - , _last_update (0) - , _system (false) - , _hidden (false) - , _immutable (false) -{ - if (id.empty()) { - _id = stringutil::form( "fake-id-%d", _fake_id++).c_str(); - } - else { - _id = id; - } - - if (name.empty()) { - _name = "Unnamed Channel"; - } - else { - _name = name; - } - - if (alias.empty()) { - _alias = name; - } - else { - _alias = alias; - } - - if (description.empty()) { - _description = "No description available."; - } - else { - _description = description; - } - - _type = CHANNEL_TYPE_UNKNOWN; - - _priority = -1; - _priority_unsubscribed = -1; - -// if (getenv ("RC_SPEW")) fprintf (stderr, "Channel() [%p] (%s)\n", this, asString().c_str()); -} - - -Channel::Channel (const XmlNodePtr node, int *subscribed, WorldPtr world) - : _world (world) - , _last_update (0) - , _system (false) - , _hidden (false) - , _immutable (false) -{ - static unsigned int dummy_id = 0xdeadbeef; - const char *subscribed_str; - const char *priority_str; - const char *priority_unsubscribed_str; - - _name = node->getProp ("name"); - _alias = node->getProp ("alias"); - - _id = node->getProp ("id"); - if (_id.empty()) { - char *temp; - asprintf (&temp, "dummy:%d", dummy_id); - _id = temp; - ++dummy_id; - } - - subscribed_str = node->getProp ("subscribed"); - *subscribed = subscribed_str ? atoi (subscribed_str) : 0; - - priority_str = node->getProp ("priority_base"); - priority_unsubscribed_str = node->getProp ("priority_unsubd"); - - _priority = priority_str ? atoi (priority_str) : 0; - _priority_unsubscribed = priority_unsubscribed_str ? atoi (priority_unsubscribed_str) : 0; - - free ((void *)subscribed_str); - free ((void *)priority_str); - free ((void *)priority_unsubscribed_str); - -// if (getenv ("RC_SPEW")) fprintf (stderr, "Channel(xml) [%p] (%s)\n", this, asString().c_str()); -} - - -Channel::~Channel() -{ -} - - -#if 0 -xmlNode * -rc_channel_to_xml_node (RCChannel *channel) -{ - xmlNode *node; - char tmp[128]; - - g_return_val_if_fail (channel != NULL, NULL); - - node = xmlNewNode (NULL, "channel"); - - xmlNewProp (node, "id", rc_channel_get_id (channel)); - - xmlNewProp (node, "name", rc_channel_get_name (channel)); - - if (rc_channel_get_alias (channel)) - xmlNewProp (node, "alias", rc_channel_get_alias (channel)); - - sprintf (tmp, "%d", rc_channel_is_subscribed (channel) ? 1 : 0); - xmlNewProp (node, "subscribed", tmp); - - sprintf (tmp, "%d", rc_channel_get_priority (channel, true)); - xmlNewProp (node, "priority_base", tmp); - - sprintf (tmp, "%d", rc_channel_get_priority (channel, false)); - xmlNewProp (node, "priority_unsubd", tmp); - - return node; -} -#endif - - -bool -Channel::isSubscribed (void) const -{ - if (_world == NULL) - fprintf (stderr, "Channel::isSubscribed() without world\n"); - return _world->isSubscribed (this); -} - - -void -Channel::setSubscription (bool subscribed) -{ - if (_world == NULL) - fprintf (stderr, "Channel::setSubscription() without world\n"); - _world->setSubscription (this, subscribed); -} - - -int -Channel::priorityParse (const char *priority_cptr) const -{ -#define DEFAULT_CHANNEL_PRIORITY 1600 - - typedef struct { - const char *str; - int priority; - } ChannelPriorityPair; - - ChannelPriorityPair channel_priority_table[] = { - { "private", 6400 }, - { "ximian", 3200 }, - { "distro", 1600 }, - { "third_party", 800 }, - { "preview", 400 }, - { "untested", 200 }, - { "snapshot", 100 }, - { NULL, 0 } - }; - - const char *c; - int i; - bool is_numeric = true; - - if (priority_cptr && *priority_cptr) { - c = priority_cptr; - while (*c && is_numeric) { - if (! isdigit (*c)) - is_numeric = false; - c++; - } - if (is_numeric) { - return atoi (priority_cptr); - } - - for (i=0; channel_priority_table[i].str != NULL; ++i) { - if (! strcasecmp (channel_priority_table[i].str, priority_cptr)) - return channel_priority_table[i].priority; - } - - } - - return DEFAULT_CHANNEL_PRIORITY; -} - - -bool -Channel::isWildcard (void) const -{ - return _type == CHANNEL_TYPE_SYSTEM - || _type == CHANNEL_TYPE_NONSYSTEM - || _type == CHANNEL_TYPE_ANY; -} - - -bool -Channel::equals (const Channel & channel) const -{ - return equals (&channel); -} - -bool -Channel::equals (constChannelPtr channel) const -{ - if (_type == CHANNEL_TYPE_ANY - || channel->_type == CHANNEL_TYPE_ANY) { - return true; - } - - if (isWildcard () && channel->isWildcard ()) { - return this == channel; - } - - /* So at this point we know that between a and b there is - at most one wildcard. */ - - if (_type == CHANNEL_TYPE_SYSTEM) { - return channel->system(); - } - else if (_type == CHANNEL_TYPE_NONSYSTEM) { - return !channel->system(); - } - - if (channel->_type == CHANNEL_TYPE_SYSTEM) { - return system(); - } - else if (channel->_type == CHANNEL_TYPE_NONSYSTEM) { - return !system(); - } - - return hasEqualId (channel); -} - - -bool -Channel::hasEqualId (const Channel & channel) const -{ - return hasEqualId (&channel); -} - - -bool -Channel::hasEqualId (constChannelPtr channel) const -{ - return (channel->id () == _id); -} - - -void -Channel::setPriorities (int subscribed_priority, int unsubscribed_priority) -{ - if (immutable()) return; - - _priority = subscribed_priority; - _priority_unsubscribed = unsubscribed_priority; -} - - -int -Channel::getPriority(bool is_subscribed) const -{ -#define UNSUBSCRIBED_CHANNEL_ADJUSTMENT(x) ((x)/2) - - int priority; - - priority = _priority; - if (priority <= 0) - priority = DEFAULT_CHANNEL_PRIORITY; - - if (!is_subscribed) { - if (_priority_unsubscribed > 0) { - priority = _priority_unsubscribed; - } else { - priority = UNSUBSCRIBED_CHANNEL_ADJUSTMENT (priority); - } - } - - return priority; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Channel); + + //--------------------------------------------------------------------------- + + int Channel::_fake_id = 1; + + //--------------------------------------------------------------------------- + + string + Channel::asString ( void ) const + { + if (this == NULL) fprintf (stderr, "Channel::asString NULL\n"); + return toString (*this); + } + + + string + Channel::toString ( const Channel & channel ) + { + string res (" *_distro_targets; /* List of targets (char *) for this channel */ + + res += ", LastUpdate: "; + res += stringutil::numstring(channel.lastUpdate()); + + if (channel.system()) res += ", System! "; + if (channel.hidden()) res += ", Hidden! "; + if (channel.immutable()) res += ", Immutable! "; + + return res + "'>"; + } + + + ostream & + Channel::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Channel& channel) + { + return os << channel.asString(); + } + + //--------------------------------------------------------------------------- + + Channel::Channel(const string & id, const string & name, const string & alias, const string & description) + : _world (NULL) + , _last_update (0) + , _system (false) + , _hidden (false) + , _immutable (false) + { + if (id.empty()) { + _id = stringutil::form( "fake-id-%d", _fake_id++).c_str(); + } + else { + _id = id; + } + + if (name.empty()) { + _name = "Unnamed Channel"; + } + else { + _name = name; + } + + if (alias.empty()) { + _alias = name; + } + else { + _alias = alias; + } + + if (description.empty()) { + _description = "No description available."; + } + else { + _description = description; + } + + _type = CHANNEL_TYPE_UNKNOWN; + + _priority = -1; + _priority_unsubscribed = -1; + + // if (getenv ("RC_SPEW")) fprintf (stderr, "Channel() [%p] (%s)\n", this, asString().c_str()); + } + + + Channel::Channel (const XmlNodePtr node, int *subscribed, WorldPtr world) + : _world (world) + , _last_update (0) + , _system (false) + , _hidden (false) + , _immutable (false) + { + static unsigned int dummy_id = 0xdeadbeef; + const char *subscribed_str; + const char *priority_str; + const char *priority_unsubscribed_str; + + _name = node->getProp ("name"); + _alias = node->getProp ("alias"); + + _id = node->getProp ("id"); + if (_id.empty()) { + char *temp; + asprintf (&temp, "dummy:%d", dummy_id); + _id = temp; + ++dummy_id; + } + + subscribed_str = node->getProp ("subscribed"); + *subscribed = subscribed_str ? atoi (subscribed_str) : 0; + + priority_str = node->getProp ("priority_base"); + priority_unsubscribed_str = node->getProp ("priority_unsubd"); + + _priority = priority_str ? atoi (priority_str) : 0; + _priority_unsubscribed = priority_unsubscribed_str ? atoi (priority_unsubscribed_str) : 0; + + free ((void *)subscribed_str); + free ((void *)priority_str); + free ((void *)priority_unsubscribed_str); + + // if (getenv ("RC_SPEW")) fprintf (stderr, "Channel(xml) [%p] (%s)\n", this, asString().c_str()); + } + + + Channel::~Channel() + { + } + + + #if 0 + xmlNode * + rc_channel_to_xml_node (RCChannel *channel) + { + xmlNode *node; + char tmp[128]; + + g_return_val_if_fail (channel != NULL, NULL); + + node = xmlNewNode (NULL, "channel"); + + xmlNewProp (node, "id", rc_channel_get_id (channel)); + + xmlNewProp (node, "name", rc_channel_get_name (channel)); + + if (rc_channel_get_alias (channel)) + xmlNewProp (node, "alias", rc_channel_get_alias (channel)); + + sprintf (tmp, "%d", rc_channel_is_subscribed (channel) ? 1 : 0); + xmlNewProp (node, "subscribed", tmp); + + sprintf (tmp, "%d", rc_channel_get_priority (channel, true)); + xmlNewProp (node, "priority_base", tmp); + + sprintf (tmp, "%d", rc_channel_get_priority (channel, false)); + xmlNewProp (node, "priority_unsubd", tmp); + + return node; + } + #endif + + + bool + Channel::isSubscribed (void) const + { + if (_world == NULL) + fprintf (stderr, "Channel::isSubscribed() without world\n"); + return _world->isSubscribed (this); + } + + + void + Channel::setSubscription (bool subscribed) + { + if (_world == NULL) + fprintf (stderr, "Channel::setSubscription() without world\n"); + _world->setSubscription (this, subscribed); + } + + + int + Channel::priorityParse (const char *priority_cptr) const + { + #define DEFAULT_CHANNEL_PRIORITY 1600 + + typedef struct { + const char *str; + int priority; + } ChannelPriorityPair; + + ChannelPriorityPair channel_priority_table[] = { + { "private", 6400 }, + { "ximian", 3200 }, + { "distro", 1600 }, + { "third_party", 800 }, + { "preview", 400 }, + { "untested", 200 }, + { "snapshot", 100 }, + { NULL, 0 } + }; + + const char *c; + int i; + bool is_numeric = true; + + if (priority_cptr && *priority_cptr) { + c = priority_cptr; + while (*c && is_numeric) { + if (! isdigit (*c)) + is_numeric = false; + c++; + } + if (is_numeric) { + return atoi (priority_cptr); + } + + for (i=0; channel_priority_table[i].str != NULL; ++i) { + if (! strcasecmp (channel_priority_table[i].str, priority_cptr)) + return channel_priority_table[i].priority; + } + + } + + return DEFAULT_CHANNEL_PRIORITY; + } + + + bool + Channel::isWildcard (void) const + { + return _type == CHANNEL_TYPE_SYSTEM + || _type == CHANNEL_TYPE_NONSYSTEM + || _type == CHANNEL_TYPE_ANY; + } + + + bool + Channel::equals (const Channel & channel) const + { + return equals (&channel); + } + + bool + Channel::equals (constChannelPtr channel) const + { + if (_type == CHANNEL_TYPE_ANY + || channel->_type == CHANNEL_TYPE_ANY) { + return true; + } + + if (isWildcard () && channel->isWildcard ()) { + return this == channel; + } + + /* So at this point we know that between a and b there is + at most one wildcard. */ + + if (_type == CHANNEL_TYPE_SYSTEM) { + return channel->system(); + } + else if (_type == CHANNEL_TYPE_NONSYSTEM) { + return !channel->system(); + } + + if (channel->_type == CHANNEL_TYPE_SYSTEM) { + return system(); + } + else if (channel->_type == CHANNEL_TYPE_NONSYSTEM) { + return !system(); + } + + return hasEqualId (channel); + } + + + bool + Channel::hasEqualId (const Channel & channel) const + { + return hasEqualId (&channel); + } + + + bool + Channel::hasEqualId (constChannelPtr channel) const + { + return (channel->id () == _id); + } + + + void + Channel::setPriorities (int subscribed_priority, int unsubscribed_priority) + { + if (immutable()) return; + + _priority = subscribed_priority; + _priority_unsubscribed = unsubscribed_priority; + } + + + int + Channel::getPriority(bool is_subscribed) const + { + #define UNSUBSCRIBED_CHANNEL_ADJUSTMENT(x) ((x)/2) + + int priority; + + priority = _priority; + if (priority <= 0) + priority = DEFAULT_CHANNEL_PRIORITY; + + if (!is_subscribed) { + if (_priority_unsubscribed > 0) { + priority = _priority_unsubscribed; + } else { + priority = UNSUBSCRIBED_CHANNEL_ADJUSTMENT (priority); + } + } + + return priority; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Channel.h b/zypp/solver/detail/Channel.h index 3c80b55..b93b64f 100644 --- a/zypp/solver/detail/Channel.h +++ b/zypp/solver/detail/Channel.h @@ -35,176 +35,186 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -typedef std::list ChannelList; - -typedef bool (*ChannelFn) (constChannelPtr channel, void *data); -typedef bool (*ChannelAndSubscribedFn) (ChannelPtr channel, bool flag, void *data); - -typedef enum { - - CHANNEL_TYPE_ANY = 0, - CHANNEL_TYPE_SYSTEM, - CHANNEL_TYPE_NONSYSTEM, - - CHANNEL_TYPE_UNKNOWN, - CHANNEL_TYPE_HELIX, - CHANNEL_TYPE_DEBIAN, - CHANNEL_TYPE_APTRPM, - CHANNEL_TYPE_YAST, - CHANNEL_TYPE_YUM - -} ChannelType; - -/////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Channel -/** - * - **/ - -class Channel : public CountedRep { - REP_BODY(Channel); - - private: - ChannelType _type; - - static int _fake_id; - - WorldPtr _world; - - std::string _id; - std::string _legacy_id; // Old ID for RCE servers - - std::string _name; - std::string _alias; - std::string _description; - // priority if channel is... - int _priority; // subscribed - int _priority_unsubscribed; // unsubscribed - - std::string _path; - std::string _file_path; - std::string _icon_file; - std::string _pkginfo_file; - -// std::list *_distro_targets; /* List of targets (std::string ) for this channel */ - - time_t _last_update; - - bool _system; - bool _hidden; - bool _immutable; - - public: - - Channel (ChannelType type) : _type (type), _world(NULL) {} - - Channel(const std::string & id = "", const std::string & name = "", const std::string & alias = "", const std::string & description = ""); - Channel(const XmlNodePtr node, int *subscribed, WorldPtr world); //RCChannel *rc_channel_from_xml_node (xmlNode *channel_node); - - virtual ~Channel(); - - // ---------------------------------- I/O - - const XmlNodePtr asXmlNode (void) const; // rc_channel_to_xml_node - - static std::string toString ( const Channel & edition ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Channel& ); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - ChannelType type(void) const { return _type; } - void setType (ChannelType type) { _type = type; } - - const char *id (void) const { return _id.c_str(); } - void setId (const char *id) { _id = std::string (id); } - - WorldPtr world (void) const { return _world; } - void setWorld (WorldPtr world) { _world = world; } - - const char *legacyId (void) const { return _legacy_id.c_str(); } // Old ID for RCE servers - void setLegacyId (const char *legacy_id) { _legacy_id = std::string (legacy_id); } - - const char *name (void) const { return _name.c_str(); } - void setName (const char *name) { _name = std::string (name); } - - const char *alias (void) const { return _alias.c_str(); } - void setAlias (const char *alias) { _alias = std::string (alias); } - - const char *description (void) const { return _description.c_str(); } - void setDescription (const char *description) { _description = std::string (description); } - - int priority (void) const { return _priority; } - void setPriority (int priority) { _priority = priority; } - - int priorityUnsubscribed (void) const { return _priority_unsubscribed; } - void setPriorityUnsubscribed (int priority_unsubscribed) { _priority_unsubscribed = priority_unsubscribed; } - - const char *path (void) const { return _path.c_str(); } - void setPath (const char *path) { _path = std::string (path); } - - const char *filePath (void) const { return _file_path.c_str(); } - void setFilePath (const char *file_path) { _file_path = std::string (file_path); } - - const char *iconFile (void) const { return _icon_file.c_str(); } - void setIconFile (const char *icon_file) { _icon_file = std::string (icon_file); } - - const char *pkginfoFile (void) const { return _pkginfo_file.c_str(); } - void setPkginfoFile (const char *pkginfo_file) { _pkginfo_file = std::string (pkginfo_file); } - -// const std::list *distroTargets (void) const { return _distro_targets; } -// void setDistroTargets (const std::list *distro_targets) { _distro_targets = distro_targets; } - - time_t lastUpdate (void) const { return _last_update; } - void setLastUpdate (time_t last_update) { _last_update = last_update; } - - bool system (void) const { return _system; } - void setSystem (bool system) { _system = system; } - bool hidden (void) const { return _hidden; } - void setHidden (bool hidden) { _hidden = hidden; } - bool immutable (void) const { return _immutable; } - void setImmutable (bool immutable) { _immutable = immutable; } - - //----------------------------------------------------------------------- - - bool isWildcard (void) const; - - virtual bool equals (const Channel & channel) const; - virtual bool equals (constChannelPtr channel) const; - bool hasEqualId (const Channel & channel) const; - bool hasEqualId (constChannelPtr channel) const; - - //RCResItemSList *rc_channel_get_resItems (RCChannel *channel); - - // Distro target functions - - void addDistroTarget (const char *target); - bool hasDistroTarget (const char *target) const; - - // Subscription management - - bool isSubscribed (void) const; - void setSubscription (bool subscribed); - - int priorityParse (const char *priority_cptr) const; - void setPriorities (int subd_priority, int unsubd_priority); - int getPriority (bool is_subscribed) const; -}; - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef std::list ChannelList; + + typedef bool (*ChannelFn) (constChannelPtr channel, void *data); + typedef bool (*ChannelAndSubscribedFn) (ChannelPtr channel, bool flag, void *data); + + typedef enum { + + CHANNEL_TYPE_ANY = 0, + CHANNEL_TYPE_SYSTEM, + CHANNEL_TYPE_NONSYSTEM, + + CHANNEL_TYPE_UNKNOWN, + CHANNEL_TYPE_HELIX, + CHANNEL_TYPE_DEBIAN, + CHANNEL_TYPE_APTRPM, + CHANNEL_TYPE_YAST, + CHANNEL_TYPE_YUM + + } ChannelType; + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Channel + /** + * + **/ + + class Channel : public CountedRep { + REP_BODY(Channel); + + private: + ChannelType _type; + + static int _fake_id; + + WorldPtr _world; + + std::string _id; + std::string _legacy_id; // Old ID for RCE servers + + std::string _name; + std::string _alias; + std::string _description; + // priority if channel is... + int _priority; // subscribed + int _priority_unsubscribed; // unsubscribed + + std::string _path; + std::string _file_path; + std::string _icon_file; + std::string _pkginfo_file; + + // std::list *_distro_targets; /* List of targets (std::string ) for this channel */ + + time_t _last_update; + + bool _system; + bool _hidden; + bool _immutable; + + public: + + Channel (ChannelType type) : _type (type), _world(NULL) {} + + Channel(const std::string & id = "", const std::string & name = "", const std::string & alias = "", const std::string & description = ""); + Channel(const XmlNodePtr node, int *subscribed, WorldPtr world); //RCChannel *rc_channel_from_xml_node (xmlNode *channel_node); + + virtual ~Channel(); + + // ---------------------------------- I/O + + const XmlNodePtr asXmlNode (void) const; // rc_channel_to_xml_node + + static std::string toString ( const Channel & edition ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Channel& ); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + ChannelType type(void) const { return _type; } + void setType (ChannelType type) { _type = type; } + + const char *id (void) const { return _id.c_str(); } + void setId (const char *id) { _id = std::string (id); } + + WorldPtr world (void) const { return _world; } + void setWorld (WorldPtr world) { _world = world; } + + const char *legacyId (void) const { return _legacy_id.c_str(); } // Old ID for RCE servers + void setLegacyId (const char *legacy_id) { _legacy_id = std::string (legacy_id); } + + const char *name (void) const { return _name.c_str(); } + void setName (const char *name) { _name = std::string (name); } + + const char *alias (void) const { return _alias.c_str(); } + void setAlias (const char *alias) { _alias = std::string (alias); } + + const char *description (void) const { return _description.c_str(); } + void setDescription (const char *description) { _description = std::string (description); } + + int priority (void) const { return _priority; } + void setPriority (int priority) { _priority = priority; } + + int priorityUnsubscribed (void) const { return _priority_unsubscribed; } + void setPriorityUnsubscribed (int priority_unsubscribed) { _priority_unsubscribed = priority_unsubscribed; } + + const char *path (void) const { return _path.c_str(); } + void setPath (const char *path) { _path = std::string (path); } + + const char *filePath (void) const { return _file_path.c_str(); } + void setFilePath (const char *file_path) { _file_path = std::string (file_path); } + + const char *iconFile (void) const { return _icon_file.c_str(); } + void setIconFile (const char *icon_file) { _icon_file = std::string (icon_file); } + + const char *pkginfoFile (void) const { return _pkginfo_file.c_str(); } + void setPkginfoFile (const char *pkginfo_file) { _pkginfo_file = std::string (pkginfo_file); } + + // const std::list *distroTargets (void) const { return _distro_targets; } + // void setDistroTargets (const std::list *distro_targets) { _distro_targets = distro_targets; } + + time_t lastUpdate (void) const { return _last_update; } + void setLastUpdate (time_t last_update) { _last_update = last_update; } + + bool system (void) const { return _system; } + void setSystem (bool system) { _system = system; } + bool hidden (void) const { return _hidden; } + void setHidden (bool hidden) { _hidden = hidden; } + bool immutable (void) const { return _immutable; } + void setImmutable (bool immutable) { _immutable = immutable; } + + //----------------------------------------------------------------------- + + bool isWildcard (void) const; + + virtual bool equals (const Channel & channel) const; + virtual bool equals (constChannelPtr channel) const; + bool hasEqualId (const Channel & channel) const; + bool hasEqualId (constChannelPtr channel) const; + + //RCResItemSList *rc_channel_get_resItems (RCChannel *channel); + + // Distro target functions + + void addDistroTarget (const char *target); + bool hasDistroTarget (const char *target) const; + + // Subscription management + + bool isSubscribed (void) const; + void setSubscription (bool subscribed); + + int priorityParse (const char *priority_cptr) const; + void setPriorities (int subd_priority, int unsubd_priority); + int getPriority (bool is_subscribed) const; + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Channel_h diff --git a/zypp/solver/detail/ChannelPtr.h b/zypp/solver/detail/ChannelPtr.h index 4b3b5c1..d202c15 100644 --- a/zypp/solver/detail/ChannelPtr.h +++ b/zypp/solver/detail/ChannelPtr.h @@ -23,18 +23,29 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ChannelPtr -// CLASS NAME : constChannelPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Channel); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ChannelPtr + // CLASS NAME : constChannelPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Channel); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +//////////////////////////////////////////////////////////////////////// #endif // _ChannelPtr_h diff --git a/zypp/solver/detail/Dependency.cc b/zypp/solver/detail/Dependency.cc index 2f90e6b..0ee2d03 100644 --- a/zypp/solver/detail/Dependency.cc +++ b/zypp/solver/detail/Dependency.cc @@ -28,490 +28,502 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(Dependency,Spec); - -//--------------------------------------------------------------------------- - -#define RELATION_INVALID -1 -#define RELATION_ANY 0 -#define RELATION_EQUAL (1 << 0) -#define RELATION_LESS (1 << 1) -#define RELATION_GREATER (1 << 2) -#define RELATION_NONE (1 << 3) - -const Relation & Relation::Invalid = Relation (RELATION_INVALID); -const Relation & Relation::Any = Relation (RELATION_ANY); -const Relation & Relation::Equal = Relation (RELATION_EQUAL); -const Relation & Relation::NotEqual = Relation (RELATION_LESS|RELATION_GREATER); -const Relation & Relation::Less = Relation (RELATION_LESS); -const Relation & Relation::LessEqual = Relation (RELATION_LESS|RELATION_EQUAL); -const Relation & Relation::Greater = Relation (RELATION_GREATER); -const Relation & Relation::GreaterEqual = Relation (RELATION_GREATER|RELATION_EQUAL); -const Relation & Relation::None = Relation (RELATION_NONE); - - -const Relation & -Relation::parse(const char *relation) -{ - if (!strcmp (relation, "(any)")) - return Any; - else if (!strcmp (relation, "=") || !strcmp (relation, "eq")) - return Equal; - else if (!strcmp (relation, "<") || !strcmp(relation, "lt") || !strcmp(relation, "<")) - return Less; - else if (!strcmp (relation, "<=") || !strcmp(relation, "lte") || !strcmp(relation, "<=")) - return LessEqual; - else if (!strcmp (relation, ">") || !strcmp(relation, "gt") || !strcmp(relation, ">")) - return Greater; - else if (!strcmp (relation, ">=") || !strcmp(relation, "gte") || !strcmp(relation, ">=")) - return GreaterEqual; - else if (!strcmp (relation, "!=") || !strcmp(relation, "ne")) - return NotEqual; - else if (!strcmp (relation, "!!") || !strcmp(relation, "none")) - return None; - else - return Invalid; -} - - -bool -Relation::isEqual () const -{ - return _op == RELATION_EQUAL; -} - - -string -Relation::asString ( void ) const -{ - return toString (*this); -} - - -string -Relation::toString ( const Relation & relation ) -{ - string res; - - switch (relation.op()) { - case RELATION_INVALID: res = "(invalid)"; - break; - case RELATION_ANY: res = ""; - break; - case RELATION_EQUAL: res = "=="; - break; - case RELATION_LESS|RELATION_GREATER: res = "!="; - break; - case RELATION_LESS: res = "<"; - break; - case RELATION_LESS|RELATION_EQUAL: res = "<="; - break; - case RELATION_GREATER: res = ">"; - break; - case RELATION_GREATER|RELATION_EQUAL: res = ">="; - break; - case RELATION_NONE: res = "!!"; - break; - default: - res = "??"; - res += stringutil::numstring (relation.op()); - res += "??"; - break; - } - return res; -} - - -string -Relation::toWord ( const Relation & relation ) -{ - string res; - - switch (relation.op()) { - case RELATION_INVALID: res = "(invalid)"; - break; - case RELATION_ANY: res = "(any)"; - break; - case RELATION_EQUAL: res = "equal to"; - break; - case RELATION_LESS|RELATION_GREATER: res = "not equal to"; - break; - case RELATION_LESS: res = "less than"; - break; - case RELATION_LESS|RELATION_EQUAL: res = "less than or equal to"; - break; - case RELATION_GREATER: res = "greater than"; - break; - case RELATION_GREATER|RELATION_EQUAL: res = "greater than or equal to"; - break; - case RELATION_NONE: res = "not installed"; - break; - default: - res = "??"; - res += stringutil::numstring (relation.op()); - res += "??"; - break; - } - return res; -} - - -ostream & -Relation::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream & os, const Relation & relation) -{ - return os << relation.asString(); -} - -//--------------------------------------------------------------------------- - -string -Dependency::asString ( void ) const -{ - return toString (*this); -} - - -string -Dependency::toString ( const Dependency & dependency ) -{ - string res; - - res += dependency.name(); - if (dependency.relation() != Relation::Any) { - res += " "; - res += dependency.relation().asString(); - res += " "; - - res += dependency.edition()->asString(); - } - if (dependency.orDep()) res += " [OR]"; - if (dependency.preDep()) res += " [PRE]"; - - return res; -} - - -string -Dependency::toString (const CDependencyList & dl) -{ - string res("["); - for (CDependencyList::const_iterator iter = dl.begin(); iter != dl.end(); iter++) { - if (iter != dl.begin()) res += ", "; - res += (*iter)->asString(); - } - return res + "]"; -} - - - - -ostream & -Dependency::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Dependency& dependency) -{ - return os << dependency.asString(); -} - -//--------------------------------------------------------------------------- - -Dependency::Dependency (const string & name, const Relation & relation, const Kind & kind, - constChannelPtr channel, - int epoch, const string & version, const string & release, const Arch * arch, - bool or_dep, bool pre_dep) - : Spec (kind, name, epoch, version, release, arch) - , _relation (relation) - , _channel (channel) - , _or_dep (or_dep) - , _pre_dep (pre_dep) -{ -} - - -Dependency::Dependency (const string & name, const Relation & relation, const Kind & kind, - constChannelPtr channel, constEditionPtr edition, bool or_dep, bool pre_dep) - : Spec (kind, name, edition) - , _relation (relation) - , _channel (channel) - , _or_dep (or_dep) - , _pre_dep (pre_dep) -{ -} - - -Dependency::Dependency (OrDependencyPtr or_dep) - : Spec (Kind::Package, or_dep->name()) - , _relation (Relation::Any) - , _channel (NULL) - , _or_dep (false) - , _pre_dep (true) -{ - or_dep->addCreatedProvide (this); -} - - -Dependency::Dependency (constXmlNodePtr node) - : Spec (Kind::Package, "") - , _relation (Relation::Any) - , _channel (new Channel(CHANNEL_TYPE_ANY)) - , _or_dep (false) - , _pre_dep (false) -{ - const char *tmp; - - if (!node->equals("dep")) { - fprintf (stderr, "Dependency::Dependency bad node\n"); - abort(); - } - - setName(node->getProp ("name")); - tmp = node->getProp ("op", NULL); - if (tmp) { - _relation = Relation::parse(tmp); - setEpoch (node->getIntValueDefault ("epoch", -1)); - setVersion (node->getProp ("version")); - setRelease (node->getProp ("release")); - } - - tmp = node->getProp ("arch", NULL); - if (tmp) { - setArch (Arch::create (node->getProp ("arch"))); - } else { - setArch (Arch::Unknown); - } -#if 0 - tmp = node->getProp ("kind", NULL); - if (tmp) { - setKind (Kind (node->getProp ("kind"))); - } -#endif - /* FIXME: should get channel from XML */ - /* FIXME: should get arch from XML */ -} - - -Dependency::~Dependency() -{ -} - -//--------------------------------------------------------------------------- - -DependencyPtr parseXml (constXmlNodePtr node) -{ - if (node->equals("dep")) { - return new Dependency (node); - } else if (node->equals("or")) { - CDependencyList or_dep_list; - - node = node->children(); - - while (node) { - if (node->isElement()) { - or_dep_list.push_back (new Dependency (node)); - } - - node = node->next(); - } - - OrDependencyPtr or_dep = OrDependency::fromDependencyList(or_dep_list); - return new Dependency (or_dep); - } - - fprintf (stderr, "Unhandled dependency [%s]\n", node->name()); - - return NULL; -} - - -bool -Dependency::verifyRelation (constDependencyPtr prov) const -{ - int compare_ret = 0; -if (getenv ("SPEW_DEP")) fprintf (stderr, "Dependency::verifyRelation(dep: %s, prov: %s)", asString().c_str(), prov->asString().c_str()); - /* No dependency can be met by a different token name */ - if (name() != prov->name()) { -if (getenv ("SPEW_DEP")) fprintf (stderr, "-> wrong name\n"); - return false; - } - - /* No dependency can be met by a different type */ - if (kind() != prov->kind()) { -if (getenv ("SPEW_DEP")) fprintf (stderr, "-> wrong kind(dep: %s, prov: %s)\n", kind().asString().c_str(), prov->kind().asString().c_str()); - return false; - } - - /* WARNING: RC_RELATION_NONE is NOT handled */ - - /* No specific version in the req, so return */ - if (_relation == Relation::Any) { -if (getenv ("SPEW_DEP")) fprintf (stderr, " (any) -> true\n"); - return true; - } - - /* No specific version in the prov. In RPM this means it will satisfy - * any version, but debian it will not satisfy a versioned dep */ - if (prov->relation() == Relation::Any) { - if (GVersion.hasProperty (VERSION_PROP_PROVIDE_ANY)) { -if (getenv ("SPEW_DEP")) fprintf (stderr, " provides (any) matches GVersion -> true\n"); - return true; - } - else { -if (getenv ("SPEW_DEP")) fprintf (stderr, " provides (any) does not match GVersion -> false\n"); - return false; - } - } - - if (!channel()->equals (prov->channel())) - { -if (getenv ("SPEW_DEP")) fprintf (stderr, " wrong channel -> false\n"); - return false; - } - - SpecPtr newdepspec; - SpecPtr newprovspec; - - if (epoch() >= 0 && prov->epoch() >= 0) { - /* HACK: This sucks, but I don't know a better way to compare elements one at a time */ - newdepspec = new Spec(kind(), "", epoch()); - newprovspec = new Spec(prov->kind(), "", prov->epoch()); - compare_ret = GVersion.compare (newprovspec, newdepspec); - } else if (prov->epoch() > 0 ) { - if (GVersion.hasProperty (VERSION_PROP_IGNORE_ABSENT_EPOCHS)) { - compare_ret = 0; - } - else { - compare_ret = 1; - } - } else if (epoch() > 0 ) { - compare_ret = -1; - } -if (getenv ("SPEW_DEP")) fprintf (stderr, "epoch(%d), prov->epoch(%d) -> compare_ret %d\n", epoch(), prov->epoch(), compare_ret); - if (compare_ret == 0) { - if (GVersion.hasProperty (VERSION_PROP_ALWAYS_VERIFY_RELEASE) - || (!(release().empty() || prov->release().empty()))) { - newdepspec = new Spec(kind(), "", -1, version(), release()); - newprovspec = new Spec(prov->kind(), "", -1, prov->version(), prov->release()); - } else { - newdepspec = new Spec(kind(), "", -1, version()); - newprovspec = new Spec(prov->kind(), "", -1, prov->version()); - } - compare_ret = GVersion.compare (newprovspec, newdepspec); - } -if (getenv ("SPEW_DEP")) fprintf (stderr, " (compare result -> %d)", compare_ret); - - if (compare_ret < 0 - && ((prov->relation().op() & Relation::Greater.op()) - || (_relation.op() & Relation::Less.op()))) - { -if (getenv ("SPEW_DEP")) fprintf (stderr, " -> true\n"); - return true; - } else if (compare_ret > 0 - && ((prov->relation().op() & Relation::Less.op()) - || (_relation.op() & Relation::Greater.op()))) - { -if (getenv ("SPEW_DEP")) fprintf (stderr, " -> true\n"); - return true; - } else if (compare_ret == 0 - && (((prov->relation().op() & Relation::Equal.op()) && (_relation.op() & Relation::Equal.op())) - || ((prov->relation().op() & Relation::Less.op()) && (_relation.op() & Relation::Less.op())) - || ((prov->relation().op() & Relation::Greater.op()) && (_relation.op() & Relation::Greater.op())))) - { -if (getenv ("SPEW_DEP")) fprintf (stderr, " -> true\n"); - return true; - } - -if (getenv ("SPEW_DEP")) fprintf (stderr, " -> false\n"); - return false; -} - -//--------------------------------------------------------------------------- - -#if 0 -xmlNode * -rc_resItem_dep_or_slist_to_xml_node (RCResItemDepSList *dep) -{ - xmlNode *or_node; - const RCResItemDepSList *dep_iter; - - or_node = xmlNewNode (NULL, "or"); - - dep_iter = dep; - while (dep_iter) { - RCResItemDep *dep_item = (RCResItemDep *)(dep_iter->data); - xmlAddChild (or_node, rc_resItem_dep_to_xml_node (dep_item)); - dep_iter = dep_iter->next; - } - - return or_node; -} /* rc_resItem_dep_or_slist_to_xml_node */ - -xmlNode * -rc_resItem_dep_to_xml_node (RCResItemDep *dep_item) -{ - RCResItemSpec *spec = (RCResItemSpec *) dep_item; - xmlNode *dep_node; - - if (rc_resItem_dep_is_or (dep_item)) { - RCResItemDepSList *dep_or_slist; - dep_or_slist = rc_dep_string_to_or_dep_slist - (rc_resItem_spec_get_name (spec)); - dep_node = rc_resItem_dep_or_slist_to_xml_node (dep_or_slist); - rc_resItem_dep_slist_free (dep_or_slist); - return dep_node; - } - - dep_node = xmlNewNode (NULL, "dep"); - - xmlSetProp (dep_node, "name", rc_resItem_spec_get_name (spec)); - - if (rc_resItem_dep_get_relation (dep_item) != Relation::Any) { - xmlSetProp (dep_node, "op", - rc_resItem_relation_to_string ( - rc_resItem_dep_get_relation (dep_item), false)); - - if (rc_resItem_spec_has_epoch (spec)) { - gchar *tmp; - - tmp = g_strdup_printf ("%d", rc_resItem_spec_get_epoch (spec)); - xmlSetProp (dep_node, "epoch", tmp); - g_free (tmp); - } - - if (spec->version) { - xmlSetProp (dep_node, "version", spec->version); - } - - if (spec->release) { - xmlSetProp (dep_node, "release", spec->release); - } - } - - return (dep_node); -} /* rc_resItem_dep_to_xml_node */ - -#endif - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(Dependency,Spec); + + //--------------------------------------------------------------------------- + + #define RELATION_INVALID -1 + #define RELATION_ANY 0 + #define RELATION_EQUAL (1 << 0) + #define RELATION_LESS (1 << 1) + #define RELATION_GREATER (1 << 2) + #define RELATION_NONE (1 << 3) + + const Relation & Relation::Invalid = Relation (RELATION_INVALID); + const Relation & Relation::Any = Relation (RELATION_ANY); + const Relation & Relation::Equal = Relation (RELATION_EQUAL); + const Relation & Relation::NotEqual = Relation (RELATION_LESS|RELATION_GREATER); + const Relation & Relation::Less = Relation (RELATION_LESS); + const Relation & Relation::LessEqual = Relation (RELATION_LESS|RELATION_EQUAL); + const Relation & Relation::Greater = Relation (RELATION_GREATER); + const Relation & Relation::GreaterEqual = Relation (RELATION_GREATER|RELATION_EQUAL); + const Relation & Relation::None = Relation (RELATION_NONE); + + + const Relation & + Relation::parse(const char *relation) + { + if (!strcmp (relation, "(any)")) + return Any; + else if (!strcmp (relation, "=") || !strcmp (relation, "eq")) + return Equal; + else if (!strcmp (relation, "<") || !strcmp(relation, "lt") || !strcmp(relation, "<")) + return Less; + else if (!strcmp (relation, "<=") || !strcmp(relation, "lte") || !strcmp(relation, "<=")) + return LessEqual; + else if (!strcmp (relation, ">") || !strcmp(relation, "gt") || !strcmp(relation, ">")) + return Greater; + else if (!strcmp (relation, ">=") || !strcmp(relation, "gte") || !strcmp(relation, ">=")) + return GreaterEqual; + else if (!strcmp (relation, "!=") || !strcmp(relation, "ne")) + return NotEqual; + else if (!strcmp (relation, "!!") || !strcmp(relation, "none")) + return None; + else + return Invalid; + } + + + bool + Relation::isEqual () const + { + return _op == RELATION_EQUAL; + } + + + string + Relation::asString ( void ) const + { + return toString (*this); + } + + + string + Relation::toString ( const Relation & relation ) + { + string res; + + switch (relation.op()) { + case RELATION_INVALID: res = "(invalid)"; + break; + case RELATION_ANY: res = ""; + break; + case RELATION_EQUAL: res = "=="; + break; + case RELATION_LESS|RELATION_GREATER: res = "!="; + break; + case RELATION_LESS: res = "<"; + break; + case RELATION_LESS|RELATION_EQUAL: res = "<="; + break; + case RELATION_GREATER: res = ">"; + break; + case RELATION_GREATER|RELATION_EQUAL: res = ">="; + break; + case RELATION_NONE: res = "!!"; + break; + default: + res = "??"; + res += stringutil::numstring (relation.op()); + res += "??"; + break; + } + return res; + } + + + string + Relation::toWord ( const Relation & relation ) + { + string res; + + switch (relation.op()) { + case RELATION_INVALID: res = "(invalid)"; + break; + case RELATION_ANY: res = "(any)"; + break; + case RELATION_EQUAL: res = "equal to"; + break; + case RELATION_LESS|RELATION_GREATER: res = "not equal to"; + break; + case RELATION_LESS: res = "less than"; + break; + case RELATION_LESS|RELATION_EQUAL: res = "less than or equal to"; + break; + case RELATION_GREATER: res = "greater than"; + break; + case RELATION_GREATER|RELATION_EQUAL: res = "greater than or equal to"; + break; + case RELATION_NONE: res = "not installed"; + break; + default: + res = "??"; + res += stringutil::numstring (relation.op()); + res += "??"; + break; + } + return res; + } + + + ostream & + Relation::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream & os, const Relation & relation) + { + return os << relation.asString(); + } + + //--------------------------------------------------------------------------- + + string + Dependency::asString ( void ) const + { + return toString (*this); + } + + + string + Dependency::toString ( const Dependency & dependency ) + { + string res; + + res += dependency.name(); + if (dependency.relation() != Relation::Any) { + res += " "; + res += dependency.relation().asString(); + res += " "; + + res += dependency.edition()->asString(); + } + if (dependency.orDep()) res += " [OR]"; + if (dependency.preDep()) res += " [PRE]"; + + return res; + } + + + string + Dependency::toString (const CDependencyList & dl) + { + string res("["); + for (CDependencyList::const_iterator iter = dl.begin(); iter != dl.end(); iter++) { + if (iter != dl.begin()) res += ", "; + res += (*iter)->asString(); + } + return res + "]"; + } + + + + + ostream & + Dependency::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Dependency& dependency) + { + return os << dependency.asString(); + } + + //--------------------------------------------------------------------------- + + Dependency::Dependency (const string & name, const Relation & relation, const Kind & kind, + constChannelPtr channel, + int epoch, const string & version, const string & release, const Arch * arch, + bool or_dep, bool pre_dep) + : Spec (kind, name, epoch, version, release, arch) + , _relation (relation) + , _channel (channel) + , _or_dep (or_dep) + , _pre_dep (pre_dep) + { + } + + + Dependency::Dependency (const string & name, const Relation & relation, const Kind & kind, + constChannelPtr channel, constEditionPtr edition, bool or_dep, bool pre_dep) + : Spec (kind, name, edition) + , _relation (relation) + , _channel (channel) + , _or_dep (or_dep) + , _pre_dep (pre_dep) + { + } + + + Dependency::Dependency (OrDependencyPtr or_dep) + : Spec (Kind::Package, or_dep->name()) + , _relation (Relation::Any) + , _channel (NULL) + , _or_dep (false) + , _pre_dep (true) + { + or_dep->addCreatedProvide (this); + } + + + Dependency::Dependency (constXmlNodePtr node) + : Spec (Kind::Package, "") + , _relation (Relation::Any) + , _channel (new Channel(CHANNEL_TYPE_ANY)) + , _or_dep (false) + , _pre_dep (false) + { + const char *tmp; + + if (!node->equals("dep")) { + fprintf (stderr, "Dependency::Dependency bad node\n"); + abort(); + } + + setName(node->getProp ("name")); + tmp = node->getProp ("op", NULL); + if (tmp) { + _relation = Relation::parse(tmp); + setEpoch (node->getIntValueDefault ("epoch", -1)); + setVersion (node->getProp ("version")); + setRelease (node->getProp ("release")); + } + + tmp = node->getProp ("arch", NULL); + if (tmp) { + setArch (Arch::create (node->getProp ("arch"))); + } else { + setArch (Arch::Unknown); + } + #if 0 + tmp = node->getProp ("kind", NULL); + if (tmp) { + setKind (Kind (node->getProp ("kind"))); + } + #endif + /* FIXME: should get channel from XML */ + /* FIXME: should get arch from XML */ + } + + + Dependency::~Dependency() + { + } + + //--------------------------------------------------------------------------- + + DependencyPtr parseXml (constXmlNodePtr node) + { + if (node->equals("dep")) { + return new Dependency (node); + } else if (node->equals("or")) { + CDependencyList or_dep_list; + + node = node->children(); + + while (node) { + if (node->isElement()) { + or_dep_list.push_back (new Dependency (node)); + } + + node = node->next(); + } + + OrDependencyPtr or_dep = OrDependency::fromDependencyList(or_dep_list); + return new Dependency (or_dep); + } + + fprintf (stderr, "Unhandled dependency [%s]\n", node->name()); + + return NULL; + } + + + bool + Dependency::verifyRelation (constDependencyPtr prov) const + { + int compare_ret = 0; + if (getenv ("SPEW_DEP")) fprintf (stderr, "Dependency::verifyRelation(dep: %s, prov: %s)", asString().c_str(), prov->asString().c_str()); + /* No dependency can be met by a different token name */ + if (name() != prov->name()) { + if (getenv ("SPEW_DEP")) fprintf (stderr, "-> wrong name\n"); + return false; + } + + /* No dependency can be met by a different type */ + if (kind() != prov->kind()) { + if (getenv ("SPEW_DEP")) fprintf (stderr, "-> wrong kind(dep: %s, prov: %s)\n", kind().asString().c_str(), prov->kind().asString().c_str()); + return false; + } + + /* WARNING: RC_RELATION_NONE is NOT handled */ + + /* No specific version in the req, so return */ + if (_relation == Relation::Any) { + if (getenv ("SPEW_DEP")) fprintf (stderr, " (any) -> true\n"); + return true; + } + + /* No specific version in the prov. In RPM this means it will satisfy + * any version, but debian it will not satisfy a versioned dep */ + if (prov->relation() == Relation::Any) { + if (GVersion.hasProperty (VERSION_PROP_PROVIDE_ANY)) { + if (getenv ("SPEW_DEP")) fprintf (stderr, " provides (any) matches GVersion -> true\n"); + return true; + } + else { + if (getenv ("SPEW_DEP")) fprintf (stderr, " provides (any) does not match GVersion -> false\n"); + return false; + } + } + + if (!channel()->equals (prov->channel())) + { + if (getenv ("SPEW_DEP")) fprintf (stderr, " wrong channel -> false\n"); + return false; + } + + SpecPtr newdepspec; + SpecPtr newprovspec; + + if (epoch() >= 0 && prov->epoch() >= 0) { + /* HACK: This sucks, but I don't know a better way to compare elements one at a time */ + newdepspec = new Spec(kind(), "", epoch()); + newprovspec = new Spec(prov->kind(), "", prov->epoch()); + compare_ret = GVersion.compare (newprovspec, newdepspec); + } else if (prov->epoch() > 0 ) { + if (GVersion.hasProperty (VERSION_PROP_IGNORE_ABSENT_EPOCHS)) { + compare_ret = 0; + } + else { + compare_ret = 1; + } + } else if (epoch() > 0 ) { + compare_ret = -1; + } + if (getenv ("SPEW_DEP")) fprintf (stderr, "epoch(%d), prov->epoch(%d) -> compare_ret %d\n", epoch(), prov->epoch(), compare_ret); + if (compare_ret == 0) { + if (GVersion.hasProperty (VERSION_PROP_ALWAYS_VERIFY_RELEASE) + || (!(release().empty() || prov->release().empty()))) { + newdepspec = new Spec(kind(), "", -1, version(), release()); + newprovspec = new Spec(prov->kind(), "", -1, prov->version(), prov->release()); + } else { + newdepspec = new Spec(kind(), "", -1, version()); + newprovspec = new Spec(prov->kind(), "", -1, prov->version()); + } + compare_ret = GVersion.compare (newprovspec, newdepspec); + } + if (getenv ("SPEW_DEP")) fprintf (stderr, " (compare result -> %d)", compare_ret); + + if (compare_ret < 0 + && ((prov->relation().op() & Relation::Greater.op()) + || (_relation.op() & Relation::Less.op()))) + { + if (getenv ("SPEW_DEP")) fprintf (stderr, " -> true\n"); + return true; + } else if (compare_ret > 0 + && ((prov->relation().op() & Relation::Less.op()) + || (_relation.op() & Relation::Greater.op()))) + { + if (getenv ("SPEW_DEP")) fprintf (stderr, " -> true\n"); + return true; + } else if (compare_ret == 0 + && (((prov->relation().op() & Relation::Equal.op()) && (_relation.op() & Relation::Equal.op())) + || ((prov->relation().op() & Relation::Less.op()) && (_relation.op() & Relation::Less.op())) + || ((prov->relation().op() & Relation::Greater.op()) && (_relation.op() & Relation::Greater.op())))) + { + if (getenv ("SPEW_DEP")) fprintf (stderr, " -> true\n"); + return true; + } + + if (getenv ("SPEW_DEP")) fprintf (stderr, " -> false\n"); + return false; + } + + //--------------------------------------------------------------------------- + + #if 0 + xmlNode * + rc_resItem_dep_or_slist_to_xml_node (RCResItemDepSList *dep) + { + xmlNode *or_node; + const RCResItemDepSList *dep_iter; + + or_node = xmlNewNode (NULL, "or"); + + dep_iter = dep; + while (dep_iter) { + RCResItemDep *dep_item = (RCResItemDep *)(dep_iter->data); + xmlAddChild (or_node, rc_resItem_dep_to_xml_node (dep_item)); + dep_iter = dep_iter->next; + } + + return or_node; + } /* rc_resItem_dep_or_slist_to_xml_node */ + + xmlNode * + rc_resItem_dep_to_xml_node (RCResItemDep *dep_item) + { + RCResItemSpec *spec = (RCResItemSpec *) dep_item; + xmlNode *dep_node; + + if (rc_resItem_dep_is_or (dep_item)) { + RCResItemDepSList *dep_or_slist; + dep_or_slist = rc_dep_string_to_or_dep_slist + (rc_resItem_spec_get_name (spec)); + dep_node = rc_resItem_dep_or_slist_to_xml_node (dep_or_slist); + rc_resItem_dep_slist_free (dep_or_slist); + return dep_node; + } + + dep_node = xmlNewNode (NULL, "dep"); + + xmlSetProp (dep_node, "name", rc_resItem_spec_get_name (spec)); + + if (rc_resItem_dep_get_relation (dep_item) != Relation::Any) { + xmlSetProp (dep_node, "op", + rc_resItem_relation_to_string ( + rc_resItem_dep_get_relation (dep_item), false)); + + if (rc_resItem_spec_has_epoch (spec)) { + gchar *tmp; + + tmp = g_strdup_printf ("%d", rc_resItem_spec_get_epoch (spec)); + xmlSetProp (dep_node, "epoch", tmp); + g_free (tmp); + } + + if (spec->version) { + xmlSetProp (dep_node, "version", spec->version); + } + + if (spec->release) { + xmlSetProp (dep_node, "release", spec->release); + } + } + + return (dep_node); + } /* rc_resItem_dep_to_xml_node */ + + #endif + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Dependency.h b/zypp/solver/detail/Dependency.h index 2bc5c2f..3511dd3 100644 --- a/zypp/solver/detail/Dependency.h +++ b/zypp/solver/detail/Dependency.h @@ -33,156 +33,168 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Relation -/** - * A dependency relation - **/ - -class Relation { - - private: - - int _op; - - Relation (int op) { _op = op; } - - public: - - virtual ~Relation() {} - - // ---------------------------------- I/O - - static std::string toString ( const Relation & relation ); - - static std::string toWord ( const Relation & relation ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream & str, const Relation & relation ); - - std::string asString ( void ) const; - - // ---------------------------------- consts - - static const Relation & Invalid; - static const Relation & Any; - static const Relation & Equal; - static const Relation & NotEqual; - static const Relation & Less; - static const Relation & LessEqual; - static const Relation & Greater; - static const Relation & GreaterEqual; - static const Relation & None; - - static const Relation & parse (const char *relation); - - // ---------------------------------- accessors - - int op (void) const { return _op; } - - bool isEqual () const; - - // equality operator - bool operator==( const Relation & rel ) const { - return (_op == rel.op()); - } - - // inequality - bool operator!=( const Relation & rel ) const { - return !(*this == rel); - } - -}; - -/////////////////////////////////////////////////////////////////// - -typedef std::list DependencyList; -typedef std::list CDependencyList; - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Dependency -/** - * - **/ - -class Dependency : public Spec { - REP_BODY(Dependency); - - private: - Relation _relation; - constChannelPtr _channel; - bool _or_dep; - bool _pre_dep; - - public: - - Dependency (const std::string & name, - const Relation & relation, - const Kind & kind = Kind::Package, - constChannelPtr channel = NULL, - int epoch = -1, - const std::string & version = "", - const std::string & release = "", - const Arch * arch = Arch::Any, - bool or_dep = false, - bool pre_dep = false); - - Dependency (const std::string & name, - const Relation & relation, - const Kind & kind = Kind::Package, - constChannelPtr channel = NULL, - constEditionPtr edition = NULL, - bool or_dep = false, - bool pre_dep = false); - - Dependency (OrDependencyPtr or_dep); //RCResItemDep *rc_dep_or_new_provide (RCDepOr *dor); - - Dependency (constXmlNodePtr node); //RCResItemDep *rc_xml_node_to_resItem_dep (const xmlNode *node); - - virtual ~Dependency(); - - // ---------------------------------- I/O - - const xmlNodePtr asXmlNode (void) const; // xmlNode *rc_resItem_dep_to_xml_node (RCResItemDep *dep_item); - - static std::string toString ( const Dependency & dep ); - - static std::string toString ( const CDependencyList & deplist ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream & str, const Dependency & dep); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - const Relation & relation() const { return _relation; } - constChannelPtr channel (void) const { return _channel; } - - bool orDep (void) const { return _or_dep; } - void setOrDep (bool or_dep) { _or_dep = or_dep; } - - bool preDep (void) const { return _pre_dep; } - void setPreDep (bool pre_dep) { _pre_dep = pre_dep; } - - // ---------------------------------- methods - - DependencyPtr parseXml (constXmlNodePtr node); - bool verifyRelation (constDependencyPtr prov) const; -}; - -// xmlNode *rc_resItem_dep_or_slist_to_xml_node (RCResItemDepSList *dep); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Relation + /** + * A dependency relation + **/ + + class Relation { + + private: + + int _op; + + Relation (int op) { _op = op; } + + public: + + virtual ~Relation() {} + + // ---------------------------------- I/O + + static std::string toString ( const Relation & relation ); + + static std::string toWord ( const Relation & relation ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream & str, const Relation & relation ); + + std::string asString ( void ) const; + + // ---------------------------------- consts + + static const Relation & Invalid; + static const Relation & Any; + static const Relation & Equal; + static const Relation & NotEqual; + static const Relation & Less; + static const Relation & LessEqual; + static const Relation & Greater; + static const Relation & GreaterEqual; + static const Relation & None; + + static const Relation & parse (const char *relation); + + // ---------------------------------- accessors + + int op (void) const { return _op; } + + bool isEqual () const; + + // equality operator + bool operator==( const Relation & rel ) const { + return (_op == rel.op()); + } + + // inequality + bool operator!=( const Relation & rel ) const { + return !(*this == rel); + } + + }; + + /////////////////////////////////////////////////////////////////// + + typedef std::list DependencyList; + typedef std::list CDependencyList; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Dependency + /** + * + **/ + + class Dependency : public Spec { + REP_BODY(Dependency); + + private: + Relation _relation; + constChannelPtr _channel; + bool _or_dep; + bool _pre_dep; + + public: + + Dependency (const std::string & name, + const Relation & relation, + const Kind & kind = Kind::Package, + constChannelPtr channel = NULL, + int epoch = -1, + const std::string & version = "", + const std::string & release = "", + const Arch * arch = Arch::Any, + bool or_dep = false, + bool pre_dep = false); + + Dependency (const std::string & name, + const Relation & relation, + const Kind & kind = Kind::Package, + constChannelPtr channel = NULL, + constEditionPtr edition = NULL, + bool or_dep = false, + bool pre_dep = false); + + Dependency (OrDependencyPtr or_dep); //RCResItemDep *rc_dep_or_new_provide (RCDepOr *dor); + + Dependency (constXmlNodePtr node); //RCResItemDep *rc_xml_node_to_resItem_dep (const xmlNode *node); + + virtual ~Dependency(); + + // ---------------------------------- I/O + + const xmlNodePtr asXmlNode (void) const; // xmlNode *rc_resItem_dep_to_xml_node (RCResItemDep *dep_item); + + static std::string toString ( const Dependency & dep ); + + static std::string toString ( const CDependencyList & deplist ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream & str, const Dependency & dep); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + const Relation & relation() const { return _relation; } + constChannelPtr channel (void) const { return _channel; } + + bool orDep (void) const { return _or_dep; } + void setOrDep (bool or_dep) { _or_dep = or_dep; } + + bool preDep (void) const { return _pre_dep; } + void setPreDep (bool pre_dep) { _pre_dep = pre_dep; } + + // ---------------------------------- methods + + DependencyPtr parseXml (constXmlNodePtr node); + bool verifyRelation (constDependencyPtr prov) const; + }; + + // xmlNode *rc_resItem_dep_or_slist_to_xml_node (RCResItemDepSList *dep); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Dependency_h diff --git a/zypp/solver/detail/DependencyPtr.h b/zypp/solver/detail/DependencyPtr.h index 46acda2..49f0755 100644 --- a/zypp/solver/detail/DependencyPtr.h +++ b/zypp/solver/detail/DependencyPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : DependencyPtr -// CLASS NAME : constDependencyPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(Dependency,Spec); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : DependencyPtr + // CLASS NAME : constDependencyPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(Dependency,Spec); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _DependencyPtr_h diff --git a/zypp/solver/detail/Edition.cc b/zypp/solver/detail/Edition.cc index da97644..ca39f68 100644 --- a/zypp/solver/detail/Edition.cc +++ b/zypp/solver/detail/Edition.cc @@ -28,115 +28,126 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Edition); - -//--------------------------------------------------------------------------- - -string -Edition::asString ( bool full ) const -{ - return toString (*this, full); -} - - -string -Edition::toString ( const Edition & edition, bool full ) -{ - string res (""); - - if (edition._epoch >= 0) { - res += stringutil::numstring (edition._epoch); - res += ":"; - } - - res += edition._version; - if (!edition._release.empty()) { - res += "-"; - res += edition._release; - } - - if (full) { - res += "."; - res += edition._arch->asString(); - } - - return res; -} - - -ostream & -Edition::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Edition& edition) -{ - return os << edition.asString(); -} - -//--------------------------------------------------------------------------- - -Edition::Edition( int epoch, const string & version, const string & release, const Arch * arch) - : _epoch (epoch) - , _version (version) - , _release (release) - , _arch (arch) -{ -} - - -Edition::~Edition() -{ -} - - -EditionPtr -Edition::copy (void) const -{ - return new Edition (_epoch, _version, _release, _arch); -} - - -EditionPtr -Edition::fromString (const char *s) -{ - return GVersion.parse (s); -} - - -bool -Edition::match( constEditionPtr edition ) const { -//fprintf (stderr, "<%s> match <%s>\n", asString().c_str(), edition->asString().c_str()); - if (_epoch != edition->_epoch) return false; -//fprintf (stderr, "epoch ok\n"); - if (_version != edition->_version) return false; -//fprintf (stderr, "version ok\n"); - if (_release != edition->_release) return false; -//fprintf (stderr, "release ok\n"); - if (_arch != edition->_arch) return false; -//fprintf (stderr, "arch ok\n"); - return true; -} - - -bool -Edition::equals( constEditionPtr edition ) const { -//fprintf (stderr, "<%s> equals <%s>\n", asString().c_str(), edition->asString().c_str()); - return match (edition); -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Edition); + + //--------------------------------------------------------------------------- + + string + Edition::asString ( bool full ) const + { + return toString (*this, full); + } + + + string + Edition::toString ( const Edition & edition, bool full ) + { + string res (""); + + if (edition._epoch >= 0) { + res += stringutil::numstring (edition._epoch); + res += ":"; + } + + res += edition._version; + if (!edition._release.empty()) { + res += "-"; + res += edition._release; + } + + if (full) { + res += "."; + res += edition._arch->asString(); + } + + return res; + } + + + ostream & + Edition::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Edition& edition) + { + return os << edition.asString(); + } + + //--------------------------------------------------------------------------- + + Edition::Edition( int epoch, const string & version, const string & release, const Arch * arch) + : _epoch (epoch) + , _version (version) + , _release (release) + , _arch (arch) + { + } + + + Edition::~Edition() + { + } + + + EditionPtr + Edition::copy (void) const + { + return new Edition (_epoch, _version, _release, _arch); + } + + + EditionPtr + Edition::fromString (const char *s) + { + return GVersion.parse (s); + } + + + bool + Edition::match( constEditionPtr edition ) const { + //fprintf (stderr, "<%s> match <%s>\n", asString().c_str(), edition->asString().c_str()); + if (_epoch != edition->_epoch) return false; + //fprintf (stderr, "epoch ok\n"); + if (_version != edition->_version) return false; + //fprintf (stderr, "version ok\n"); + if (_release != edition->_release) return false; + //fprintf (stderr, "release ok\n"); + if (_arch != edition->_arch) return false; + //fprintf (stderr, "arch ok\n"); + return true; + } + + + bool + Edition::equals( constEditionPtr edition ) const { + //fprintf (stderr, "<%s> equals <%s>\n", asString().c_str(), edition->asString().c_str()); + return match (edition); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Edition.h b/zypp/solver/detail/Edition.h index d2823c2..2426898 100644 --- a/zypp/solver/detail/Edition.h +++ b/zypp/solver/detail/Edition.h @@ -34,72 +34,84 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Edition -/** - * - **/ -class Edition : public CountedRep { - REP_BODY(Edition); - - private: - int _epoch; - std::string _version; - std::string _release; - const Arch *_arch; - - public: - - // - // -1 resp. NULL values are treated as 'any' - // - - Edition( int epoch = -1, const std::string & version = "", const std::string & release = "", const Arch * arch = Arch::Unknown); - virtual ~Edition(); - - // ---------------------------------- I/O - - const XmlNodePtr asXmlNode (void) const; - - static std::string toString ( const Edition & edition, bool full = false ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Edition& ); - - std::string asString ( bool full = false ) const; - - // ---------------------------------- accessors - - void setVersion (const std::string & version) { _version = version; } - void setRelease (const std::string & release) { _release = release; } - void setEpoch (int epoch) { _epoch = epoch; } - void setArch (const std::string & arch) { _arch = Arch::create(arch); } - void setArch (const Arch * arch) { _arch = arch; } - - const std::string & version() const { return _version; } - const std::string & release() const { return _release; } - const int epoch() const { return _epoch; } - bool hasEpoch() const { return _epoch >= 0; } - const Arch * arch() const { return _arch; } - - bool match( constEditionPtr edition ) const; - bool equals( constEditionPtr edition ) const; - - // ---------------------------------- accessors - - EditionPtr copy (void) const; - static EditionPtr fromString (const char *s); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Edition + /** + * + **/ + class Edition : public CountedRep { + REP_BODY(Edition); + + private: + int _epoch; + std::string _version; + std::string _release; + const Arch *_arch; + + public: + + // + // -1 resp. NULL values are treated as 'any' + // + + Edition( int epoch = -1, const std::string & version = "", const std::string & release = "", const Arch * arch = Arch::Unknown); + virtual ~Edition(); + + // ---------------------------------- I/O + + const XmlNodePtr asXmlNode (void) const; + + static std::string toString ( const Edition & edition, bool full = false ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Edition& ); + + std::string asString ( bool full = false ) const; + + // ---------------------------------- accessors + + void setVersion (const std::string & version) { _version = version; } + void setRelease (const std::string & release) { _release = release; } + void setEpoch (int epoch) { _epoch = epoch; } + void setArch (const std::string & arch) { _arch = Arch::create(arch); } + void setArch (const Arch * arch) { _arch = arch; } + + const std::string & version() const { return _version; } + const std::string & release() const { return _release; } + const int epoch() const { return _epoch; } + bool hasEpoch() const { return _epoch >= 0; } + const Arch * arch() const { return _arch; } + + bool match( constEditionPtr edition ) const; + bool equals( constEditionPtr edition ) const; + + // ---------------------------------- accessors + + EditionPtr copy (void) const; + static EditionPtr fromString (const char *s); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Edition_h diff --git a/zypp/solver/detail/EditionPtr.h b/zypp/solver/detail/EditionPtr.h index 957178a..3117f8d 100644 --- a/zypp/solver/detail/EditionPtr.h +++ b/zypp/solver/detail/EditionPtr.h @@ -23,18 +23,30 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : EditionPtr + // CLASS NAME : constEditionPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Edition); -/////////////////////////////////////////////////////////////////// -// CLASS NAME : EditionPtr -// CLASS NAME : constEditionPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Edition); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _EditionPtr_h diff --git a/zypp/solver/detail/Hash.h b/zypp/solver/detail/Hash.h index d4cf5a8..2bb3e79 100644 --- a/zypp/solver/detail/Hash.h +++ b/zypp/solver/detail/Hash.h @@ -20,14 +20,26 @@ #ifndef _Hash_h #define _Hash_h -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef unsigned int HashValue; -typedef unsigned int HashValue; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Hash_h diff --git a/zypp/solver/detail/Importance.cc b/zypp/solver/detail/Importance.cc index 54bcd7a..4890616 100644 --- a/zypp/solver/detail/Importance.cc +++ b/zypp/solver/detail/Importance.cc @@ -25,108 +25,119 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -const Importance & Importance::Undefined= Importance("undefined"); - -//--------------------------------------------------------------------------- -string -Importance::asString ( void ) const -{ - return toString (*this); -} - - -string -Importance::toString ( const Importance & importance ) -{ - string res; - - switch (importance.importance()) { - case IMPORTANCE_UNDEFINED: res = "undefined"; break; - case IMPORTANCE_INVALID: res = "invalid"; break; - case IMPORTANCE_NECESSARY: res = "necessary"; break; - case IMPORTANCE_URGENT: res = "urgent"; break; - case IMPORTANCE_SUGGESTED: res = "suggested"; break; - case IMPORTANCE_FEATURE: res = "feature"; break; - case IMPORTANCE_MINOR: res = "minor"; break; - default: - rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid importance %d\n", importance.importance()); - res = "invalid"; - } - return res; -} - - -ostream & -Importance::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Importance& importance) -{ - return os << importance.asString(); -} - -//--------------------------------------------------------------------------- - -Importance::Importance(const char *importance_str) -{ - _importance = IMPORTANCE_INVALID; - if (importance_str != NULL) { - switch (*importance_str) { - case 'f': - if (!strcmp (importance_str, "feature")) { - _importance = IMPORTANCE_FEATURE; - } - break; - case 'm': - if (!strcmp (importance_str, "minor")) { - _importance = IMPORTANCE_MINOR; - } - break; - case 'n': - if (!strcmp (importance_str, "necessary")) { - _importance = IMPORTANCE_NECESSARY; - } - break; - case 's': - if (!strcmp (importance_str, "suggested")) { - _importance = IMPORTANCE_SUGGESTED; - } - break; - case 'u': - if (!strcmp (importance_str, "urgent")) { - _importance = IMPORTANCE_URGENT; - } - else if (!strcmp (importance_str, "undefined")) { - _importance = IMPORTANCE_UNDEFINED; - } - default: - break; - } - } - if (_importance == IMPORTANCE_INVALID) - rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid importance '%s'\n", importance_str ? importance_str : ""); - -} - - -Importance::~Importance() -{ -} - - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + const Importance & Importance::Undefined= Importance("undefined"); + + //--------------------------------------------------------------------------- + string + Importance::asString ( void ) const + { + return toString (*this); + } + + + string + Importance::toString ( const Importance & importance ) + { + string res; + + switch (importance.importance()) { + case IMPORTANCE_UNDEFINED: res = "undefined"; break; + case IMPORTANCE_INVALID: res = "invalid"; break; + case IMPORTANCE_NECESSARY: res = "necessary"; break; + case IMPORTANCE_URGENT: res = "urgent"; break; + case IMPORTANCE_SUGGESTED: res = "suggested"; break; + case IMPORTANCE_FEATURE: res = "feature"; break; + case IMPORTANCE_MINOR: res = "minor"; break; + default: + rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid importance %d\n", importance.importance()); + res = "invalid"; + } + return res; + } + + + ostream & + Importance::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Importance& importance) + { + return os << importance.asString(); + } + + //--------------------------------------------------------------------------- + + Importance::Importance(const char *importance_str) + { + _importance = IMPORTANCE_INVALID; + if (importance_str != NULL) { + switch (*importance_str) { + case 'f': + if (!strcmp (importance_str, "feature")) { + _importance = IMPORTANCE_FEATURE; + } + break; + case 'm': + if (!strcmp (importance_str, "minor")) { + _importance = IMPORTANCE_MINOR; + } + break; + case 'n': + if (!strcmp (importance_str, "necessary")) { + _importance = IMPORTANCE_NECESSARY; + } + break; + case 's': + if (!strcmp (importance_str, "suggested")) { + _importance = IMPORTANCE_SUGGESTED; + } + break; + case 'u': + if (!strcmp (importance_str, "urgent")) { + _importance = IMPORTANCE_URGENT; + } + else if (!strcmp (importance_str, "undefined")) { + _importance = IMPORTANCE_UNDEFINED; + } + default: + break; + } + } + if (_importance == IMPORTANCE_INVALID) + rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid importance '%s'\n", importance_str ? importance_str : ""); + + } + + + Importance::~Importance() + { + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + diff --git a/zypp/solver/detail/Importance.h b/zypp/solver/detail/Importance.h index f74f839..6eaf634 100644 --- a/zypp/solver/detail/Importance.h +++ b/zypp/solver/detail/Importance.h @@ -27,72 +27,84 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Importance -/** - * - **/ -class Importance { - - private: - - typedef enum { - IMPORTANCE_INVALID = -1, - - IMPORTANCE_NECESSARY, - IMPORTANCE_URGENT, - IMPORTANCE_SUGGESTED, - IMPORTANCE_FEATURE, - IMPORTANCE_MINOR, - IMPORTANCE_UNDEFINED, - - // Not a real importance - IMPORTANCE_LAST - } importance_t; - - importance_t _importance; - - private: - importance_t importance () const { return _importance; } - - public: - - Importance(const char *importance_str); - virtual ~Importance(); - - static const Importance & Undefined; - - // ---------------------------------- I/O - - static std::string toString ( const Importance & importance); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Importance & importance); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - // equality - bool operator==( const Importance & importance) const { - return _importance == importance.importance(); - } - - // inequality - bool operator!=( const Importance & importance) const { - return !(*this == importance); - } - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Importance + /** + * + **/ + class Importance { + + private: + + typedef enum { + IMPORTANCE_INVALID = -1, + + IMPORTANCE_NECESSARY, + IMPORTANCE_URGENT, + IMPORTANCE_SUGGESTED, + IMPORTANCE_FEATURE, + IMPORTANCE_MINOR, + IMPORTANCE_UNDEFINED, + + // Not a real importance + IMPORTANCE_LAST + } importance_t; + + importance_t _importance; + + private: + importance_t importance () const { return _importance; } + + public: + + Importance(const char *importance_str); + virtual ~Importance(); + + static const Importance & Undefined; + + // ---------------------------------- I/O + + static std::string toString ( const Importance & importance); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Importance & importance); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + // equality + bool operator==( const Importance & importance) const { + return _importance == importance.importance(); + } + + // inequality + bool operator!=( const Importance & importance) const { + return !(*this == importance); + } + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Importance_h diff --git a/zypp/solver/detail/Match.cc b/zypp/solver/detail/Match.cc index 1a4c9cf..1d75832 100644 --- a/zypp/solver/detail/Match.cc +++ b/zypp/solver/detail/Match.cc @@ -24,157 +24,169 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Match); - -//--------------------------------------------------------------------------- - -string -Match::asString ( void ) const -{ - return toString (*this); -} - - -string -Match::toString ( const Match & lock ) -{ - return ""; -} - - -ostream & -Match::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Match& edition) -{ - return os << edition.asString(); -} - -//--------------------------------------------------------------------------- - -Match::Match() - : _importance (Importance::Undefined) -{ -} - -Match::Match (XmlNodePtr node) - : _importance (Importance::Undefined) -{ -} - -Match::~Match() -{ -} - -//--------------------------------------------------------------------------- - -XmlNodePtr -Match::asXmlNode (void) const -{ - return new XmlNode("match"); -} - - -// equality -bool -Match::equals ( const Match & lock ) const { - - // Check the name glob - - if ((_name_glob.empty()) ^ (lock._name_glob.empty())) - return false; - if (_name_glob != lock._name_glob) - return false; - - // Check the channel - - if ((_channel_id.empty()) ^ (lock._channel_id.empty())) - return false; - if (_channel_id != lock._channel_id) - return false; - - // Check the importance - - if (_importance != lock._importance - || _importance_gteq != lock._importance_gteq) - { - return false; - } - - // Check the dep - if ((_dependency == NULL) ^ (lock._dependency == NULL)) - return false; - if (_dependency && lock._dependency) { - if (!( ((constSpecPtr) _dependency)->equals((constSpecPtr) lock._dependency)) - || (_dependency->relation() != lock._dependency->relation()) - || (_dependency->kind() != lock._dependency->kind())) - { - return false; - } - } - - return true; -} - - -bool -Match::test (constResItemPtr resItem, WorldPtr world) const -{ - string name; - constChannelPtr channel = resItem->channel (); - - if (channel != NULL && !_channel_id.empty()) { - if (! channel->hasEqualId (_channel_id)) { - return false; - } - } - - name = resItem->name (); - -// FIXME, implement regexp -#if 0 - if (match->_pattern_spec - && ! g_pattern_match_string (match->pattern_spec, name)) { - return false; - } -#endif - - /* FIXME: ResItems don't have ResItemUpdate right now */ -/* if (match->importance != RC_IMPORTANCE_INVALID && */ -/* !rc_resItem_is_installed (resItem)) { */ -/* RCResItemUpdate *up = rc_resItem_get_latest_update (pkg); */ -/* if (up) { */ -/* if (match->importance_gteq ? up->importance > match->importance */ -/* : up->importance < match->importance) */ -/* return FALSE; */ -/* } */ -/* } */ - - if (_dependency) { - DependencyPtr dependency; - bool check; - - dependency = new Dependency (resItem->name(), Relation::Equal, Kind::Package, resItem->channel(), resItem->edition()); - check = _dependency->verifyRelation (dependency); - return check; - } - - return true; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Match); + + //--------------------------------------------------------------------------- + + string + Match::asString ( void ) const + { + return toString (*this); + } + + + string + Match::toString ( const Match & lock ) + { + return ""; + } + + + ostream & + Match::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Match& edition) + { + return os << edition.asString(); + } + + //--------------------------------------------------------------------------- + + Match::Match() + : _importance (Importance::Undefined) + { + } + + Match::Match (XmlNodePtr node) + : _importance (Importance::Undefined) + { + } + + Match::~Match() + { + } + + //--------------------------------------------------------------------------- + + XmlNodePtr + Match::asXmlNode (void) const + { + return new XmlNode("match"); + } + + + // equality + bool + Match::equals ( const Match & lock ) const { + + // Check the name glob + + if ((_name_glob.empty()) ^ (lock._name_glob.empty())) + return false; + if (_name_glob != lock._name_glob) + return false; + + // Check the channel + + if ((_channel_id.empty()) ^ (lock._channel_id.empty())) + return false; + if (_channel_id != lock._channel_id) + return false; + + // Check the importance + + if (_importance != lock._importance + || _importance_gteq != lock._importance_gteq) + { + return false; + } + + // Check the dep + if ((_dependency == NULL) ^ (lock._dependency == NULL)) + return false; + if (_dependency && lock._dependency) { + if (!( ((constSpecPtr) _dependency)->equals((constSpecPtr) lock._dependency)) + || (_dependency->relation() != lock._dependency->relation()) + || (_dependency->kind() != lock._dependency->kind())) + { + return false; + } + } + + return true; + } + + + bool + Match::test (constResItemPtr resItem, WorldPtr world) const + { + string name; + constChannelPtr channel = resItem->channel (); + + if (channel != NULL && !_channel_id.empty()) { + if (! channel->hasEqualId (_channel_id)) { + return false; + } + } + + name = resItem->name (); + + // FIXME, implement regexp + #if 0 + if (match->_pattern_spec + && ! g_pattern_match_string (match->pattern_spec, name)) { + return false; + } + #endif + + /* FIXME: ResItems don't have ResItemUpdate right now */ + /* if (match->importance != RC_IMPORTANCE_INVALID && */ + /* !rc_resItem_is_installed (resItem)) { */ + /* RCResItemUpdate *up = rc_resItem_get_latest_update (pkg); */ + /* if (up) { */ + /* if (match->importance_gteq ? up->importance > match->importance */ + /* : up->importance < match->importance) */ + /* return FALSE; */ + /* } */ + /* } */ + + if (_dependency) { + DependencyPtr dependency; + bool check; + + dependency = new Dependency (resItem->name(), Relation::Equal, Kind::Package, resItem->channel(), resItem->edition()); + check = _dependency->verifyRelation (dependency); + return check; + } + + return true; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Match.h b/zypp/solver/detail/Match.h index fcc0a3c..14f5165 100644 --- a/zypp/solver/detail/Match.h +++ b/zypp/solver/detail/Match.h @@ -34,81 +34,93 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -class Match; -typedef std::list MatchList; - -class World; -typedef bool (*MatchFn) (constMatchPtr match, void *data); - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Match -/** - * - **/ -class Match : public CountedRep { - REP_BODY(Match); - - private: - std::string _channel_id; - - constDependencyPtr _dependency; - - std::string _name_glob; -// GPatternSpec *_pattern_spec; - - Importance _importance; - bool _importance_gteq; - - public: - - Match(); - Match(XmlNodePtr node); - virtual ~Match(); - - // ---------------------------------- I/O - - static std::string toString ( const Match & lock ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Match & lock ); - - std::string asString ( void ) const; - - XmlNodePtr asXmlNode (void) const; - - // ---------------------------------- accessors - - const std::string & channelId () const { return _channel_id; } - void setChannel (constChannelPtr channel) { _channel_id = channel->id(); } - void setChannelId (const std::string & channel_id) { _channel_id = channel_id; } - - constDependencyPtr dependency () const { return _dependency; } - void setDependency (constDependencyPtr dependency) { _dependency = dependency; } - - const std::string & glob () const { return _name_glob; } - void setGlob (const std::string & glob_str) { _name_glob = glob_str; } - - const Importance & importance (bool *match_gteq) const { *match_gteq = _importance_gteq; return _importance; } - void setImportance (const Importance & importance, bool match_gteq) { _importance = importance; _importance_gteq = match_gteq; } - - // ---------------------------------- methods - - typedef bool (*MatchFn) (constMatchPtr, void *data); - - // equality - bool equals (const Match & match) const; - - bool test (constResItemPtr resItem, WorldPtr world) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + class Match; + typedef std::list MatchList; + + class World; + typedef bool (*MatchFn) (constMatchPtr match, void *data); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Match + /** + * + **/ + class Match : public CountedRep { + REP_BODY(Match); + + private: + std::string _channel_id; + + constDependencyPtr _dependency; + + std::string _name_glob; + // GPatternSpec *_pattern_spec; + + Importance _importance; + bool _importance_gteq; + + public: + + Match(); + Match(XmlNodePtr node); + virtual ~Match(); + + // ---------------------------------- I/O + + static std::string toString ( const Match & lock ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Match & lock ); + + std::string asString ( void ) const; + + XmlNodePtr asXmlNode (void) const; + + // ---------------------------------- accessors + + const std::string & channelId () const { return _channel_id; } + void setChannel (constChannelPtr channel) { _channel_id = channel->id(); } + void setChannelId (const std::string & channel_id) { _channel_id = channel_id; } + + constDependencyPtr dependency () const { return _dependency; } + void setDependency (constDependencyPtr dependency) { _dependency = dependency; } + + const std::string & glob () const { return _name_glob; } + void setGlob (const std::string & glob_str) { _name_glob = glob_str; } + + const Importance & importance (bool *match_gteq) const { *match_gteq = _importance_gteq; return _importance; } + void setImportance (const Importance & importance, bool match_gteq) { _importance = importance; _importance_gteq = match_gteq; } + + // ---------------------------------- methods + + typedef bool (*MatchFn) (constMatchPtr, void *data); + + // equality + bool equals (const Match & match) const; + + bool test (constResItemPtr resItem, WorldPtr world) const; + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Match_h diff --git a/zypp/solver/detail/MatchPtr.h b/zypp/solver/detail/MatchPtr.h index 418fba0..1881240 100644 --- a/zypp/solver/detail/MatchPtr.h +++ b/zypp/solver/detail/MatchPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : MatchPtr -// CLASS NAME : constMatchPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Match); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : MatchPtr + // CLASS NAME : constMatchPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Match); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _MatchPtr_h diff --git a/zypp/solver/detail/MultiWorld.cc b/zypp/solver/detail/MultiWorld.cc index afd4c2f..ad161b1 100644 --- a/zypp/solver/detail/MultiWorld.cc +++ b/zypp/solver/detail/MultiWorld.cc @@ -23,642 +23,653 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -//=========================================================================== - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : SubWorldInfo - -class SubWorldInfo { - - private: - WorldPtr _subworld; - WorldPtr _refreshed_subworld; - - bool _refreshed_ready; - - unsigned int _changed_resItems_id; - unsigned int _changed_channels_id; - unsigned int _changed_subscriptions_id; - unsigned int _changed_locks_id; - - public: - - SubWorldInfo (WorldPtr subworld, MultiWorldPtr multiworld); - virtual ~SubWorldInfo(); - - // ---------------------------------- I/O - - static std::string toString (const SubWorldInfo & subworldinfo); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const SubWorldInfo & subworldinfo); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - WorldPtr subworld () const { return _subworld; } - - // ---------------------------------- methods - -}; - -//--------------------------------------------------------------------------- - -string -SubWorldInfo::asString ( void ) const -{ - return toString (*this); -} - - -string -SubWorldInfo::toString ( const SubWorldInfo & subworldinfo ) -{ - return ""; -} - - -ostream & -SubWorldInfo::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const SubWorldInfo & subworldinfo) -{ - return os << subworldinfo.asString(); -} - -//--------------------------------------------------------------------------- - -SubWorldInfo::SubWorldInfo (WorldPtr subworld, MultiWorldPtr multiworld) - : _subworld (subworld) - , _changed_resItems_id (0) - , _changed_channels_id (0) - , _changed_subscriptions_id (0) - , _changed_locks_id (0) - -{ -#if 0 - _changed_resItems_id = - g_signal_connect (G_OBJECT (subworld), - "changed_resItems", - (GCallback) changed_resItems_cb, - world); - - _changed_channels_id = - g_signal_connect (G_OBJECT (subworld), - "changed_channels", - (GCallback) changed_channels_cb, - world); - - _changed_subscriptions_id = - g_signal_connect (G_OBJECT (subworld), - "changed_subscriptions", - (GCallback) changed_subscriptions_cb, - world); - - _changed_locks_id = - g_signal_connect (G_OBJECT (subworld), - "changed_locks", - (GCallback) changed_locks_cb, - world); -#endif -} - - -SubWorldInfo::~SubWorldInfo() -{ -} - - -//=========================================================================== - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : NameConflictInfo - -class NameConflictInfo { - - private: - int _depth; - MultiWorldPtr _multiworld; - WorldPtr _subworld; - const char *_name; - - public: - NameConflictInfo(int depth, MultiWorldPtr multiworld, WorldPtr subworld, const char *name); - virtual ~NameConflictInfo(); - - // ---------------------------------- I/O - - static std::string toString (const NameConflictInfo & nameconflictinfo); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const NameConflictInfo & nameconflictinfo); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - int depth () const { return _depth; } - MultiWorldPtr multiworld () const { return _multiworld; } - WorldPtr subworld () const { return _subworld; } - const char *name () const { return _name; } - void setName (const char *name) { free((void *)_name); _name = strdup (name); } - - // ---------------------------------- methods - - void incDepth (void) { _depth++; } -}; - - -//--------------------------------------------------------------------------- - -string -NameConflictInfo::asString ( void ) const -{ - return toString (*this); -} - - -string -NameConflictInfo::toString ( const NameConflictInfo & subworldinfo ) -{ - return ""; -} - - -ostream & -NameConflictInfo::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const NameConflictInfo & subworldinfo) -{ - return os << subworldinfo.asString(); -} - -//--------------------------------------------------------------------------- - -NameConflictInfo::NameConflictInfo (int depth, MultiWorldPtr multiworld, WorldPtr subworld, const char *name) - : _depth (depth) - , _multiworld (multiworld) - , _subworld (subworld) - , _name (strdup (name)) -{ -} - - -NameConflictInfo::~NameConflictInfo() -{ - free ((void *)_name); -} - - -//=========================================================================== - -IMPL_DERIVED_POINTER(MultiWorld, World); - -string -MultiWorld::asString ( void ) const -{ - return toString (*this); -} - - -string -MultiWorld::toString ( const MultiWorld & world ) -{ - return ""; -} - - -ostream & -MultiWorld::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const MultiWorld & world) -{ - return os << world.asString(); -} - -//--------------------------------------------------------------------------- - -MultiWorld::MultiWorld () - : World (MULTI_WORLD) -{ -} - - -MultiWorld::~MultiWorld() -{ -} - -//--------------------------------------------------------------------------- - -class ForeachByTypeInfo { - public: - WorldType type; - WorldFn callback; - NameConflictInfo *name_conflict_info; - - int count; -}; - - -int -MultiWorld::foreachSubworld (WorldFn callback, void *user_data) -{ - if (callback == NULL) return -1; - - /* Make a copy of subworlds for case where user callback is - running main loop and a refresh starts at that time. */ - - WorldList copied_subworlds; - - for (SubWorldInfoList::iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - copied_subworlds.push_front ((*iter)->subworld()); - } - - int count = 0; - - for (WorldList::const_iterator iter = copied_subworlds.begin(); iter != copied_subworlds.end(); iter++) { - if (! callback (*iter, user_data)) { - count = -1; - break; - } else - ++count; - } - - return count; -} - - -static bool -foreach_by_type_cb (constWorldPtr subworld, void *user_data) -{ - ForeachByTypeInfo *info = (ForeachByTypeInfo *)user_data; - - if ((subworld->type() != info->type) - || info->callback == NULL) - { - return true; - } - - if (! info->callback (subworld, info->name_conflict_info)) { - info->count = -1; - return false; - } else { - ++info->count; - return true; - } -} - - -int -MultiWorld::foreachSubworldByType (WorldType type, WorldFn callback, NameConflictInfo *name_conflict_info) -{ - ForeachByTypeInfo info; - - info.type = type; - info.callback = callback; - info.name_conflict_info = name_conflict_info; - info.count = 0; - - foreachSubworld (foreach_by_type_cb, (void *)(&info)); - - return info.count; -} - -//--------------------------------------------------------------------------- -// subworld - -static bool -service_name_conflict_cb (constWorldPtr world, void *user_data) -{ - constServiceWorldPtr service = world; - if (service == NULL) { - fprintf (stderr, "OOPS: service_name_conflict_cb: world is no service\n"); - abort(); - } - - NameConflictInfo *info = (NameConflictInfo *)user_data; - if (!strcasecmp (service->name(), info->name())) { - info->incDepth(); - ServiceWorldPtr infoservice = info->subworld(); - if (infoservice == NULL) { - fprintf (stderr, "OOPS: service_name_conflict_cb: info->subworld is no service\n"); - abort(); - } - info->setName (stringutil::form ("%s (%d)", infoservice->name(), info->depth()).c_str()); - info->multiworld()->foreachSubworldByType (SERVICE_WORLD, service_name_conflict_cb, info); - return false; - } - - return true; -} - - -void -MultiWorld::addSubworld (WorldPtr subworld) -{ - if (subworld == NULL) return; - - /* - * If we're adding a service, make sure that the name of the service - * doesn't conflict with any other. - */ - ServiceWorldPtr service = subworld; // service will be NULL if subworld is not a ServiceWorld - - if (service != NULL) { - NameConflictInfo conflict_info (0, this, subworld, service->name()); - - foreachSubworldByType (SERVICE_WORLD, service_name_conflict_cb, &conflict_info); - - service->setName (conflict_info.name()); - } - - SubWorldInfo *subworld_info = new SubWorldInfo (subworld, this); - - _subworlds.push_back (subworld_info); - -// g_signal_emit (multi, signals[SUBWORLD_ADDED], 0, subworld); - - return; -} - - -void -MultiWorld::removeSubworld (WorldPtr subworld) -{ - if (subworld == NULL) return; - - for (SubWorldInfoList::iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - if ((*iter)->subworld() == subworld) { - _subworlds.erase (iter); -// g_signal_emit (multi, signals[SUBWORLD_REMOVED], 0, subworld); - return; - } - } - return; -} - - -//--------------------------------------------------------------------------- -// channels - -ChannelList -MultiWorld::channels () const -{ - ChannelList cl; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - cl = (*iter)->subworld()->channels(); -//FIXME cl.merge ((*iter)->subworld()->channels()); - } - return cl; -} - - -bool -MultiWorld::containsChannel (constChannelPtr channel) const -{ - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - if ((*iter)->subworld()->containsChannel(channel)) - return true; - } - return false; -} - - -ChannelPtr -MultiWorld::getChannelByName (const char *channel_name) const -{ - ChannelPtr channel; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - channel = (*iter)->subworld()->getChannelByName(channel_name); - if (channel != NULL) - return channel; - } - return NULL; -} - - -ChannelPtr -MultiWorld::getChannelByAlias (const char *alias) const -{ - ChannelPtr channel; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - channel = (*iter)->subworld()->getChannelByAlias(alias); - if (channel != NULL) - return channel; - } - return NULL; -} - - -ChannelPtr -MultiWorld::getChannelById (const char *channel_id) const -{ - ChannelPtr channel; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - channel = (*iter)->subworld()->getChannelById(channel_id); - if (channel != NULL) - return channel; - } - return NULL; -} - - -int -MultiWorld::foreachChannel (ChannelFn fn, void *data) const -{ - int count = 0; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - int this_count; - this_count = (*iter)->subworld()->foreachChannel(fn, data); - if (this_count < 0) - return -1; - count += this_count; - } - return count; -} - - -//--------------------------------------------------------------------------- -// Single resItem queries - -constResItemPtr -MultiWorld::findInstalledResItem (constResItemPtr resItem) -{ - constResItemPtr installed; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - installed = (*iter)->subworld()->findInstalledResItem(resItem); - if (installed != NULL) - return installed; - } - return NULL; -} - - -constResItemPtr -MultiWorld::findResItem (constChannelPtr channel, const char *name) const -{ - constResItemPtr resItem; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - resItem = (*iter)->subworld()->findResItem(channel, name); - if (resItem != NULL) - return resItem; - } - return NULL; -} - - -constResItemPtr -MultiWorld::findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const -{ - constResItemPtr resItem; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - resItem = (*iter)->subworld()->findResItemWithConstraint(channel, name, constraint, is_and); - if (resItem != NULL) - return resItem; - } - return NULL; -} - - -ChannelPtr -MultiWorld::guessResItemChannel (constResItemPtr resItem) const -{ - ChannelPtr channel; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - channel = (*iter)->subworld()->guessResItemChannel(resItem); - if (channel != NULL) - return channel; - } - return NULL; -} - -//--------------------------------------------------------------------------- -// iterate over resItems - -int -MultiWorld::foreachResItem (ChannelPtr channel, CResItemFn fn, void *data) -{ - return foreachResItemByName ("", channel, fn, data); -} - - -int -MultiWorld::foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data) -{ - int count = 0; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - int this_count; - this_count = (*iter)->subworld()->foreachResItemByName(name, channel, fn, data); - if (this_count < 0) - return -1; - count += this_count; - } - return count; -} - - -int -MultiWorld::foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data) -{ - fprintf (stderr, "MultiWorld::foreachResItemByMatch not implemented\n"); - return 0; -} - - -//----------------------------------------------------------------------------- -// iterater over resItems with dependency - -int -MultiWorld::foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data) -{ - int count = 0; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - int this_count; - this_count = (*iter)->subworld()->foreachProvidingResItem (dep, fn, data); - if (this_count < 0) - return -1; - count += this_count; - } - return count; -} - -int -MultiWorld::foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) -{ - int count = 0; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - int this_count; - this_count = (*iter)->subworld()->foreachRequiringResItem (dep, fn, data); - if (this_count < 0) - return -1; - count += this_count; - } - return count; -} - -int -MultiWorld::foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) -{ - int count = 0; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - int this_count; - this_count = (*iter)->subworld()->foreachConflictingResItem (dep, fn, data); - if (this_count < 0) - return -1; - count += this_count; - } - return count; -} - - -//----------------------------------------------------------------------------- -// iterater over resItems with locks - -int -MultiWorld::foreachLock (MatchFn fn, void *data) const -{ - int count = 0; - for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { - int this_count; - this_count = (*iter)->subworld()->foreachLock(fn, data); - if (this_count < 0) - return -1; - count += this_count; - } - return count; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + //=========================================================================== + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SubWorldInfo + + class SubWorldInfo { + + private: + WorldPtr _subworld; + WorldPtr _refreshed_subworld; + + bool _refreshed_ready; + + unsigned int _changed_resItems_id; + unsigned int _changed_channels_id; + unsigned int _changed_subscriptions_id; + unsigned int _changed_locks_id; + + public: + + SubWorldInfo (WorldPtr subworld, MultiWorldPtr multiworld); + virtual ~SubWorldInfo(); + + // ---------------------------------- I/O + + static std::string toString (const SubWorldInfo & subworldinfo); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const SubWorldInfo & subworldinfo); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + WorldPtr subworld () const { return _subworld; } + + // ---------------------------------- methods + + }; + + //--------------------------------------------------------------------------- + + string + SubWorldInfo::asString ( void ) const + { + return toString (*this); + } + + + string + SubWorldInfo::toString ( const SubWorldInfo & subworldinfo ) + { + return ""; + } + + + ostream & + SubWorldInfo::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const SubWorldInfo & subworldinfo) + { + return os << subworldinfo.asString(); + } + + //--------------------------------------------------------------------------- + + SubWorldInfo::SubWorldInfo (WorldPtr subworld, MultiWorldPtr multiworld) + : _subworld (subworld) + , _changed_resItems_id (0) + , _changed_channels_id (0) + , _changed_subscriptions_id (0) + , _changed_locks_id (0) + + { + #if 0 + _changed_resItems_id = + g_signal_connect (G_OBJECT (subworld), + "changed_resItems", + (GCallback) changed_resItems_cb, + world); + + _changed_channels_id = + g_signal_connect (G_OBJECT (subworld), + "changed_channels", + (GCallback) changed_channels_cb, + world); + + _changed_subscriptions_id = + g_signal_connect (G_OBJECT (subworld), + "changed_subscriptions", + (GCallback) changed_subscriptions_cb, + world); + + _changed_locks_id = + g_signal_connect (G_OBJECT (subworld), + "changed_locks", + (GCallback) changed_locks_cb, + world); + #endif + } + + + SubWorldInfo::~SubWorldInfo() + { + } + + + //=========================================================================== + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : NameConflictInfo + + class NameConflictInfo { + + private: + int _depth; + MultiWorldPtr _multiworld; + WorldPtr _subworld; + const char *_name; + + public: + NameConflictInfo(int depth, MultiWorldPtr multiworld, WorldPtr subworld, const char *name); + virtual ~NameConflictInfo(); + + // ---------------------------------- I/O + + static std::string toString (const NameConflictInfo & nameconflictinfo); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const NameConflictInfo & nameconflictinfo); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + int depth () const { return _depth; } + MultiWorldPtr multiworld () const { return _multiworld; } + WorldPtr subworld () const { return _subworld; } + const char *name () const { return _name; } + void setName (const char *name) { free((void *)_name); _name = strdup (name); } + + // ---------------------------------- methods + + void incDepth (void) { _depth++; } + }; + + + //--------------------------------------------------------------------------- + + string + NameConflictInfo::asString ( void ) const + { + return toString (*this); + } + + + string + NameConflictInfo::toString ( const NameConflictInfo & subworldinfo ) + { + return ""; + } + + + ostream & + NameConflictInfo::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const NameConflictInfo & subworldinfo) + { + return os << subworldinfo.asString(); + } + + //--------------------------------------------------------------------------- + + NameConflictInfo::NameConflictInfo (int depth, MultiWorldPtr multiworld, WorldPtr subworld, const char *name) + : _depth (depth) + , _multiworld (multiworld) + , _subworld (subworld) + , _name (strdup (name)) + { + } + + + NameConflictInfo::~NameConflictInfo() + { + free ((void *)_name); + } + + + //=========================================================================== + + IMPL_DERIVED_POINTER(MultiWorld, World); + + string + MultiWorld::asString ( void ) const + { + return toString (*this); + } + + + string + MultiWorld::toString ( const MultiWorld & world ) + { + return ""; + } + + + ostream & + MultiWorld::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const MultiWorld & world) + { + return os << world.asString(); + } + + //--------------------------------------------------------------------------- + + MultiWorld::MultiWorld () + : World (MULTI_WORLD) + { + } + + + MultiWorld::~MultiWorld() + { + } + + //--------------------------------------------------------------------------- + + class ForeachByTypeInfo { + public: + WorldType type; + WorldFn callback; + NameConflictInfo *name_conflict_info; + + int count; + }; + + + int + MultiWorld::foreachSubworld (WorldFn callback, void *user_data) + { + if (callback == NULL) return -1; + + /* Make a copy of subworlds for case where user callback is + running main loop and a refresh starts at that time. */ + + WorldList copied_subworlds; + + for (SubWorldInfoList::iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + copied_subworlds.push_front ((*iter)->subworld()); + } + + int count = 0; + + for (WorldList::const_iterator iter = copied_subworlds.begin(); iter != copied_subworlds.end(); iter++) { + if (! callback (*iter, user_data)) { + count = -1; + break; + } else + ++count; + } + + return count; + } + + + static bool + foreach_by_type_cb (constWorldPtr subworld, void *user_data) + { + ForeachByTypeInfo *info = (ForeachByTypeInfo *)user_data; + + if ((subworld->type() != info->type) + || info->callback == NULL) + { + return true; + } + + if (! info->callback (subworld, info->name_conflict_info)) { + info->count = -1; + return false; + } else { + ++info->count; + return true; + } + } + + + int + MultiWorld::foreachSubworldByType (WorldType type, WorldFn callback, NameConflictInfo *name_conflict_info) + { + ForeachByTypeInfo info; + + info.type = type; + info.callback = callback; + info.name_conflict_info = name_conflict_info; + info.count = 0; + + foreachSubworld (foreach_by_type_cb, (void *)(&info)); + + return info.count; + } + + //--------------------------------------------------------------------------- + // subworld + + static bool + service_name_conflict_cb (constWorldPtr world, void *user_data) + { + constServiceWorldPtr service = world; + if (service == NULL) { + fprintf (stderr, "OOPS: service_name_conflict_cb: world is no service\n"); + abort(); + } + + NameConflictInfo *info = (NameConflictInfo *)user_data; + if (!strcasecmp (service->name(), info->name())) { + info->incDepth(); + ServiceWorldPtr infoservice = info->subworld(); + if (infoservice == NULL) { + fprintf (stderr, "OOPS: service_name_conflict_cb: info->subworld is no service\n"); + abort(); + } + info->setName (stringutil::form ("%s (%d)", infoservice->name(), info->depth()).c_str()); + info->multiworld()->foreachSubworldByType (SERVICE_WORLD, service_name_conflict_cb, info); + return false; + } + + return true; + } + + + void + MultiWorld::addSubworld (WorldPtr subworld) + { + if (subworld == NULL) return; + + /* + * If we're adding a service, make sure that the name of the service + * doesn't conflict with any other. + */ + ServiceWorldPtr service = subworld; // service will be NULL if subworld is not a ServiceWorld + + if (service != NULL) { + NameConflictInfo conflict_info (0, this, subworld, service->name()); + + foreachSubworldByType (SERVICE_WORLD, service_name_conflict_cb, &conflict_info); + + service->setName (conflict_info.name()); + } + + SubWorldInfo *subworld_info = new SubWorldInfo (subworld, this); + + _subworlds.push_back (subworld_info); + + // g_signal_emit (multi, signals[SUBWORLD_ADDED], 0, subworld); + + return; + } + + + void + MultiWorld::removeSubworld (WorldPtr subworld) + { + if (subworld == NULL) return; + + for (SubWorldInfoList::iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + if ((*iter)->subworld() == subworld) { + _subworlds.erase (iter); + // g_signal_emit (multi, signals[SUBWORLD_REMOVED], 0, subworld); + return; + } + } + return; + } + + + //--------------------------------------------------------------------------- + // channels + + ChannelList + MultiWorld::channels () const + { + ChannelList cl; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + cl = (*iter)->subworld()->channels(); + //FIXME cl.merge ((*iter)->subworld()->channels()); + } + return cl; + } + + + bool + MultiWorld::containsChannel (constChannelPtr channel) const + { + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + if ((*iter)->subworld()->containsChannel(channel)) + return true; + } + return false; + } + + + ChannelPtr + MultiWorld::getChannelByName (const char *channel_name) const + { + ChannelPtr channel; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + channel = (*iter)->subworld()->getChannelByName(channel_name); + if (channel != NULL) + return channel; + } + return NULL; + } + + + ChannelPtr + MultiWorld::getChannelByAlias (const char *alias) const + { + ChannelPtr channel; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + channel = (*iter)->subworld()->getChannelByAlias(alias); + if (channel != NULL) + return channel; + } + return NULL; + } + + + ChannelPtr + MultiWorld::getChannelById (const char *channel_id) const + { + ChannelPtr channel; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + channel = (*iter)->subworld()->getChannelById(channel_id); + if (channel != NULL) + return channel; + } + return NULL; + } + + + int + MultiWorld::foreachChannel (ChannelFn fn, void *data) const + { + int count = 0; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + int this_count; + this_count = (*iter)->subworld()->foreachChannel(fn, data); + if (this_count < 0) + return -1; + count += this_count; + } + return count; + } + + + //--------------------------------------------------------------------------- + // Single resItem queries + + constResItemPtr + MultiWorld::findInstalledResItem (constResItemPtr resItem) + { + constResItemPtr installed; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + installed = (*iter)->subworld()->findInstalledResItem(resItem); + if (installed != NULL) + return installed; + } + return NULL; + } + + + constResItemPtr + MultiWorld::findResItem (constChannelPtr channel, const char *name) const + { + constResItemPtr resItem; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + resItem = (*iter)->subworld()->findResItem(channel, name); + if (resItem != NULL) + return resItem; + } + return NULL; + } + + + constResItemPtr + MultiWorld::findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const + { + constResItemPtr resItem; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + resItem = (*iter)->subworld()->findResItemWithConstraint(channel, name, constraint, is_and); + if (resItem != NULL) + return resItem; + } + return NULL; + } + + + ChannelPtr + MultiWorld::guessResItemChannel (constResItemPtr resItem) const + { + ChannelPtr channel; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + channel = (*iter)->subworld()->guessResItemChannel(resItem); + if (channel != NULL) + return channel; + } + return NULL; + } + + //--------------------------------------------------------------------------- + // iterate over resItems + + int + MultiWorld::foreachResItem (ChannelPtr channel, CResItemFn fn, void *data) + { + return foreachResItemByName ("", channel, fn, data); + } + + + int + MultiWorld::foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data) + { + int count = 0; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + int this_count; + this_count = (*iter)->subworld()->foreachResItemByName(name, channel, fn, data); + if (this_count < 0) + return -1; + count += this_count; + } + return count; + } + + + int + MultiWorld::foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data) + { + fprintf (stderr, "MultiWorld::foreachResItemByMatch not implemented\n"); + return 0; + } + + + //----------------------------------------------------------------------------- + // iterater over resItems with dependency + + int + MultiWorld::foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data) + { + int count = 0; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + int this_count; + this_count = (*iter)->subworld()->foreachProvidingResItem (dep, fn, data); + if (this_count < 0) + return -1; + count += this_count; + } + return count; + } + + int + MultiWorld::foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) + { + int count = 0; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + int this_count; + this_count = (*iter)->subworld()->foreachRequiringResItem (dep, fn, data); + if (this_count < 0) + return -1; + count += this_count; + } + return count; + } + + int + MultiWorld::foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) + { + int count = 0; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + int this_count; + this_count = (*iter)->subworld()->foreachConflictingResItem (dep, fn, data); + if (this_count < 0) + return -1; + count += this_count; + } + return count; + } + + + //----------------------------------------------------------------------------- + // iterater over resItems with locks + + int + MultiWorld::foreachLock (MatchFn fn, void *data) const + { + int count = 0; + for (SubWorldInfoList::const_iterator iter = _subworlds.begin(); iter != _subworlds.end(); iter++) { + int this_count; + this_count = (*iter)->subworld()->foreachLock(fn, data); + if (this_count < 0) + return -1; + count += this_count; + } + return count; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/MultiWorld.h b/zypp/solver/detail/MultiWorld.h index dce8f7f..1bed9c9 100644 --- a/zypp/solver/detail/MultiWorld.h +++ b/zypp/solver/detail/MultiWorld.h @@ -30,9 +30,15 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// class SubWorldInfo; class NameConflictInfo; @@ -47,81 +53,87 @@ typedef std::list SubWorldInfoList; class MultiWorld : public World { REP_BODY(MultiWorld); - private: - - SubWorldInfoList _subworlds; - - PendingPtr _multi_pending; - PendingList _subworld_pendings; - - void (*_subworld_added) (WorldPtr subworld); - void (*_subworld_removed) (WorldPtr subworld); - - public: - - MultiWorld (); - MultiWorld (XmlNodePtr node); - MultiWorld (const char *filename); - virtual ~MultiWorld(); - - // ---------------------------------- I/O - - static std::string toString (const MultiWorld & section); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const MultiWorld & section); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - void addSubworld (WorldPtr subworld); - void removeSubworld (WorldPtr subworld); - - // ---------------------------------- methods - - virtual ChannelList channels () const; - virtual bool containsChannel (constChannelPtr channel) const; - virtual ChannelPtr getChannelByName (const char *channel_name) const; - virtual ChannelPtr getChannelByAlias (const char *alias) const; - virtual ChannelPtr getChannelById (const char *channel_id) const; - virtual ChannelPtr guessResItemChannel (constResItemPtr resItem) const; - virtual int foreachChannel (ChannelFn fn, void *data) const; - - int foreachSubworld (WorldFn callback, void *user_data); - int foreachSubworldByType (WorldType type, WorldFn callback, NameConflictInfo *info); - WorldList getSubworlds (); - ServiceWorldPtr lookupService (const char *url); - ServiceWorldPtr lookupServiceById (const char *id); - bool mountService (const char *url, void *error); // GError **error); - - // Single resItem queries - - virtual constResItemPtr findInstalledResItem (constResItemPtr resItem); - virtual constResItemPtr findResItem (constChannelPtr channel, const char *name) const; - virtual constResItemPtr findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const; - - // Iterate over resItems - - virtual int foreachResItem (ChannelPtr channel, CResItemFn fn, void *data); - virtual int foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data); - virtual int foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data); - - // Iterate across provides or requirement - - virtual int foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data); - virtual int foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); - virtual int foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); - - // locks - - virtual int foreachLock (MatchFn fn, void *data) const; - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + private: + + SubWorldInfoList _subworlds; + + PendingPtr _multi_pending; + PendingList _subworld_pendings; + + void (*_subworld_added) (WorldPtr subworld); + void (*_subworld_removed) (WorldPtr subworld); + + public: + + MultiWorld (); + MultiWorld (XmlNodePtr node); + MultiWorld (const char *filename); + virtual ~MultiWorld(); + + // ---------------------------------- I/O + + static std::string toString (const MultiWorld & section); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const MultiWorld & section); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + void addSubworld (WorldPtr subworld); + void removeSubworld (WorldPtr subworld); + + // ---------------------------------- methods + + virtual ChannelList channels () const; + virtual bool containsChannel (constChannelPtr channel) const; + virtual ChannelPtr getChannelByName (const char *channel_name) const; + virtual ChannelPtr getChannelByAlias (const char *alias) const; + virtual ChannelPtr getChannelById (const char *channel_id) const; + virtual ChannelPtr guessResItemChannel (constResItemPtr resItem) const; + virtual int foreachChannel (ChannelFn fn, void *data) const; + + int foreachSubworld (WorldFn callback, void *user_data); + int foreachSubworldByType (WorldType type, WorldFn callback, NameConflictInfo *info); + WorldList getSubworlds (); + ServiceWorldPtr lookupService (const char *url); + ServiceWorldPtr lookupServiceById (const char *id); + bool mountService (const char *url, void *error); // GError **error); + + // Single resItem queries + + virtual constResItemPtr findInstalledResItem (constResItemPtr resItem); + virtual constResItemPtr findResItem (constChannelPtr channel, const char *name) const; + virtual constResItemPtr findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const; + + // Iterate over resItems + + virtual int foreachResItem (ChannelPtr channel, CResItemFn fn, void *data); + virtual int foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data); + virtual int foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data); + + // Iterate across provides or requirement + + virtual int foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data); + virtual int foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); + virtual int foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); + + // locks + + virtual int foreachLock (MatchFn fn, void *data) const; + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _MultiWorld_h diff --git a/zypp/solver/detail/MultiWorldPtr.h b/zypp/solver/detail/MultiWorldPtr.h index 687939c..19770f2 100644 --- a/zypp/solver/detail/MultiWorldPtr.h +++ b/zypp/solver/detail/MultiWorldPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : MultiWorldPtr -// CLASS NAME : constMultiWorldPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(MultiWorld, World); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : MultiWorldPtr + // CLASS NAME : constMultiWorldPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(MultiWorld, World); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _MultiWorldPtr_h diff --git a/zypp/solver/detail/OrDependency.cc b/zypp/solver/detail/OrDependency.cc index 702c9a1..7bb40c2 100644 --- a/zypp/solver/detail/OrDependency.cc +++ b/zypp/solver/detail/OrDependency.cc @@ -26,258 +26,270 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(OrDependency); - -OrDependency::OrDependencyTable OrDependency::_or_dep_table; - -//--------------------------------------------------------------------------- - -string -OrDependency::asString ( void ) const -{ - return toString (*this); -} - - -string -OrDependency::toString ( const OrDependency & dependency ) -{ - string res (""); - - return res; -} - - -ostream & -OrDependency::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream & os, const OrDependency & dependency) -{ - return os << dependency.asString(); -} - -//--------------------------------------------------------------------------- - -OrDependency::OrDependency (string & dep, const CDependencyList & split_ors) - : _or_dep (dep) - , _split_ors (split_ors) - , _ref(1) -{ -} - - -OrDependency::OrDependency (constXmlNodePtr node) -{ -} - - -OrDependency::~OrDependency() -{ -} - - -//--------------------------------------------------------------------------- - -OrDependencyPtr -OrDependency::fromDependencyList (const CDependencyList & deplist) -{ - string depstr = dependencyListToString(deplist); - - OrDependencyTable::iterator pos = _or_dep_table.find(depstr); - if (pos != _or_dep_table.end()) { - (*pos).second->incRef(); - return (*pos).second; - } - - OrDependencyPtr or_dep = new OrDependency (depstr, deplist); - _or_dep_table[depstr] = or_dep; - return or_dep; -} - - -OrDependencyPtr -OrDependency::fromString (const char *dep) -{ - string depstr = string (dep); - - OrDependencyTable::iterator pos = _or_dep_table.find(depstr); - if (pos != _or_dep_table.end()) { - (*pos).second->incRef(); - return (*pos).second; - } - - CDependencyList deplist = stringToDependencyList (dep); - OrDependencyPtr or_dep = new OrDependency (depstr, deplist); - _or_dep_table[depstr] = or_dep; - return or_dep; - -} - - -string -OrDependency::dependencyListToString (const CDependencyList & deplist) -{ - string str ("(||"); - - for (CDependencyList::const_iterator dep = deplist.begin(); dep != deplist.end(); dep++) { - if (dep != deplist.begin()) - str += "|"; - - str += (*dep)->name(); - - Relation relation = (*dep)->relation(); - - if (relation != Relation::Any) { - str += "&"; - str += relation.asString(); - str += "&"; - - if ((*dep)->epoch() >= 0) { - str += stringutil::form("%d:", (*dep)->epoch()); - } - - str += (*dep)->version(); - - string rel = (*dep)->release(); - if (!rel.empty()) { - str += "-"; - str += rel; - } - } - - } - - str += ")"; - - return str; -} - - -CDependencyList -OrDependency::stringToDependencyList (const char *s) -{ - const char *p, *zz; - CDependencyList out_dep; - bool have_more = true; - - if (strncmp (s, "(||", 3)) { - fprintf (stderr, "'%s' is not a 'munged or' string!\n", s); - return out_dep; - } - - s += 3; - - zz = strchr (s, ')'); - - if (!zz) - return out_dep; - - /* s now points to the start of the first thing */ - do { - char *z; - SpecPtr spec; - char *name; - Relation relation = Relation::Any; - EditionPtr edition = NULL; - - /* grab the name */ - - z = strchr (s, '|'); - p = strchr (s, '&'); - - if (!z) { - have_more = false; - } - else { - /* We don't want to get a p from a later element. */ - if (p > z) - p = NULL; - } - - name = strndup (s, p ? p - s : (z ? z - s : zz - s)); - - if (p) { - char *e; - char op[4]; - char *vstr; - - /* We need to parse version things */ - p++; - e = strchr (p, '&'); - if (!e || e-p > 3) { - /* Bad. */ - fprintf (stderr, "Couldn't parse ver str [%s]\n", p); - } - - /* text between p and e is an operator */ - strncpy (op, p, e - p); - op[e - p] = 0; - relation = Relation::parse (op); - - e++; - if (z) { - p = z; - } else { - p = zz; - } - - /* e .. p is the epoch:version-release */ - vstr = strndup (e, p - e); - - EditionPtr edition = Edition::fromString (vstr); - - free ((void *)vstr); - - } - - DependencyPtr dep = new Dependency (name, relation, Kind::Package, NULL, edition); - - out_dep.push_back (dep); - free ((void *)name); - - s = z + 1; - - if (p == zz) - have_more = false; - } while (have_more); - - return out_dep; -} - - -void -OrDependency::addCreatedProvide (constDependencyPtr dep) -{ - _created_provides.push_back (dep); -} - - -constDependencyPtr -OrDependency::find (const char *dep) -{ - string depstr (dep); - - OrDependencyTable::iterator pos = _or_dep_table.find(depstr); - if (pos != _or_dep_table.end()) { - return new Dependency ((*pos).second); - } - - return NULL; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(OrDependency); + + OrDependency::OrDependencyTable OrDependency::_or_dep_table; + + //--------------------------------------------------------------------------- + + string + OrDependency::asString ( void ) const + { + return toString (*this); + } + + + string + OrDependency::toString ( const OrDependency & dependency ) + { + string res (""); + + return res; + } + + + ostream & + OrDependency::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream & os, const OrDependency & dependency) + { + return os << dependency.asString(); + } + + //--------------------------------------------------------------------------- + + OrDependency::OrDependency (string & dep, const CDependencyList & split_ors) + : _or_dep (dep) + , _split_ors (split_ors) + , _ref(1) + { + } + + + OrDependency::OrDependency (constXmlNodePtr node) + { + } + + + OrDependency::~OrDependency() + { + } + + + //--------------------------------------------------------------------------- + + OrDependencyPtr + OrDependency::fromDependencyList (const CDependencyList & deplist) + { + string depstr = dependencyListToString(deplist); + + OrDependencyTable::iterator pos = _or_dep_table.find(depstr); + if (pos != _or_dep_table.end()) { + (*pos).second->incRef(); + return (*pos).second; + } + + OrDependencyPtr or_dep = new OrDependency (depstr, deplist); + _or_dep_table[depstr] = or_dep; + return or_dep; + } + + + OrDependencyPtr + OrDependency::fromString (const char *dep) + { + string depstr = string (dep); + + OrDependencyTable::iterator pos = _or_dep_table.find(depstr); + if (pos != _or_dep_table.end()) { + (*pos).second->incRef(); + return (*pos).second; + } + + CDependencyList deplist = stringToDependencyList (dep); + OrDependencyPtr or_dep = new OrDependency (depstr, deplist); + _or_dep_table[depstr] = or_dep; + return or_dep; + + } + + + string + OrDependency::dependencyListToString (const CDependencyList & deplist) + { + string str ("(||"); + + for (CDependencyList::const_iterator dep = deplist.begin(); dep != deplist.end(); dep++) { + if (dep != deplist.begin()) + str += "|"; + + str += (*dep)->name(); + + Relation relation = (*dep)->relation(); + + if (relation != Relation::Any) { + str += "&"; + str += relation.asString(); + str += "&"; + + if ((*dep)->epoch() >= 0) { + str += stringutil::form("%d:", (*dep)->epoch()); + } + + str += (*dep)->version(); + + string rel = (*dep)->release(); + if (!rel.empty()) { + str += "-"; + str += rel; + } + } + + } + + str += ")"; + + return str; + } + + + CDependencyList + OrDependency::stringToDependencyList (const char *s) + { + const char *p, *zz; + CDependencyList out_dep; + bool have_more = true; + + if (strncmp (s, "(||", 3)) { + fprintf (stderr, "'%s' is not a 'munged or' string!\n", s); + return out_dep; + } + + s += 3; + + zz = strchr (s, ')'); + + if (!zz) + return out_dep; + + /* s now points to the start of the first thing */ + do { + char *z; + SpecPtr spec; + char *name; + Relation relation = Relation::Any; + EditionPtr edition = NULL; + + /* grab the name */ + + z = strchr (s, '|'); + p = strchr (s, '&'); + + if (!z) { + have_more = false; + } + else { + /* We don't want to get a p from a later element. */ + if (p > z) + p = NULL; + } + + name = strndup (s, p ? p - s : (z ? z - s : zz - s)); + + if (p) { + char *e; + char op[4]; + char *vstr; + + /* We need to parse version things */ + p++; + e = strchr (p, '&'); + if (!e || e-p > 3) { + /* Bad. */ + fprintf (stderr, "Couldn't parse ver str [%s]\n", p); + } + + /* text between p and e is an operator */ + strncpy (op, p, e - p); + op[e - p] = 0; + relation = Relation::parse (op); + + e++; + if (z) { + p = z; + } else { + p = zz; + } + + /* e .. p is the epoch:version-release */ + vstr = strndup (e, p - e); + + EditionPtr edition = Edition::fromString (vstr); + + free ((void *)vstr); + + } + + DependencyPtr dep = new Dependency (name, relation, Kind::Package, NULL, edition); + + out_dep.push_back (dep); + free ((void *)name); + + s = z + 1; + + if (p == zz) + have_more = false; + } while (have_more); + + return out_dep; + } + + + void + OrDependency::addCreatedProvide (constDependencyPtr dep) + { + _created_provides.push_back (dep); + } + + + constDependencyPtr + OrDependency::find (const char *dep) + { + string depstr (dep); + + OrDependencyTable::iterator pos = _or_dep_table.find(depstr); + if (pos != _or_dep_table.end()) { + return new Dependency ((*pos).second); + } + + return NULL; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/OrDependency.h b/zypp/solver/detail/OrDependency.h index e30e03c..6e5090a 100644 --- a/zypp/solver/detail/OrDependency.h +++ b/zypp/solver/detail/OrDependency.h @@ -32,70 +32,81 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : OrDependency -/** - * - **/ - -class OrDependency : public CountedRep { - REP_BODY(OrDependency); - - private: - typedef std::map OrDependencyTable; - - static OrDependencyTable _or_dep_table; - - std::string _or_dep; - CDependencyList _split_ors; - CDependencyList _created_provides; - int _ref; - - OrDependency (std::string & dep, const CDependencyList & split_ors); - - static std::string dependencyListToString (const CDependencyList & deplist); - static CDependencyList stringToDependencyList (const char *s); - - void incRef() { _ref++; } - void decRef() { _ref--; } - - public: - - OrDependency (constXmlNodePtr node); +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// - virtual ~OrDependency(); - - // ---------------------------------- I/O - - const xmlNodePtr asXmlNode (void) const; - - static std::string toString ( const OrDependency & ordep ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const OrDependency & ordep ); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - const char *name (void) const { return _or_dep.c_str(); } - void addCreatedProvide (constDependencyPtr dep); - - // ---------------------------------- methods - - static OrDependencyPtr fromDependencyList (const CDependencyList & deplist); - static OrDependencyPtr fromString (const char *dep); - static constDependencyPtr find (const char *dep); -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp /////////////////////////////////////////////////////////////////// - + // + // CLASS NAME : OrDependency + /** + * + **/ + + class OrDependency : public CountedRep { + REP_BODY(OrDependency); + + private: + typedef std::map OrDependencyTable; + + static OrDependencyTable _or_dep_table; + + std::string _or_dep; + CDependencyList _split_ors; + CDependencyList _created_provides; + int _ref; + + OrDependency (std::string & dep, const CDependencyList & split_ors); + + static std::string dependencyListToString (const CDependencyList & deplist); + static CDependencyList stringToDependencyList (const char *s); + + void incRef() { _ref++; } + void decRef() { _ref--; } + + public: + + OrDependency (constXmlNodePtr node); + + virtual ~OrDependency(); + + // ---------------------------------- I/O + + const xmlNodePtr asXmlNode (void) const; + + static std::string toString ( const OrDependency & ordep ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const OrDependency & ordep ); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + const char *name (void) const { return _or_dep.c_str(); } + void addCreatedProvide (constDependencyPtr dep); + + // ---------------------------------- methods + + static OrDependencyPtr fromDependencyList (const CDependencyList & deplist); + static OrDependencyPtr fromString (const char *dep); + static constDependencyPtr find (const char *dep); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _OrDependency_h diff --git a/zypp/solver/detail/OrDependencyPtr.h b/zypp/solver/detail/OrDependencyPtr.h index a7c021e..e5972ae 100644 --- a/zypp/solver/detail/OrDependencyPtr.h +++ b/zypp/solver/detail/OrDependencyPtr.h @@ -23,18 +23,30 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : OrDependencyPtr -// CLASS NAME : constOrDependencyPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(OrDependency); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : OrDependencyPtr + // CLASS NAME : constOrDependencyPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(OrDependency); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _DependencyPtr_h diff --git a/zypp/solver/detail/Package.cc b/zypp/solver/detail/Package.cc index bf71bcc..d2015bb 100644 --- a/zypp/solver/detail/Package.cc +++ b/zypp/solver/detail/Package.cc @@ -27,613 +27,625 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(Package,Spec); - -struct DepTable { - CDependencyList requires; - CDependencyList provides; - CDependencyList conflicts; - CDependencyList obsoletes; - CDependencyList children; - CDependencyList suggests; - CDependencyList recommends; -}; - -//--------------------------------------------------------------------------- - -static void -extract_dep_info (constXmlNodePtr iter, struct DepTable & dep_table) -{ - if (iter->equals("requires")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - dep_table.requires.push_back(new Dependency (iter2)); - iter2 = iter2->next(); - } - - } else if (iter->equals("recommends")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - dep_table.recommends.push_back (new Dependency (iter2)); - iter2 = iter2->next(); - } - - } else if (iter->equals("suggests")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - dep_table.suggests.push_back (new Dependency (iter2)); - iter2 = iter2->next(); - } - - } else if (iter->equals("conflicts")) { - XmlNodePtr iter2; - bool all_are_obs = false, this_is_obs = false; - const char *obs; - - iter2 = iter->children(); - - obs = iter->getProp ("obsoletes", NULL); - if (obs) { - all_are_obs = true; - free ((void *)obs); - } - - while (iter2) { - - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - DependencyPtr dep = new Dependency (iter2); - - if (! all_are_obs) { - this_is_obs = false; - obs = iter2->getProp ("obsoletes", NULL); - if (obs) { - this_is_obs = true; - free ((void *)obs); - } - } - - if (all_are_obs || this_is_obs) { - dep_table.obsoletes.push_back (dep); - } else { - dep_table.conflicts.push_back (dep); - } - - iter2 = iter2->next(); - } - - } else if (iter->equals("obsoletes")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - dep_table.obsoletes.push_back (new Dependency (iter2)); - iter2 = iter2->next(); - } - - } else if (iter->equals("provides")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - dep_table.provides.push_back (new Dependency (iter2)); - iter2 = iter2->next(); - } - - } else if (iter->equals("children")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - dep_table.children.push_back (new Dependency (iter2)); - iter2 = iter2->next(); - } - } -} - -//--------------------------------------------------------------------------- - - -string -Package::asString ( bool full ) const -{ - return toString (*this, full); -} - - -string -Package::toString ( const PackageUpdateList & l, bool full ) -{ - string ret ("["); - for (PackageUpdateList::const_iterator i = l.begin(); i != l.end(); i++) { - if (i != l.begin()) ret += ", "; - ret += (*i)->asString(full); - } - return ret + "]"; -} - -string -Package::toString ( const Package & package, bool full ) -{ - string ret; - ret += ResItem::toString(package, full); - if (full) { -// if (package._section != NULL) ret += (string ("
asString() + "'/>"); -// if (!package._pretty_name.empty()) ret += (string (""); -// if (!package._summary.empty()) ret += (string (""); -// if (!package._description.empty()) ret += (string (""); - ret += (string (""); - } - return ret; -} - - -ostream & -Package::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Package& package) -{ - return os << package.asString(); -} - -//--------------------------------------------------------------------------- - -Package::Package (constChannelPtr channel) - : ResItem (Kind::Package, "") - , _section (NULL) - , _pretty_name ("") - , _summary ("") - , _description ("") - , _package_filename ("") - , _signature_filename ("") - , _install_only (false) - , _package_set (false) - , _id ("") -{ - setChannel (channel); -} - - -Package::Package (constXmlNodePtr node, constChannelPtr channel) - : ResItem (Kind::Package, "") - , _section (NULL) - , _pretty_name ("") - , _summary ("") - , _description ("") - , _package_filename ("") - , _signature_filename ("") - , _install_only (false) - , _package_set (false) - , _id ("") -{ - if (!node->equals("package")) { - fprintf (stderr, "Package::Package() not a package node\n"); - exit (1); - } - - const char *epoch = NULL, *version = NULL, *release = NULL; - struct DepTable dep_table; - - setChannel (channel); - - constXmlNodePtr iter = node->children(); - - while (iter) { - bool extracted_deps = false; - - if (iter->equals("name")) { setName (iter->getContent()); - } else if (iter->equals("epoch")) { setEpoch (atoi (iter->getContent())); - } else if (iter->equals("version")) { setVersion (iter->getContent()); - } else if (iter->equals("release")) { setRelease (iter->getContent()); - } else if (iter->equals("summary")) { _summary = strdup (iter->getContent()); - } else if (iter->equals("description")) { _description = strdup (iter->getContent()); - } else if (iter->equals("section")) { _section = new Section (iter->getContent()); - } else if (iter->equals("arch")) { setArch (iter->getContent()); - } else if (iter->equals("filesize")) { - const char *tmp = iter->getContent(); - setFileSize (tmp && *tmp ? atoi (tmp) : 0); - free ((void *)tmp); - } else if (iter->equals("installedsize")) { - const char *tmp = iter->getContent(); - setInstalledSize (tmp && *tmp ? atoi (tmp) : 0); - free ((void *)tmp); - } else if (iter->equals("install_only")) { _install_only = true; - } else if (iter->equals("package_set")) { _package_set = true; - } else if (iter->equals("history")) { - constXmlNodePtr iter2; - - iter2 = iter->children(); - - while (iter2) { - if (!iter2->isElement()) { - iter2 = iter2->next(); - continue; - } - - PackageUpdatePtr update = new PackageUpdate (iter2, this); - addUpdate (update); - - iter2 = iter2->next(); - } - } else if (iter->equals("deps")) { - constXmlNodePtr iter2; - - for (iter2 = iter->children(); iter2; iter2 = iter2->next()) { - if (!iter2->isElement()) - continue; - - extract_dep_info (iter2, dep_table); - } - - extracted_deps = true; - } - else { - if (!extracted_deps) - extract_dep_info (iter, dep_table); - else { - /* FIXME: Bitch to the user here? */ - } - } - - iter = iter->next(); - } - - if (!dep_table.children.empty()) { - // children are used in package sets - // treat them as normal requires - // -#warning Children are handled as requires - CDependencyList::const_iterator iter; - for (iter = dep_table.children.begin(); iter != dep_table.children.end(); iter++) - { - dep_table.requires.push_back (*iter); - } - } - - - // check if we're already listed in the provides - // if not, provide ourself - - CDependencyList::const_iterator piter; - for (piter = dep_table.provides.begin(); piter != dep_table.provides.end(); piter++) { - if ((*piter)->relation().isEqual() - && ((*piter)->name() == name())) - { - break; - } - } - if (piter == dep_table.provides.end()) { // no self provide found, construct one - constDependencyPtr selfdep = new Dependency (name(), Relation::Equal, kind(), this->channel(), edition()); -if (getenv ("RC_SPEW")) fprintf (stderr, "Adding self-provide [%s]\n", selfdep->asString().c_str()); - dep_table.provides.push_front (selfdep); - } - - setRequires (dep_table.requires); - setProvides (dep_table.provides); - setConflicts (dep_table.conflicts); - setObsoletes (dep_table.obsoletes); - setSuggests (dep_table.suggests); - setRecommends (dep_table.recommends); - - if (version) { - - setEpoch (epoch ? atoi (epoch) : -1); - setVersion (version); - setRelease (release); - - /* We set these to NULL so that they won't get freed when we - clean up before returning. */ - version = release = NULL; - - } else if (!_history.empty()) { - - /* If possible, we grab the version info from the most - recent update. */ - - PackageUpdatePtr update = _history.front(); - - setEpoch (update->package()->epoch()); - setVersion (update->package()->version()); - setRelease (update->package()->release()); - - } else { - - /* Otherwise, try to find where the package provides itself, - and use that version info. */ - - if (!provides().empty()) - for (CDependencyList::const_iterator iter = provides().begin(); iter != provides().end(); iter++) { - if ((*iter)->relation() == Relation::Equal && - ((*iter)->name() == name())) - { - setEpoch ((*iter)->epoch()); - setVersion ((*iter)->version()); - setRelease ((*iter)->release()); - break; - } - } - } - - /* clean-up */ - if (epoch) free ((void *)epoch); - if (version) free ((void *)version); - if (release) free ((void *)release); - - /* Hack for no archs in the XML yet */ - if (arch()->isUnknown()) - setArch (Arch::System); -} - -Package::~Package() -{ -} - -//--------------------------------------------------------------------------- - - -void -Package::addUpdate (PackageUpdatePtr update) -{ - if (update == NULL) return; - - assert (update->package() == NULL || update->package() == this); - - update->setPackage(this); - - if (_history.empty()) { - _history.push_back (update); - } else { -#warning addUpdate incomplete -#if 1 - for (PackageUpdateList::iterator iter = _history.begin(); iter != _history.end(); iter++) { - int result = GVersion.compare ((SpecPtr)update, (SpecPtr)(*iter)); - - if (result > 0 || (result == 0 && update->parent() != NULL)) { - _history.insert (iter, update); // = g_slist_insert_before (package->history, l, update); - break; - } else if (iter == _history.end() || // FIXME list.last() ? - (result == 0 && update->parent() == NULL)) { - _history.insert (++iter, update); // = g_slist_insert_before (package->history, l->next, update); - break; - } - } -#endif - } -} - - -PackageUpdatePtr -Package::getLatestUpdate (void) const -{ - WorldPtr world; - - if (_history.empty()) { - return NULL; - } - - PackageUpdatePtr latest = _history.back(); - /* if the absolute latest is not a patch, just return that */ - if (latest->parent() == NULL) { - return latest; - } - - world = World::globalWorld(); - - for (PackageUpdateList::const_iterator l = _history.begin(); l != _history.end(); l++) { - PackageUpdatePtr update = *l; - constResItemPtr installed; - - if (!update->equals (latest)) { - return NULL; - } - - /* found a non-patch package equal to the latest, so use that */ - if (update->parent() == NULL) { - return update; - } - - /* see if the required parent for this patch is installed */ - installed = world->findInstalledResItem (update->parent()); - - if (installed != NULL && - installed->equals(update->parent())) - return update; - } - - /* no suitable update found */ - return NULL; -} - - -#if 0 -xmlNode * -rc_package_to_xml_node (RCPackage *package) -{ - xmlNode *package_node; - xmlNode *tmp_node; - xmlNode *deps_node; - RCResItem *r; - RCResItemSpec *spec; - RCPackageUpdateSList *history_iter; - int i; - char buffer[128]; - char *tmp_str; - - r = RC_RESOLVABLE (package); - spec = rc_resItem_get_spec (r); - - package_node = xmlNewNode (NULL, "package"); - - xmlNewTextChild (package_node, NULL, "name", rc_resItem_get_name (r)); - - if (spec->has_epoch) { - g_snprintf (buffer, 128, "%d", spec->epoch); - xmlNewTextChild (package_node, NULL, "epoch", buffer); - } - - xmlNewTextChild (package_node, NULL, "version", spec->version); - - if (spec->release) { - xmlNewTextChild (package_node, NULL, "release", spec->release); - } - - tmp_str = sanitize_string (package->summary); - xmlNewTextChild (package_node, NULL, "summary", tmp_str); - g_free (tmp_str); - - tmp_str = sanitize_string (package->description); - xmlNewTextChild (package_node, NULL, "description", tmp_str); - g_free (tmp_str); - - xmlNewTextChild (package_node, NULL, "arch", - rc_arch_to_string (spec->arch)); - - xmlNewTextChild (package_node, NULL, "section", - rc_package_section_to_string (package->section)); - - g_snprintf (buffer, 128, "%u", rc_resItem_get_file_size (r)); - xmlNewTextChild (package_node, NULL, "filesize", buffer); - - g_snprintf (buffer, 128, "%u", rc_resItem_get_installed_size (r)); - xmlNewTextChild (package_node, NULL, "installedsize", buffer); - - if (package->install_only) { - xmlNewTextChild (package_node, NULL, "install_only", "1"); - } - - if (package->package_set) { - xmlNewTextChild (package_node, NULL, "package_set", "1"); - } - - if (package->history) { - tmp_node = xmlNewChild (package_node, NULL, "history", NULL); - for (history_iter = package->history; history_iter; - history_iter = history_iter->next) - { - RCPackageUpdate *update = (RCPackageUpdate *)(history_iter->data); - xmlAddChild (tmp_node, rc_package_update_to_xml_node (update)); - } - } - - deps_node = xmlNewChild (package_node, NULL, "deps", NULL); - - if (r->requires_a) { - tmp_node = xmlNewChild (deps_node, NULL, "requires", NULL); - for (i = 0; i < r->requires_a->len; i++) { - RCResItemDep *dep = r->requires_a->data[i]; - - xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); - } - } - - if (r->recommends_a) { - tmp_node = xmlNewChild (deps_node, NULL, "recommends", NULL); - for (i = 0; i < r->recommends_a->len; i++) { - RCResItemDep *dep = r->recommends_a->data[i]; - - xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); - } - } - - if (r->suggests_a) { - tmp_node = xmlNewChild (deps_node, NULL, "suggests", NULL); - for (i = 0; i < r->suggests_a->len; i++) { - RCResItemDep *dep = r->suggests_a->data[i]; - - xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); - } - } - - if (r->conflicts_a) { - tmp_node = xmlNewChild (deps_node, NULL, "conflicts", NULL); - for (i = 0; i < r->conflicts_a->len; i++) { - RCResItemDep *dep = r->conflicts_a->data[i]; - - xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); - } - } - - if (r->obsoletes_a) { - tmp_node = xmlNewChild (deps_node, NULL, "obsoletes", NULL); - for (i = 0; i < r->obsoletes_a->len; i++) { - RCResItemDep *dep = r->obsoletes_a->data[i]; - - xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); - } - } - - if (r->provides_a) { - tmp_node = xmlNewChild (deps_node, NULL, "provides", NULL); - for (i = 0; i < r->provides_a->len; i++) { - RCResItemDep *dep = r->provides_a->data[i]; - - xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); - } - } - - return (package_node); -} /* rc_package_to_xml_node */ - -#endif - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(Package,Spec); + + struct DepTable { + CDependencyList requires; + CDependencyList provides; + CDependencyList conflicts; + CDependencyList obsoletes; + CDependencyList children; + CDependencyList suggests; + CDependencyList recommends; + }; + + //--------------------------------------------------------------------------- + + static void + extract_dep_info (constXmlNodePtr iter, struct DepTable & dep_table) + { + if (iter->equals("requires")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + dep_table.requires.push_back(new Dependency (iter2)); + iter2 = iter2->next(); + } + + } else if (iter->equals("recommends")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + dep_table.recommends.push_back (new Dependency (iter2)); + iter2 = iter2->next(); + } + + } else if (iter->equals("suggests")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + dep_table.suggests.push_back (new Dependency (iter2)); + iter2 = iter2->next(); + } + + } else if (iter->equals("conflicts")) { + XmlNodePtr iter2; + bool all_are_obs = false, this_is_obs = false; + const char *obs; + + iter2 = iter->children(); + + obs = iter->getProp ("obsoletes", NULL); + if (obs) { + all_are_obs = true; + free ((void *)obs); + } + + while (iter2) { + + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + DependencyPtr dep = new Dependency (iter2); + + if (! all_are_obs) { + this_is_obs = false; + obs = iter2->getProp ("obsoletes", NULL); + if (obs) { + this_is_obs = true; + free ((void *)obs); + } + } + + if (all_are_obs || this_is_obs) { + dep_table.obsoletes.push_back (dep); + } else { + dep_table.conflicts.push_back (dep); + } + + iter2 = iter2->next(); + } + + } else if (iter->equals("obsoletes")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + dep_table.obsoletes.push_back (new Dependency (iter2)); + iter2 = iter2->next(); + } + + } else if (iter->equals("provides")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + dep_table.provides.push_back (new Dependency (iter2)); + iter2 = iter2->next(); + } + + } else if (iter->equals("children")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + dep_table.children.push_back (new Dependency (iter2)); + iter2 = iter2->next(); + } + } + } + + //--------------------------------------------------------------------------- + + + string + Package::asString ( bool full ) const + { + return toString (*this, full); + } + + + string + Package::toString ( const PackageUpdateList & l, bool full ) + { + string ret ("["); + for (PackageUpdateList::const_iterator i = l.begin(); i != l.end(); i++) { + if (i != l.begin()) ret += ", "; + ret += (*i)->asString(full); + } + return ret + "]"; + } + + string + Package::toString ( const Package & package, bool full ) + { + string ret; + ret += ResItem::toString(package, full); + if (full) { + // if (package._section != NULL) ret += (string ("
asString() + "'/>"); + // if (!package._pretty_name.empty()) ret += (string (""); + // if (!package._summary.empty()) ret += (string (""); + // if (!package._description.empty()) ret += (string (""); + ret += (string (""); + } + return ret; + } + + + ostream & + Package::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Package& package) + { + return os << package.asString(); + } + + //--------------------------------------------------------------------------- + + Package::Package (constChannelPtr channel) + : ResItem (Kind::Package, "") + , _section (NULL) + , _pretty_name ("") + , _summary ("") + , _description ("") + , _package_filename ("") + , _signature_filename ("") + , _install_only (false) + , _package_set (false) + , _id ("") + { + setChannel (channel); + } + + + Package::Package (constXmlNodePtr node, constChannelPtr channel) + : ResItem (Kind::Package, "") + , _section (NULL) + , _pretty_name ("") + , _summary ("") + , _description ("") + , _package_filename ("") + , _signature_filename ("") + , _install_only (false) + , _package_set (false) + , _id ("") + { + if (!node->equals("package")) { + fprintf (stderr, "Package::Package() not a package node\n"); + exit (1); + } + + const char *epoch = NULL, *version = NULL, *release = NULL; + struct DepTable dep_table; + + setChannel (channel); + + constXmlNodePtr iter = node->children(); + + while (iter) { + bool extracted_deps = false; + + if (iter->equals("name")) { setName (iter->getContent()); + } else if (iter->equals("epoch")) { setEpoch (atoi (iter->getContent())); + } else if (iter->equals("version")) { setVersion (iter->getContent()); + } else if (iter->equals("release")) { setRelease (iter->getContent()); + } else if (iter->equals("summary")) { _summary = strdup (iter->getContent()); + } else if (iter->equals("description")) { _description = strdup (iter->getContent()); + } else if (iter->equals("section")) { _section = new Section (iter->getContent()); + } else if (iter->equals("arch")) { setArch (iter->getContent()); + } else if (iter->equals("filesize")) { + const char *tmp = iter->getContent(); + setFileSize (tmp && *tmp ? atoi (tmp) : 0); + free ((void *)tmp); + } else if (iter->equals("installedsize")) { + const char *tmp = iter->getContent(); + setInstalledSize (tmp && *tmp ? atoi (tmp) : 0); + free ((void *)tmp); + } else if (iter->equals("install_only")) { _install_only = true; + } else if (iter->equals("package_set")) { _package_set = true; + } else if (iter->equals("history")) { + constXmlNodePtr iter2; + + iter2 = iter->children(); + + while (iter2) { + if (!iter2->isElement()) { + iter2 = iter2->next(); + continue; + } + + PackageUpdatePtr update = new PackageUpdate (iter2, this); + addUpdate (update); + + iter2 = iter2->next(); + } + } else if (iter->equals("deps")) { + constXmlNodePtr iter2; + + for (iter2 = iter->children(); iter2; iter2 = iter2->next()) { + if (!iter2->isElement()) + continue; + + extract_dep_info (iter2, dep_table); + } + + extracted_deps = true; + } + else { + if (!extracted_deps) + extract_dep_info (iter, dep_table); + else { + /* FIXME: Bitch to the user here? */ + } + } + + iter = iter->next(); + } + + if (!dep_table.children.empty()) { + // children are used in package sets + // treat them as normal requires + // + #warning Children are handled as requires + CDependencyList::const_iterator iter; + for (iter = dep_table.children.begin(); iter != dep_table.children.end(); iter++) + { + dep_table.requires.push_back (*iter); + } + } + + + // check if we're already listed in the provides + // if not, provide ourself + + CDependencyList::const_iterator piter; + for (piter = dep_table.provides.begin(); piter != dep_table.provides.end(); piter++) { + if ((*piter)->relation().isEqual() + && ((*piter)->name() == name())) + { + break; + } + } + if (piter == dep_table.provides.end()) { // no self provide found, construct one + constDependencyPtr selfdep = new Dependency (name(), Relation::Equal, kind(), this->channel(), edition()); + if (getenv ("RC_SPEW")) fprintf (stderr, "Adding self-provide [%s]\n", selfdep->asString().c_str()); + dep_table.provides.push_front (selfdep); + } + + setRequires (dep_table.requires); + setProvides (dep_table.provides); + setConflicts (dep_table.conflicts); + setObsoletes (dep_table.obsoletes); + setSuggests (dep_table.suggests); + setRecommends (dep_table.recommends); + + if (version) { + + setEpoch (epoch ? atoi (epoch) : -1); + setVersion (version); + setRelease (release); + + /* We set these to NULL so that they won't get freed when we + clean up before returning. */ + version = release = NULL; + + } else if (!_history.empty()) { + + /* If possible, we grab the version info from the most + recent update. */ + + PackageUpdatePtr update = _history.front(); + + setEpoch (update->package()->epoch()); + setVersion (update->package()->version()); + setRelease (update->package()->release()); + + } else { + + /* Otherwise, try to find where the package provides itself, + and use that version info. */ + + if (!provides().empty()) + for (CDependencyList::const_iterator iter = provides().begin(); iter != provides().end(); iter++) { + if ((*iter)->relation() == Relation::Equal && + ((*iter)->name() == name())) + { + setEpoch ((*iter)->epoch()); + setVersion ((*iter)->version()); + setRelease ((*iter)->release()); + break; + } + } + } + + /* clean-up */ + if (epoch) free ((void *)epoch); + if (version) free ((void *)version); + if (release) free ((void *)release); + + /* Hack for no archs in the XML yet */ + if (arch()->isUnknown()) + setArch (Arch::System); + } + + Package::~Package() + { + } + + //--------------------------------------------------------------------------- + + + void + Package::addUpdate (PackageUpdatePtr update) + { + if (update == NULL) return; + + assert (update->package() == NULL || update->package() == this); + + update->setPackage(this); + + if (_history.empty()) { + _history.push_back (update); + } else { + #warning addUpdate incomplete + #if 1 + for (PackageUpdateList::iterator iter = _history.begin(); iter != _history.end(); iter++) { + int result = GVersion.compare ((SpecPtr)update, (SpecPtr)(*iter)); + + if (result > 0 || (result == 0 && update->parent() != NULL)) { + _history.insert (iter, update); // = g_slist_insert_before (package->history, l, update); + break; + } else if (iter == _history.end() || // FIXME list.last() ? + (result == 0 && update->parent() == NULL)) { + _history.insert (++iter, update); // = g_slist_insert_before (package->history, l->next, update); + break; + } + } + #endif + } + } + + + PackageUpdatePtr + Package::getLatestUpdate (void) const + { + WorldPtr world; + + if (_history.empty()) { + return NULL; + } + + PackageUpdatePtr latest = _history.back(); + /* if the absolute latest is not a patch, just return that */ + if (latest->parent() == NULL) { + return latest; + } + + world = World::globalWorld(); + + for (PackageUpdateList::const_iterator l = _history.begin(); l != _history.end(); l++) { + PackageUpdatePtr update = *l; + constResItemPtr installed; + + if (!update->equals (latest)) { + return NULL; + } + + /* found a non-patch package equal to the latest, so use that */ + if (update->parent() == NULL) { + return update; + } + + /* see if the required parent for this patch is installed */ + installed = world->findInstalledResItem (update->parent()); + + if (installed != NULL && + installed->equals(update->parent())) + return update; + } + + /* no suitable update found */ + return NULL; + } + + + #if 0 + xmlNode * + rc_package_to_xml_node (RCPackage *package) + { + xmlNode *package_node; + xmlNode *tmp_node; + xmlNode *deps_node; + RCResItem *r; + RCResItemSpec *spec; + RCPackageUpdateSList *history_iter; + int i; + char buffer[128]; + char *tmp_str; + + r = RC_RESOLVABLE (package); + spec = rc_resItem_get_spec (r); + + package_node = xmlNewNode (NULL, "package"); + + xmlNewTextChild (package_node, NULL, "name", rc_resItem_get_name (r)); + + if (spec->has_epoch) { + g_snprintf (buffer, 128, "%d", spec->epoch); + xmlNewTextChild (package_node, NULL, "epoch", buffer); + } + + xmlNewTextChild (package_node, NULL, "version", spec->version); + + if (spec->release) { + xmlNewTextChild (package_node, NULL, "release", spec->release); + } + + tmp_str = sanitize_string (package->summary); + xmlNewTextChild (package_node, NULL, "summary", tmp_str); + g_free (tmp_str); + + tmp_str = sanitize_string (package->description); + xmlNewTextChild (package_node, NULL, "description", tmp_str); + g_free (tmp_str); + + xmlNewTextChild (package_node, NULL, "arch", + rc_arch_to_string (spec->arch)); + + xmlNewTextChild (package_node, NULL, "section", + rc_package_section_to_string (package->section)); + + g_snprintf (buffer, 128, "%u", rc_resItem_get_file_size (r)); + xmlNewTextChild (package_node, NULL, "filesize", buffer); + + g_snprintf (buffer, 128, "%u", rc_resItem_get_installed_size (r)); + xmlNewTextChild (package_node, NULL, "installedsize", buffer); + + if (package->install_only) { + xmlNewTextChild (package_node, NULL, "install_only", "1"); + } + + if (package->package_set) { + xmlNewTextChild (package_node, NULL, "package_set", "1"); + } + + if (package->history) { + tmp_node = xmlNewChild (package_node, NULL, "history", NULL); + for (history_iter = package->history; history_iter; + history_iter = history_iter->next) + { + RCPackageUpdate *update = (RCPackageUpdate *)(history_iter->data); + xmlAddChild (tmp_node, rc_package_update_to_xml_node (update)); + } + } + + deps_node = xmlNewChild (package_node, NULL, "deps", NULL); + + if (r->requires_a) { + tmp_node = xmlNewChild (deps_node, NULL, "requires", NULL); + for (i = 0; i < r->requires_a->len; i++) { + RCResItemDep *dep = r->requires_a->data[i]; + + xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); + } + } + + if (r->recommends_a) { + tmp_node = xmlNewChild (deps_node, NULL, "recommends", NULL); + for (i = 0; i < r->recommends_a->len; i++) { + RCResItemDep *dep = r->recommends_a->data[i]; + + xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); + } + } + + if (r->suggests_a) { + tmp_node = xmlNewChild (deps_node, NULL, "suggests", NULL); + for (i = 0; i < r->suggests_a->len; i++) { + RCResItemDep *dep = r->suggests_a->data[i]; + + xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); + } + } + + if (r->conflicts_a) { + tmp_node = xmlNewChild (deps_node, NULL, "conflicts", NULL); + for (i = 0; i < r->conflicts_a->len; i++) { + RCResItemDep *dep = r->conflicts_a->data[i]; + + xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); + } + } + + if (r->obsoletes_a) { + tmp_node = xmlNewChild (deps_node, NULL, "obsoletes", NULL); + for (i = 0; i < r->obsoletes_a->len; i++) { + RCResItemDep *dep = r->obsoletes_a->data[i]; + + xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); + } + } + + if (r->provides_a) { + tmp_node = xmlNewChild (deps_node, NULL, "provides", NULL); + for (i = 0; i < r->provides_a->len; i++) { + RCResItemDep *dep = r->provides_a->data[i]; + + xmlAddChild (tmp_node, rc_resItem_dep_to_xml_node (dep)); + } + } + + return (package_node); + } /* rc_package_to_xml_node */ + + #endif + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Package.h b/zypp/solver/detail/Package.h index dd66459..95e410d 100644 --- a/zypp/solver/detail/Package.h +++ b/zypp/solver/detail/Package.h @@ -33,9 +33,15 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// typedef std::list PackageList; typedef PackageList * PackageListPtr; @@ -53,98 +59,103 @@ typedef PackageUpdateList * PackageUpdateListPtr; class Package : public ResItem { REP_BODY(Package); - - private: - SectionPtr _section; - - // Filled in by package info XML - std::string _pretty_name; - std::string _summary; - std::string _description; - - PackageUpdateList _history; - - // After downloading this package, fill in the local file name, - // and signature, if appropriate - std::string _package_filename; - std::string _signature_filename; - - bool _install_only; // Only install, don't upgrade this package - bool _package_set; - - std::string _id; - - public: - - Package(constChannelPtr channel); - Package(constXmlNodePtr node, constChannelPtr channel); //RCPackage *rc_xml_node_to_package (const xmlNode *node, const RCChannel *channel); - virtual ~Package(); - - // ---------------------------------- I/O - - const xmlNodePtr asXmlNode (void) const; // xmlNode *rc_package_to_xml_node (RCPackage *package); - - static std::string toString ( const Package & spec, bool full = false ); - - static std::string toString ( const PackageUpdateList & l, bool full = false ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Package& ); - - std::string asString ( bool full = false ) const; - - // ---------------------------------- accessors - - // accessor for _section - const SectionPtr section() const { return _section; } - void setSection (const SectionPtr section) { _section = section; } - - // accessor for _pretty_name - const std::string prettyName() const { return _pretty_name; } - void setPrettyName(const std::string & pretty_name) { _pretty_name = pretty_name; } - - // accessor for _summary - const std::string summary() const { return _summary; } - void setSummary (const std::string & summary) { _summary = summary; } - - // accessor for _description - const std::string description() const { return _description; } - void setDescription(const std::string & description) { _description = description; } - - // accessor for _package_filename - const PackageUpdateList & history() const { return _history; } - void setHistory(const PackageUpdateList & history) { _history = history; } - - // accessor for _package_filename - const std::string packageFilename() const { return _package_filename; } - void setPackageFilename(const std::string & package_filename) { _package_filename = package_filename; } - - // accessor for _signature_filename - const std::string signatureFilename() const { return _signature_filename; } - void setSignatureFilename(const std::string & signature_filename) { _signature_filename = signature_filename; } - - // accessor for _install_only - bool installOnly() const { return _install_only; } - void setInstallOnly(bool install_only) { _install_only = install_only; } - - // accessor for _package_set - bool packageSet() const { return _package_set; } - void setPackageSet(bool package_set) { _package_set = package_set; } - - // accessor for id - const std::string id() const { return _id; } - void setId (const std::string & id) { _id = id; } - - // ---------------------------------- methods - - void addUpdate (PackageUpdatePtr update); - - PackageUpdatePtr getLatestUpdate (void) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - + + private: + SectionPtr _section; + + // Filled in by package info XML + std::string _pretty_name; + std::string _summary; + std::string _description; + + PackageUpdateList _history; + + // After downloading this package, fill in the local file name, + // and signature, if appropriate + std::string _package_filename; + std::string _signature_filename; + + bool _install_only; // Only install, don't upgrade this package + bool _package_set; + + std::string _id; + + public: + + Package(constChannelPtr channel); + Package(constXmlNodePtr node, constChannelPtr channel); //RCPackage *rc_xml_node_to_package (const xmlNode *node, const RCChannel *channel); + virtual ~Package(); + + // ---------------------------------- I/O + + const xmlNodePtr asXmlNode (void) const; // xmlNode *rc_package_to_xml_node (RCPackage *package); + + static std::string toString ( const Package & spec, bool full = false ); + + static std::string toString ( const PackageUpdateList & l, bool full = false ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Package& ); + + std::string asString ( bool full = false ) const; + + // ---------------------------------- accessors + + // accessor for _section + const SectionPtr section() const { return _section; } + void setSection (const SectionPtr section) { _section = section; } + + // accessor for _pretty_name + const std::string prettyName() const { return _pretty_name; } + void setPrettyName(const std::string & pretty_name) { _pretty_name = pretty_name; } + + // accessor for _summary + const std::string summary() const { return _summary; } + void setSummary (const std::string & summary) { _summary = summary; } + + // accessor for _description + const std::string description() const { return _description; } + void setDescription(const std::string & description) { _description = description; } + + // accessor for _package_filename + const PackageUpdateList & history() const { return _history; } + void setHistory(const PackageUpdateList & history) { _history = history; } + + // accessor for _package_filename + const std::string packageFilename() const { return _package_filename; } + void setPackageFilename(const std::string & package_filename) { _package_filename = package_filename; } + + // accessor for _signature_filename + const std::string signatureFilename() const { return _signature_filename; } + void setSignatureFilename(const std::string & signature_filename) { _signature_filename = signature_filename; } + + // accessor for _install_only + bool installOnly() const { return _install_only; } + void setInstallOnly(bool install_only) { _install_only = install_only; } + + // accessor for _package_set + bool packageSet() const { return _package_set; } + void setPackageSet(bool package_set) { _package_set = package_set; } + + // accessor for id + const std::string id() const { return _id; } + void setId (const std::string & id) { _id = id; } + + // ---------------------------------- methods + + void addUpdate (PackageUpdatePtr update); + + PackageUpdatePtr getLatestUpdate (void) const; + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Package_h diff --git a/zypp/solver/detail/PackagePtr.h b/zypp/solver/detail/PackagePtr.h index 6fa5a17..dc56e0c 100644 --- a/zypp/solver/detail/PackagePtr.h +++ b/zypp/solver/detail/PackagePtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : PackagePtr -// CLASS NAME : constPackagePtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(Package,Spec); + /////////////////////////////////////////////////////////////////// + // CLASS NAME : PackagePtr + // CLASS NAME : constPackagePtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(Package,Spec); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _PackagePtr_h diff --git a/zypp/solver/detail/PackageUpdate.cc b/zypp/solver/detail/PackageUpdate.cc index 9aab1bf..154b659 100644 --- a/zypp/solver/detail/PackageUpdate.cc +++ b/zypp/solver/detail/PackageUpdate.cc @@ -29,208 +29,219 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(PackageUpdate, Spec); - -//--------------------------------------------------------------------------- - -string -PackageUpdate::asString ( bool full ) const -{ - return toString (*this); -} - - -string -PackageUpdate::toString ( const PackageUpdate & package_update, bool full ) -{ - string ret; - ret += ((const Spec &)package_update).asString(full); - - return ret; -} - - -ostream & -PackageUpdate::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const PackageUpdate& package_update) -{ - return os << package_update.asString(); -} - - -const XmlNodePtr -PackageUpdate::asXmlNode (void) const -{ - XmlNodePtr update_node = new XmlNode("update"); - string tmp; - - if (hasEpoch()) { - tmp = stringutil::form("%d", epoch()); - update_node->addTextChild ("epoch", tmp.c_str()); - } - - update_node->addTextChild ("version", version().c_str()); - - if (!release().empty()) { - update_node->addTextChild ("release", release().c_str()); - } - - if (_package_url && *_package_url) { - update_node->addTextChild ("filename", basename (strdup (_package_url))); - } - - tmp = stringutil::form ("%ld", (unsigned long)_package_size); - update_node->addTextChild ("filesize", tmp.c_str()); - - tmp = stringutil::form ("%ld", (unsigned long)_installed_size); - update_node->addTextChild ("installedsize", tmp.c_str()); - - if (_signature_url) { - update_node->addTextChild ("signaturename", _signature_url); - - tmp = stringutil::form ("%ld", (unsigned long)_signature_size); - update_node->addTextChild ("signaturesize", tmp.c_str()); - } - - if (_md5sum) { - update_node->addTextChild ("md5sum", _md5sum); - } - - update_node->addTextChild ("importance", _importance->asString().c_str()); - - update_node->addTextChild ("description", _description); - - if (_hid) { - tmp = stringutil::form ("%d", _hid); - update_node->addTextChild ("hid", tmp.c_str()); - } - - if (_license) { - update_node->addTextChild ("license", _license); - } - - return update_node; -} - -//--------------------------------------------------------------------------- - -PackageUpdate::PackageUpdate (const string & name) - : Spec (Kind::Package, name) - , _package (NULL) - , _package_url (NULL) - , _package_size (0) - , _installed_size (0) - , _signature_url (NULL) - , _signature_size (0) - , _md5sum (NULL) - , _importance (NULL) - , _hid (0) - , _description (NULL) - , _license (NULL) - , _parent (NULL) -{ -} - - -PackageUpdate::PackageUpdate (constXmlNodePtr node, PackagePtr package) - : Spec (Kind::Package, package->name()) - , _package (NULL) - , _package_url (NULL) - , _package_size (0) - , _installed_size (0) - , _signature_url (NULL) - , _signature_size (0) - , _md5sum (NULL) - , _importance (NULL) - , _hid (0) - , _description (NULL) - , _license (NULL) - , _parent (NULL) -{ - constChannelPtr channel; - const char *url_prefix = NULL; - - if (node == NULL) { - fprintf (stderr, "PackageUpdate::PackageUpdate(NULL)\n"); - exit (1); - } - - /* Make sure this is an update node */ - if (strcasecmp (node->name(), "update")) { - fprintf (stderr, "PackageUpdate::PackageUpdate() wrong node (%s)\n", node->name()); - exit (1); - } - - channel = package->channel(); - - _package = package; - - if (channel) { - url_prefix = channel->filePath(); - } - - XmlNodePtr iter = node->children(); - - while (iter) { - if (iter->equals ("epoch")) { setEpoch (iter->getUnsignedIntContentDefault (0)); - } else if (iter->equals ("version")) { setVersion (iter->getContent()); - } else if (iter->equals ("release")) { setRelease (iter->getContent()); - } else if (iter->equals ("arch")) { setArch (iter->getContent()); - } else if (iter->equals ("filename")) { - const char *tmp = iter->getContent(); - if (url_prefix) { - _package_url = maybe_merge_paths (url_prefix, tmp); - } else { - _package_url = strdup (tmp); - } - } else if (iter->equals ("filesize")) { _package_size = iter->getUnsignedIntContentDefault (0); - } else if (iter->equals ("installedsize")) { _installed_size = iter->getUnsignedIntContentDefault (0); - } else if (iter->equals ("signaturename")) { - const char *tmp = iter->getContent(); - if (url_prefix) { - _signature_url = maybe_merge_paths (url_prefix, tmp); - } else { - _signature_url = strdup (tmp); - } - } else if (iter->equals ("signaturesize")) { _signature_size = iter->getUnsignedIntContentDefault (0); - } else if (iter->equals ("md5sum")) { _md5sum = iter->getContent(); - } else if (iter->equals ("importance")) { _importance = new Importance (iter->getContent()); - } else if (iter->equals ("description")) { _description = iter->getContent(); - } else if (iter->equals ("hid")) { _hid = iter->getUnsignedIntContentDefault (0); - } else if (iter->equals ("license")) { _license = iter->getContent(); - } - - iter = iter->next(); - } -} - - -PackageUpdate::~PackageUpdate() -{ - if (_package != NULL) _package = NULL; - if (_package_url != NULL) free ((void *)_package_url); - if (_signature_url != NULL) free ((void *)_signature_url); - if (_md5sum != NULL) free ((void *)_md5sum); - if (_description != NULL) free ((void *)_description); - if (_license != NULL) free ((void *)_license); - if (_parent != NULL) _parent = NULL; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(PackageUpdate, Spec); + + //--------------------------------------------------------------------------- + + string + PackageUpdate::asString ( bool full ) const + { + return toString (*this); + } + + + string + PackageUpdate::toString ( const PackageUpdate & package_update, bool full ) + { + string ret; + ret += ((const Spec &)package_update).asString(full); + + return ret; + } + + + ostream & + PackageUpdate::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const PackageUpdate& package_update) + { + return os << package_update.asString(); + } + + + const XmlNodePtr + PackageUpdate::asXmlNode (void) const + { + XmlNodePtr update_node = new XmlNode("update"); + string tmp; + + if (hasEpoch()) { + tmp = stringutil::form("%d", epoch()); + update_node->addTextChild ("epoch", tmp.c_str()); + } + + update_node->addTextChild ("version", version().c_str()); + + if (!release().empty()) { + update_node->addTextChild ("release", release().c_str()); + } + + if (_package_url && *_package_url) { + update_node->addTextChild ("filename", basename (strdup (_package_url))); + } + + tmp = stringutil::form ("%ld", (unsigned long)_package_size); + update_node->addTextChild ("filesize", tmp.c_str()); + + tmp = stringutil::form ("%ld", (unsigned long)_installed_size); + update_node->addTextChild ("installedsize", tmp.c_str()); + + if (_signature_url) { + update_node->addTextChild ("signaturename", _signature_url); + + tmp = stringutil::form ("%ld", (unsigned long)_signature_size); + update_node->addTextChild ("signaturesize", tmp.c_str()); + } + + if (_md5sum) { + update_node->addTextChild ("md5sum", _md5sum); + } + + update_node->addTextChild ("importance", _importance->asString().c_str()); + + update_node->addTextChild ("description", _description); + + if (_hid) { + tmp = stringutil::form ("%d", _hid); + update_node->addTextChild ("hid", tmp.c_str()); + } + + if (_license) { + update_node->addTextChild ("license", _license); + } + + return update_node; + } + + //--------------------------------------------------------------------------- + + PackageUpdate::PackageUpdate (const string & name) + : Spec (Kind::Package, name) + , _package (NULL) + , _package_url (NULL) + , _package_size (0) + , _installed_size (0) + , _signature_url (NULL) + , _signature_size (0) + , _md5sum (NULL) + , _importance (NULL) + , _hid (0) + , _description (NULL) + , _license (NULL) + , _parent (NULL) + { + } + + + PackageUpdate::PackageUpdate (constXmlNodePtr node, PackagePtr package) + : Spec (Kind::Package, package->name()) + , _package (NULL) + , _package_url (NULL) + , _package_size (0) + , _installed_size (0) + , _signature_url (NULL) + , _signature_size (0) + , _md5sum (NULL) + , _importance (NULL) + , _hid (0) + , _description (NULL) + , _license (NULL) + , _parent (NULL) + { + constChannelPtr channel; + const char *url_prefix = NULL; + + if (node == NULL) { + fprintf (stderr, "PackageUpdate::PackageUpdate(NULL)\n"); + exit (1); + } + + /* Make sure this is an update node */ + if (strcasecmp (node->name(), "update")) { + fprintf (stderr, "PackageUpdate::PackageUpdate() wrong node (%s)\n", node->name()); + exit (1); + } + + channel = package->channel(); + + _package = package; + + if (channel) { + url_prefix = channel->filePath(); + } + + XmlNodePtr iter = node->children(); + + while (iter) { + if (iter->equals ("epoch")) { setEpoch (iter->getUnsignedIntContentDefault (0)); + } else if (iter->equals ("version")) { setVersion (iter->getContent()); + } else if (iter->equals ("release")) { setRelease (iter->getContent()); + } else if (iter->equals ("arch")) { setArch (iter->getContent()); + } else if (iter->equals ("filename")) { + const char *tmp = iter->getContent(); + if (url_prefix) { + _package_url = maybe_merge_paths (url_prefix, tmp); + } else { + _package_url = strdup (tmp); + } + } else if (iter->equals ("filesize")) { _package_size = iter->getUnsignedIntContentDefault (0); + } else if (iter->equals ("installedsize")) { _installed_size = iter->getUnsignedIntContentDefault (0); + } else if (iter->equals ("signaturename")) { + const char *tmp = iter->getContent(); + if (url_prefix) { + _signature_url = maybe_merge_paths (url_prefix, tmp); + } else { + _signature_url = strdup (tmp); + } + } else if (iter->equals ("signaturesize")) { _signature_size = iter->getUnsignedIntContentDefault (0); + } else if (iter->equals ("md5sum")) { _md5sum = iter->getContent(); + } else if (iter->equals ("importance")) { _importance = new Importance (iter->getContent()); + } else if (iter->equals ("description")) { _description = iter->getContent(); + } else if (iter->equals ("hid")) { _hid = iter->getUnsignedIntContentDefault (0); + } else if (iter->equals ("license")) { _license = iter->getContent(); + } + + iter = iter->next(); + } + } + + + PackageUpdate::~PackageUpdate() + { + if (_package != NULL) _package = NULL; + if (_package_url != NULL) free ((void *)_package_url); + if (_signature_url != NULL) free ((void *)_signature_url); + if (_md5sum != NULL) free ((void *)_md5sum); + if (_description != NULL) free ((void *)_description); + if (_license != NULL) free ((void *)_license); + if (_parent != NULL) _parent = NULL; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/PackageUpdate.h b/zypp/solver/detail/PackageUpdate.h index 468d07f..2e3d2e6 100644 --- a/zypp/solver/detail/PackageUpdate.h +++ b/zypp/solver/detail/PackageUpdate.h @@ -33,9 +33,15 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // @@ -45,95 +51,100 @@ namespace zypp { **/ class PackageUpdate : public Spec { - REP_BODY(PackageUpdate); - - private: - PackagePtr _package; - - const char *_package_url; - size_t _package_size; - size_t _installed_size; - - const char *_signature_url; - size_t _signature_size; - - const char *_md5sum; - - const Importance *_importance; - - unsigned int _hid; - - const char *_description; - - const char *_license; - - // refers to the parent package for SuSE patch RPMs - constPackagePtr _parent; - - public: - - PackageUpdate(const std::string & name); - PackageUpdate(constXmlNodePtr node, PackagePtr package); - - virtual ~PackageUpdate(); - - // ---------------------------------- I/O - - const XmlNodePtr asXmlNode (void) const; - - static std::string toString ( const PackageUpdate & packageupdate, bool full = false ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const PackageUpdate& ); - - std::string asString ( bool full = false ) const; - - // ---------------------------------- accessors - - constPackagePtr package() const { return _package; } - void setPackage (PackagePtr package) { _package = package; } - - const char *packageUrl() const { return _package_url; } - void setPackageUrl (const char *package_url) { _package_url = package_url; } - - size_t packageSize() const { return _package_size; } - void setPackageSize (size_t package_size) { _package_size = package_size; } - - size_t installedSize() const { return _installed_size; } - void setInstalledSize (size_t installed_size ) { _installed_size = installed_size; } - - const char *description() const { return _description; } - void setDescription(const char *description) { _description = strdup (description); } - - const char *signatureUrl() const { return _signature_url; } - void setSignatureUrl (const char *signature_url) { _signature_url = signature_url; } - - size_t signatureSize() const { return _signature_size; } - void setSignatureSize (size_t signature_size) { _signature_size = signature_size; } - - const char *md5sum() const { return _md5sum; } - void setMd5sum (const char *md5sum) { _md5sum = md5sum; } - - const Importance *importance() const { return _importance; } - void setImportance (const Importance *importance) { _importance = importance; } - - unsigned int hid() const { return _hid; } - void setHid (unsigned int hid) { _hid = hid; } - - const char *license() const { return _license; } - void setLicense (const char *license) { _license = license; } - - // refers to the parent package for SuSE patch RPMs - constPackagePtr parent() const { return _parent; } - void setParent (constPackagePtr parent) { _parent = parent; } - - // ---------------------------------- methods - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - + REP_BODY(PackageUpdate); + + private: + PackagePtr _package; + + const char *_package_url; + size_t _package_size; + size_t _installed_size; + + const char *_signature_url; + size_t _signature_size; + + const char *_md5sum; + + const Importance *_importance; + + unsigned int _hid; + + const char *_description; + + const char *_license; + + // refers to the parent package for SuSE patch RPMs + constPackagePtr _parent; + + public: + + PackageUpdate(const std::string & name); + PackageUpdate(constXmlNodePtr node, PackagePtr package); + + virtual ~PackageUpdate(); + + // ---------------------------------- I/O + + const XmlNodePtr asXmlNode (void) const; + + static std::string toString ( const PackageUpdate & packageupdate, bool full = false ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const PackageUpdate& ); + + std::string asString ( bool full = false ) const; + + // ---------------------------------- accessors + + constPackagePtr package() const { return _package; } + void setPackage (PackagePtr package) { _package = package; } + + const char *packageUrl() const { return _package_url; } + void setPackageUrl (const char *package_url) { _package_url = package_url; } + + size_t packageSize() const { return _package_size; } + void setPackageSize (size_t package_size) { _package_size = package_size; } + + size_t installedSize() const { return _installed_size; } + void setInstalledSize (size_t installed_size ) { _installed_size = installed_size; } + + const char *description() const { return _description; } + void setDescription(const char *description) { _description = strdup (description); } + + const char *signatureUrl() const { return _signature_url; } + void setSignatureUrl (const char *signature_url) { _signature_url = signature_url; } + + size_t signatureSize() const { return _signature_size; } + void setSignatureSize (size_t signature_size) { _signature_size = signature_size; } + + const char *md5sum() const { return _md5sum; } + void setMd5sum (const char *md5sum) { _md5sum = md5sum; } + + const Importance *importance() const { return _importance; } + void setImportance (const Importance *importance) { _importance = importance; } + + unsigned int hid() const { return _hid; } + void setHid (unsigned int hid) { _hid = hid; } + + const char *license() const { return _license; } + void setLicense (const char *license) { _license = license; } + + // refers to the parent package for SuSE patch RPMs + constPackagePtr parent() const { return _parent; } + void setParent (constPackagePtr parent) { _parent = parent; } + + // ---------------------------------- methods + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _PackageUpdate_h diff --git a/zypp/solver/detail/PackageUpdatePtr.h b/zypp/solver/detail/PackageUpdatePtr.h index 92a341c..562917a 100644 --- a/zypp/solver/detail/PackageUpdatePtr.h +++ b/zypp/solver/detail/PackageUpdatePtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : PackageUpdatePtr -// CLASS NAME : constPackageUpdatePtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(PackageUpdate,Spec); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : PackageUpdatePtr + // CLASS NAME : constPackageUpdatePtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(PackageUpdate,Spec); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _PackageUpdatePtr_h diff --git a/zypp/solver/detail/Packman.cc b/zypp/solver/detail/Packman.cc index ce967d7..3a20c44 100644 --- a/zypp/solver/detail/Packman.cc +++ b/zypp/solver/detail/Packman.cc @@ -24,59 +24,70 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Packman); - -//--------------------------------------------------------------------------- - -string -Packman::asString ( void ) const -{ - return toString (*this); -} - - -string -Packman::toString ( const Packman & store ) -{ - string res (""); - - return res; -} - - -ostream & -Packman::dumpOn (ostream & str) const -{ - str << asString(); - return str; -} - - -ostream & -operator<< (ostream & os, const Packman & store) -{ - return os << store.asString(); -} - -//--------------------------------------------------------------------------- - -Packman::Packman () -{ -} - - -Packman::~Packman() -{ -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Packman); + + //--------------------------------------------------------------------------- + + string + Packman::asString ( void ) const + { + return toString (*this); + } + + + string + Packman::toString ( const Packman & store ) + { + string res (""); + + return res; + } + + + ostream & + Packman::dumpOn (ostream & str) const + { + str << asString(); + return str; + } + + + ostream & + operator<< (ostream & os, const Packman & store) + { + return os << store.asString(); + } + + //--------------------------------------------------------------------------- + + Packman::Packman () + { + } + + + Packman::~Packman() + { + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Packman.h b/zypp/solver/detail/Packman.h index 3dc61bd..a3e96cf 100644 --- a/zypp/solver/detail/Packman.h +++ b/zypp/solver/detail/Packman.h @@ -28,45 +28,56 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Packman - -class Packman : public CountedRep { - REP_BODY(Packman); - - private: - - - public: - - Packman (); - virtual ~Packman(); - - // ---------------------------------- I/O - - static std::string toString (const Packman & section); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const Packman & section); - - std::string asString (void) const; - - // ---------------------------------- accessors - - - // ---------------------------------- methods - - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Packman + + class Packman : public CountedRep { + REP_BODY(Packman); + + private: + + + public: + + Packman (); + virtual ~Packman(); + + // ---------------------------------- I/O + + static std::string toString (const Packman & section); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const Packman & section); + + std::string asString (void) const; + + // ---------------------------------- accessors + + + // ---------------------------------- methods + + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Packman_h diff --git a/zypp/solver/detail/PackmanPtr.h b/zypp/solver/detail/PackmanPtr.h index 0622b9a..55572c8 100644 --- a/zypp/solver/detail/PackmanPtr.h +++ b/zypp/solver/detail/PackmanPtr.h @@ -23,18 +23,29 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : PackmanPtr -// CLASS NAME : constPackmanPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Packman); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : PackmanPtr + // CLASS NAME : constPackmanPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Packman); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _PackmanPtr_h diff --git a/zypp/solver/detail/Pending.cc b/zypp/solver/detail/Pending.cc index 8fa35cb..48609f9 100644 --- a/zypp/solver/detail/Pending.cc +++ b/zypp/solver/detail/Pending.cc @@ -24,59 +24,70 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Pending); - -//--------------------------------------------------------------------------- - -string -Pending::asString ( void ) const -{ - return toString (*this); -} - - -string -Pending::toString ( const Pending & pending ) -{ - return ""; -} - - -ostream & -Pending::dumpOn (ostream & str) const -{ - str << asString(); - return str; -} - - -ostream & -operator<< (ostream & os, const Pending & pending) -{ - return os << pending.asString(); -} - -//--------------------------------------------------------------------------- - -Pending::Pending (const char *description) -{ -} - - -Pending::~Pending() -{ -} - -//--------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Pending); + + //--------------------------------------------------------------------------- + + string + Pending::asString ( void ) const + { + return toString (*this); + } + + + string + Pending::toString ( const Pending & pending ) + { + return ""; + } + + + ostream & + Pending::dumpOn (ostream & str) const + { + str << asString(); + return str; + } + + + ostream & + operator<< (ostream & os, const Pending & pending) + { + return os << pending.asString(); + } + + //--------------------------------------------------------------------------- + + Pending::Pending (const char *description) + { + } + + + Pending::~Pending() + { + } + + //--------------------------------------------------------------------------- + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Pending.h b/zypp/solver/detail/Pending.h index 995b4fc..4c41295 100644 --- a/zypp/solver/detail/Pending.h +++ b/zypp/solver/detail/Pending.h @@ -28,119 +28,131 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// - -class Pending; -typedef std::list PendingList; -typedef PendingList * PendingListPtr; - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Pending - -class Pending : public CountedRep { - REP_BODY(Pending); - -typedef enum { - PENDING_STATUS_INVALID = 0, - PENDING_STATUS_PRE_BEGIN, - PENDING_STATUS_RUNNING, - PENDING_STATUS_BLOCKING, - PENDING_STATUS_ABORTED, - PENDING_STATUS_FAILED, - PENDING_STATUS_FINISHED -} PendingStatus; - -const char *pendingStatusToString (PendingStatus status); - -#define INVALID_PENDING_ID 0 - - - private: - - char *_description; - int _id; - - PendingStatus _status; - - double _percent_complete; - - size_t _completed_size; - size_t _total_size; - - time_t _start_time; - time_t _last_time; - time_t _poll_time; - - int _retval; - char *_error_msg; - - std::list _messages; - - void (*_update) (PendingPtr); - void (*_complete) (PendingPtr); - void (*_message) (PendingPtr); - - public: - - Pending (const char *description); - virtual ~Pending(); - - // ---------------------------------- I/O - - static std::string toString (const Pending & section); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const Pending & section); - - std::string asString (void) const; - - // ---------------------------------- accessors - - const char *description (void) const { return _description; } - void setDescription (const char *description) { _description = strdup (description); } - int id (void) const { return _id; } - PendingStatus status (void) const { return _status; } - double percentComplete (void) const { return _percent_complete; } - size_t completedSize (void) const { return _completed_size; } - size_t totalSize (void) const { return _total_size; } - time_t startTime (void) const { return _start_time; } - time_t lastTime (void) const { return _last_time; } - time_t pollTime (void) const { return _poll_time; } - - int elapsedSecs (void) const { return 0; } - int expectedSecs (void) const { return 0; } - int remainingSecs (void) const { return 0; } - - std::list messages (void) const { return _messages; } - const char *latestMessage (void) const { return _error_msg; } - - // ---------------------------------- methods - - PendingPtr lookupById (int id); - std::list getAllActiveIds (void); - - void begin (void); - void update (double percent_complete); - void updateBySize (size_t size, size_t total_size); - - void finished (int retval); - void abort (int retval); - void fail (int retval, const char *error_msg); - - bool isActive (void); - - const char *errorMsg (void); - - void addMessage (const char *message); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + class Pending; + typedef std::list PendingList; + typedef PendingList * PendingListPtr; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Pending + + class Pending : public CountedRep { + REP_BODY(Pending); + + typedef enum { + PENDING_STATUS_INVALID = 0, + PENDING_STATUS_PRE_BEGIN, + PENDING_STATUS_RUNNING, + PENDING_STATUS_BLOCKING, + PENDING_STATUS_ABORTED, + PENDING_STATUS_FAILED, + PENDING_STATUS_FINISHED + } PendingStatus; + + const char *pendingStatusToString (PendingStatus status); + + #define INVALID_PENDING_ID 0 + + + private: + + char *_description; + int _id; + + PendingStatus _status; + + double _percent_complete; + + size_t _completed_size; + size_t _total_size; + + time_t _start_time; + time_t _last_time; + time_t _poll_time; + + int _retval; + char *_error_msg; + + std::list _messages; + + void (*_update) (PendingPtr); + void (*_complete) (PendingPtr); + void (*_message) (PendingPtr); + + public: + + Pending (const char *description); + virtual ~Pending(); + + // ---------------------------------- I/O + + static std::string toString (const Pending & section); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const Pending & section); + + std::string asString (void) const; + + // ---------------------------------- accessors + + const char *description (void) const { return _description; } + void setDescription (const char *description) { _description = strdup (description); } + int id (void) const { return _id; } + PendingStatus status (void) const { return _status; } + double percentComplete (void) const { return _percent_complete; } + size_t completedSize (void) const { return _completed_size; } + size_t totalSize (void) const { return _total_size; } + time_t startTime (void) const { return _start_time; } + time_t lastTime (void) const { return _last_time; } + time_t pollTime (void) const { return _poll_time; } + + int elapsedSecs (void) const { return 0; } + int expectedSecs (void) const { return 0; } + int remainingSecs (void) const { return 0; } + + std::list messages (void) const { return _messages; } + const char *latestMessage (void) const { return _error_msg; } + + // ---------------------------------- methods + + PendingPtr lookupById (int id); + std::list getAllActiveIds (void); + + void begin (void); + void update (double percent_complete); + void updateBySize (size_t size, size_t total_size); + + void finished (int retval); + void abort (int retval); + void fail (int retval, const char *error_msg); + + bool isActive (void); + + const char *errorMsg (void); + + void addMessage (const char *message); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Pending_h diff --git a/zypp/solver/detail/PendingPtr.h b/zypp/solver/detail/PendingPtr.h index add7dd3..daedb09 100644 --- a/zypp/solver/detail/PendingPtr.h +++ b/zypp/solver/detail/PendingPtr.h @@ -22,19 +22,30 @@ #define _PendingPtr_h #include +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : PendingPtr + // CLASS NAME : constPendingPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Pending); -/////////////////////////////////////////////////////////////////// -// CLASS NAME : PendingPtr -// CLASS NAME : constPendingPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Pending); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _PendingPtr_h diff --git a/zypp/solver/detail/QueueItem.cc b/zypp/solver/detail/QueueItem.cc index 0878821..ed917d4 100644 --- a/zypp/solver/detail/QueueItem.cc +++ b/zypp/solver/detail/QueueItem.cc @@ -22,102 +22,115 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItem::asString ( void ) const -{ - return toString (*this); -} - - -string -QueueItem::toString ( const QueueItem & item ) -{ - return ""; -} - - -string -QueueItem::toString ( const QueueItemList & itemlist, const string & sep ) -{ - string res = "["; - for (QueueItemList::const_iterator iter = itemlist.begin(); iter != itemlist.end(); iter++) { - if (iter != itemlist.begin()) - res += sep; - res += (*iter)->asString(); - } - return res + "]"; -} - - -ostream & -QueueItem::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const QueueItem & item ) -{ - return os << item.asString(); -} - -//--------------------------------------------------------------------------- - -QueueItem::QueueItem (QueueItemType type, WorldPtr world) - : _type (type) - , _world (world) - , _priority (0) - , _size (0) -{ -} - - -QueueItem::~QueueItem() -{ -} - -//--------------------------------------------------------------------------- - -void -QueueItem::copy (constQueueItemPtr from) -{ - _priority = from->_priority; - _size = from->_size; - _pending_info = ResolverInfoList (from->_pending_info.begin(), from->_pending_info.end()); -} - - -//--------------------------------------------------------------------------- - -void -QueueItem::addInfo (ResolverInfoPtr info) -{ - _pending_info.push_back (info); -} - - -void -QueueItem::logInfo (ResolverContextPtr context) -{ - for (ResolverInfoList::const_iterator iter = _pending_info.begin(); iter != _pending_info.end(); iter++) { - context->addInfo (*iter); - } - _pending_info.clear(); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + + using namespace std; + + IMPL_BASE_POINTER(QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItem::asString ( void ) const + { + return toString (*this); + } + + + string + QueueItem::toString ( const QueueItem & item ) + { + return ""; + } + + + string + QueueItem::toString ( const QueueItemList & itemlist, const string & sep ) + { + string res = "["; + for (QueueItemList::const_iterator iter = itemlist.begin(); iter != itemlist.end(); iter++) { + if (iter != itemlist.begin()) + res += sep; + res += (*iter)->asString(); + } + return res + "]"; + } + + + ostream & + QueueItem::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const QueueItem & item ) + { + return os << item.asString(); + } + + //--------------------------------------------------------------------------- + + QueueItem::QueueItem (QueueItemType type, WorldPtr world) + : _type (type) + , _world (world) + , _priority (0) + , _size (0) + { + } + + + QueueItem::~QueueItem() + { + } + + //--------------------------------------------------------------------------- + + void + QueueItem::copy (constQueueItemPtr from) + { + _priority = from->_priority; + _size = from->_size; + _pending_info = ResolverInfoList (from->_pending_info.begin(), from->_pending_info.end()); + } + + + //--------------------------------------------------------------------------- + + void + QueueItem::addInfo (ResolverInfoPtr info) + { + _pending_info.push_back (info); + } + + + void + QueueItem::logInfo (ResolverContextPtr context) + { + for (ResolverInfoList::const_iterator iter = _pending_info.begin(); iter != _pending_info.end(); iter++) { + context->addInfo (*iter); + } + _pending_info.clear(); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItem.h b/zypp/solver/detail/QueueItem.h index f38606e..a4b5d45 100644 --- a/zypp/solver/detail/QueueItem.h +++ b/zypp/solver/detail/QueueItem.h @@ -33,100 +33,110 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - -typedef enum { - QUEUE_ITEM_TYPE_UNKNOWN = 0, // ordering is important ! - QUEUE_ITEM_TYPE_INSTALL, - QUEUE_ITEM_TYPE_REQUIRE, - QUEUE_ITEM_TYPE_BRANCH, - QUEUE_ITEM_TYPE_GROUP, - QUEUE_ITEM_TYPE_CONFLICT, - QUEUE_ITEM_TYPE_UNINSTALL, - QUEUE_ITEM_TYPE_LAST -} QueueItemType; - - -typedef std::list QueueItemList; - -#define CMP(a,b) (((a) < (b)) - ((b) < (a))) - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItem - -class QueueItem : public CountedRep { - REP_BODY(QueueItem); - - private: - - QueueItemType _type; - WorldPtr _world; - - int _priority; - size_t _size; - ResolverInfoList _pending_info; - - protected: - - QueueItem (QueueItemType type, WorldPtr world); - - public: - - virtual ~QueueItem(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItem & item); - - static std::string toString (const QueueItemList & itemlist, const std::string & sep = ", "); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItem & item); - - virtual std::string asString (void ) const; - - // ---------------------------------- accessors - - WorldPtr world (void) const { return _world; } - int priority (void) const { return _priority; } - void setPriority (int priority) { _priority = priority; } - int size (void) const { return _size; } - - // ---------------------------------- methods - - void copy (constQueueItemPtr from); - - bool isBranch (void) const { return _type == QUEUE_ITEM_TYPE_BRANCH; } - bool isConflict (void) const { return _type == QUEUE_ITEM_TYPE_CONFLICT; } - bool isGroup (void) const { return _type == QUEUE_ITEM_TYPE_GROUP; } - bool isInstall (void) const { return _type == QUEUE_ITEM_TYPE_INSTALL; } - bool isRequire (void) const { return _type == QUEUE_ITEM_TYPE_REQUIRE; } - bool isUninstall (void) const { return _type == QUEUE_ITEM_TYPE_UNINSTALL; } - - virtual bool process (ResolverContextPtr context, QueueItemList & qil) = 0; - virtual QueueItemPtr copy (void) const = 0; - virtual int cmp (constQueueItemPtr item) const = 0; - int compare (constQueueItemPtr item) const { return CMP(_type, item->_type); } - - // isRedundant true == can be dropped from any branch - virtual bool isRedundant (ResolverContextPtr context) const = 0; - - // isSatisfied true == can be dropped from any queue, and any - // branch containing it can also be dropped - virtual bool isSatisfied (ResolverContextPtr context) const = 0; - - void addInfo (ResolverInfoPtr); - void logInfo (ResolverContextPtr); -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef enum { + QUEUE_ITEM_TYPE_UNKNOWN = 0, // ordering is important ! + QUEUE_ITEM_TYPE_INSTALL, + QUEUE_ITEM_TYPE_REQUIRE, + QUEUE_ITEM_TYPE_BRANCH, + QUEUE_ITEM_TYPE_GROUP, + QUEUE_ITEM_TYPE_CONFLICT, + QUEUE_ITEM_TYPE_UNINSTALL, + QUEUE_ITEM_TYPE_LAST + } QueueItemType; + + + typedef std::list QueueItemList; + + #define CMP(a,b) (((a) < (b)) - ((b) < (a))) + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItem + + class QueueItem : public CountedRep { + REP_BODY(QueueItem); + + private: + + QueueItemType _type; + WorldPtr _world; + + int _priority; + size_t _size; + ResolverInfoList _pending_info; + + protected: + + QueueItem (QueueItemType type, WorldPtr world); + + public: + + virtual ~QueueItem(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItem & item); + + static std::string toString (const QueueItemList & itemlist, const std::string & sep = ", "); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItem & item); + + virtual std::string asString (void ) const; + + // ---------------------------------- accessors + + WorldPtr world (void) const { return _world; } + int priority (void) const { return _priority; } + void setPriority (int priority) { _priority = priority; } + int size (void) const { return _size; } + + // ---------------------------------- methods + + void copy (constQueueItemPtr from); + + bool isBranch (void) const { return _type == QUEUE_ITEM_TYPE_BRANCH; } + bool isConflict (void) const { return _type == QUEUE_ITEM_TYPE_CONFLICT; } + bool isGroup (void) const { return _type == QUEUE_ITEM_TYPE_GROUP; } + bool isInstall (void) const { return _type == QUEUE_ITEM_TYPE_INSTALL; } + bool isRequire (void) const { return _type == QUEUE_ITEM_TYPE_REQUIRE; } + bool isUninstall (void) const { return _type == QUEUE_ITEM_TYPE_UNINSTALL; } + + virtual bool process (ResolverContextPtr context, QueueItemList & qil) = 0; + virtual QueueItemPtr copy (void) const = 0; + virtual int cmp (constQueueItemPtr item) const = 0; + int compare (constQueueItemPtr item) const { return CMP(_type, item->_type); } + + // isRedundant true == can be dropped from any branch + virtual bool isRedundant (ResolverContextPtr context) const = 0; + + // isSatisfied true == can be dropped from any queue, and any + // branch containing it can also be dropped + virtual bool isSatisfied (ResolverContextPtr context) const = 0; + + void addInfo (ResolverInfoPtr); + void logInfo (ResolverContextPtr); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItem_h diff --git a/zypp/solver/detail/QueueItemBranch.cc b/zypp/solver/detail/QueueItemBranch.cc index 5b11b8a..4ba1b7e 100644 --- a/zypp/solver/detail/QueueItemBranch.cc +++ b/zypp/solver/detail/QueueItemBranch.cc @@ -23,248 +23,260 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(QueueItemBranch,QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItemBranch::asString ( void ) const -{ - return toString (*this); -} - - -string -QueueItemBranch::toString ( const QueueItemBranch & item) -{ - string res = "[Branch: "; - if (!item._label.empty()) { - res += item._label; - } - res += "\n\t"; - res += QueueItem::toString(item._possible_items, "\n\t"); - res += "]"; - return res; -} - - -ostream & -QueueItemBranch::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const QueueItemBranch & item) -{ - return os << item.asString(); -} - -//--------------------------------------------------------------------------- - -QueueItemBranch::QueueItemBranch (WorldPtr world) - : QueueItem (QUEUE_ITEM_TYPE_BRANCH, world) -{ -} - - -QueueItemBranch::~QueueItemBranch() -{ -} - -//--------------------------------------------------------------------------- - -void -QueueItemBranch::addItem (QueueItemPtr subitem) -{ - assert (this != subitem); -#if 0 - // We want to keep the list of possible items sorted for easy comparison later. - for (QueueItemList::iterator pos = _possible_items.begin(); pos != _possible_items.end(); pos++) { - - if ((*pos)->cmp(subitem) >= 0) { // found a larger one - _possible_items.insert (pos, subitem); // insert before - return; - } - } -#endif - _possible_items.push_back (subitem); // no larger found, subitem must be largest - - return; -} - - -bool -QueueItemBranch::contains (QueueItemPtr possible_subbranch) -{ - QueueItemBranchPtr branch = (QueueItemBranchPtr)possible_subbranch; - - if (branch == NULL - || !branch->isBranch()) { - return false; - } - - - if (_possible_items.size() < branch->_possible_items.size()) { - return false; - } - - QueueItemList::iterator iter = _possible_items.begin(); - QueueItemList::iterator iter_sub = branch->_possible_items.begin(); - - /* For every item inside the possible sub-branch, look for a matching item - in the branch. If we can't find a match, fail. (We can do this in one - pass since the possible_items lists are sorted) - */ - while (iter_sub != branch->_possible_items.end()) { - - while (iter != _possible_items.end() - && (*iter)->cmp (*iter_sub)) { - iter++; - } - - if (iter == _possible_items.end()) - return false; - - iter++; - iter_sub++; - } - - return true; -} - -//--------------------------------------------------------------------------- - -bool -QueueItemBranch::process (ResolverContextPtr context, QueueItemList & qil) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemBranch::process(%s)\n", asString().c_str()); - - QueueItemList live_branches; - unsigned int branch_count; - bool did_something = true; - - for (QueueItemList::const_iterator iter = _possible_items.begin(); iter != _possible_items.end(); iter++) { - - QueueItemPtr item = *iter; - - if (item->isSatisfied (context)) - goto finished; - - /* Drop any useless branch items */ - if (! item->isRedundant (context)) { - live_branches.push_front (item); - } - } - - branch_count = live_branches.size(); - - if (branch_count == 0) { - - /* Do nothing */ - - } else if (branch_count == 1) { - - /* If we just have one possible item, process it. */ - - QueueItemPtr item = live_branches.front(); - did_something = item->process (context, qil); - - /* Set the item pointer to NULL inside of our original branch - item, since our call to rc_queue_item_process is now - responsible for freeing it. */ - - for (QueueItemList::iterator iter = _possible_items.begin(); iter != _possible_items.end(); iter++) { - if (*iter == item) { - _possible_items.erase (iter); - break; - } - } - - } else if (branch_count == _possible_items.size()) { - - /* Nothing was eliminated, so just pass the branch through (and set it to - NULL so that it won't get freed when we exit. */ - - qil.push_front (this); -// FIXME: dont free item = NULL; - did_something = false; - - } else { -//fprintf (stderr, "QueueItemBranch::process rebranching\n"); - QueueItemBranchPtr new_branch = new QueueItemBranch (world()); - for (QueueItemList::const_iterator iter = live_branches.begin(); iter != live_branches.end(); iter++) { - new_branch->addItem ((*iter)->copy()); - } - qil.push_front (new_branch); - } - - finished: -//FIXME rc_queue_item_free (item); - - return did_something; -} - - -int -QueueItemBranch::cmp (constQueueItemPtr item) const -{ - int cmp = this->compare (item); // assures equal type - if (cmp != 0) - return cmp; - - constQueueItemBranchPtr branch = item; - - /* First, sort by # of possible items. */ - cmp = CMP(_possible_items.size(), branch->_possible_items.size()); - if (cmp != 0) - return cmp; - - /* We can do a by-item cmp since the possible items are kept in sorted order. */ - QueueItemList::const_iterator ia = _possible_items.begin(); - QueueItemList::const_iterator ib = branch->_possible_items.begin(); - - while (ia != _possible_items.end() && ib != branch->_possible_items.end()) { - if (*ia && *ib) { - cmp = (*ia)->cmp (*ib); - if (cmp != 0) { - return cmp; - } - } - ia++; - ib++; - } - - /* Both lists should end at the same time, since we initially sorted on length. */ - assert (ia == _possible_items.end() && ib == branch->_possible_items.end()); - - return 0; -} - - -QueueItemPtr -QueueItemBranch::copy (void) const -{ - QueueItemBranchPtr new_branch = new QueueItemBranch (world()); - ((QueueItemPtr)new_branch)->copy((constQueueItemPtr)this); - - for (QueueItemList::const_iterator iter = _possible_items.begin(); iter != _possible_items.end(); iter++) { - QueueItemPtr cpy = (*iter)->copy(); - new_branch->_possible_items.push_front (cpy); - } - - return new_branch; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(QueueItemBranch,QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItemBranch::asString ( void ) const + { + return toString (*this); + } + + + string + QueueItemBranch::toString ( const QueueItemBranch & item) + { + string res = "[Branch: "; + if (!item._label.empty()) { + res += item._label; + } + res += "\n\t"; + res += QueueItem::toString(item._possible_items, "\n\t"); + res += "]"; + return res; + } + + + ostream & + QueueItemBranch::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const QueueItemBranch & item) + { + return os << item.asString(); + } + + //--------------------------------------------------------------------------- + + QueueItemBranch::QueueItemBranch (WorldPtr world) + : QueueItem (QUEUE_ITEM_TYPE_BRANCH, world) + { + } + + + QueueItemBranch::~QueueItemBranch() + { + } + + //--------------------------------------------------------------------------- + + void + QueueItemBranch::addItem (QueueItemPtr subitem) + { + assert (this != subitem); + #if 0 + // We want to keep the list of possible items sorted for easy comparison later. + for (QueueItemList::iterator pos = _possible_items.begin(); pos != _possible_items.end(); pos++) { + + if ((*pos)->cmp(subitem) >= 0) { // found a larger one + _possible_items.insert (pos, subitem); // insert before + return; + } + } + #endif + _possible_items.push_back (subitem); // no larger found, subitem must be largest + + return; + } + + + bool + QueueItemBranch::contains (QueueItemPtr possible_subbranch) + { + QueueItemBranchPtr branch = (QueueItemBranchPtr)possible_subbranch; + + if (branch == NULL + || !branch->isBranch()) { + return false; + } + + + if (_possible_items.size() < branch->_possible_items.size()) { + return false; + } + + QueueItemList::iterator iter = _possible_items.begin(); + QueueItemList::iterator iter_sub = branch->_possible_items.begin(); + + /* For every item inside the possible sub-branch, look for a matching item + in the branch. If we can't find a match, fail. (We can do this in one + pass since the possible_items lists are sorted) + */ + while (iter_sub != branch->_possible_items.end()) { + + while (iter != _possible_items.end() + && (*iter)->cmp (*iter_sub)) { + iter++; + } + + if (iter == _possible_items.end()) + return false; + + iter++; + iter_sub++; + } + + return true; + } + + //--------------------------------------------------------------------------- + + bool + QueueItemBranch::process (ResolverContextPtr context, QueueItemList & qil) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemBranch::process(%s)\n", asString().c_str()); + + QueueItemList live_branches; + unsigned int branch_count; + bool did_something = true; + + for (QueueItemList::const_iterator iter = _possible_items.begin(); iter != _possible_items.end(); iter++) { + + QueueItemPtr item = *iter; + + if (item->isSatisfied (context)) + goto finished; + + /* Drop any useless branch items */ + if (! item->isRedundant (context)) { + live_branches.push_front (item); + } + } + + branch_count = live_branches.size(); + + if (branch_count == 0) { + + /* Do nothing */ + + } else if (branch_count == 1) { + + /* If we just have one possible item, process it. */ + + QueueItemPtr item = live_branches.front(); + did_something = item->process (context, qil); + + /* Set the item pointer to NULL inside of our original branch + item, since our call to rc_queue_item_process is now + responsible for freeing it. */ + + for (QueueItemList::iterator iter = _possible_items.begin(); iter != _possible_items.end(); iter++) { + if (*iter == item) { + _possible_items.erase (iter); + break; + } + } + + } else if (branch_count == _possible_items.size()) { + + /* Nothing was eliminated, so just pass the branch through (and set it to + NULL so that it won't get freed when we exit. */ + + qil.push_front (this); + // FIXME: dont free item = NULL; + did_something = false; + + } else { + //fprintf (stderr, "QueueItemBranch::process rebranching\n"); + QueueItemBranchPtr new_branch = new QueueItemBranch (world()); + for (QueueItemList::const_iterator iter = live_branches.begin(); iter != live_branches.end(); iter++) { + new_branch->addItem ((*iter)->copy()); + } + qil.push_front (new_branch); + } + + finished: + //FIXME rc_queue_item_free (item); + + return did_something; + } + + + int + QueueItemBranch::cmp (constQueueItemPtr item) const + { + int cmp = this->compare (item); // assures equal type + if (cmp != 0) + return cmp; + + constQueueItemBranchPtr branch = item; + + /* First, sort by # of possible items. */ + cmp = CMP(_possible_items.size(), branch->_possible_items.size()); + if (cmp != 0) + return cmp; + + /* We can do a by-item cmp since the possible items are kept in sorted order. */ + QueueItemList::const_iterator ia = _possible_items.begin(); + QueueItemList::const_iterator ib = branch->_possible_items.begin(); + + while (ia != _possible_items.end() && ib != branch->_possible_items.end()) { + if (*ia && *ib) { + cmp = (*ia)->cmp (*ib); + if (cmp != 0) { + return cmp; + } + } + ia++; + ib++; + } + + /* Both lists should end at the same time, since we initially sorted on length. */ + assert (ia == _possible_items.end() && ib == branch->_possible_items.end()); + + return 0; + } + + + QueueItemPtr + QueueItemBranch::copy (void) const + { + QueueItemBranchPtr new_branch = new QueueItemBranch (world()); + ((QueueItemPtr)new_branch)->copy((constQueueItemPtr)this); + + for (QueueItemList::const_iterator iter = _possible_items.begin(); iter != _possible_items.end(); iter++) { + QueueItemPtr cpy = (*iter)->copy(); + new_branch->_possible_items.push_front (cpy); + } + + return new_branch; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItemBranch.h b/zypp/solver/detail/QueueItemBranch.h index 38fc971..6b33733 100644 --- a/zypp/solver/detail/QueueItemBranch.h +++ b/zypp/solver/detail/QueueItemBranch.h @@ -31,63 +31,70 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItemBranch - -class QueueItemBranch : public QueueItem { - REP_BODY(QueueItemBranch); - - private: - std::string _label; - QueueItemList _possible_items; - - public: - - QueueItemBranch (WorldPtr world); - virtual ~QueueItemBranch(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItemBranch & item); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItemBranch & item); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - QueueItemList possibleItems (void) const { return _possible_items; } - - const std::string & label (void) const { return _label; } - void setLabel (const std::string & label) { _label = label; } - - bool isEmpty (void) const { return _possible_items.empty(); } - - // ---------------------------------- methods - - virtual bool process (ResolverContextPtr context, QueueItemList & qil); - virtual QueueItemPtr copy (void) const; - virtual int cmp (constQueueItemPtr item) const; - virtual bool isRedundant (ResolverContextPtr context) const { return false; } - virtual bool isSatisfied (ResolverContextPtr context) const { return false; } - - void addItem (QueueItemPtr subitem); - bool contains (QueueItemPtr possible_subbranch); -}; - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItemBranch + + class QueueItemBranch : public QueueItem { + REP_BODY(QueueItemBranch); + + private: + std::string _label; + QueueItemList _possible_items; + + public: + + QueueItemBranch (WorldPtr world); + virtual ~QueueItemBranch(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItemBranch & item); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItemBranch & item); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + QueueItemList possibleItems (void) const { return _possible_items; } + + const std::string & label (void) const { return _label; } + void setLabel (const std::string & label) { _label = label; } + + bool isEmpty (void) const { return _possible_items.empty(); } + + // ---------------------------------- methods + + virtual bool process (ResolverContextPtr context, QueueItemList & qil); + virtual QueueItemPtr copy (void) const; + virtual int cmp (constQueueItemPtr item) const; + virtual bool isRedundant (ResolverContextPtr context) const { return false; } + virtual bool isSatisfied (ResolverContextPtr context) const { return false; } + + void addItem (QueueItemPtr subitem); + bool contains (QueueItemPtr possible_subbranch); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemBranch_h diff --git a/zypp/solver/detail/QueueItemBranchPtr.h b/zypp/solver/detail/QueueItemBranchPtr.h index 3491fe3..5b0e41a 100644 --- a/zypp/solver/detail/QueueItemBranchPtr.h +++ b/zypp/solver/detail/QueueItemBranchPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemBranchPtr -// CLASS NAME : constQueueItemBranchPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(QueueItemBranch,QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemBranchPtr + // CLASS NAME : constQueueItemBranchPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(QueueItemBranch,QueueItem); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemBranchPtr_h diff --git a/zypp/solver/detail/QueueItemConflict.cc b/zypp/solver/detail/QueueItemConflict.cc index 0558a22..d76b5f1 100644 --- a/zypp/solver/detail/QueueItemConflict.cc +++ b/zypp/solver/detail/QueueItemConflict.cc @@ -33,309 +33,319 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(QueueItemConflict,QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItemConflict::asString ( void ) const -{ - return toString (*this); -} - - -string -QueueItemConflict::toString ( const QueueItemConflict & item) -{ - string res = "[Conflict: "; - res += item._dep->asString(); - res += ", Triggered by "; - res += item._conflicting_resItem->asString(); - if (item._actually_an_obsolete) res += ", Obsolete !"; - res += "]"; - return res; -} - - -ostream & -QueueItemConflict::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const QueueItemConflict & item) -{ - return os << item.asString(); -} - -//--------------------------------------------------------------------------- - -QueueItemConflict::QueueItemConflict (WorldPtr world, constDependencyPtr dep, constResItemPtr resItem) - : QueueItem (QUEUE_ITEM_TYPE_CONFLICT, world) - , _dep (dep) - , _conflicting_resItem (resItem) - , _actually_an_obsolete (false) -{ -} - - -QueueItemConflict::~QueueItemConflict() -{ -} - -//--------------------------------------------------------------------------- - -#if PHI - -// on conflict, try to find upgrade candidates for the installed resItem triggering the conflict -// there are cases where upgrading prevents the conflict -// rc tends to uninstall the resItem -// phi tends to upgrade the resItem -// testcases: exercise-02conflict-08-test.xml, exercise-02conflict-09-test.xml - -typedef struct { - ResolverContextPtr context; - CResItemList upgrades; -} UpgradeCandidateInfo; - - -static bool -upgrade_candidates_cb (constResItemPtr resItem, constSpecPtr spec, void *data) -{ -//fprintf (stderr, "upgrade_candidates_cb(%s,%s)\n", resItem->asString().c_str(), spec->asString().c_str()); - UpgradeCandidateInfo *info = (UpgradeCandidateInfo *)data; - if (info->context->getStatus (resItem) == RESOLVABLE_STATUS_UNINSTALLED) { - info->upgrades.push_back (resItem); - } - return true; -} - -#endif // PHI - - -typedef struct { - WorldPtr world; - constResItemPtr conflicting_resItem; - constDependencyPtr dep; - ResolverContextPtr context; - QueueItemList & new_items; - - string pkg_str; - string dep_str; - - bool actually_an_obsolete; -} ConflictProcessInfo; - - -static bool -conflict_process_cb (constResItemPtr resItem, constSpecPtr spec, void *data) -{ - ConflictProcessInfo *info = (ConflictProcessInfo *)data; - ResItemStatus status; - string pkg_str, spec_str, msg; - ResolverInfoPtr log_info; - - if (getenv ("RC_SPEW")) fprintf (stderr, "conflict_process_cb (resolvable[%s], spec[%s], info [%s]\n", resItem->asString().c_str(), spec->asString().c_str(), info->conflicting_resItem->asString().c_str()); - if (getenv ("RC_SPEW")) fprintf (stderr, "conflict_process_cb (resolvable equals spec: %s, info->dep [%s]\n", resItem->equals(spec) ? "YES" : "NO", info->dep->asString().c_str()); - - /* We conflict with ourself. For the purpose of installing ourself, we - * just ignore it, but it's Debian's way of saying that one and only one - * resItem with this provide may exist on the system at a time. */ - - if (info->conflicting_resItem - && resItem->equals (info->conflicting_resItem)) { - return true; - } - - /* FIXME: This should probably be a GVersion capability. */ - /* Obsoletes don't apply to virtual provides, only the resItems - * themselves. A provide is "virtual" if it's not the same spec - * as the resItem that's providing it. This, of course, only - * applies to RPM, since it's the only one with obsoletes right - * now. */ - - if (info->actually_an_obsolete - && !(resItem->equals(spec))) - { - return true; - } - - pkg_str = resItem->asString(); - spec_str = spec->asString(); - - status = info->context->getStatus (resItem); - - if (getenv ("RC_SPEW")) fprintf (stderr, "conflict_process_cb (resolvable[%s]<%s>\n", resItem->asString().c_str(), ResolverContext::toString(status).c_str()); - - switch (status) { - - case RESOLVABLE_STATUS_INSTALLED: - case RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT: { - QueueItemUninstallPtr uninstall; - ResolverInfoPtr log_info; - -#if PHI - // maybe an upgrade can resolve the conflict ? - // check if other resItem is available which upgrades - - // find non-installed packages which provide the conflicting name - - UpgradeCandidateInfo upgrade_info; - upgrade_info.context = info->context; - - DependencyPtr maybe_upgrade_dep = new Dependency (resItem->name(), Relation::Any, Kind::Package, new Channel (CHANNEL_TYPE_NONSYSTEM), -1); - info->world->foreachProvidingResItem (maybe_upgrade_dep, upgrade_candidates_cb, (void *)&upgrade_info); - -#endif - - uninstall = new QueueItemUninstall (info->world, resItem, "conflict"); - uninstall->setDependency (info->dep); - - if (info->actually_an_obsolete) { - uninstall->setDueToObsolete (); - log_info = new ResolverInfoObsoletes (resItem, info->conflicting_resItem); - } else { - uninstall->setDueToConflict (); - log_info = new ResolverInfoConflictsWith (resItem, info->conflicting_resItem); - } - - uninstall->addInfo (log_info); - -#if PHI - if (upgrade_info.upgrades.empty ()) { -#endif - - info->new_items.push_back (uninstall); - -#if PHI - } - else { - // there are upgrade candidates for the conflicting resItem - // branch to: 1. uninstall, 2. upgrade (for each upgrading resItem) - - QueueItemBranchPtr branch = new QueueItemBranch (info->world); - - branch->addItem (uninstall); // try uninstall - - for (CResItemList::const_iterator iter = upgrade_info.upgrades.begin(); iter != upgrade_info.upgrades.end(); iter++) { - QueueItemInstallPtr upgrade = new QueueItemInstall (info->world, *iter); - upgrade->setUpgrades (resItem); - branch->addItem (upgrade); // try upgrade - } - info->new_items.push_back (branch); - } -#endif - - break; - } - - case RESOLVABLE_STATUS_TO_BE_INSTALLED: { - msg = string ("A conflict over ") + info->dep_str + " (" + spec_str + ") requires the removal of the to-be-installed resolvable " + pkg_str; - - ResolverInfoMiscPtr misc_info = new ResolverInfoMisc (resItem,RESOLVER_INFO_PRIORITY_VERBOSE, msg); - - misc_info->flagAsError (); - if (info->conflicting_resItem) { - misc_info->addRelatedResItem (info->conflicting_resItem); - } - info->context->addInfo (misc_info); - - break; - } - - case RESOLVABLE_STATUS_UNINSTALLED: { - info->context->setStatus (resItem, RESOLVABLE_STATUS_TO_BE_UNINSTALLED); - msg = string ("Marking ") + pkg_str + " as uninstallable due to conflicts over " + info->dep_str + " (" + spec_str + ")"; - if (!(info->pkg_str.empty())) { - msg += " from "; - msg += info->pkg_str; - } - - ResolverInfoMiscPtr misc_info = new ResolverInfoMisc (NULL, RESOLVER_INFO_PRIORITY_VERBOSE, msg); - - misc_info->addRelatedResItem (resItem); - if (info->conflicting_resItem) { - misc_info->addRelatedResItem(info->conflicting_resItem); - } - info->context->addInfo (misc_info); - - break; - } - - case RESOLVABLE_STATUS_TO_BE_UNINSTALLED: - case RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE: - /* This is the easy case -- we do nothing. */ - break; - - default: - abort(); - } - - return true; -} - - -bool -QueueItemConflict::process (ResolverContextPtr context, QueueItemList & new_items) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemConflict::process(%s)\n", this->asString().c_str()); - - ConflictProcessInfo info = { world(), _conflicting_resItem, _dep, context, new_items, "", "", _actually_an_obsolete }; - - if (_conflicting_resItem) { - info.pkg_str = _conflicting_resItem->asString(); - } - - info.dep_str = _dep->relation().asString() + " " + ((constSpecPtr)_dep)->asString(); - - world()->foreachProvidingResItem (_dep, conflict_process_cb, (void *)&info); - -// FIXME: free self - - return true; -} - - -//--------------------------------------------------------------------------- - -QueueItemPtr -QueueItemConflict::copy (void) const -{ - QueueItemConflictPtr new_conflict = new QueueItemConflict (world(), _dep, _conflicting_resItem); - ((QueueItemPtr)new_conflict)->copy((constQueueItemPtr)this); - - // _actually_an_obsolete is not being copied ! - - return new_conflict; -} - - -int -QueueItemConflict::cmp (constQueueItemPtr item) const -{ - int cmp = this->compare (item); // assures equal type - if (cmp != 0) - return cmp; - - constQueueItemConflictPtr conflict = item; - cmp = GVersion.compare ((constSpecPtr) _dep, ((constSpecPtr)(conflict->dependency()))); - if (cmp) - return cmp; - - return CMP ((int) _dep->relation().op(), (int) (conflict->dependency()->relation().op())); -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(QueueItemConflict,QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItemConflict::asString ( void ) const + { + return toString (*this); + } + + + string + QueueItemConflict::toString ( const QueueItemConflict & item) + { + string res = "[Conflict: "; + res += item._dep->asString(); + res += ", Triggered by "; + res += item._conflicting_resItem->asString(); + if (item._actually_an_obsolete) res += ", Obsolete !"; + res += "]"; + return res; + } + + + ostream & + QueueItemConflict::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const QueueItemConflict & item) + { + return os << item.asString(); + } + + //--------------------------------------------------------------------------- + + QueueItemConflict::QueueItemConflict (WorldPtr world, constDependencyPtr dep, constResItemPtr resItem) + : QueueItem (QUEUE_ITEM_TYPE_CONFLICT, world) + , _dep (dep) + , _conflicting_resItem (resItem) + , _actually_an_obsolete (false) + { + } + + + QueueItemConflict::~QueueItemConflict() + { + } + + //--------------------------------------------------------------------------- + + #if PHI + + // on conflict, try to find upgrade candidates for the installed resItem triggering the conflict + // there are cases where upgrading prevents the conflict + // rc tends to uninstall the resItem + // phi tends to upgrade the resItem + // testcases: exercise-02conflict-08-test.xml, exercise-02conflict-09-test.xml + + typedef struct { + ResolverContextPtr context; + CResItemList upgrades; + } UpgradeCandidateInfo; + + + static bool + upgrade_candidates_cb (constResItemPtr resItem, constSpecPtr spec, void *data) + { + //fprintf (stderr, "upgrade_candidates_cb(%s,%s)\n", resItem->asString().c_str(), spec->asString().c_str()); + UpgradeCandidateInfo *info = (UpgradeCandidateInfo *)data; + if (info->context->getStatus (resItem) == RESOLVABLE_STATUS_UNINSTALLED) { + info->upgrades.push_back (resItem); + } + return true; + } + + #endif // PHI + + + typedef struct { + WorldPtr world; + constResItemPtr conflicting_resItem; + constDependencyPtr dep; + ResolverContextPtr context; + QueueItemList & new_items; + + string pkg_str; + string dep_str; + + bool actually_an_obsolete; + } ConflictProcessInfo; + + + static bool + conflict_process_cb (constResItemPtr resItem, constSpecPtr spec, void *data) + { + ConflictProcessInfo *info = (ConflictProcessInfo *)data; + ResItemStatus status; + string pkg_str, spec_str, msg; + ResolverInfoPtr log_info; + + if (getenv ("RC_SPEW")) fprintf (stderr, "conflict_process_cb (resolvable[%s], spec[%s], info [%s]\n", resItem->asString().c_str(), spec->asString().c_str(), info->conflicting_resItem->asString().c_str()); + if (getenv ("RC_SPEW")) fprintf (stderr, "conflict_process_cb (resolvable equals spec: %s, info->dep [%s]\n", resItem->equals(spec) ? "YES" : "NO", info->dep->asString().c_str()); + + /* We conflict with ourself. For the purpose of installing ourself, we + * just ignore it, but it's Debian's way of saying that one and only one + * resItem with this provide may exist on the system at a time. */ + + if (info->conflicting_resItem + && resItem->equals (info->conflicting_resItem)) { + return true; + } + + /* FIXME: This should probably be a GVersion capability. */ + /* Obsoletes don't apply to virtual provides, only the resItems + * themselves. A provide is "virtual" if it's not the same spec + * as the resItem that's providing it. This, of course, only + * applies to RPM, since it's the only one with obsoletes right + * now. */ + + if (info->actually_an_obsolete + && !(resItem->equals(spec))) + { + return true; + } + + pkg_str = resItem->asString(); + spec_str = spec->asString(); + + status = info->context->getStatus (resItem); + + if (getenv ("RC_SPEW")) fprintf (stderr, "conflict_process_cb (resolvable[%s]<%s>\n", resItem->asString().c_str(), ResolverContext::toString(status).c_str()); + + switch (status) { + + case RESOLVABLE_STATUS_INSTALLED: + case RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT: { + QueueItemUninstallPtr uninstall; + ResolverInfoPtr log_info; + + #if PHI + // maybe an upgrade can resolve the conflict ? + // check if other resItem is available which upgrades + + // find non-installed packages which provide the conflicting name + + UpgradeCandidateInfo upgrade_info; + upgrade_info.context = info->context; + + DependencyPtr maybe_upgrade_dep = new Dependency (resItem->name(), Relation::Any, Kind::Package, new Channel (CHANNEL_TYPE_NONSYSTEM), -1); + info->world->foreachProvidingResItem (maybe_upgrade_dep, upgrade_candidates_cb, (void *)&upgrade_info); + + #endif + + uninstall = new QueueItemUninstall (info->world, resItem, "conflict"); + uninstall->setDependency (info->dep); + + if (info->actually_an_obsolete) { + uninstall->setDueToObsolete (); + log_info = new ResolverInfoObsoletes (resItem, info->conflicting_resItem); + } else { + uninstall->setDueToConflict (); + log_info = new ResolverInfoConflictsWith (resItem, info->conflicting_resItem); + } + + uninstall->addInfo (log_info); + + #if PHI + if (upgrade_info.upgrades.empty ()) { + #endif + + info->new_items.push_back (uninstall); + + #if PHI + } + else { + // there are upgrade candidates for the conflicting resItem + // branch to: 1. uninstall, 2. upgrade (for each upgrading resItem) + + QueueItemBranchPtr branch = new QueueItemBranch (info->world); + + branch->addItem (uninstall); // try uninstall + + for (CResItemList::const_iterator iter = upgrade_info.upgrades.begin(); iter != upgrade_info.upgrades.end(); iter++) { + QueueItemInstallPtr upgrade = new QueueItemInstall (info->world, *iter); + upgrade->setUpgrades (resItem); + branch->addItem (upgrade); // try upgrade + } + info->new_items.push_back (branch); + } + #endif + + break; + } + + case RESOLVABLE_STATUS_TO_BE_INSTALLED: { + msg = string ("A conflict over ") + info->dep_str + " (" + spec_str + ") requires the removal of the to-be-installed resolvable " + pkg_str; + + ResolverInfoMiscPtr misc_info = new ResolverInfoMisc (resItem,RESOLVER_INFO_PRIORITY_VERBOSE, msg); + + misc_info->flagAsError (); + if (info->conflicting_resItem) { + misc_info->addRelatedResItem (info->conflicting_resItem); + } + info->context->addInfo (misc_info); + + break; + } + + case RESOLVABLE_STATUS_UNINSTALLED: { + info->context->setStatus (resItem, RESOLVABLE_STATUS_TO_BE_UNINSTALLED); + msg = string ("Marking ") + pkg_str + " as uninstallable due to conflicts over " + info->dep_str + " (" + spec_str + ")"; + if (!(info->pkg_str.empty())) { + msg += " from "; + msg += info->pkg_str; + } + + ResolverInfoMiscPtr misc_info = new ResolverInfoMisc (NULL, RESOLVER_INFO_PRIORITY_VERBOSE, msg); + + misc_info->addRelatedResItem (resItem); + if (info->conflicting_resItem) { + misc_info->addRelatedResItem(info->conflicting_resItem); + } + info->context->addInfo (misc_info); + + break; + } + + case RESOLVABLE_STATUS_TO_BE_UNINSTALLED: + case RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE: + /* This is the easy case -- we do nothing. */ + break; + + default: + abort(); + } + + return true; + } + + + bool + QueueItemConflict::process (ResolverContextPtr context, QueueItemList & new_items) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemConflict::process(%s)\n", this->asString().c_str()); + + ConflictProcessInfo info = { world(), _conflicting_resItem, _dep, context, new_items, "", "", _actually_an_obsolete }; + + if (_conflicting_resItem) { + info.pkg_str = _conflicting_resItem->asString(); + } + + info.dep_str = _dep->relation().asString() + " " + ((constSpecPtr)_dep)->asString(); + + world()->foreachProvidingResItem (_dep, conflict_process_cb, (void *)&info); + + // FIXME: free self + + return true; + } + + + //--------------------------------------------------------------------------- + + QueueItemPtr + QueueItemConflict::copy (void) const + { + QueueItemConflictPtr new_conflict = new QueueItemConflict (world(), _dep, _conflicting_resItem); + ((QueueItemPtr)new_conflict)->copy((constQueueItemPtr)this); + + // _actually_an_obsolete is not being copied ! + + return new_conflict; + } + + + int + QueueItemConflict::cmp (constQueueItemPtr item) const + { + int cmp = this->compare (item); // assures equal type + if (cmp != 0) + return cmp; + + constQueueItemConflictPtr conflict = item; + cmp = GVersion.compare ((constSpecPtr) _dep, ((constSpecPtr)(conflict->dependency()))); + if (cmp) + return cmp; + + return CMP ((int) _dep->relation().op(), (int) (conflict->dependency()->relation().op())); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItemConflict.h b/zypp/solver/detail/QueueItemConflict.h index f0bf549..2376a1c 100644 --- a/zypp/solver/detail/QueueItemConflict.h +++ b/zypp/solver/detail/QueueItemConflict.h @@ -31,60 +31,67 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItemConflict - -class QueueItemConflict : public QueueItem { - REP_BODY(QueueItemConflict); - - private: - constDependencyPtr _dep; - constResItemPtr _conflicting_resItem; - - bool _actually_an_obsolete; - - public: - - QueueItemConflict (WorldPtr world, constDependencyPtr dep, constResItemPtr resItem); - virtual ~QueueItemConflict(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItemConflict & item); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItemConflict & item); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - constDependencyPtr dependency (void) const { return _dep; } - bool actuallyAnObsolete (void) const { return _actually_an_obsolete; } - void setActuallyAnObsolete (void) { _actually_an_obsolete = true; } - - // ---------------------------------- methods - - virtual bool process (ResolverContextPtr context, QueueItemList & qil); - virtual QueueItemPtr copy (void) const; - virtual int cmp (constQueueItemPtr item) const; - virtual bool isRedundant (ResolverContextPtr context) const { return false; } - virtual bool isSatisfied (ResolverContextPtr context) const { return false; } - -}; - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItemConflict + + class QueueItemConflict : public QueueItem { + REP_BODY(QueueItemConflict); + + private: + constDependencyPtr _dep; + constResItemPtr _conflicting_resItem; + + bool _actually_an_obsolete; + + public: + + QueueItemConflict (WorldPtr world, constDependencyPtr dep, constResItemPtr resItem); + virtual ~QueueItemConflict(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItemConflict & item); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItemConflict & item); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + constDependencyPtr dependency (void) const { return _dep; } + bool actuallyAnObsolete (void) const { return _actually_an_obsolete; } + void setActuallyAnObsolete (void) { _actually_an_obsolete = true; } + + // ---------------------------------- methods + + virtual bool process (ResolverContextPtr context, QueueItemList & qil); + virtual QueueItemPtr copy (void) const; + virtual int cmp (constQueueItemPtr item) const; + virtual bool isRedundant (ResolverContextPtr context) const { return false; } + virtual bool isSatisfied (ResolverContextPtr context) const { return false; } + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemConflict_h diff --git a/zypp/solver/detail/QueueItemConflictPtr.h b/zypp/solver/detail/QueueItemConflictPtr.h index 1207538..03edc53 100644 --- a/zypp/solver/detail/QueueItemConflictPtr.h +++ b/zypp/solver/detail/QueueItemConflictPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemConflictPtr -// CLASS NAME : constQueueItemConflictPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(QueueItemConflict,QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemConflictPtr + // CLASS NAME : constQueueItemConflictPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(QueueItemConflict,QueueItem); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemConflictPtr_h diff --git a/zypp/solver/detail/QueueItemGroup.cc b/zypp/solver/detail/QueueItemGroup.cc index dc05f8a..d1d6723 100644 --- a/zypp/solver/detail/QueueItemGroup.cc +++ b/zypp/solver/detail/QueueItemGroup.cc @@ -22,135 +22,146 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(QueueItemGroup,QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItemGroup::asString ( void ) const -{ - return toString (*this); -} - - -string -QueueItemGroup::toString ( const QueueItemGroup & item) -{ - string ret = "[Group: "; - ret += QueueItem::toString(item._subitems); - ret += "]"; - return ret; -} - - -ostream & -QueueItemGroup::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const QueueItemGroup & item) -{ - return os << item.asString(); -} - -//--------------------------------------------------------------------------- - -QueueItemGroup::QueueItemGroup (WorldPtr world) - : QueueItem (QUEUE_ITEM_TYPE_GROUP, world) -{ -} - - -QueueItemGroup::~QueueItemGroup() -{ -} - -//--------------------------------------------------------------------------- - -bool -QueueItemGroup::process (ResolverContextPtr context, QueueItemList & new_items) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemGroup::process\n"); - - bool did_something = false; - - // Just move all of the group's subitems onto the new_items list. - - for (QueueItemList::const_iterator iter = _subitems.begin(); iter != _subitems.end(); iter++) { - new_items.push_front (*iter); - did_something = true; - } - - _subitems.clear(); - -// FIXME: delete self - - return did_something; -} - - -QueueItemPtr -QueueItemGroup::copy (void) const -{ - QueueItemGroupPtr new_group = new QueueItemGroup (world()); - ((QueueItemPtr)new_group)->copy((constQueueItemPtr)this); - - for (QueueItemList::const_iterator iter = _subitems.begin(); iter != _subitems.end(); iter++) { - new_group->_subitems.push_back ((*iter)->copy()); - } - return new_group; -} - - -int -QueueItemGroup::cmp (constQueueItemPtr item) const -{ - int cmp = this->compare (item); // assures equal type - if (cmp != 0) - return cmp; - - constQueueItemGroupPtr group = item; - - // First, sort by # of subitems - - cmp = CMP(_subitems.size(), group->_subitems.size()); - if (cmp) - return cmp; - - // We can do a by-item cmp since the possible items are kept in sorted order. - QueueItemList::const_iterator iter2; - for (QueueItemList::const_iterator iter = _subitems.begin(), iter2 = group->_subitems.begin(); - iter != _subitems.end() && iter2 != group->_subitems.end(); iter++, iter2++) { - cmp = (*iter)->cmp (*iter2); - if (cmp) { - return cmp; - } - } - - return 0; -} - - -void -QueueItemGroup::addItem (QueueItemPtr subitem) -{ - // We need to keep the list sorted for comparison purposes. - _subitems.push_back (subitem); -// FIXME _subitems.sort(cmp) -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(QueueItemGroup,QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItemGroup::asString ( void ) const + { + return toString (*this); + } + + + string + QueueItemGroup::toString ( const QueueItemGroup & item) + { + string ret = "[Group: "; + ret += QueueItem::toString(item._subitems); + ret += "]"; + return ret; + } + + + ostream & + QueueItemGroup::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const QueueItemGroup & item) + { + return os << item.asString(); + } + + //--------------------------------------------------------------------------- + + QueueItemGroup::QueueItemGroup (WorldPtr world) + : QueueItem (QUEUE_ITEM_TYPE_GROUP, world) + { + } + + + QueueItemGroup::~QueueItemGroup() + { + } + + //--------------------------------------------------------------------------- + + bool + QueueItemGroup::process (ResolverContextPtr context, QueueItemList & new_items) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemGroup::process\n"); + + bool did_something = false; + + // Just move all of the group's subitems onto the new_items list. + + for (QueueItemList::const_iterator iter = _subitems.begin(); iter != _subitems.end(); iter++) { + new_items.push_front (*iter); + did_something = true; + } + + _subitems.clear(); + + // FIXME: delete self + + return did_something; + } + + + QueueItemPtr + QueueItemGroup::copy (void) const + { + QueueItemGroupPtr new_group = new QueueItemGroup (world()); + ((QueueItemPtr)new_group)->copy((constQueueItemPtr)this); + + for (QueueItemList::const_iterator iter = _subitems.begin(); iter != _subitems.end(); iter++) { + new_group->_subitems.push_back ((*iter)->copy()); + } + return new_group; + } + + + int + QueueItemGroup::cmp (constQueueItemPtr item) const + { + int cmp = this->compare (item); // assures equal type + if (cmp != 0) + return cmp; + + constQueueItemGroupPtr group = item; + + // First, sort by # of subitems + + cmp = CMP(_subitems.size(), group->_subitems.size()); + if (cmp) + return cmp; + + // We can do a by-item cmp since the possible items are kept in sorted order. + QueueItemList::const_iterator iter2; + for (QueueItemList::const_iterator iter = _subitems.begin(), iter2 = group->_subitems.begin(); + iter != _subitems.end() && iter2 != group->_subitems.end(); iter++, iter2++) { + cmp = (*iter)->cmp (*iter2); + if (cmp) { + return cmp; + } + } + + return 0; + } + + + void + QueueItemGroup::addItem (QueueItemPtr subitem) + { + // We need to keep the list sorted for comparison purposes. + _subitems.push_back (subitem); + // FIXME _subitems.sort(cmp) + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItemGroup.h b/zypp/solver/detail/QueueItemGroup.h index 447238f..91f8745 100644 --- a/zypp/solver/detail/QueueItemGroup.h +++ b/zypp/solver/detail/QueueItemGroup.h @@ -31,54 +31,62 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItemGroup - -class QueueItemGroup : public QueueItem { - REP_BODY(QueueItemGroup); - - private: - QueueItemList _subitems; - - public: - - QueueItemGroup (WorldPtr world); - virtual ~QueueItemGroup(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItemGroup & item); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItemGroup & item); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - - // ---------------------------------- methods - - virtual bool process (ResolverContextPtr context, QueueItemList & qil); - virtual QueueItemPtr copy (void) const; - virtual int cmp (constQueueItemPtr item) const; - virtual bool isRedundant (ResolverContextPtr context) const { return false; } - virtual bool isSatisfied (ResolverContextPtr context) const { return false; } - - void addItem (QueueItemPtr subitem); -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItemGroup + + class QueueItemGroup : public QueueItem { + REP_BODY(QueueItemGroup); + + private: + QueueItemList _subitems; + + public: + + QueueItemGroup (WorldPtr world); + virtual ~QueueItemGroup(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItemGroup & item); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItemGroup & item); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + + // ---------------------------------- methods + + virtual bool process (ResolverContextPtr context, QueueItemList & qil); + virtual QueueItemPtr copy (void) const; + virtual int cmp (constQueueItemPtr item) const; + virtual bool isRedundant (ResolverContextPtr context) const { return false; } + virtual bool isSatisfied (ResolverContextPtr context) const { return false; } + + void addItem (QueueItemPtr subitem); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemGroup_h diff --git a/zypp/solver/detail/QueueItemGroupPtr.h b/zypp/solver/detail/QueueItemGroupPtr.h index 819ab3e..49974ea 100644 --- a/zypp/solver/detail/QueueItemGroupPtr.h +++ b/zypp/solver/detail/QueueItemGroupPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemGroupPtr -// CLASS NAME : constQueueItemGroupPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(QueueItemGroup,QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemGroupPtr + // CLASS NAME : constQueueItemGroupPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(QueueItemGroup,QueueItem); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +//////////////////////////////////////////////////////////////////////// #endif // _QueueItemGroupPtr_h diff --git a/zypp/solver/detail/QueueItemInstall.cc b/zypp/solver/detail/QueueItemInstall.cc index 209c5ea..61f7580 100644 --- a/zypp/solver/detail/QueueItemInstall.cc +++ b/zypp/solver/detail/QueueItemInstall.cc @@ -35,330 +35,342 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(QueueItemInstall,QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItemInstall::asString ( void ) const -{ - 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 "; - ret += Dependency::toString(item._deps_satisfied_by_this_install); - } - 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; -} - - -ostream& -operator<<( ostream& os, const QueueItemInstall & item) -{ - 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) -{ - 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 - && ! (((constSpecPtr)upgrades)->equals (resItem))) { - setUpgrades(upgrades); - } -} - - -QueueItemInstall::~QueueItemInstall() -{ -} - -//--------------------------------------------------------------------------- - -bool -QueueItemInstall::isSatisfied (ResolverContextPtr context) const -{ - return context->resItemIsPresent (_resItem); -} - - -//--------------------------------------------------------------------------- - -// Handle system resItem's that conflict with us -> uninstall them - -static bool -build_conflict_list (constResItemPtr resItem, constDependencyPtr dep, void *data) -{ - 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); - - CDependencyList 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 - && ((constSpecPtr)_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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { - constDependencyPtr 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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { - constDependencyPtr 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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { - constDependencyPtr 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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { - constDependencyPtr 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 (((constSpecPtr)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; -} - - -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 = CDependencyList(_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 GVersion.compare (_resItem, install->_resItem); -} - -//--------------------------------------------------------------------------- - -void -QueueItemInstall::addDependency (constDependencyPtr dep) -{ - _deps_satisfied_by_this_install.push_front (dep); -} - - -void -QueueItemInstall::addNeededBy (constResItemPtr resItem) -{ - _needed_by.push_front (resItem); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(QueueItemInstall,QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItemInstall::asString ( void ) const + { + 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 "; + ret += Dependency::toString(item._deps_satisfied_by_this_install); + } + 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; + } + + + ostream& + operator<<( ostream& os, const QueueItemInstall & item) + { + 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) + { + 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 + && ! (((constSpecPtr)upgrades)->equals (resItem))) { + setUpgrades(upgrades); + } + } + + + QueueItemInstall::~QueueItemInstall() + { + } + + //--------------------------------------------------------------------------- + + bool + QueueItemInstall::isSatisfied (ResolverContextPtr context) const + { + return context->resItemIsPresent (_resItem); + } + + + //--------------------------------------------------------------------------- + + // Handle system resItem's that conflict with us -> uninstall them + + static bool + build_conflict_list (constResItemPtr resItem, constDependencyPtr dep, void *data) + { + 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); + + CDependencyList 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 + && ((constSpecPtr)_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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { + constDependencyPtr 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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { + constDependencyPtr 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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { + constDependencyPtr 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 (CDependencyList::const_iterator iter = deps.begin(); iter != deps.end(); iter++) { + constDependencyPtr 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 (((constSpecPtr)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; + } + + + 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 = CDependencyList(_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 GVersion.compare (_resItem, install->_resItem); + } + + //--------------------------------------------------------------------------- + + void + QueueItemInstall::addDependency (constDependencyPtr dep) + { + _deps_satisfied_by_this_install.push_front (dep); + } + + + void + QueueItemInstall::addNeededBy (constResItemPtr resItem) + { + _needed_by.push_front (resItem); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItemInstall.h b/zypp/solver/detail/QueueItemInstall.h index 3eeacc1..4f8d0e4 100644 --- a/zypp/solver/detail/QueueItemInstall.h +++ b/zypp/solver/detail/QueueItemInstall.h @@ -31,77 +31,85 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItemInstall - -class QueueItemInstall : public QueueItem { - REP_BODY(QueueItemInstall); - - private: - constResItemPtr _resItem; - constResItemPtr _upgrades; - CDependencyList _deps_satisfied_by_this_install; - CResItemList _needed_by; - int _channel_priority; - int _other_penalty; - - bool _explicitly_requested; - - public: - - QueueItemInstall (WorldPtr world, constResItemPtr resItem); - virtual ~QueueItemInstall(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItemInstall & item); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItemInstall & item); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - constResItemPtr resItem (void) const { return _resItem; } - - constResItemPtr upgrades (void) const { return _upgrades; } - void setUpgrades (constResItemPtr upgrades) { _upgrades = upgrades; } - - int channelPriority (void) const { return _channel_priority; } - void setChannelPriority (int channel_priority) { _channel_priority = channel_priority; } - - int otherPenalty (void) { return _other_penalty; } - void setOtherPenalty (int other_penalty) { _other_penalty = other_penalty; } - - void setExplicitlyRequested (void) { _explicitly_requested = true; } - - // ---------------------------------- methods - - virtual bool process (ResolverContextPtr context, QueueItemList & qil); - virtual QueueItemPtr copy (void) const; - virtual int cmp (constQueueItemPtr item) const; - - virtual bool isRedundant (ResolverContextPtr context) const { return false; } - virtual bool isSatisfied (ResolverContextPtr context) const; - - void addDependency (constDependencyPtr dep); - void addNeededBy (constResItemPtr resItem); - -}; - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItemInstall + + class QueueItemInstall : public QueueItem { + REP_BODY(QueueItemInstall); + + private: + constResItemPtr _resItem; + constResItemPtr _upgrades; + CDependencyList _deps_satisfied_by_this_install; + CResItemList _needed_by; + int _channel_priority; + int _other_penalty; + + bool _explicitly_requested; + + public: + + QueueItemInstall (WorldPtr world, constResItemPtr resItem); + virtual ~QueueItemInstall(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItemInstall & item); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItemInstall & item); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + constResItemPtr resItem (void) const { return _resItem; } + + constResItemPtr upgrades (void) const { return _upgrades; } + void setUpgrades (constResItemPtr upgrades) { _upgrades = upgrades; } + + int channelPriority (void) const { return _channel_priority; } + void setChannelPriority (int channel_priority) { _channel_priority = channel_priority; } + + int otherPenalty (void) { return _other_penalty; } + void setOtherPenalty (int other_penalty) { _other_penalty = other_penalty; } + + void setExplicitlyRequested (void) { _explicitly_requested = true; } + + // ---------------------------------- methods + + virtual bool process (ResolverContextPtr context, QueueItemList & qil); + virtual QueueItemPtr copy (void) const; + virtual int cmp (constQueueItemPtr item) const; + + virtual bool isRedundant (ResolverContextPtr context) const { return false; } + virtual bool isSatisfied (ResolverContextPtr context) const; + + void addDependency (constDependencyPtr dep); + void addNeededBy (constResItemPtr resItem); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItem_h diff --git a/zypp/solver/detail/QueueItemInstallPtr.h b/zypp/solver/detail/QueueItemInstallPtr.h index 803d240..d587cda 100644 --- a/zypp/solver/detail/QueueItemInstallPtr.h +++ b/zypp/solver/detail/QueueItemInstallPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemInstallPtr -// CLASS NAME : constQueueItemInstallPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(QueueItemInstall,QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemInstallPtr + // CLASS NAME : constQueueItemInstallPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(QueueItemInstall,QueueItem); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemInstallPtr_h diff --git a/zypp/solver/detail/QueueItemPtr.h b/zypp/solver/detail/QueueItemPtr.h index 08d5f1f..f2b0469 100644 --- a/zypp/solver/detail/QueueItemPtr.h +++ b/zypp/solver/detail/QueueItemPtr.h @@ -23,18 +23,29 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemPtr -// CLASS NAME : constQueueItemPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemPtr + // CLASS NAME : constQueueItemPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(QueueItem); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemPtr_h diff --git a/zypp/solver/detail/QueueItemRequire.cc b/zypp/solver/detail/QueueItemRequire.cc index 8dfa76c..7e26fd7 100644 --- a/zypp/solver/detail/QueueItemRequire.cc +++ b/zypp/solver/detail/QueueItemRequire.cc @@ -33,452 +33,464 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(QueueItemRequire,QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItemRequire::asString ( void ) const -{ - return toString (*this); -} - - -string -QueueItemRequire::toString ( const QueueItemRequire & item) -{ - string ret = "[Require: "; - ret += item._dep->asString(); - if (item._requiring_resItem != NULL) { - ret += ", Required by "; - ret += item._requiring_resItem->asString(); - } - if (item._upgraded_resItem != NULL) { - ret += ", Upgrades "; - ret += item._upgraded_resItem->asString(); - } - if (item._lost_resItem != NULL) { - ret += ", Lost "; - ret += item._lost_resItem->asString(); - } - if (item._remove_only) ret += ", Remove Only"; - if (item._is_child) ret += ", Child"; - ret += "]"; - - return ret; -} - - -ostream & -QueueItemRequire::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const QueueItemRequire & item) -{ - return os << item.asString(); -} - -//--------------------------------------------------------------------------- - -QueueItemRequire::QueueItemRequire (WorldPtr world, constDependencyPtr dep) - : QueueItem (QUEUE_ITEM_TYPE_REQUIRE, world) - , _dep (dep) - , _requiring_resItem (NULL) - , _upgraded_resItem (NULL) - , _lost_resItem (NULL) - , _remove_only (false) - , _is_child (false) -{ -} - - -QueueItemRequire::~QueueItemRequire() -{ -} - -//--------------------------------------------------------------------------- - -void -QueueItemRequire::addResItem (constResItemPtr resItem) -{ - assert (_requiring_resItem == NULL); - _requiring_resItem = resItem; -} - - -//--------------------------------------------------------------------------- - -typedef std::map UniqTable; - -typedef struct { - constResItemPtr resItem; - constSpecPtr dep; - ResolverContextPtr context; - WorldPtr world; - CResItemList providers; - UniqTable *uniq; -} RequireProcessInfo; - - -static bool -require_process_cb (constResItemPtr resItem, constSpecPtr spec, void *data) -{ - RequireProcessInfo *info = (RequireProcessInfo *)data; - ResItemStatus status; - - status = info->context->getStatus (resItem); -//fprintf (stderr, "require_process_cb(res: %s, spec %s, status %s)\n", resItem->asString().c_str(), spec->asString().c_str(), ResolverContext::toString(status).c_str()); -//fprintf (stderr, "require_process_cb(info->dep: %s)\n", info->dep ? info->dep->asString().c_str() : "(null)"); -//fprintf (stderr, "require_process_cb(resItemIsPossible -> %d)\n", info->context->resItemIsPossible (resItem)); - /* info->dep is set for resItem set childern only. If it is set - allow only exactly required version */ - if (info->dep != NULL - && !info->dep->equals(spec)) { - return true; - } - - if ((! resItem_status_is_to_be_uninstalled (status)) - && ! info->context->isParallelInstall (resItem) - && info->uniq->find((constSpecPtr)resItem) == info->uniq->end() - && info->context->resItemIsPossible (resItem) - && ! info->world->resItemIsLocked (resItem)) { - - info->providers.push_front (resItem); - (*(info->uniq))[resItem] = true; - } - - return true; -} - - -static bool -no_installable_providers_info_cb (constResItemPtr resItem, constSpecPtr spec, void *data) -{ - RequireProcessInfo *info = (RequireProcessInfo *)data; - ResItemStatus status; - string msg_str; - - status = info->context->getStatus (resItem); - - if (resItem_status_is_to_be_uninstalled (status)) { - msg_str = resItem->name() + " provides " + spec->asString() + ", but is scheduled to be uninstalled."; - } else if (info->context->isParallelInstall (resItem)) { - msg_str = resItem->name() + " provides " + spec->asString() + ", but another version of that resItem is already installed."; - } else if (! info->context->resItemIsPossible (resItem)) { - msg_str = resItem->name() + " provides " + spec->asString() + ", but it is uninstallable. Try installing it on its own for more details."; - } else if (info->world->resItemIsLocked (resItem)) { - msg_str = resItem->name() + " provides " + spec->asString() + ", but it is locked."; - } - - if (!msg_str.empty()) { - info->context->addInfoString (info->resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg_str); - } - - return true; -} - - -static bool -look_for_upgrades_cb (constResItemPtr resItem, void *data) -{ - CResItemList *rl = (CResItemList *)data; - rl->push_front (resItem); - return true; -} - - -static bool -codependent_resItems (constResItemPtr r1, constResItemPtr r2) -{ - string name1 = r1->name(); - string name2 = r2->name(); - int len1 = name1.size(); - int len2 = name2.size(); - - if (len2 < len1) { - string swap = name1; - int swap_len = len1; - name1 = name2; - name2 = swap; - len1 = len2; - len2 = swap_len; - } - - // foo and foo-bar are automatically co-dependent - if (len1 < len2 - && strncmp (name1.c_str(), name2.c_str(), len1) == 0 - && name2[len1] == '-') { - return true; - } - - return false; -} - - -bool -QueueItemRequire::process (ResolverContextPtr context, QueueItemList & new_items) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemRequire::process(%s)\n", this->asString().c_str()); - - if (context->requirementIsMet (_dep, _is_child)) { - if (getenv ("RC_SPEW")) fprintf (stderr, "requirement is already met in current context\n"); -// rc_queue_item_free (item); - return true; - } - - RequireProcessInfo info; - - info.resItem = _requiring_resItem; - info.dep = _is_child ? _dep : NULL; - info.context = context; - info.world = world(); - info.uniq = new UniqTable(); //FIXME: op: g_hash_table_new (rc_resItem_spec_hash, rc_resItem_spec_equal); - - int num_providers = 0; - - if (! _remove_only) { - - world()->foreachProvidingResItem (_dep, require_process_cb, &info); - - num_providers = info.providers.size(); - - if (getenv ("RC_SPEW")) fprintf (stderr, "requirement is met by %d resolvable\n", num_providers); - } - - std::string msg; - - if (num_providers == 0) { - - if (getenv ("RC_SPEW")) fprintf (stderr, "Unfulfilled requirement, try different solution\n"); - - QueueItemUninstallPtr uninstall_item = NULL; - QueueItemBranchPtr branch_item = NULL; - bool explore_uninstall_branch = true; - - if (_upgraded_resItem == NULL) { - ResolverInfoPtr err_info; - - msg = string ("There are no ") + (_remove_only ? "alternative installed" : "installable") + " providers of " + _dep->asString(); - if (_requiring_resItem != NULL) { - msg += " for "; - msg += _requiring_resItem->asString(); - } - - err_info = new ResolverInfoMisc (_requiring_resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); - - context->addInfo (err_info); - - // Maybe we can add some extra info on why none of the providers are suitable. - world()->foreachProvidingResItem (_dep, no_installable_providers_info_cb, (void *)&info); - } - - // If this is an upgrade, we might be able to avoid removing stuff by upgrading it instead. - if (_upgraded_resItem != NULL - && _requiring_resItem != NULL) { - - CResItemList upgrade_list; - - world()->foreachUpgrade (_requiring_resItem, new Channel(CHANNEL_TYPE_ANY), look_for_upgrades_cb, (void *)&upgrade_list); - - if (!upgrade_list.empty()) { - string label, req_str, up_str; - - branch_item = new QueueItemBranch (world()); - - req_str = _requiring_resItem->asString(); - up_str = _upgraded_resItem->asString(); - - label = string ("for requiring ") + _dep->asString() + " for " + req_str + " when upgrading " + up_str; - branch_item->setLabel (label); -//fprintf (stderr, "Branching: %s\n", label.c_str()); - for (CResItemList::const_iterator iter = upgrade_list.begin(); iter != upgrade_list.end(); iter++) { - constResItemPtr upgrade_resItem = *iter; - QueueItemInstallPtr install_item; - - if (context->resItemIsPossible (upgrade_resItem)) { - - install_item = new QueueItemInstall (world(), upgrade_resItem); - install_item->setUpgrades (_requiring_resItem); - branch_item->addItem (install_item); - - ResolverInfoNeededByPtr upgrade_info = new ResolverInfoNeededBy (upgrade_resItem); - upgrade_info->addRelatedResItem (_upgraded_resItem); - install_item->addInfo (upgrade_info); - - // If an upgrade resItem has its requirements met, don't do the uninstall branch. - // FIXME: should we also look at conflicts here? - - if (explore_uninstall_branch) { - CDependencyList requires = upgrade_resItem->requires(); - CDependencyList::const_iterator iter = requires.begin(); - for (; iter != requires.end(); iter++) { - constDependencyPtr req = *iter; - if (! context->requirementIsMet (req, false)) { - break; - } - } - if (iter == requires.end()) { - explore_uninstall_branch = false; - } - } - - } /* if (context->resItemIsPossible ( ... */ - } /* for (iter = upgrade_list; ... */ - } /* if (upgrade_list) ... */ - - if (!upgrade_list.empty() - && branch_item->isEmpty ()) { - - for (CResItemList::const_iterator iter = upgrade_list.begin(); iter != upgrade_list.end(); iter++) { - string str; - string p1, p2; - - p1 = _requiring_resItem->asString(); - p2 = (*iter)->asString(); - str = string ("Upgrade to ") + p2 + " to avoid removing " + p1 + " is not possible."; - - ResolverInfoMiscPtr misc_info = new ResolverInfoMisc (NULL, RESOLVER_INFO_PRIORITY_VERBOSE, str); - misc_info->addRelatedResItem (_requiring_resItem); - misc_info->addRelatedResItem (*iter); - context->addInfo (misc_info); - - explore_uninstall_branch = true; - } - - // - // The exception: we always want to consider uninstalling - // when the requirement has resulted from a resItem losing - // one of it's provides. - - } else if (!upgrade_list.empty() - && explore_uninstall_branch - && codependent_resItems (_requiring_resItem, _upgraded_resItem) - && _lost_resItem == NULL) { - explore_uninstall_branch = false; - } - - } /* if (_upgrade_resItem && _requiring_resItem) ... */ - - // We always consider uninstalling when in verification mode. - - if (context->verifying()) { - explore_uninstall_branch = true; - } - - if (explore_uninstall_branch && _requiring_resItem) { - ResolverInfoPtr log_info; - uninstall_item = new QueueItemUninstall (world(),_requiring_resItem, "unsatisfied requirements"); - uninstall_item->setDependency (_dep); - - if (_lost_resItem) { - log_info = new ResolverInfoDependsOn (_requiring_resItem, _lost_resItem); - uninstall_item->addInfo (log_info); - } - - if (_remove_only) - uninstall_item->setRemoveOnly (); - } - - if (uninstall_item && branch_item) { - branch_item->addItem (uninstall_item); - new_items.push_front (branch_item); - } else if (uninstall_item) { - new_items.push_front (uninstall_item); - } else if (branch_item) { - new_items.push_front (branch_item); - } else { - // We can't do anything to resolve the missing requirement, so we fail. - string msg = string ("Can't satisfy requirement '") + _dep->asString() + "'"; - - context->addErrorString (NULL, msg); - } - - } else if (num_providers == 1) { - - if (getenv ("RC_SPEW")) fprintf (stderr, "Found exactly one resolvable, installing it.\n"); - - QueueItemInstallPtr install_item = new QueueItemInstall (world(), info.providers.front()); - install_item->addDependency (_dep); - - // The requiring resItem could be NULL if the requirement was added as an extra dependency. - if (_requiring_resItem) { - install_item->addNeededBy (_requiring_resItem); - } - new_items.push_front (install_item); - - } else if (num_providers > 1) { - - if (getenv ("RC_SPEW")) fprintf (stderr, "Found more than one resolvable, branching.\n"); - -//fprintf (stderr, "Found more than one resItem, branching.\n"); - QueueItemBranchPtr branch_item = new QueueItemBranch (world()); - - for (CResItemList::const_iterator iter = info.providers.begin(); iter != info.providers.end(); iter++) { - QueueItemInstallPtr install_item = new QueueItemInstall (world(), *iter); - install_item->addDependency (_dep); - branch_item->addItem (install_item); - - // The requiring resItem could be NULL if the requirement was added as an extra dependency. - if (_requiring_resItem) { - install_item->addNeededBy (_requiring_resItem); - } - } - - new_items.push_front (branch_item); - - } else { - abort (); - } - - -// rc_queue_item_free (item); - return true; -} - -//--------------------------------------------------------------------------- - -QueueItemPtr -QueueItemRequire::copy (void) const -{ - QueueItemRequirePtr new_require = new QueueItemRequire (world(), _dep); - ((QueueItemPtr)new_require)->copy((constQueueItemPtr)this); - - new_require->_requiring_resItem = _requiring_resItem; - new_require->_upgraded_resItem = _upgraded_resItem; - new_require->_remove_only = _remove_only; - - return new_require; -} - - -int -QueueItemRequire::cmp (constQueueItemPtr item) const -{ - int cmp = this->compare (item); // assures equal type - if (cmp != 0) - return cmp; - - constQueueItemRequirePtr require = item; - - cmp = GVersion.compare ((constSpecPtr) _dep, ((constSpecPtr)(require->dependency()))); - if (cmp) - return cmp; - - return CMP ((int) _dep->relation().op(), (int) (require->dependency()->relation().op())); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(QueueItemRequire,QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItemRequire::asString ( void ) const + { + return toString (*this); + } + + + string + QueueItemRequire::toString ( const QueueItemRequire & item) + { + string ret = "[Require: "; + ret += item._dep->asString(); + if (item._requiring_resItem != NULL) { + ret += ", Required by "; + ret += item._requiring_resItem->asString(); + } + if (item._upgraded_resItem != NULL) { + ret += ", Upgrades "; + ret += item._upgraded_resItem->asString(); + } + if (item._lost_resItem != NULL) { + ret += ", Lost "; + ret += item._lost_resItem->asString(); + } + if (item._remove_only) ret += ", Remove Only"; + if (item._is_child) ret += ", Child"; + ret += "]"; + + return ret; + } + + + ostream & + QueueItemRequire::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const QueueItemRequire & item) + { + return os << item.asString(); + } + + //--------------------------------------------------------------------------- + + QueueItemRequire::QueueItemRequire (WorldPtr world, constDependencyPtr dep) + : QueueItem (QUEUE_ITEM_TYPE_REQUIRE, world) + , _dep (dep) + , _requiring_resItem (NULL) + , _upgraded_resItem (NULL) + , _lost_resItem (NULL) + , _remove_only (false) + , _is_child (false) + { + } + + + QueueItemRequire::~QueueItemRequire() + { + } + + //--------------------------------------------------------------------------- + + void + QueueItemRequire::addResItem (constResItemPtr resItem) + { + assert (_requiring_resItem == NULL); + _requiring_resItem = resItem; + } + + + //--------------------------------------------------------------------------- + + typedef std::map UniqTable; + + typedef struct { + constResItemPtr resItem; + constSpecPtr dep; + ResolverContextPtr context; + WorldPtr world; + CResItemList providers; + UniqTable *uniq; + } RequireProcessInfo; + + + static bool + require_process_cb (constResItemPtr resItem, constSpecPtr spec, void *data) + { + RequireProcessInfo *info = (RequireProcessInfo *)data; + ResItemStatus status; + + status = info->context->getStatus (resItem); + //fprintf (stderr, "require_process_cb(res: %s, spec %s, status %s)\n", resItem->asString().c_str(), spec->asString().c_str(), ResolverContext::toString(status).c_str()); + //fprintf (stderr, "require_process_cb(info->dep: %s)\n", info->dep ? info->dep->asString().c_str() : "(null)"); + //fprintf (stderr, "require_process_cb(resItemIsPossible -> %d)\n", info->context->resItemIsPossible (resItem)); + /* info->dep is set for resItem set childern only. If it is set + allow only exactly required version */ + if (info->dep != NULL + && !info->dep->equals(spec)) { + return true; + } + + if ((! resItem_status_is_to_be_uninstalled (status)) + && ! info->context->isParallelInstall (resItem) + && info->uniq->find((constSpecPtr)resItem) == info->uniq->end() + && info->context->resItemIsPossible (resItem) + && ! info->world->resItemIsLocked (resItem)) { + + info->providers.push_front (resItem); + (*(info->uniq))[resItem] = true; + } + + return true; + } + + + static bool + no_installable_providers_info_cb (constResItemPtr resItem, constSpecPtr spec, void *data) + { + RequireProcessInfo *info = (RequireProcessInfo *)data; + ResItemStatus status; + string msg_str; + + status = info->context->getStatus (resItem); + + if (resItem_status_is_to_be_uninstalled (status)) { + msg_str = resItem->name() + " provides " + spec->asString() + ", but is scheduled to be uninstalled."; + } else if (info->context->isParallelInstall (resItem)) { + msg_str = resItem->name() + " provides " + spec->asString() + ", but another version of that resItem is already installed."; + } else if (! info->context->resItemIsPossible (resItem)) { + msg_str = resItem->name() + " provides " + spec->asString() + ", but it is uninstallable. Try installing it on its own for more details."; + } else if (info->world->resItemIsLocked (resItem)) { + msg_str = resItem->name() + " provides " + spec->asString() + ", but it is locked."; + } + + if (!msg_str.empty()) { + info->context->addInfoString (info->resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg_str); + } + + return true; + } + + + static bool + look_for_upgrades_cb (constResItemPtr resItem, void *data) + { + CResItemList *rl = (CResItemList *)data; + rl->push_front (resItem); + return true; + } + + + static bool + codependent_resItems (constResItemPtr r1, constResItemPtr r2) + { + string name1 = r1->name(); + string name2 = r2->name(); + int len1 = name1.size(); + int len2 = name2.size(); + + if (len2 < len1) { + string swap = name1; + int swap_len = len1; + name1 = name2; + name2 = swap; + len1 = len2; + len2 = swap_len; + } + + // foo and foo-bar are automatically co-dependent + if (len1 < len2 + && strncmp (name1.c_str(), name2.c_str(), len1) == 0 + && name2[len1] == '-') { + return true; + } + + return false; + } + + + bool + QueueItemRequire::process (ResolverContextPtr context, QueueItemList & new_items) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemRequire::process(%s)\n", this->asString().c_str()); + + if (context->requirementIsMet (_dep, _is_child)) { + if (getenv ("RC_SPEW")) fprintf (stderr, "requirement is already met in current context\n"); + // rc_queue_item_free (item); + return true; + } + + RequireProcessInfo info; + + info.resItem = _requiring_resItem; + info.dep = _is_child ? _dep : NULL; + info.context = context; + info.world = world(); + info.uniq = new UniqTable(); //FIXME: op: g_hash_table_new (rc_resItem_spec_hash, rc_resItem_spec_equal); + + int num_providers = 0; + + if (! _remove_only) { + + world()->foreachProvidingResItem (_dep, require_process_cb, &info); + + num_providers = info.providers.size(); + + if (getenv ("RC_SPEW")) fprintf (stderr, "requirement is met by %d resolvable\n", num_providers); + } + + std::string msg; + + if (num_providers == 0) { + + if (getenv ("RC_SPEW")) fprintf (stderr, "Unfulfilled requirement, try different solution\n"); + + QueueItemUninstallPtr uninstall_item = NULL; + QueueItemBranchPtr branch_item = NULL; + bool explore_uninstall_branch = true; + + if (_upgraded_resItem == NULL) { + ResolverInfoPtr err_info; + + msg = string ("There are no ") + (_remove_only ? "alternative installed" : "installable") + " providers of " + _dep->asString(); + if (_requiring_resItem != NULL) { + msg += " for "; + msg += _requiring_resItem->asString(); + } + + err_info = new ResolverInfoMisc (_requiring_resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); + + context->addInfo (err_info); + + // Maybe we can add some extra info on why none of the providers are suitable. + world()->foreachProvidingResItem (_dep, no_installable_providers_info_cb, (void *)&info); + } + + // If this is an upgrade, we might be able to avoid removing stuff by upgrading it instead. + if (_upgraded_resItem != NULL + && _requiring_resItem != NULL) { + + CResItemList upgrade_list; + + world()->foreachUpgrade (_requiring_resItem, new Channel(CHANNEL_TYPE_ANY), look_for_upgrades_cb, (void *)&upgrade_list); + + if (!upgrade_list.empty()) { + string label, req_str, up_str; + + branch_item = new QueueItemBranch (world()); + + req_str = _requiring_resItem->asString(); + up_str = _upgraded_resItem->asString(); + + label = string ("for requiring ") + _dep->asString() + " for " + req_str + " when upgrading " + up_str; + branch_item->setLabel (label); + //fprintf (stderr, "Branching: %s\n", label.c_str()); + for (CResItemList::const_iterator iter = upgrade_list.begin(); iter != upgrade_list.end(); iter++) { + constResItemPtr upgrade_resItem = *iter; + QueueItemInstallPtr install_item; + + if (context->resItemIsPossible (upgrade_resItem)) { + + install_item = new QueueItemInstall (world(), upgrade_resItem); + install_item->setUpgrades (_requiring_resItem); + branch_item->addItem (install_item); + + ResolverInfoNeededByPtr upgrade_info = new ResolverInfoNeededBy (upgrade_resItem); + upgrade_info->addRelatedResItem (_upgraded_resItem); + install_item->addInfo (upgrade_info); + + // If an upgrade resItem has its requirements met, don't do the uninstall branch. + // FIXME: should we also look at conflicts here? + + if (explore_uninstall_branch) { + CDependencyList requires = upgrade_resItem->requires(); + CDependencyList::const_iterator iter = requires.begin(); + for (; iter != requires.end(); iter++) { + constDependencyPtr req = *iter; + if (! context->requirementIsMet (req, false)) { + break; + } + } + if (iter == requires.end()) { + explore_uninstall_branch = false; + } + } + + } /* if (context->resItemIsPossible ( ... */ + } /* for (iter = upgrade_list; ... */ + } /* if (upgrade_list) ... */ + + if (!upgrade_list.empty() + && branch_item->isEmpty ()) { + + for (CResItemList::const_iterator iter = upgrade_list.begin(); iter != upgrade_list.end(); iter++) { + string str; + string p1, p2; + + p1 = _requiring_resItem->asString(); + p2 = (*iter)->asString(); + str = string ("Upgrade to ") + p2 + " to avoid removing " + p1 + " is not possible."; + + ResolverInfoMiscPtr misc_info = new ResolverInfoMisc (NULL, RESOLVER_INFO_PRIORITY_VERBOSE, str); + misc_info->addRelatedResItem (_requiring_resItem); + misc_info->addRelatedResItem (*iter); + context->addInfo (misc_info); + + explore_uninstall_branch = true; + } + + // + // The exception: we always want to consider uninstalling + // when the requirement has resulted from a resItem losing + // one of it's provides. + + } else if (!upgrade_list.empty() + && explore_uninstall_branch + && codependent_resItems (_requiring_resItem, _upgraded_resItem) + && _lost_resItem == NULL) { + explore_uninstall_branch = false; + } + + } /* if (_upgrade_resItem && _requiring_resItem) ... */ + + // We always consider uninstalling when in verification mode. + + if (context->verifying()) { + explore_uninstall_branch = true; + } + + if (explore_uninstall_branch && _requiring_resItem) { + ResolverInfoPtr log_info; + uninstall_item = new QueueItemUninstall (world(),_requiring_resItem, "unsatisfied requirements"); + uninstall_item->setDependency (_dep); + + if (_lost_resItem) { + log_info = new ResolverInfoDependsOn (_requiring_resItem, _lost_resItem); + uninstall_item->addInfo (log_info); + } + + if (_remove_only) + uninstall_item->setRemoveOnly (); + } + + if (uninstall_item && branch_item) { + branch_item->addItem (uninstall_item); + new_items.push_front (branch_item); + } else if (uninstall_item) { + new_items.push_front (uninstall_item); + } else if (branch_item) { + new_items.push_front (branch_item); + } else { + // We can't do anything to resolve the missing requirement, so we fail. + string msg = string ("Can't satisfy requirement '") + _dep->asString() + "'"; + + context->addErrorString (NULL, msg); + } + + } else if (num_providers == 1) { + + if (getenv ("RC_SPEW")) fprintf (stderr, "Found exactly one resolvable, installing it.\n"); + + QueueItemInstallPtr install_item = new QueueItemInstall (world(), info.providers.front()); + install_item->addDependency (_dep); + + // The requiring resItem could be NULL if the requirement was added as an extra dependency. + if (_requiring_resItem) { + install_item->addNeededBy (_requiring_resItem); + } + new_items.push_front (install_item); + + } else if (num_providers > 1) { + + if (getenv ("RC_SPEW")) fprintf (stderr, "Found more than one resolvable, branching.\n"); + + //fprintf (stderr, "Found more than one resItem, branching.\n"); + QueueItemBranchPtr branch_item = new QueueItemBranch (world()); + + for (CResItemList::const_iterator iter = info.providers.begin(); iter != info.providers.end(); iter++) { + QueueItemInstallPtr install_item = new QueueItemInstall (world(), *iter); + install_item->addDependency (_dep); + branch_item->addItem (install_item); + + // The requiring resItem could be NULL if the requirement was added as an extra dependency. + if (_requiring_resItem) { + install_item->addNeededBy (_requiring_resItem); + } + } + + new_items.push_front (branch_item); + + } else { + abort (); + } + + + // rc_queue_item_free (item); + return true; + } + + //--------------------------------------------------------------------------- + + QueueItemPtr + QueueItemRequire::copy (void) const + { + QueueItemRequirePtr new_require = new QueueItemRequire (world(), _dep); + ((QueueItemPtr)new_require)->copy((constQueueItemPtr)this); + + new_require->_requiring_resItem = _requiring_resItem; + new_require->_upgraded_resItem = _upgraded_resItem; + new_require->_remove_only = _remove_only; + + return new_require; + } + + + int + QueueItemRequire::cmp (constQueueItemPtr item) const + { + int cmp = this->compare (item); // assures equal type + if (cmp != 0) + return cmp; + + constQueueItemRequirePtr require = item; + + cmp = GVersion.compare ((constSpecPtr) _dep, ((constSpecPtr)(require->dependency()))); + if (cmp) + return cmp; + + return CMP ((int) _dep->relation().op(), (int) (require->dependency()->relation().op())); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItemRequire.h b/zypp/solver/detail/QueueItemRequire.h index 198c86b..ef9f057 100644 --- a/zypp/solver/detail/QueueItemRequire.h +++ b/zypp/solver/detail/QueueItemRequire.h @@ -31,66 +31,75 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItemRequire - -class QueueItemRequire : public QueueItem { - REP_BODY(QueueItemRequire); - - private: - constDependencyPtr _dep; - constResItemPtr _requiring_resItem; - constResItemPtr _upgraded_resItem; - constResItemPtr _lost_resItem; - bool _remove_only; - bool _is_child; - - public: - - QueueItemRequire (WorldPtr world, constDependencyPtr dep); - virtual ~QueueItemRequire(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItemRequire & item); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItemRequire & item); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - constDependencyPtr dependency (void) const { return _dep; } - - void setRemoveOnly (void) { _remove_only = true; } - void setUpgradedResItem (constResItemPtr upgraded_resItem) { _upgraded_resItem = upgraded_resItem; } - void setLostResItem (constResItemPtr lost_resItem) { _lost_resItem = lost_resItem; } - - // ---------------------------------- methods - - virtual bool process (ResolverContextPtr context, QueueItemList & qil); - virtual QueueItemPtr copy (void) const; - virtual int cmp (constQueueItemPtr item) const; - virtual bool isRedundant (ResolverContextPtr context) const { return false; } - virtual bool isSatisfied (ResolverContextPtr context) const { return false; } - - void addResItem (constResItemPtr resItem); - - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItemRequire + + class QueueItemRequire : public QueueItem { + REP_BODY(QueueItemRequire); + + private: + constDependencyPtr _dep; + constResItemPtr _requiring_resItem; + constResItemPtr _upgraded_resItem; + constResItemPtr _lost_resItem; + bool _remove_only; + bool _is_child; + + public: + + QueueItemRequire (WorldPtr world, constDependencyPtr dep); + virtual ~QueueItemRequire(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItemRequire & item); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItemRequire & item); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + constDependencyPtr dependency (void) const { return _dep; } + + void setRemoveOnly (void) { _remove_only = true; } + void setUpgradedResItem (constResItemPtr upgraded_resItem) { _upgraded_resItem = upgraded_resItem; } + void setLostResItem (constResItemPtr lost_resItem) { _lost_resItem = lost_resItem; } + + // ---------------------------------- methods + + virtual bool process (ResolverContextPtr context, QueueItemList & qil); + virtual QueueItemPtr copy (void) const; + virtual int cmp (constQueueItemPtr item) const; + virtual bool isRedundant (ResolverContextPtr context) const { return false; } + virtual bool isSatisfied (ResolverContextPtr context) const { return false; } + + void addResItem (constResItemPtr resItem); + + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemRequire_h diff --git a/zypp/solver/detail/QueueItemRequirePtr.h b/zypp/solver/detail/QueueItemRequirePtr.h index 65d4bfe..a782ebf 100644 --- a/zypp/solver/detail/QueueItemRequirePtr.h +++ b/zypp/solver/detail/QueueItemRequirePtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemRequirePtr -// CLASS NAME : constQueueItemRequirePtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(QueueItemRequire,QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemRequirePtr + // CLASS NAME : constQueueItemRequirePtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(QueueItemRequire,QueueItem); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemRequirePtr_h diff --git a/zypp/solver/detail/QueueItemUninstall.cc b/zypp/solver/detail/QueueItemUninstall.cc index 26c36ba..6747f14 100644 --- a/zypp/solver/detail/QueueItemUninstall.cc +++ b/zypp/solver/detail/QueueItemUninstall.cc @@ -27,296 +27,308 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(QueueItemUninstall,QueueItem); - -//--------------------------------------------------------------------------- - -string -QueueItemUninstall::asString ( void ) const -{ - return toString (*this); -} - - -string -QueueItemUninstall::toString ( const QueueItemUninstall & item) -{ - string ret = "[Uninstall: "; - - ret += item._resItem->asString(); - ret += " ("; ret += item._reason; ret += ")"; - if (item._dep_leading_to_uninstall != NULL) { - ret += ", Triggered By "; - ret += item._dep_leading_to_uninstall->asString(); - } - if (item._upgraded_to != NULL) { - ret += ", Upgraded To "; - ret += item._upgraded_to->asString(); - } - if (item._explicitly_requested) ret += ", Explicit"; - if (item._remove_only) ret += ", Remove Only"; - if (item._due_to_conflict) ret += ", Due To Conflict"; - if (item._due_to_obsolete) ret += ", Due To Obsolete"; - if (item._unlink) ret += ", Unlink"; - ret += "]"; - - return ret; -} - - -ostream & -QueueItemUninstall::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const QueueItemUninstall & item) -{ - return os << item.asString(); -} - -//--------------------------------------------------------------------------- - -QueueItemUninstall::QueueItemUninstall (WorldPtr world, constResItemPtr resItem, const std::string & reason) - : QueueItem (QUEUE_ITEM_TYPE_UNINSTALL, world) - , _resItem (resItem) - , _reason (reason) - , _dep_leading_to_uninstall (NULL) - , _upgraded_to (NULL) - , _explicitly_requested (false) - , _remove_only (false) - , _due_to_conflict (false) - , _due_to_obsolete (false) - , _unlink (false) -{ -} - - -QueueItemUninstall::~QueueItemUninstall() -{ -} - -//--------------------------------------------------------------------------- - -void -QueueItemUninstall::setUnlink () -{ - _unlink = true; - /* Reduce the priority so that unlink items will tend to get - processed later. We want to process unlinks as late as possible... - this will make our "is this item in use" check more accurate. */ - setPriority (0); - - return; -} - -//--------------------------------------------------------------------------- - -typedef struct { - ResolverContextPtr context; - bool cancel_unlink; -} UnlinkCheckInfo; - - -static bool -unlink_check_cb (constResItemPtr resItem, constDependencyPtr dep, void *data) -{ - UnlinkCheckInfo *info = (UnlinkCheckInfo *)data; - - if (info->cancel_unlink) - return true; - - if (! info->context->resItemIsPresent (resItem)) - return true; - - if (info->context->requirementIsMet (dep, false)) - return true; - - info->cancel_unlink = true; - - return true; -} - -typedef struct { - WorldPtr world; - ResolverContextPtr context; - constResItemPtr uninstalled_resItem; - constResItemPtr upgraded_resItem; - QueueItemList *require_items; - bool remove_only; -} UninstallProcessInfo; - - -static bool -uninstall_process_cb (constResItemPtr resItem, constDependencyPtr dep, void *data) -{ - UninstallProcessInfo *info = (UninstallProcessInfo *)data; - - if (! info->context->resItemIsPresent (resItem)) - return true; - - if (info->context->requirementIsMet (dep, false)) - return true; - - QueueItemRequirePtr require_item = new QueueItemRequire (info->world, dep); - require_item->addResItem (resItem); - if (info->remove_only) { - require_item->setRemoveOnly (); - } - require_item->setUpgradedResItem (info->upgraded_resItem); - require_item->setLostResItem (info->uninstalled_resItem); - - info->require_items->push_front (require_item); - - return true; -} - - -bool -QueueItemUninstall::process (ResolverContextPtr context, QueueItemList & qil) -{ - ResItemStatus status; - string pkg_str; - - pkg_str = ((constSpecPtr)_resItem)->asString(); - - status = context->getStatus (_resItem); - - if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemUninstall::process(<%s>%s)%s\n", ResolverContext::toString(status).c_str(), _resItem->asString().c_str(), _unlink ? "[unlink]" : ""); - - /* In the case of an unlink, we only want to uninstall the resItem if it is - being used by something else. We can't really determine this with 100% - accuracy, since some later queue item could cause something that requires - the resItem to be uninstalled. The alternative is to try to do something - really clever... but I'm not clever enough to think of an algorithm that - (1) Would do the right thing. - (2) Is guaranteed to terminate. (!) - so this will have to do. In practice, I don't think that this is a serious - problem. */ - - if (_unlink) { - bool unlink_cancelled = false; - - /* If the resItem is to-be-installed, obviously it is being use! */ - if (status == RESOLVABLE_STATUS_TO_BE_INSTALLED) { - - unlink_cancelled = true; - - } else if (status == RESOLVABLE_STATUS_INSTALLED) { - UnlinkCheckInfo info; - - /* Flag the resItem as to-be-uninstalled so that it won't - satisfy any other resItem's deps during this check. */ - context->setStatus (_resItem, RESOLVABLE_STATUS_TO_BE_UNINSTALLED); - - info.context = context; - info.cancel_unlink = false; - - CDependencyList provides = _resItem->provides(); - for (CDependencyList::const_iterator iter = provides.begin(); iter != provides.end() && ! info.cancel_unlink; iter++) { - world()->foreachRequiringResItem (*iter, unlink_check_cb, &info); - } - - /* Set the status back to normal. */ - context->setStatus (_resItem, status); - - if (info.cancel_unlink) - unlink_cancelled = true; - } - - if (unlink_cancelled) { - string msg = pkg_str + " is required by other installed resolvable, so it won't be unlinked."; - context->addInfoString (_resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); - goto finished; - } - } - - context->uninstallResItem (_resItem, _upgraded_to != NULL, _due_to_obsolete, _unlink); - - if (status == RESOLVABLE_STATUS_INSTALLED) { - - if (! _explicitly_requested - && world()->resItemIsLocked (_resItem)) { - string msg = pkg_str + " is locked, and cannot be uninstalled."; - context->addErrorString (_resItem, msg); - goto finished; - } - - this->logInfo (context); - - if (_dep_leading_to_uninstall - && !_due_to_conflict - && !_due_to_obsolete) - { - ResolverInfoPtr info = new ResolverInfoMissingReq (_resItem, _dep_leading_to_uninstall); - context->addInfo (info); - } - - CDependencyList provides = _resItem->provides(); - for (CDependencyList::const_iterator iter = provides.begin(); iter != provides.end(); iter++) { - UninstallProcessInfo info; - - info.world = world(); - info.context = context; - info.uninstalled_resItem = _resItem; - info.upgraded_resItem = _upgraded_to; - info.require_items = &qil; - info.remove_only = _remove_only; - - world()->foreachRequiringResItem (*iter, uninstall_process_cb, &info); - } - } - - finished: -// FIXME rc_queue_item_free (item); - - return true; -} - -//--------------------------------------------------------------------------- - -int -QueueItemUninstall::cmp (constQueueItemPtr item) const -{ - int cmp = this->compare (item); // assures equal type - if (cmp != 0) - return cmp; - - constQueueItemUninstallPtr uninstall = item; - return GVersion.compare (_resItem, uninstall->_resItem); -} - - -QueueItemPtr -QueueItemUninstall::copy (void) const -{ - QueueItemUninstallPtr new_uninstall = new QueueItemUninstall (world(), _resItem, _reason); - ((QueueItemPtr)new_uninstall)->copy((constQueueItemPtr)this); - - - new_uninstall->_resItem = _resItem; - new_uninstall->_dep_leading_to_uninstall = _dep_leading_to_uninstall; - new_uninstall->_upgraded_to = _upgraded_to; - - new_uninstall->_explicitly_requested = _explicitly_requested; - new_uninstall->_remove_only = _remove_only; - new_uninstall->_due_to_conflict = _due_to_conflict; - new_uninstall->_due_to_obsolete = _due_to_obsolete; - new_uninstall->_unlink = _unlink; - - return new_uninstall; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(QueueItemUninstall,QueueItem); + + //--------------------------------------------------------------------------- + + string + QueueItemUninstall::asString ( void ) const + { + return toString (*this); + } + + + string + QueueItemUninstall::toString ( const QueueItemUninstall & item) + { + string ret = "[Uninstall: "; + + ret += item._resItem->asString(); + ret += " ("; ret += item._reason; ret += ")"; + if (item._dep_leading_to_uninstall != NULL) { + ret += ", Triggered By "; + ret += item._dep_leading_to_uninstall->asString(); + } + if (item._upgraded_to != NULL) { + ret += ", Upgraded To "; + ret += item._upgraded_to->asString(); + } + if (item._explicitly_requested) ret += ", Explicit"; + if (item._remove_only) ret += ", Remove Only"; + if (item._due_to_conflict) ret += ", Due To Conflict"; + if (item._due_to_obsolete) ret += ", Due To Obsolete"; + if (item._unlink) ret += ", Unlink"; + ret += "]"; + + return ret; + } + + + ostream & + QueueItemUninstall::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const QueueItemUninstall & item) + { + return os << item.asString(); + } + + //--------------------------------------------------------------------------- + + QueueItemUninstall::QueueItemUninstall (WorldPtr world, constResItemPtr resItem, const std::string & reason) + : QueueItem (QUEUE_ITEM_TYPE_UNINSTALL, world) + , _resItem (resItem) + , _reason (reason) + , _dep_leading_to_uninstall (NULL) + , _upgraded_to (NULL) + , _explicitly_requested (false) + , _remove_only (false) + , _due_to_conflict (false) + , _due_to_obsolete (false) + , _unlink (false) + { + } + + + QueueItemUninstall::~QueueItemUninstall() + { + } + + //--------------------------------------------------------------------------- + + void + QueueItemUninstall::setUnlink () + { + _unlink = true; + /* Reduce the priority so that unlink items will tend to get + processed later. We want to process unlinks as late as possible... + this will make our "is this item in use" check more accurate. */ + setPriority (0); + + return; + } + + //--------------------------------------------------------------------------- + + typedef struct { + ResolverContextPtr context; + bool cancel_unlink; + } UnlinkCheckInfo; + + + static bool + unlink_check_cb (constResItemPtr resItem, constDependencyPtr dep, void *data) + { + UnlinkCheckInfo *info = (UnlinkCheckInfo *)data; + + if (info->cancel_unlink) + return true; + + if (! info->context->resItemIsPresent (resItem)) + return true; + + if (info->context->requirementIsMet (dep, false)) + return true; + + info->cancel_unlink = true; + + return true; + } + + typedef struct { + WorldPtr world; + ResolverContextPtr context; + constResItemPtr uninstalled_resItem; + constResItemPtr upgraded_resItem; + QueueItemList *require_items; + bool remove_only; + } UninstallProcessInfo; + + + static bool + uninstall_process_cb (constResItemPtr resItem, constDependencyPtr dep, void *data) + { + UninstallProcessInfo *info = (UninstallProcessInfo *)data; + + if (! info->context->resItemIsPresent (resItem)) + return true; + + if (info->context->requirementIsMet (dep, false)) + return true; + + QueueItemRequirePtr require_item = new QueueItemRequire (info->world, dep); + require_item->addResItem (resItem); + if (info->remove_only) { + require_item->setRemoveOnly (); + } + require_item->setUpgradedResItem (info->upgraded_resItem); + require_item->setLostResItem (info->uninstalled_resItem); + + info->require_items->push_front (require_item); + + return true; + } + + + bool + QueueItemUninstall::process (ResolverContextPtr context, QueueItemList & qil) + { + ResItemStatus status; + string pkg_str; + + pkg_str = ((constSpecPtr)_resItem)->asString(); + + status = context->getStatus (_resItem); + + if (getenv ("RC_SPEW")) fprintf (stderr, "QueueItemUninstall::process(<%s>%s)%s\n", ResolverContext::toString(status).c_str(), _resItem->asString().c_str(), _unlink ? "[unlink]" : ""); + + /* In the case of an unlink, we only want to uninstall the resItem if it is + being used by something else. We can't really determine this with 100% + accuracy, since some later queue item could cause something that requires + the resItem to be uninstalled. The alternative is to try to do something + really clever... but I'm not clever enough to think of an algorithm that + (1) Would do the right thing. + (2) Is guaranteed to terminate. (!) + so this will have to do. In practice, I don't think that this is a serious + problem. */ + + if (_unlink) { + bool unlink_cancelled = false; + + /* If the resItem is to-be-installed, obviously it is being use! */ + if (status == RESOLVABLE_STATUS_TO_BE_INSTALLED) { + + unlink_cancelled = true; + + } else if (status == RESOLVABLE_STATUS_INSTALLED) { + UnlinkCheckInfo info; + + /* Flag the resItem as to-be-uninstalled so that it won't + satisfy any other resItem's deps during this check. */ + context->setStatus (_resItem, RESOLVABLE_STATUS_TO_BE_UNINSTALLED); + + info.context = context; + info.cancel_unlink = false; + + CDependencyList provides = _resItem->provides(); + for (CDependencyList::const_iterator iter = provides.begin(); iter != provides.end() && ! info.cancel_unlink; iter++) { + world()->foreachRequiringResItem (*iter, unlink_check_cb, &info); + } + + /* Set the status back to normal. */ + context->setStatus (_resItem, status); + + if (info.cancel_unlink) + unlink_cancelled = true; + } + + if (unlink_cancelled) { + string msg = pkg_str + " is required by other installed resolvable, so it won't be unlinked."; + context->addInfoString (_resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); + goto finished; + } + } + + context->uninstallResItem (_resItem, _upgraded_to != NULL, _due_to_obsolete, _unlink); + + if (status == RESOLVABLE_STATUS_INSTALLED) { + + if (! _explicitly_requested + && world()->resItemIsLocked (_resItem)) { + string msg = pkg_str + " is locked, and cannot be uninstalled."; + context->addErrorString (_resItem, msg); + goto finished; + } + + this->logInfo (context); + + if (_dep_leading_to_uninstall + && !_due_to_conflict + && !_due_to_obsolete) + { + ResolverInfoPtr info = new ResolverInfoMissingReq (_resItem, _dep_leading_to_uninstall); + context->addInfo (info); + } + + CDependencyList provides = _resItem->provides(); + for (CDependencyList::const_iterator iter = provides.begin(); iter != provides.end(); iter++) { + UninstallProcessInfo info; + + info.world = world(); + info.context = context; + info.uninstalled_resItem = _resItem; + info.upgraded_resItem = _upgraded_to; + info.require_items = &qil; + info.remove_only = _remove_only; + + world()->foreachRequiringResItem (*iter, uninstall_process_cb, &info); + } + } + + finished: + // FIXME rc_queue_item_free (item); + + return true; + } + + //--------------------------------------------------------------------------- + + int + QueueItemUninstall::cmp (constQueueItemPtr item) const + { + int cmp = this->compare (item); // assures equal type + if (cmp != 0) + return cmp; + + constQueueItemUninstallPtr uninstall = item; + return GVersion.compare (_resItem, uninstall->_resItem); + } + + + QueueItemPtr + QueueItemUninstall::copy (void) const + { + QueueItemUninstallPtr new_uninstall = new QueueItemUninstall (world(), _resItem, _reason); + ((QueueItemPtr)new_uninstall)->copy((constQueueItemPtr)this); + + + new_uninstall->_resItem = _resItem; + new_uninstall->_dep_leading_to_uninstall = _dep_leading_to_uninstall; + new_uninstall->_upgraded_to = _upgraded_to; + + new_uninstall->_explicitly_requested = _explicitly_requested; + new_uninstall->_remove_only = _remove_only; + new_uninstall->_due_to_conflict = _due_to_conflict; + new_uninstall->_due_to_obsolete = _due_to_obsolete; + new_uninstall->_unlink = _unlink; + + return new_uninstall; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/QueueItemUninstall.h b/zypp/solver/detail/QueueItemUninstall.h index c7baa82..730a343 100644 --- a/zypp/solver/detail/QueueItemUninstall.h +++ b/zypp/solver/detail/QueueItemUninstall.h @@ -31,70 +31,78 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : QueueItemUninstall - -class QueueItemUninstall : public QueueItem { - REP_BODY(QueueItemUninstall); - - private: - constResItemPtr _resItem; - const std::string _reason; - constDependencyPtr _dep_leading_to_uninstall; - constResItemPtr _upgraded_to; - - bool _explicitly_requested; - bool _remove_only; - bool _due_to_conflict; - bool _due_to_obsolete; - bool _unlink; - - public: - - QueueItemUninstall (WorldPtr world, constResItemPtr resItem, const std::string & reason); - virtual ~QueueItemUninstall(); - - // ---------------------------------- I/O - - static std::string toString (const QueueItemUninstall & item); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const QueueItemUninstall & item); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - void setDependency (constDependencyPtr dep) { _dep_leading_to_uninstall = dep; } - void setExplicitlyRequested (void) { _explicitly_requested = true; } - void setRemoveOnly (void) { _remove_only = true; } - void setUpgradedTo (constResItemPtr resItem) { _upgraded_to = resItem; } - void setDueToConflict (void) { _due_to_conflict = true; } - void setDueToObsolete (void) { _due_to_obsolete = true; } - void setUnlink (void); - - // ---------------------------------- methods - - virtual bool process (ResolverContextPtr context, QueueItemList & qil); - virtual QueueItemPtr copy (void) const; - virtual int cmp (constQueueItemPtr item) const; - virtual bool isRedundant (ResolverContextPtr context) const { return false; } - virtual bool isSatisfied (ResolverContextPtr context) const { return false; } - -}; - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : QueueItemUninstall + + class QueueItemUninstall : public QueueItem { + REP_BODY(QueueItemUninstall); + + private: + constResItemPtr _resItem; + const std::string _reason; + constDependencyPtr _dep_leading_to_uninstall; + constResItemPtr _upgraded_to; + + bool _explicitly_requested; + bool _remove_only; + bool _due_to_conflict; + bool _due_to_obsolete; + bool _unlink; + + public: + + QueueItemUninstall (WorldPtr world, constResItemPtr resItem, const std::string & reason); + virtual ~QueueItemUninstall(); + + // ---------------------------------- I/O + + static std::string toString (const QueueItemUninstall & item); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const QueueItemUninstall & item); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + void setDependency (constDependencyPtr dep) { _dep_leading_to_uninstall = dep; } + void setExplicitlyRequested (void) { _explicitly_requested = true; } + void setRemoveOnly (void) { _remove_only = true; } + void setUpgradedTo (constResItemPtr resItem) { _upgraded_to = resItem; } + void setDueToConflict (void) { _due_to_conflict = true; } + void setDueToObsolete (void) { _due_to_obsolete = true; } + void setUnlink (void); + + // ---------------------------------- methods + + virtual bool process (ResolverContextPtr context, QueueItemList & qil); + virtual QueueItemPtr copy (void) const; + virtual int cmp (constQueueItemPtr item) const; + virtual bool isRedundant (ResolverContextPtr context) const { return false; } + virtual bool isSatisfied (ResolverContextPtr context) const { return false; } + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemUninstall_h diff --git a/zypp/solver/detail/QueueItemUninstallPtr.h b/zypp/solver/detail/QueueItemUninstallPtr.h index 7037046..6d85049 100644 --- a/zypp/solver/detail/QueueItemUninstallPtr.h +++ b/zypp/solver/detail/QueueItemUninstallPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : QueueItemUninstallPtr -// CLASS NAME : constQueueItemUninstallPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(QueueItemUninstall,QueueItem); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : QueueItemUninstallPtr + // CLASS NAME : constQueueItemUninstallPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(QueueItemUninstall,QueueItem); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _QueueItemUninstallPtr_h diff --git a/zypp/solver/detail/ResItem.cc b/zypp/solver/detail/ResItem.cc index fdfd7fb..36a3bcb 100644 --- a/zypp/solver/detail/ResItem.cc +++ b/zypp/solver/detail/ResItem.cc @@ -24,136 +24,147 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - - -IMPL_DERIVED_POINTER(ResItem,Spec); - -//--------------------------------------------------------------------------- - -string -ResItem::asString ( bool full ) const -{ - return toString (*this, full); -} - - -string -ResItem::toString ( const ResItem & resItem, bool full ) -{ - string res; - - res += Spec::toString(resItem); - if (!resItem.channel()->system()) { - res += "["; - res += (resItem.channel() == NULL) ? "(channel?)" : resItem.channel()->name(); - res += "]"; - } - if (!full) return res; - - if (resItem.isInstalled()) res += ""; - if (resItem.local()) res += ""; - - res += "FileSize "; - res += stringutil::numstring (resItem.fileSize()); - res += ", InstalledSize "; - res += stringutil::numstring (resItem.installedSize()); - - if (!resItem.requires().empty()) { - res += ", Requires: "; - res += Dependency::toString(resItem.requires()); - } - - if (!resItem.provides().empty()) { - res += ", Provides: "; - res += Dependency::toString(resItem.provides()); - } - if (!resItem.conflicts().empty()) { - res += ", Conflicts: "; - res += Dependency::toString(resItem.conflicts()); - } - if (!resItem.obsoletes().empty()) { - res += ", Obsoletes: "; - res += Dependency::toString(resItem.obsoletes()); - } - - if (!resItem.suggests().empty()) { - res += ", Suggests: "; - res += Dependency::toString(resItem.suggests()); - } - if (!resItem.recommends().empty()) { - res += ", Recommends: "; - res += Dependency::toString(resItem.recommends()); - } - if (!resItem.freshens().empty()) { - res += ", Freshens: "; - res += Dependency::toString(resItem.freshens()); - } - return res; -} - - -string -ResItem::toString ( const CResItemList & rl, bool full ) -{ - string res("["); - for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { - if (iter != rl.begin()) res += ", "; - res += (*iter)->asString(full); - } - return res + "]"; -} - - -ostream & -ResItem::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResItem& edition) -{ - return os << edition.asString(); -} - -//--------------------------------------------------------------------------- - -ResItem::ResItem (const Kind & kind, const string & name, int epoch, const string & version, const string & release, const Arch * arch) - :Spec (kind, name, epoch, version, release, arch) - , _channel (false) - , _installed (false) - , _local (false) - , _locked (false) - , _file_size (0) - , _installed_size (0) - -{ -} - - -ResItem::~ResItem() -{ -} - -//--------------------------------------------------------------------------- - -bool -ResItem::isInstalled () const -{ - if (_channel != NULL - && _channel->system()) { - return true; - } - return false; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + + IMPL_DERIVED_POINTER(ResItem,Spec); + + //--------------------------------------------------------------------------- + + string + ResItem::asString ( bool full ) const + { + return toString (*this, full); + } + + + string + ResItem::toString ( const ResItem & resItem, bool full ) + { + string res; + + res += Spec::toString(resItem); + if (!resItem.channel()->system()) { + res += "["; + res += (resItem.channel() == NULL) ? "(channel?)" : resItem.channel()->name(); + res += "]"; + } + if (!full) return res; + + if (resItem.isInstalled()) res += ""; + if (resItem.local()) res += ""; + + res += "FileSize "; + res += stringutil::numstring (resItem.fileSize()); + res += ", InstalledSize "; + res += stringutil::numstring (resItem.installedSize()); + + if (!resItem.requires().empty()) { + res += ", Requires: "; + res += Dependency::toString(resItem.requires()); + } + + if (!resItem.provides().empty()) { + res += ", Provides: "; + res += Dependency::toString(resItem.provides()); + } + if (!resItem.conflicts().empty()) { + res += ", Conflicts: "; + res += Dependency::toString(resItem.conflicts()); + } + if (!resItem.obsoletes().empty()) { + res += ", Obsoletes: "; + res += Dependency::toString(resItem.obsoletes()); + } + + if (!resItem.suggests().empty()) { + res += ", Suggests: "; + res += Dependency::toString(resItem.suggests()); + } + if (!resItem.recommends().empty()) { + res += ", Recommends: "; + res += Dependency::toString(resItem.recommends()); + } + if (!resItem.freshens().empty()) { + res += ", Freshens: "; + res += Dependency::toString(resItem.freshens()); + } + return res; + } + + + string + ResItem::toString ( const CResItemList & rl, bool full ) + { + string res("["); + for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { + if (iter != rl.begin()) res += ", "; + res += (*iter)->asString(full); + } + return res + "]"; + } + + + ostream & + ResItem::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResItem& edition) + { + return os << edition.asString(); + } + + //--------------------------------------------------------------------------- + + ResItem::ResItem (const Kind & kind, const string & name, int epoch, const string & version, const string & release, const Arch * arch) + :Spec (kind, name, epoch, version, release, arch) + , _channel (false) + , _installed (false) + , _local (false) + , _locked (false) + , _file_size (0) + , _installed_size (0) + + { + } + + + ResItem::~ResItem() + { + } + + //--------------------------------------------------------------------------- + + bool + ResItem::isInstalled () const + { + if (_channel != NULL + && _channel->system()) { + return true; + } + return false; + } + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResItem.h b/zypp/solver/detail/ResItem.h index 4d32b9c..f9bccf9 100644 --- a/zypp/solver/detail/ResItem.h +++ b/zypp/solver/detail/ResItem.h @@ -30,121 +30,134 @@ #include #include #include - -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -typedef std::list ResItemList; -typedef std::list CResItemList; - -typedef bool (*ResItemFn) (ResItemPtr r, void *data); -typedef bool (*CResItemFn) (constResItemPtr r, void *data); -typedef bool (*ResItemPairFn) (constResItemPtr r1, constResItemPtr r2, void *data); -typedef bool (*ResItemAndSpecFn) (constResItemPtr r, constSpecPtr spec, void *data); -typedef bool (*ResItemAndDepFn) (constResItemPtr r, constDependencyPtr dep, void *data); - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResItem -/** - * - **/ - -class ResItem : public Spec { - REP_BODY(ResItem); - - private: - constChannelPtr _channel; - - bool _installed; - bool _local; - bool _locked; - - size_t _file_size; - size_t _installed_size; - - CDependencyList _requires; - CDependencyList _provides; - CDependencyList _conflicts; - CDependencyList _obsoletes; - - CDependencyList _suggests; - CDependencyList _recommends; - CDependencyList _freshens; - - protected: - - // ---------------------------------- accessors - - void setLocal (bool local) { _local = local; } - - public: - - ResItem(const Kind & kind, const std::string & name, int epoch = -1, const std::string & version = "", const std::string & release = "", const Arch * arch = Arch::Unknown); - - ResItem(const XmlNodePtr node); - - virtual ~ResItem(); - - // ---------------------------------- I/O - - const XmlNodePtr asXmlNode (void) const; - - static std::string toString ( const ResItem & res, bool full = false ); - - static std::string toString ( const CResItemList & reslist, bool full = false ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream & str, const ResItem & str); - - std::string asString ( bool full = false ) const; - - // ---------------------------------- accessors - - constChannelPtr channel() const { return _channel; } - void setChannel (constChannelPtr channel) { _channel = channel; } - - bool locked () const { return _locked; } - void setLocked (bool locked) { _locked = locked; } - - bool isInstalled() const; // does *not* reflect _installed - void setInstalled (bool installed) { _installed = installed; } - - bool local() const { return _local; } - - size_t fileSize() const { return _file_size; } - void setFileSize (size_t file_size) { _file_size = file_size; } - - size_t installedSize() const { return _installed_size; } - void setInstalledSize (size_t installed_size) { _installed_size = installed_size; } - - const CDependencyList & requires() const { return _requires; } - void setRequires (const CDependencyList & requires) { _requires = requires; } - - const CDependencyList & provides() const { return _provides; } - void setProvides (const CDependencyList & provides) { _provides = provides; } - - const CDependencyList & conflicts() const { return _conflicts; } - void setConflicts (const CDependencyList & conflicts) { _conflicts = conflicts; } - - const CDependencyList & obsoletes() const { return _obsoletes; } - void setObsoletes (const CDependencyList & obsoletes) { _obsoletes = obsoletes; } - - const CDependencyList & suggests() const { return _suggests; } - void setSuggests (const CDependencyList & suggests) { _suggests = suggests; } - - const CDependencyList & recommends() const { return _recommends; } - void setRecommends (const CDependencyList & recommends) { _recommends = recommends; } - - const CDependencyList & freshens() const { return _freshens; } - void setFreshens (const CDependencyList & freshens) { _freshens = freshens; } - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef std::list ResItemList; + typedef std::list CResItemList; + + typedef bool (*ResItemFn) (ResItemPtr r, void *data); + typedef bool (*CResItemFn) (constResItemPtr r, void *data); + typedef bool (*ResItemPairFn) (constResItemPtr r1, constResItemPtr r2, void *data); + typedef bool (*ResItemAndSpecFn) (constResItemPtr r, constSpecPtr spec, void *data); + typedef bool (*ResItemAndDepFn) (constResItemPtr r, constDependencyPtr dep, void *data); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResItem + /** + * + **/ + + class ResItem : public Spec { + REP_BODY(ResItem); + + private: + constChannelPtr _channel; + + bool _installed; + bool _local; + bool _locked; + + size_t _file_size; + size_t _installed_size; + + CDependencyList _requires; + CDependencyList _provides; + CDependencyList _conflicts; + CDependencyList _obsoletes; + + CDependencyList _suggests; + CDependencyList _recommends; + CDependencyList _freshens; + + protected: + + // ---------------------------------- accessors + + void setLocal (bool local) { _local = local; } + + public: + + ResItem(const Kind & kind, const std::string & name, int epoch = -1, const std::string & version = "", const std::string & release = "", const Arch * arch = Arch::Unknown); + + ResItem(const XmlNodePtr node); + + virtual ~ResItem(); + + // ---------------------------------- I/O + + const XmlNodePtr asXmlNode (void) const; + + static std::string toString ( const ResItem & res, bool full = false ); + + static std::string toString ( const CResItemList & reslist, bool full = false ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream & str, const ResItem & str); + + std::string asString ( bool full = false ) const; + + // ---------------------------------- accessors + + constChannelPtr channel() const { return _channel; } + void setChannel (constChannelPtr channel) { _channel = channel; } + + bool locked () const { return _locked; } + void setLocked (bool locked) { _locked = locked; } + + bool isInstalled() const; // does *not* reflect _installed + void setInstalled (bool installed) { _installed = installed; } + + bool local() const { return _local; } + + size_t fileSize() const { return _file_size; } + void setFileSize (size_t file_size) { _file_size = file_size; } + + size_t installedSize() const { return _installed_size; } + void setInstalledSize (size_t installed_size) { _installed_size = installed_size; } + + const CDependencyList & requires() const { return _requires; } + void setRequires (const CDependencyList & requires) { _requires = requires; } + + const CDependencyList & provides() const { return _provides; } + void setProvides (const CDependencyList & provides) { _provides = provides; } + + const CDependencyList & conflicts() const { return _conflicts; } + void setConflicts (const CDependencyList & conflicts) { _conflicts = conflicts; } + + const CDependencyList & obsoletes() const { return _obsoletes; } + void setObsoletes (const CDependencyList & obsoletes) { _obsoletes = obsoletes; } + + const CDependencyList & suggests() const { return _suggests; } + void setSuggests (const CDependencyList & suggests) { _suggests = suggests; } + + const CDependencyList & recommends() const { return _recommends; } + void setRecommends (const CDependencyList & recommends) { _recommends = recommends; } + + const CDependencyList & freshens() const { return _freshens; } + void setFreshens (const CDependencyList & freshens) { _freshens = freshens; } + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResItem_h diff --git a/zypp/solver/detail/ResItemAndDependency.cc b/zypp/solver/detail/ResItemAndDependency.cc index 1437970..25b1f96 100644 --- a/zypp/solver/detail/ResItemAndDependency.cc +++ b/zypp/solver/detail/ResItemAndDependency.cc @@ -26,78 +26,90 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(ResItemAndDependency); - -//--------------------------------------------------------------------------- - -ResItemAndDependency::ResItemAndDependency (constResItemPtr resItem, constDependencyPtr dependency) - : _resItem(resItem) - , _dependency(dependency) -{ -} - -//--------------------------------------------------------------------------- - -string -ResItemAndDependency::asString (bool full) const -{ - return toString (*this, full); -} - - -string -ResItemAndDependency::toString ( const ResItemAndDependency & r_and_d, bool full ) -{ - string res ("{"); - res += r_and_d._resItem->asString(full); - res += ", "; - res += r_and_d._dependency->asString(); - res += "}"; - return res; -} - - -ostream & -ResItemAndDependency::dumpOn (ostream & str) const -{ - str << asString(); - return str; -} - - -ostream & -operator<< (ostream & os, const ResItemAndDependency & r_and_d) -{ - return os << r_and_d.asString(); -} - -//--------------------------------------------------------------------------- - -/* This function also checks channels in addition to just dep relations */ -/* FIXME: rc_resItem_dep_verify_relation already checks the channel */ - -bool -ResItemAndDependency::verifyRelation (constDependencyPtr dep) const -{ -#if PHI - // don't check the channel, thereby honoring conflicts from installed resItems to to-be-installed resItems - return dep->verifyRelation (_dependency); -#else - if (!dep->verifyRelation (_dependency)) { - return false; - } - if (getenv ("SPEW_DEP")) fprintf (stderr, "ResItemAndDependency::verifyRelation _resItem->channel() %s, dep->channel() %s\n", _resItem->channel()->asString().c_str(), dep->channel()->asString().c_str()); - return _resItem->channel()->equals (dep->channel()); -#endif -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(ResItemAndDependency); + + //--------------------------------------------------------------------------- + + ResItemAndDependency::ResItemAndDependency (constResItemPtr resItem, constDependencyPtr dependency) + : _resItem(resItem) + , _dependency(dependency) + { + } + + //--------------------------------------------------------------------------- + + string + ResItemAndDependency::asString (bool full) const + { + return toString (*this, full); + } + + + string + ResItemAndDependency::toString ( const ResItemAndDependency & r_and_d, bool full ) + { + string res ("{"); + res += r_and_d._resItem->asString(full); + res += ", "; + res += r_and_d._dependency->asString(); + res += "}"; + return res; + } + + + ostream & + ResItemAndDependency::dumpOn (ostream & str) const + { + str << asString(); + return str; + } + + + ostream & + operator<< (ostream & os, const ResItemAndDependency & r_and_d) + { + return os << r_and_d.asString(); + } + + //--------------------------------------------------------------------------- + + /* This function also checks channels in addition to just dep relations */ + /* FIXME: rc_resItem_dep_verify_relation already checks the channel */ + + bool + ResItemAndDependency::verifyRelation (constDependencyPtr dep) const + { + #if PHI + // don't check the channel, thereby honoring conflicts from installed resItems to to-be-installed resItems + return dep->verifyRelation (_dependency); + #else + if (!dep->verifyRelation (_dependency)) { + return false; + } + if (getenv ("SPEW_DEP")) fprintf (stderr, "ResItemAndDependency::verifyRelation _resItem->channel() %s, dep->channel() %s\n", _resItem->channel()->asString().c_str(), dep->channel()->asString().c_str()); + return _resItem->channel()->equals (dep->channel()); + #endif + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResItemAndDependency.h b/zypp/solver/detail/ResItemAndDependency.h index a532d09..690e316 100644 --- a/zypp/solver/detail/ResItemAndDependency.h +++ b/zypp/solver/detail/ResItemAndDependency.h @@ -31,55 +31,67 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// typedef std::multimap ResItemTable; -typedef std::multimap ResItemAndDependencyTable; - -#if PHI -typedef std::list CResItemAndDependencyList; -#endif - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResItemAndDependency - -class ResItemAndDependency: public CountedRep { - REP_BODY(ResItemAndDependency); - - private: - constResItemPtr _resItem; - constDependencyPtr _dependency; - - public: - - ResItemAndDependency (constResItemPtr resItem, constDependencyPtr dependency); - ~ResItemAndDependency () {} - - // ---------------------------------- I/O - - static std::string toString (const ResItemAndDependency & r_and_d, bool full = false); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const ResItemAndDependency & r_and_d); - - std::string asString (bool full = false) const; - - // ---------------------------------- accessors - - constResItemPtr resItem() const { return _resItem; } - constDependencyPtr dependency() const { return _dependency; } - - // ---------------------------------- methods - - bool verifyRelation (constDependencyPtr dep) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + typedef std::multimap ResItemAndDependencyTable; + + #if PHI + typedef std::list CResItemAndDependencyList; + #endif + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResItemAndDependency + + class ResItemAndDependency: public CountedRep { + REP_BODY(ResItemAndDependency); + + private: + constResItemPtr _resItem; + constDependencyPtr _dependency; + + public: + + ResItemAndDependency (constResItemPtr resItem, constDependencyPtr dependency); + ~ResItemAndDependency () {} + + // ---------------------------------- I/O + + static std::string toString (const ResItemAndDependency & r_and_d, bool full = false); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const ResItemAndDependency & r_and_d); + + std::string asString (bool full = false) const; + + // ---------------------------------- accessors + + constResItemPtr resItem() const { return _resItem; } + constDependencyPtr dependency() const { return _dependency; } + + // ---------------------------------- methods + + bool verifyRelation (constDependencyPtr dep) const; + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResItemAndDependency_h diff --git a/zypp/solver/detail/ResItemAndDependencyPtr.h b/zypp/solver/detail/ResItemAndDependencyPtr.h index f325340..61ba26e 100644 --- a/zypp/solver/detail/ResItemAndDependencyPtr.h +++ b/zypp/solver/detail/ResItemAndDependencyPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResItemAndDependencyPtr -// CLASS NAME : constResItemAndDependencyPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(ResItemAndDependency); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResItemAndDependencyPtr + // CLASS NAME : constResItemAndDependencyPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(ResItemAndDependency); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResItemAndDependencyPtr_h diff --git a/zypp/solver/detail/ResItemPtr.h b/zypp/solver/detail/ResItemPtr.h index a6490d1..f4bb47a 100644 --- a/zypp/solver/detail/ResItemPtr.h +++ b/zypp/solver/detail/ResItemPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResItemPtr -// CLASS NAME : constResItemPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResItem,Spec); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResItemPtr + // CLASS NAME : constResItemPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResItem,Spec); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResItemPtr_h diff --git a/zypp/solver/detail/Resolver.cc b/zypp/solver/detail/Resolver.cc index 4af6ea9..28a80c3 100644 --- a/zypp/solver/detail/Resolver.cc +++ b/zypp/solver/detail/Resolver.cc @@ -28,380 +28,392 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Resolver); - -//--------------------------------------------------------------------------- - -string -Resolver::asString ( void ) const -{ - return toString (*this); -} - - -string -Resolver::toString ( const Resolver & resolver ) -{ - return ""; -} - - -ostream & -Resolver::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Resolver & resolver) -{ - return os << resolver.asString(); -} - -//--------------------------------------------------------------------------- - -Resolver::Resolver (WorldPtr world) - : _current_channel (NULL) - , _world (world) - , _timeout_seconds (0) - , _verifying (false) - , _valid_solution_count (0) - , _best_context (NULL) - , _timed_out (false) -{ -} - - -Resolver::~Resolver() -{ -} - -//--------------------------------------------------------------------------- - -WorldPtr -Resolver::world (void) const -{ - if (_world == NULL) - return World::globalWorld(); - - return _world; -} - -//--------------------------------------------------------------------------- - -void -Resolver::addSubscribedChannel (constChannelPtr channel) -{ - fprintf (stderr, "Resolver::addSubscribedChannel() not implemented\n"); -} - -void -Resolver::addResItemToInstall (constResItemPtr resItem) -{ - _resItems_to_install.push_front (resItem); -} - -void -Resolver::addResItemsToInstallFromList (CResItemList & rl) -{ - for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { - addResItemToInstall (*iter); - } -} - -void -Resolver::addResItemToRemove (constResItemPtr resItem) -{ - _resItems_to_remove.push_front (resItem); -} - -void -Resolver::addResItemsToRemoveFromList (CResItemList & rl) -{ - for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { - addResItemToRemove (*iter); - } -} - -void -Resolver::addResItemToVerify (constResItemPtr resItem) -{ - _resItems_to_verify.push_front (resItem); - _resItems_to_verify.sort (); //(GCompareFunc) rc_resItem_compare_name); -} - -void -Resolver::addExtraDependency (constDependencyPtr dependency) -{ - _extra_deps.push_front (dependency); -} - -void -Resolver::addExtraConflict (constDependencyPtr dependency) -{ - _extra_conflicts.push_front (dependency); -} - - -//--------------------------------------------------------------------------- - -static bool -verify_system_cb (constResItemPtr resItem, void *data) -{ - Resolver *resolver = (Resolver *)data; - - resolver->addResItemToVerify (resItem); - - return true; -} - - -void -Resolver::verifySystem (void) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "Resolver::verifySystem()\n"); - world()->foreachResItem (new Channel(CHANNEL_TYPE_SYSTEM), verify_system_cb, this); - - _verifying = true; - -#if 0 // commented out in libredcarpet also - /* - Walk across the (sorted-by-name) list of installed packages and look for - packages with the same name. If they exist, construct a branch item - containing multiple group items. Each group item corresponds to removing - all but one of the duplicates. - */ - - for (CResItemList::const_iterator i0 = _resItems_to_verify.begin(); i0 != _resItems_to_verify.end();) { - CResItemList::const_iterator i1 = i0; - i1++; - CResItemList::const_iterator i2 = i1; - for (; i1 != _resItems_to_verify.end()&& ! (*i0)->compareName (*i1); i1++) { - //empty - } - - if (i1 != i2) { - QueueItemBranchPtr branch_item; - - branch_item = new QueueItemBranch(world()); - - for (CResItemList::const_iterator i = i0; i != i1; i++) { - - QueueItemGroupPtr grp_item = new QueueItemGroup(world()); - - for (CResItemList::const_iterator j = i0; j != i1; j++) { - constPackagePtr dup_pkg = *j; - QueueItemUninstallPtr uninstall_item; - - if (i != j) { - uninstall_item = new QueueItemUninstall (world(), dup_pkg, "duplicate install"); - grp_item->addItem (uninstall_item); - } - - } - - branch_item->adddIitem (grp_item); - } - - _initial_items.push_back (branch_item); - } - - i0 = i1; - } -#endif - - /* OK, that was fun. Now just resolve the dependencies. */ - resolveDependencies (); - - return; -} - - -//--------------------------------------------------------------------------- - - -void -Resolver::resolveDependencies (void) -{ - - time_t t_start, t_now; - bool extremely_noisy = getenv ("RC_SPEW") != NULL; - bool have_local_resItems = false; - - if (extremely_noisy) fprintf (stderr, "Resolver::resolveDependencies()\n"); - - /* Walk through are list of to-be-installed packages and see if any of them are local. */ - - for (CResItemList::const_iterator iter = _resItems_to_install.begin(); iter != _resItems_to_install.end(); iter++) { - if ((*iter)->local()) { - have_local_resItems = true; - break; - } - } - - WorldPtr the_world = world(); - StoreWorldPtr local_world = NULL; - MultiWorldPtr local_multiworld = NULL; - - ChannelPtr local_channel = NULL; - - if (have_local_resItems) { - local_multiworld = new MultiWorld(); - local_world = new StoreWorld(); - - local_channel = new Channel ("", "Local ResItems", "@local", ""); - - local_world->addChannel (local_channel); - - local_multiworld->addSubworld (local_world); - local_multiworld->addSubworld (the_world); - - the_world = local_multiworld; - } - - // create initial_queue - - ResolverQueuePtr initial_queue = new ResolverQueue(); - - /* Stick the current/subscribed channel and world info into the context */ - - initial_queue->context()->setWorld(the_world); - - initial_queue->context()->setCurrentChannel (_current_channel); - - /* If this is a verify, we do a "soft resolution" */ - - initial_queue->context()->setVerifying (_verifying); - - /* Add extra items. */ - - for (QueueItemList::const_iterator iter = _initial_items.begin(); iter != _initial_items.end(); iter++) { - initial_queue->addItem (*iter); - } - _initial_items.clear(); - - for (CResItemList::const_iterator iter = _resItems_to_install.begin(); iter != _resItems_to_install.end(); iter++) { - constResItemPtr r = *iter; - - /* Add local packages to our dummy channel. */ - if (r->local()) { - assert (local_channel != NULL); - ResItemPtr r1 = ResItemPtr::cast_away_const (r); - r1->setChannel (local_channel); - local_world->addResItem (r); - } - - initial_queue->addResItemToInstall (r); - } - - for (CResItemList::const_iterator iter = _resItems_to_remove.begin(); iter != _resItems_to_remove.end(); iter++) { - initial_queue->addResItemToRemove (*iter, true /* remove-only mode */); - } - - for (CResItemList::const_iterator iter = _resItems_to_verify.begin(); iter != _resItems_to_verify.end(); iter++) { - initial_queue->addResItemToVerify (*iter); - } - - for (CDependencyList::const_iterator iter = _extra_deps.begin(); iter != _extra_deps.end(); iter++) { - initial_queue->addExtraDependency (*iter); - } - - for (CDependencyList::const_iterator iter = _extra_conflicts.begin(); iter != _extra_conflicts.end(); iter++) { - initial_queue->addExtraConflict (*iter); - } - - if (extremely_noisy) fprintf (stderr, "Initial Queue: [%s]\n", initial_queue->asString().c_str()); - - _pending_queues.push_front (initial_queue); - - time (&t_start); - - while (!_pending_queues.empty()) { - - if (extremely_noisy) { - printf ("Pend %ld / Cmpl %ld / Prun %ld / Defr %ld / Invl %ld\n\n", (long) _pending_queues.size(), (long) _complete_queues.size(), (long) _pruned_queues.size(), (long) _deferred_queues.size(), (long) _invalid_queues.size()); - } - - if (_timeout_seconds > 0) { - time (&t_now); - if (difftime (t_now, t_start) > _timeout_seconds) { - _timed_out = true; - break; - } - } - - ResolverQueuePtr queue = _pending_queues.front(); - _pending_queues.pop_front(); - ResolverContextPtr context = queue->context(); - - queue->process(); - - if (queue->isInvalid ()) { - if (extremely_noisy) printf ("Invalid Queue\n"); - _invalid_queues.push_front (queue); - - } else if (queue->isEmpty ()) { - if (extremely_noisy) printf ("Empty Queue\n"); - - _complete_queues.push_front (queue); - - ++_valid_solution_count; - - /* Compare this solution to our previous favorite. In the case of a tie, - the first solution wins --- yeah, I know this is lame, but it shouldn't - be an issue too much of the time. */ - - if (_best_context == NULL - || _best_context->compare (context) < 0) { - - _best_context = context; - } - - } else if (_best_context != NULL - && _best_context->partialCompare (context) > 0) { - - /* If we aren't currently as good as our previous best complete solution, - this solution gets pruned. */ - - if (extremely_noisy) printf ("PRUNED!\n"); - - _pruned_queues.push_front(queue); - - } else { - - /* If our queue is isn't empty and isn't invalid, that can only mean - one thing: we are down to nothing but branches. */ - - queue->splitFirstBranch (_pending_queues, _deferred_queues); - } - - /* If we have run out of pending queues w/o finding any solutions, - and if we have deferred queues, make the first deferred queue - pending. */ - - if (_pending_queues.empty() - && _complete_queues.empty() - && !_deferred_queues.empty()) { - _pending_queues.push_front (_deferred_queues.front()); - } - } - - if (extremely_noisy) { - printf ("Pend %ld / Cmpl %ld / Prun %ld / Defr %ld / Invl %ld\n--------\n", (long) _pending_queues.size(), (long) _complete_queues.size(), (long) _pruned_queues.size(), (long) _deferred_queues.size(), (long) _invalid_queues.size()); - } - - return; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Resolver); + + //--------------------------------------------------------------------------- + + string + Resolver::asString ( void ) const + { + return toString (*this); + } + + + string + Resolver::toString ( const Resolver & resolver ) + { + return ""; + } + + + ostream & + Resolver::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Resolver & resolver) + { + return os << resolver.asString(); + } + + //--------------------------------------------------------------------------- + + Resolver::Resolver (WorldPtr world) + : _current_channel (NULL) + , _world (world) + , _timeout_seconds (0) + , _verifying (false) + , _valid_solution_count (0) + , _best_context (NULL) + , _timed_out (false) + { + } + + + Resolver::~Resolver() + { + } + + //--------------------------------------------------------------------------- + + WorldPtr + Resolver::world (void) const + { + if (_world == NULL) + return World::globalWorld(); + + return _world; + } + + //--------------------------------------------------------------------------- + + void + Resolver::addSubscribedChannel (constChannelPtr channel) + { + fprintf (stderr, "Resolver::addSubscribedChannel() not implemented\n"); + } + + void + Resolver::addResItemToInstall (constResItemPtr resItem) + { + _resItems_to_install.push_front (resItem); + } + + void + Resolver::addResItemsToInstallFromList (CResItemList & rl) + { + for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { + addResItemToInstall (*iter); + } + } + + void + Resolver::addResItemToRemove (constResItemPtr resItem) + { + _resItems_to_remove.push_front (resItem); + } + + void + Resolver::addResItemsToRemoveFromList (CResItemList & rl) + { + for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { + addResItemToRemove (*iter); + } + } + + void + Resolver::addResItemToVerify (constResItemPtr resItem) + { + _resItems_to_verify.push_front (resItem); + _resItems_to_verify.sort (); //(GCompareFunc) rc_resItem_compare_name); + } + + void + Resolver::addExtraDependency (constDependencyPtr dependency) + { + _extra_deps.push_front (dependency); + } + + void + Resolver::addExtraConflict (constDependencyPtr dependency) + { + _extra_conflicts.push_front (dependency); + } + + + //--------------------------------------------------------------------------- + + static bool + verify_system_cb (constResItemPtr resItem, void *data) + { + Resolver *resolver = (Resolver *)data; + + resolver->addResItemToVerify (resItem); + + return true; + } + + + void + Resolver::verifySystem (void) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "Resolver::verifySystem()\n"); + world()->foreachResItem (new Channel(CHANNEL_TYPE_SYSTEM), verify_system_cb, this); + + _verifying = true; + + #if 0 // commented out in libredcarpet also + /* + Walk across the (sorted-by-name) list of installed packages and look for + packages with the same name. If they exist, construct a branch item + containing multiple group items. Each group item corresponds to removing + all but one of the duplicates. + */ + + for (CResItemList::const_iterator i0 = _resItems_to_verify.begin(); i0 != _resItems_to_verify.end();) { + CResItemList::const_iterator i1 = i0; + i1++; + CResItemList::const_iterator i2 = i1; + for (; i1 != _resItems_to_verify.end()&& ! (*i0)->compareName (*i1); i1++) { + //empty + } + + if (i1 != i2) { + QueueItemBranchPtr branch_item; + + branch_item = new QueueItemBranch(world()); + + for (CResItemList::const_iterator i = i0; i != i1; i++) { + + QueueItemGroupPtr grp_item = new QueueItemGroup(world()); + + for (CResItemList::const_iterator j = i0; j != i1; j++) { + constPackagePtr dup_pkg = *j; + QueueItemUninstallPtr uninstall_item; + + if (i != j) { + uninstall_item = new QueueItemUninstall (world(), dup_pkg, "duplicate install"); + grp_item->addItem (uninstall_item); + } + + } + + branch_item->adddIitem (grp_item); + } + + _initial_items.push_back (branch_item); + } + + i0 = i1; + } + #endif + + /* OK, that was fun. Now just resolve the dependencies. */ + resolveDependencies (); + + return; + } + + + //--------------------------------------------------------------------------- + + + void + Resolver::resolveDependencies (void) + { + + time_t t_start, t_now; + bool extremely_noisy = getenv ("RC_SPEW") != NULL; + bool have_local_resItems = false; + + if (extremely_noisy) fprintf (stderr, "Resolver::resolveDependencies()\n"); + + /* Walk through are list of to-be-installed packages and see if any of them are local. */ + + for (CResItemList::const_iterator iter = _resItems_to_install.begin(); iter != _resItems_to_install.end(); iter++) { + if ((*iter)->local()) { + have_local_resItems = true; + break; + } + } + + WorldPtr the_world = world(); + StoreWorldPtr local_world = NULL; + MultiWorldPtr local_multiworld = NULL; + + ChannelPtr local_channel = NULL; + + if (have_local_resItems) { + local_multiworld = new MultiWorld(); + local_world = new StoreWorld(); + + local_channel = new Channel ("", "Local ResItems", "@local", ""); + + local_world->addChannel (local_channel); + + local_multiworld->addSubworld (local_world); + local_multiworld->addSubworld (the_world); + + the_world = local_multiworld; + } + + // create initial_queue + + ResolverQueuePtr initial_queue = new ResolverQueue(); + + /* Stick the current/subscribed channel and world info into the context */ + + initial_queue->context()->setWorld(the_world); + + initial_queue->context()->setCurrentChannel (_current_channel); + + /* If this is a verify, we do a "soft resolution" */ + + initial_queue->context()->setVerifying (_verifying); + + /* Add extra items. */ + + for (QueueItemList::const_iterator iter = _initial_items.begin(); iter != _initial_items.end(); iter++) { + initial_queue->addItem (*iter); + } + _initial_items.clear(); + + for (CResItemList::const_iterator iter = _resItems_to_install.begin(); iter != _resItems_to_install.end(); iter++) { + constResItemPtr r = *iter; + + /* Add local packages to our dummy channel. */ + if (r->local()) { + assert (local_channel != NULL); + ResItemPtr r1 = ResItemPtr::cast_away_const (r); + r1->setChannel (local_channel); + local_world->addResItem (r); + } + + initial_queue->addResItemToInstall (r); + } + + for (CResItemList::const_iterator iter = _resItems_to_remove.begin(); iter != _resItems_to_remove.end(); iter++) { + initial_queue->addResItemToRemove (*iter, true /* remove-only mode */); + } + + for (CResItemList::const_iterator iter = _resItems_to_verify.begin(); iter != _resItems_to_verify.end(); iter++) { + initial_queue->addResItemToVerify (*iter); + } + + for (CDependencyList::const_iterator iter = _extra_deps.begin(); iter != _extra_deps.end(); iter++) { + initial_queue->addExtraDependency (*iter); + } + + for (CDependencyList::const_iterator iter = _extra_conflicts.begin(); iter != _extra_conflicts.end(); iter++) { + initial_queue->addExtraConflict (*iter); + } + + if (extremely_noisy) fprintf (stderr, "Initial Queue: [%s]\n", initial_queue->asString().c_str()); + + _pending_queues.push_front (initial_queue); + + time (&t_start); + + while (!_pending_queues.empty()) { + + if (extremely_noisy) { + printf ("Pend %ld / Cmpl %ld / Prun %ld / Defr %ld / Invl %ld\n\n", (long) _pending_queues.size(), (long) _complete_queues.size(), (long) _pruned_queues.size(), (long) _deferred_queues.size(), (long) _invalid_queues.size()); + } + + if (_timeout_seconds > 0) { + time (&t_now); + if (difftime (t_now, t_start) > _timeout_seconds) { + _timed_out = true; + break; + } + } + + ResolverQueuePtr queue = _pending_queues.front(); + _pending_queues.pop_front(); + ResolverContextPtr context = queue->context(); + + queue->process(); + + if (queue->isInvalid ()) { + if (extremely_noisy) printf ("Invalid Queue\n"); + _invalid_queues.push_front (queue); + + } else if (queue->isEmpty ()) { + if (extremely_noisy) printf ("Empty Queue\n"); + + _complete_queues.push_front (queue); + + ++_valid_solution_count; + + /* Compare this solution to our previous favorite. In the case of a tie, + the first solution wins --- yeah, I know this is lame, but it shouldn't + be an issue too much of the time. */ + + if (_best_context == NULL + || _best_context->compare (context) < 0) { + + _best_context = context; + } + + } else if (_best_context != NULL + && _best_context->partialCompare (context) > 0) { + + /* If we aren't currently as good as our previous best complete solution, + this solution gets pruned. */ + + if (extremely_noisy) printf ("PRUNED!\n"); + + _pruned_queues.push_front(queue); + + } else { + + /* If our queue is isn't empty and isn't invalid, that can only mean + one thing: we are down to nothing but branches. */ + + queue->splitFirstBranch (_pending_queues, _deferred_queues); + } + + /* If we have run out of pending queues w/o finding any solutions, + and if we have deferred queues, make the first deferred queue + pending. */ + + if (_pending_queues.empty() + && _complete_queues.empty() + && !_deferred_queues.empty()) { + _pending_queues.push_front (_deferred_queues.front()); + } + } + + if (extremely_noisy) { + printf ("Pend %ld / Cmpl %ld / Prun %ld / Defr %ld / Invl %ld\n--------\n", (long) _pending_queues.size(), (long) _complete_queues.size(), (long) _pruned_queues.size(), (long) _deferred_queues.size(), (long) _invalid_queues.size()); + } + + return; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Resolver.h b/zypp/solver/detail/Resolver.h index e1be283..9e9c84e 100644 --- a/zypp/solver/detail/Resolver.h +++ b/zypp/solver/detail/Resolver.h @@ -32,101 +32,111 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - - -////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// // // CLASS NAME : Resolver -class Resolver : public CountedRep { - REP_BODY(Resolver); - - private: - constChannelPtr _current_channel; - - WorldPtr _world; - - int _timeout_seconds; - bool _verifying; - - QueueItemList _initial_items; - CResItemList _resItems_to_install; - CResItemList _resItems_to_remove; - CResItemList _resItems_to_verify; - - CDependencyList _extra_deps; - CDependencyList _extra_conflicts; - - ResolverQueueList _pending_queues; - ResolverQueueList _pruned_queues; - ResolverQueueList _complete_queues; - ResolverQueueList _deferred_queues; - ResolverQueueList _invalid_queues; - - int _valid_solution_count; - - ResolverContextPtr _best_context; - bool _timed_out; - - public: - - Resolver (WorldPtr world = NULL); - virtual ~Resolver(); - - // ---------------------------------- I/O - - static std::string toString (const Resolver & resolver); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const Resolver & resolver); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - QueueItemList initialItems () const { return _initial_items; } - - ResolverQueueList pendingQueues () const { return _pending_queues; } - ResolverQueueList prunedQueues () const { return _pruned_queues; } - ResolverQueueList completeQueues () const { return _complete_queues; } - ResolverQueueList deferredQueues () const { return _deferred_queues; } - ResolverQueueList invalidQueues () const { return _invalid_queues; } - - ResolverContextPtr bestContext (void) const { return _best_context; } - - // ---------------------------------- methods - - void setTimeout (int seconds) { _timeout_seconds = seconds; } - - WorldPtr world (void) const; // returns global world if _world == NULL - void setWorld (WorldPtr world) { _world = world; } - - void setCurrentChannel (constChannelPtr channel) { _current_channel = channel; } - void addSubscribedChannel (constChannelPtr channel); - - void addResItemToInstall (constResItemPtr resItem); - void addResItemsToInstallFromList (CResItemList & rl); - - void addResItemToRemove (constResItemPtr resItem); - void addResItemsToRemoveFromList (CResItemList & rl); - - void addResItemToVerify (constResItemPtr resItem); - - void addExtraDependency (constDependencyPtr dependency); - void addExtraConflict (constDependencyPtr dependency); - - void verifySystem (void); - void resolveDependencies (void); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + class Resolver : public CountedRep { + REP_BODY(Resolver); + + private: + constChannelPtr _current_channel; + + WorldPtr _world; + + int _timeout_seconds; + bool _verifying; + + QueueItemList _initial_items; + CResItemList _resItems_to_install; + CResItemList _resItems_to_remove; + CResItemList _resItems_to_verify; + + CDependencyList _extra_deps; + CDependencyList _extra_conflicts; + + ResolverQueueList _pending_queues; + ResolverQueueList _pruned_queues; + ResolverQueueList _complete_queues; + ResolverQueueList _deferred_queues; + ResolverQueueList _invalid_queues; + + int _valid_solution_count; + + ResolverContextPtr _best_context; + bool _timed_out; + + public: + + Resolver (WorldPtr world = NULL); + virtual ~Resolver(); + + // ---------------------------------- I/O + + static std::string toString (const Resolver & resolver); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const Resolver & resolver); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + QueueItemList initialItems () const { return _initial_items; } + + ResolverQueueList pendingQueues () const { return _pending_queues; } + ResolverQueueList prunedQueues () const { return _pruned_queues; } + ResolverQueueList completeQueues () const { return _complete_queues; } + ResolverQueueList deferredQueues () const { return _deferred_queues; } + ResolverQueueList invalidQueues () const { return _invalid_queues; } + + ResolverContextPtr bestContext (void) const { return _best_context; } + + // ---------------------------------- methods + + void setTimeout (int seconds) { _timeout_seconds = seconds; } + + WorldPtr world (void) const; // returns global world if _world == NULL + void setWorld (WorldPtr world) { _world = world; } + + void setCurrentChannel (constChannelPtr channel) { _current_channel = channel; } + void addSubscribedChannel (constChannelPtr channel); + + void addResItemToInstall (constResItemPtr resItem); + void addResItemsToInstallFromList (CResItemList & rl); + + void addResItemToRemove (constResItemPtr resItem); + void addResItemsToRemoveFromList (CResItemList & rl); + + void addResItemToVerify (constResItemPtr resItem); + + void addExtraDependency (constDependencyPtr dependency); + void addExtraConflict (constDependencyPtr dependency); + + void verifySystem (void); + void resolveDependencies (void); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Resolver_h diff --git a/zypp/solver/detail/ResolverContext.cc b/zypp/solver/detail/ResolverContext.cc index dbe9200..10f7d51 100644 --- a/zypp/solver/detail/ResolverContext.cc +++ b/zypp/solver/detail/ResolverContext.cc @@ -27,1108 +27,1119 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(ResolverContext); - -//--------------------------------------------------------------------------- - -string -ResolverContext::toString (const ResItemStatus & status) -{ - string ret; - switch (status) { - case RESOLVABLE_STATUS_UNKNOWN: ret = "unknown"; break; - case RESOLVABLE_STATUS_INSTALLED: ret = "installed"; break; - case RESOLVABLE_STATUS_UNINSTALLED: ret = "uninstalled"; break; - case RESOLVABLE_STATUS_TO_BE_INSTALLED: ret = "to be installed"; break; - case RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT: ret = "to be installed (soft)"; break; - case RESOLVABLE_STATUS_TO_BE_UNINSTALLED: ret = "to be uninstalled"; break; - case RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE: ret = "to be uninstalled due to obsolete"; break; - case RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK: ret = "to be uninstalled due to unlink"; break; - default: ret = "Huh ?"; break; - } - - return ret; -} - -//--------------------------------------------------------------------------- - -string -ResolverContext::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverContext::toString ( const ResolverContext & context ) -{ - string ret; - if (context._parent != NULL) { - ret += "Parent: ["; - ret += stringutil::form("<@%p> ", (const void *)(context._parent)); - ret += context._parent->asString(); - ret += "],\n\t"; - } - ret += stringutil::form ("Download Size: %lld", context._download_size); - ret += stringutil::form (", Install Size: %lld", context._install_size); - ret += stringutil::form (", Total Priority: %d", context._total_priority); - ret += stringutil::form (", Min Priority: %d", context._min_priority); - ret += stringutil::form (", Max Priority: %d", context._max_priority); - ret += stringutil::form (", Other Penalties: %d", context._other_penalties); - if (context._current_channel != 0) { - ret += ", Current Channel"; - ret += context._current_channel->asString(); - } - if (context._verifying) ret += ", Verifying"; - if (context._invalid) ret += ", Invalid"; - - return ret; -} - - -ostream & -ResolverContext::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverContext & ResolverContext) -{ - return os << ResolverContext.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverContext::ResolverContext (ResolverContextPtr parent) - : _parent (parent) - , _refs (0) - , _world (NULL) - , _last_checked_resItem (NULL) - , _last_checked_status (RESOLVABLE_STATUS_UNKNOWN) - , _download_size (0) - , _install_size (0) - , _total_priority (0) - , _min_priority (0) - , _max_priority (0) - , _other_penalties (0) - , _current_channel (NULL) - , _verifying (false) - , _invalid (false) -{ - if (parent != NULL) { - _world = parent->_world; - _download_size = parent->_download_size; - _install_size = parent->_install_size; - _total_priority = parent->_total_priority; - _max_priority = parent->_max_priority; - _min_priority = parent->_min_priority; - _other_penalties = parent->_other_penalties; - _verifying = parent->_verifying; - } else { - _min_priority = MAXINT; - } -} - - -ResolverContext::~ResolverContext() -{ -} - -//--------------------------------------------------------------------------- - -WorldPtr -ResolverContext::world (void) const -{ - if (_world == NULL) { - return World::globalWorld(); - } - return _world; -} - - -void -ResolverContext::setStatus (constResItemPtr resItem, ResItemStatus status) -{ - if (_invalid) return; - - ResItemStatus old_status = getStatus (resItem); - - if (status != old_status) { - _status[resItem] = status; - } - - // Update our cache if we changed the status of the last checked resItem. - - if (_last_checked_resItem == resItem) - _last_checked_status = status; -} - - -ResItemStatus -ResolverContext::getStatus (constResItemPtr resItem) -{ - ResItemStatus status = RESOLVABLE_STATUS_UNKNOWN; - - // We often end up getting the status of the same resItem several times - // in a row. By caching the status of the last checked resItem, we can - // in practice eliminate the need for any hash table lookups in about - // 50% of our calls to get_status. - - if (resItem == _last_checked_resItem) - { - return _last_checked_status; - } - - ResolverContextPtr context = this; - - while (status == RESOLVABLE_STATUS_UNKNOWN - && context != NULL) { - StatusTable::const_iterator pos = context->_status.find (resItem); - if (pos != context->_status.end()) { - status = (*pos).second; - } - context = context->_parent; - } - - if (status == RESOLVABLE_STATUS_UNKNOWN) { - status = resItem->isInstalled() ? RESOLVABLE_STATUS_INSTALLED : RESOLVABLE_STATUS_UNINSTALLED; - } - - _last_checked_resItem = resItem; - _last_checked_status = status; - - return status; -} - - -bool -ResolverContext::installResItem (constResItemPtr resItem, bool is_soft, int other_penalty) -{ - ResItemStatus status, new_status; - int priority; - std::string msg; - - status = getStatus (resItem); - if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::installResItem(<%s>%s)\n", this, ResolverContext::toString(status).c_str(), resItem->asString().c_str()); - - if (resItem_status_is_to_be_uninstalled (status) - && status != RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { - msg = string ("Can't install ") + ((constSpecPtr)resItem)->asString() + " since it is already marked as needing to be uninstalled"; - - addErrorString (resItem, msg); - return false; - } - - if (resItem_status_is_to_be_installed (status)) { - return true; - } - - if (isParallelInstall (resItem)) { - msg = string ("Can't install ") + ((constSpecPtr)resItem)->asString() + ", since a resolvable of the same name is already marked as needing to be installed"; - addErrorString (resItem, msg); - return false; - } - - if (is_soft) - new_status = RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT; - else if (status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) - new_status = RESOLVABLE_STATUS_INSTALLED; - else - new_status = RESOLVABLE_STATUS_TO_BE_INSTALLED; - - setStatus (resItem, new_status); - - if (status == RESOLVABLE_STATUS_UNINSTALLED) { - /* FIXME: Incomplete */ - _download_size += resItem->fileSize(); - _install_size += resItem->installedSize(); - - if (resItem->local()) - priority = 0; - else { - priority = getChannelPriority (resItem->channel ()); - } - - if (priority < _min_priority) _min_priority = priority; - if (priority > _max_priority) _max_priority = priority; - - _other_penalties += other_penalty; - - } - - return true; -} - - -bool -ResolverContext::upgradeResItem (constResItemPtr resItem, constResItemPtr old_resItem, bool is_soft, int other_penalty) -{ - ResItemStatus status; - int priority; - - if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::upgradeResItem(%s upgrades %s)\n", this, resItem->asString().c_str(), old_resItem->asString().c_str()); - - status = getStatus (resItem); - - if (resItem_status_is_to_be_uninstalled (status)) - return false; - - if (resItem_status_is_to_be_installed (status)) - return true; - - setStatus (resItem, is_soft ? RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT : RESOLVABLE_STATUS_TO_BE_INSTALLED); - - if (status == RESOLVABLE_STATUS_UNINSTALLED) { +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(ResolverContext); + + //--------------------------------------------------------------------------- + + string + ResolverContext::toString (const ResItemStatus & status) + { + string ret; + switch (status) { + case RESOLVABLE_STATUS_UNKNOWN: ret = "unknown"; break; + case RESOLVABLE_STATUS_INSTALLED: ret = "installed"; break; + case RESOLVABLE_STATUS_UNINSTALLED: ret = "uninstalled"; break; + case RESOLVABLE_STATUS_TO_BE_INSTALLED: ret = "to be installed"; break; + case RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT: ret = "to be installed (soft)"; break; + case RESOLVABLE_STATUS_TO_BE_UNINSTALLED: ret = "to be uninstalled"; break; + case RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE: ret = "to be uninstalled due to obsolete"; break; + case RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK: ret = "to be uninstalled due to unlink"; break; + default: ret = "Huh ?"; break; + } + + return ret; + } + + //--------------------------------------------------------------------------- + + string + ResolverContext::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverContext::toString ( const ResolverContext & context ) + { + string ret; + if (context._parent != NULL) { + ret += "Parent: ["; + ret += stringutil::form("<@%p> ", (const void *)(context._parent)); + ret += context._parent->asString(); + ret += "],\n\t"; + } + ret += stringutil::form ("Download Size: %lld", context._download_size); + ret += stringutil::form (", Install Size: %lld", context._install_size); + ret += stringutil::form (", Total Priority: %d", context._total_priority); + ret += stringutil::form (", Min Priority: %d", context._min_priority); + ret += stringutil::form (", Max Priority: %d", context._max_priority); + ret += stringutil::form (", Other Penalties: %d", context._other_penalties); + if (context._current_channel != 0) { + ret += ", Current Channel"; + ret += context._current_channel->asString(); + } + if (context._verifying) ret += ", Verifying"; + if (context._invalid) ret += ", Invalid"; + + return ret; + } + + + ostream & + ResolverContext::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverContext & ResolverContext) + { + return os << ResolverContext.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverContext::ResolverContext (ResolverContextPtr parent) + : _parent (parent) + , _refs (0) + , _world (NULL) + , _last_checked_resItem (NULL) + , _last_checked_status (RESOLVABLE_STATUS_UNKNOWN) + , _download_size (0) + , _install_size (0) + , _total_priority (0) + , _min_priority (0) + , _max_priority (0) + , _other_penalties (0) + , _current_channel (NULL) + , _verifying (false) + , _invalid (false) + { + if (parent != NULL) { + _world = parent->_world; + _download_size = parent->_download_size; + _install_size = parent->_install_size; + _total_priority = parent->_total_priority; + _max_priority = parent->_max_priority; + _min_priority = parent->_min_priority; + _other_penalties = parent->_other_penalties; + _verifying = parent->_verifying; + } else { + _min_priority = MAXINT; + } + } + + + ResolverContext::~ResolverContext() + { + } + + //--------------------------------------------------------------------------- + + WorldPtr + ResolverContext::world (void) const + { + if (_world == NULL) { + return World::globalWorld(); + } + return _world; + } + + + void + ResolverContext::setStatus (constResItemPtr resItem, ResItemStatus status) + { + if (_invalid) return; + + ResItemStatus old_status = getStatus (resItem); + + if (status != old_status) { + _status[resItem] = status; + } + + // Update our cache if we changed the status of the last checked resItem. + + if (_last_checked_resItem == resItem) + _last_checked_status = status; + } + + + ResItemStatus + ResolverContext::getStatus (constResItemPtr resItem) + { + ResItemStatus status = RESOLVABLE_STATUS_UNKNOWN; + + // We often end up getting the status of the same resItem several times + // in a row. By caching the status of the last checked resItem, we can + // in practice eliminate the need for any hash table lookups in about + // 50% of our calls to get_status. + + if (resItem == _last_checked_resItem) + { + return _last_checked_status; + } + + ResolverContextPtr context = this; + + while (status == RESOLVABLE_STATUS_UNKNOWN + && context != NULL) { + StatusTable::const_iterator pos = context->_status.find (resItem); + if (pos != context->_status.end()) { + status = (*pos).second; + } + context = context->_parent; + } + + if (status == RESOLVABLE_STATUS_UNKNOWN) { + status = resItem->isInstalled() ? RESOLVABLE_STATUS_INSTALLED : RESOLVABLE_STATUS_UNINSTALLED; + } + + _last_checked_resItem = resItem; + _last_checked_status = status; + + return status; + } + + + bool + ResolverContext::installResItem (constResItemPtr resItem, bool is_soft, int other_penalty) + { + ResItemStatus status, new_status; + int priority; + std::string msg; + + status = getStatus (resItem); + if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::installResItem(<%s>%s)\n", this, ResolverContext::toString(status).c_str(), resItem->asString().c_str()); + + if (resItem_status_is_to_be_uninstalled (status) + && status != RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { + msg = string ("Can't install ") + ((constSpecPtr)resItem)->asString() + " since it is already marked as needing to be uninstalled"; + + addErrorString (resItem, msg); + return false; + } + + if (resItem_status_is_to_be_installed (status)) { + return true; + } + + if (isParallelInstall (resItem)) { + msg = string ("Can't install ") + ((constSpecPtr)resItem)->asString() + ", since a resolvable of the same name is already marked as needing to be installed"; + addErrorString (resItem, msg); + return false; + } + + if (is_soft) + new_status = RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT; + else if (status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) + new_status = RESOLVABLE_STATUS_INSTALLED; + else + new_status = RESOLVABLE_STATUS_TO_BE_INSTALLED; + + setStatus (resItem, new_status); + + if (status == RESOLVABLE_STATUS_UNINSTALLED) { + /* FIXME: Incomplete */ + _download_size += resItem->fileSize(); + _install_size += resItem->installedSize(); + + if (resItem->local()) + priority = 0; + else { + priority = getChannelPriority (resItem->channel ()); + } + + if (priority < _min_priority) _min_priority = priority; + if (priority > _max_priority) _max_priority = priority; + + _other_penalties += other_penalty; + + } + + return true; + } + + + bool + ResolverContext::upgradeResItem (constResItemPtr resItem, constResItemPtr old_resItem, bool is_soft, int other_penalty) + { + ResItemStatus status; + int priority; + + if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::upgradeResItem(%s upgrades %s)\n", this, resItem->asString().c_str(), old_resItem->asString().c_str()); + + status = getStatus (resItem); + + if (resItem_status_is_to_be_uninstalled (status)) + return false; + + if (resItem_status_is_to_be_installed (status)) + return true; + + setStatus (resItem, is_soft ? RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT : RESOLVABLE_STATUS_TO_BE_INSTALLED); + + if (status == RESOLVABLE_STATUS_UNINSTALLED) { + + _download_size += resItem->fileSize(); + + // FIXME: Incomplete + // We should change installed_size to reflect the difference in + // installed size between the old and new versions. + + if (resItem->local()) + priority = 0; + else { + priority = getChannelPriority (resItem->channel()); + } + + if (priority < _min_priority) _min_priority = priority; + if (priority > _max_priority) _max_priority = priority; + + _other_penalties += other_penalty; + } + + return true; + } + + + bool + ResolverContext::uninstallResItem (constResItemPtr resItem, bool part_of_upgrade, bool due_to_obsolete, bool due_to_unlink) + { + ResItemStatus status, new_status; + std::string msg; + + if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::uninstallResItem(%s %s %s %s)\n", this, resItem->asString().c_str(), part_of_upgrade ? "part_of_upgrade" : "", due_to_obsolete ? "due_to_obsolete": "", due_to_unlink ? "due_to_unlink" : ""); + + assert (! (due_to_obsolete && due_to_unlink)); + + status = getStatus (resItem); + + if (status == RESOLVABLE_STATUS_TO_BE_INSTALLED) { + msg = ((constSpecPtr)resItem)->asString() + " is scheduled to be installed, but this is not possible because of dependency problems."; + addErrorString (resItem, msg); + return false; + } + + if (resItem_status_is_to_be_uninstalled (status) + && status != RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { + return true; + } + + if (status == RESOLVABLE_STATUS_UNINSTALLED + || status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { + msg = string ("Marking resolvable ") + ((constSpecPtr)resItem)->asString() + " as uninstallable"; + addInfoString (resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); + } + + + if (due_to_obsolete) new_status = RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE; + else if (due_to_unlink) new_status = RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK; + else new_status = RESOLVABLE_STATUS_TO_BE_UNINSTALLED; + + setStatus (resItem, new_status); + + if (status == RESOLVABLE_STATUS_INSTALLED) { + /* FIXME: incomplete */ + } + + return true; + } + + + bool + ResolverContext::resItemIsPresent (constResItemPtr resItem) + { + ResItemStatus status; + + status = getStatus (resItem); + //fprintf (stderr, "ResolverContext::resItemIsPresent(<%s>%s)\n", ResolverContext::toString(status).c_str(), resItem->asString().c_str()); + if (status == RESOLVABLE_STATUS_UNKNOWN) + return false; + + return (status == RESOLVABLE_STATUS_INSTALLED) || resItem_status_is_to_be_installed (status); + } + + + bool + ResolverContext::resItemIsAbsent (constResItemPtr resItem) + { + ResItemStatus status; + + status = getStatus (resItem); + if (status == RESOLVABLE_STATUS_UNKNOWN) + return false; + + return status == RESOLVABLE_STATUS_UNINSTALLED || resItem_status_is_to_be_uninstalled (status); + } + + + //--------------------------------------------------------------------------- + // marked + + void + ResolverContext::foreachMarkedResItem (MarkedResItemFn fn, void *data) const + { + constResolverContextPtr context = this; + while (context) { + for (StatusTable::const_iterator iter = context->_status.begin(); iter != context->_status.end(); iter++) { + fn (iter->first, iter->second, data); + } + context = context->_parent; + } + } + + + //--------------------------------------------------------------------------- + // collect + + static void + marked_resItem_collector (constResItemPtr resItem, ResItemStatus status, void *data) + { + CResItemList *rl = (CResItemList *)data; + rl->push_back (resItem); + } + + + CResItemList + ResolverContext::getMarkedResItems (void) const + { + CResItemList rl; + + foreachMarkedResItem (marked_resItem_collector, &rl); + + return rl; + } + + //--------------------------------------------------------------------------- + // install + + typedef struct { + WorldPtr world; + MarkedResItemFn fn; + CResItemList *rl; + int count; + } InstallInfo; + + static void + install_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *data) + { + InstallInfo *info = (InstallInfo *)data; + if (resItem_status_is_to_be_installed (status) + && ! resItem->isInstalled () + && info->world->findInstalledResItem (resItem) == NULL) { + + if (info->fn) info->fn (resItem, status, info->rl); + ++info->count; + } + } + + + int + ResolverContext::foreachInstall (MarkedResItemFn fn, void *data) const + { + CResItemList *rl = (CResItemList *)data; + InstallInfo info = { world(), fn, rl, 0 }; + + foreachMarkedResItem (install_pkg_cb, (void *)&info); + + return info.count; + } + + + static void + context_resItem_collector (constResItemPtr resItem, ResItemStatus status, void *data) + { + CResItemList *rl = (CResItemList *)data; + if (resItem_status_is_to_be_installed (status) + || (resItem_status_is_to_be_uninstalled (status) && resItem->isInstalled ())) { + rl->push_front (resItem); + } + } + + + CResItemList + ResolverContext::getInstalls (void) const + { + CResItemList rl; + + foreachInstall (context_resItem_collector, (void *)&rl); + + return rl; + } + + + //--------------------------------------------------------------------------- + // upgrade + + typedef struct { + WorldPtr world; + MarkedResItemPairFn fn; + void *data; + ResolverContextPtr context; + int count; + } UpgradeInfo; + + static void + upgrade_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *data) + { + UpgradeInfo *info = (UpgradeInfo *)data; + + constResItemPtr to_be_upgraded; + ResItemStatus tbu_status; + + if (resItem_status_is_to_be_installed (status) + && ! resItem->isInstalled ()) { + + to_be_upgraded = info->world->findInstalledResItem (resItem); + if (to_be_upgraded) { + tbu_status = info->context->getStatus (to_be_upgraded); + if (info->fn) { + info->fn (resItem, status, to_be_upgraded, tbu_status, info->data); + } + ++info->count; + } + } + } + + + int + ResolverContext::foreachUpgrade (MarkedResItemPairFn fn, void *data) + { + UpgradeInfo info = { world(), fn, data, this, 0 }; + + foreachMarkedResItem (upgrade_pkg_cb, (void *)&info); + + return info.count; + } + + + static void + pair_resItem_collector (constResItemPtr resItem, ResItemStatus status, constResItemPtr old, ResItemStatus old_status, void *data) + { + CResItemList *rl = (CResItemList *)data; + rl->push_back (resItem); + } + + + CResItemList + ResolverContext::getUpgrades (void) + { + CResItemList rl; + + foreachUpgrade (pair_resItem_collector, (void *)&rl); + + return rl; + } + + + //--------------------------------------------------------------------------- + // uninstall + + typedef std::map UpgradeTable; + + typedef struct { + MarkedResItemFn fn; + CResItemList *rl; + UpgradeTable upgrade_hash; + int count; + } UninstallInfo; + + static void + uninstall_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *data) + { + UninstallInfo *info = (UninstallInfo *)data; + + UpgradeTable::const_iterator pos = info->upgrade_hash.find(resItem->name()); + + if (resItem_status_is_to_be_uninstalled (status) + && pos == info->upgrade_hash.end()) { + if (info->fn) + info->fn (resItem, status, info->rl); + ++info->count; + } + } + + static void + build_upgrade_hash_cb (constResItemPtr resItem_add, ResItemStatus status_add, constResItemPtr resItem_del, ResItemStatus status_del, void *data) + { + UpgradeTable *upgrade_hash = (UpgradeTable *)data; + (*upgrade_hash)[resItem_del->name()] = resItem_del; + } + + + int + ResolverContext::foreachUninstall (MarkedResItemFn fn, void *data) + { + UninstallInfo info; // inits upgrade_hash + + info.fn = fn; + info.rl = (CResItemList *)data; + info.count = 0; + + foreachUpgrade (build_upgrade_hash_cb, (void *)&(info.upgrade_hash)); + foreachMarkedResItem (uninstall_pkg_cb, (void *)&info); + + return info.count; + } + + + CResItemList + ResolverContext::getUninstalls (void) + { + CResItemList rl; + + foreachUninstall (context_resItem_collector, (void *)&rl); + + return rl; + } + + + //--------------------------------------------------------------------------- + + static void + install_count_cb (constResItemPtr resItem, ResItemStatus status, void *data) + { + int *count = (int *)data; + if (! resItem->isInstalled ()) { + ++*count; + } + } + + int + ResolverContext::installCount (void) const + { + int count = 0; + + foreachInstall (install_count_cb, (void *)&count); + + return count; + } + + + static void + uninstall_count_cb (constResItemPtr resItem, ResItemStatus status, void *data) + { + int *count = (int *)data; + if (resItem->isInstalled ()) { + ++*count; + } + } + + + int + ResolverContext::uninstallCount (void) + { + int count = 0; + + foreachUninstall (uninstall_count_cb, (void *)&count); + + return count; + } + + + int + ResolverContext::upgradeCount (void) + { + return foreachUpgrade ((MarkedResItemPairFn)NULL, (void *)NULL); + } + + + //--------------------------------------------------------------------------- + // info + + void + ResolverContext::addInfo (ResolverInfoPtr info) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::addInfo(%s)\n", this, info->asString().c_str()); + _log.push_back (info); + + // _propagated_importance = false; + + if (info->error ()) { + + if (! _invalid) { + ResolverInfoPtr info = new ResolverInfoMisc (NULL, RESOLVER_INFO_PRIORITY_VERBOSE, "Marking this resolution attempt as invalid."); + info->flagAsError (); + _log.push_back (info); + } + + _invalid = true; + } + } + + + void + ResolverContext::addInfoString (constResItemPtr resItem, int priority, string msg) + { + // if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext::addInfoString(%s) %s\n", resItem ? resItem->asString().c_str() : "", msg.c_str()); + ResolverInfoPtr info = new ResolverInfoMisc (resItem, priority, msg); + addInfo (info); + } + + + void + ResolverContext::addErrorString (constResItemPtr resItem, string msg) + { + ResolverInfoPtr info = new ResolverInfoMisc (resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); + info->flagAsError (); + addInfo (info); + } + + + //--------------------------------------------------------------------------- + // foreach info + + // We call a resItem mentioned by an error info an "error-resItem". + // We call a resItem mentioned by an important info an "important-resItem". + // + // The rules: + // (1) An info item that mentions an error-resItem is important. + // (2) An info item is about an important-resItem is important. + + static void + mark_important_info (InfoList & il) + { + CResItemList error_list; // FIXME, a map is faster + + bool did_something; + int pass_num = 1; + + /* First of all, store all error-resItems in a list. */ + + for (InfoList::iterator iter = il.begin(); iter != il.end(); iter++) { + if ((*iter) != NULL // list items might be set to NULL + && (*iter)->error ()) { + constResItemPtr resItem = (*iter)->resItem(); + if (resItem != NULL) { + CResItemList::iterator pos; + for (pos = error_list.begin(); pos != error_list.end(); pos++) { + if (*pos == resItem) + break; + } + if (pos == error_list.end()) { + error_list.push_front (resItem); + } + } + + CResItemList resItems; + + constResolverInfoContainerPtr c = *iter; // check if it really is a container + if (c != NULL) resItems = c->resItems(); + + for (CResItemList::iterator res_iter = resItems.begin(); res_iter != resItems.end(); res_iter++) { + CResItemList::iterator pos; + for (pos = error_list.begin(); pos != error_list.end(); pos++) { + if (*pos == *iter) + break; + } + if (pos == error_list.end()) { + error_list.push_front (*res_iter); + } + } + } + } + + CResItemList important_list; // FIXME, hash is faster + + do { + ++pass_num; + assert (pass_num < 10000); + + did_something = false; + + for (InfoList::iterator iter = il.begin(); iter != il.end(); iter++) { + if ((*iter) != NULL // list items might be set to NULL + && (*iter)->important ()) { + bool should_be_important = false; + + for (CResItemList::const_iterator res_iter = error_list.begin(); res_iter != error_list.end() && ! should_be_important; res_iter++) { + constResolverInfoContainerPtr c = *iter; + if (c != NULL // check if it really is a container + && c->mentions (*res_iter)) { + should_be_important = true; + } + } + + for (CResItemList::const_iterator res_iter = important_list.begin(); res_iter != important_list.end() && ! should_be_important; res_iter++) { + if ((*iter)->isAbout (*res_iter)) { + should_be_important = true; + break; + } + } + + if (should_be_important) { + did_something = true; + (*iter)->flagAsImportant (); + CResItemList resItems; + constResolverInfoContainerPtr c = *iter; // check if it really is a container + if (c != NULL) resItems = c->resItems(); + for (CResItemList::iterator res_iter = resItems.begin(); res_iter != resItems.end(); res_iter++) { + CResItemList::iterator pos; + for (pos = important_list.begin(); pos != important_list.end(); pos++) { + if (*pos == *res_iter) + break; + } + if (pos == important_list.end()) { + important_list.push_front (*res_iter); + } + } + } + } + } + + } while (did_something); + + } + + + void + ResolverContext::foreachInfo (ResItemPtr resItem, int priority, ResolverInfoFn fn, void *data) + { + InfoList info_list; + + ResolverContextPtr context = this; + + + // Assemble a list of copies of all of the info objects + while (context != NULL) { + for (InfoList::iterator iter = context->_log.begin(); iter != context->_log.end(); iter++) { + if ((resItem == NULL || (*iter)->resItem() == resItem) + && (*iter)->priority() >= priority) { + info_list.push_back ((*iter)->copy()); + } + } + context = context->_parent; + } + #if 0 + // Merge info objects + for (InfoList::iterator iter = info_list.begin(); iter != info_list.end(); iter++) { + + ResolverInfoPtr info1 = (*iter); + InfoList::iterator subiter = iter; + if (info1 != NULL) { + for (subiter++; subiter != info_list.end(); subiter++) { + ResolverInfoPtr info2 = *subiter; + if (info2 && info1->merge (info2)) { + *subiter = NULL; + } + } + } + } + #endif + mark_important_info (info_list); + + // Walk across the list of info objects and invoke our callback + + for (InfoList::iterator iter = info_list.begin(); iter != info_list.end(); iter++) { + if (*iter != NULL) { + fn (*iter, data); + } + } + } + + + + static void + get_info_foreach_cb (ResolverInfoPtr info, void *data) + { + InfoList *il = (InfoList *)data; + + if (info->important ()) { + il->push_back (info); + } + } + + + + InfoList + ResolverContext::getInfo (void) + { + InfoList il; + foreachInfo (NULL, -1, get_info_foreach_cb, (void *)&il); + return il; + } + + + //--------------------------------------------------------------------------- + // spew + + static void + spew_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *unused) + { + printf (" %s (%s)\n", resItem->asString().c_str(), ResolverContext::toString(status).c_str()); + } + + + void + spew_pkg2_cb (constResItemPtr resItem1, ResItemStatus status1, constResItemPtr resItem2, ResItemStatus status2, void *unused) + { + const char *s1, *s2; + + s1 = resItem1->asString().c_str(); + s2 = resItem2->asString().c_str(); + + printf (" %s (%s) => %s (%s)\n", s2, ResolverContext::toString(status2).c_str(), s1, ResolverContext::toString(status1).c_str()); + } + + + void + ResolverContext::spew (void) + { + printf ("TO INSTALL:\n"); + foreachInstall (spew_pkg_cb, NULL); + printf ("\n"); + + printf ("TO REMOVE:\n"); + foreachUninstall (spew_pkg_cb, NULL); + printf ("\n"); + + printf ("TO UPGRADE:\n"); + foreachUpgrade (spew_pkg2_cb, NULL); + printf ("\n"); + } + + + static void + spew_info_cb (ResolverInfoPtr info, void *unused) + { + const char *msg = info->asString().c_str(); + if (info->error ()) printf ("[ERROR] "); + else if (info->important()) printf ("[>>>>>] "); + printf ("%s\n", msg); + } + + + void + ResolverContext::spewInfo (void) + { + if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::spewInfo()\n", this); + foreachInfo (NULL, -1, spew_info_cb, NULL); + } + + //--------------------------------------------------------------------------- + // requirements - _download_size += resItem->fileSize(); - - // FIXME: Incomplete - // We should change installed_size to reflect the difference in - // installed size between the old and new versions. - - if (resItem->local()) - priority = 0; - else { - priority = getChannelPriority (resItem->channel()); - } - - if (priority < _min_priority) _min_priority = priority; - if (priority > _max_priority) _max_priority = priority; - - _other_penalties += other_penalty; - } - - return true; -} - - -bool -ResolverContext::uninstallResItem (constResItemPtr resItem, bool part_of_upgrade, bool due_to_obsolete, bool due_to_unlink) -{ - ResItemStatus status, new_status; - std::string msg; - - if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::uninstallResItem(%s %s %s %s)\n", this, resItem->asString().c_str(), part_of_upgrade ? "part_of_upgrade" : "", due_to_obsolete ? "due_to_obsolete": "", due_to_unlink ? "due_to_unlink" : ""); - - assert (! (due_to_obsolete && due_to_unlink)); - - status = getStatus (resItem); - - if (status == RESOLVABLE_STATUS_TO_BE_INSTALLED) { - msg = ((constSpecPtr)resItem)->asString() + " is scheduled to be installed, but this is not possible because of dependency problems."; - addErrorString (resItem, msg); - return false; - } - - if (resItem_status_is_to_be_uninstalled (status) - && status != RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { - return true; - } - - if (status == RESOLVABLE_STATUS_UNINSTALLED - || status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { - msg = string ("Marking resolvable ") + ((constSpecPtr)resItem)->asString() + " as uninstallable"; - addInfoString (resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); - } - - - if (due_to_obsolete) new_status = RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE; - else if (due_to_unlink) new_status = RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK; - else new_status = RESOLVABLE_STATUS_TO_BE_UNINSTALLED; - - setStatus (resItem, new_status); - - if (status == RESOLVABLE_STATUS_INSTALLED) { - /* FIXME: incomplete */ - } - - return true; -} - - -bool -ResolverContext::resItemIsPresent (constResItemPtr resItem) -{ - ResItemStatus status; - - status = getStatus (resItem); -//fprintf (stderr, "ResolverContext::resItemIsPresent(<%s>%s)\n", ResolverContext::toString(status).c_str(), resItem->asString().c_str()); - if (status == RESOLVABLE_STATUS_UNKNOWN) - return false; - - return (status == RESOLVABLE_STATUS_INSTALLED) || resItem_status_is_to_be_installed (status); -} - - -bool -ResolverContext::resItemIsAbsent (constResItemPtr resItem) -{ - ResItemStatus status; - - status = getStatus (resItem); - if (status == RESOLVABLE_STATUS_UNKNOWN) - return false; - - return status == RESOLVABLE_STATUS_UNINSTALLED || resItem_status_is_to_be_uninstalled (status); -} - - -//--------------------------------------------------------------------------- -// marked - -void -ResolverContext::foreachMarkedResItem (MarkedResItemFn fn, void *data) const -{ - constResolverContextPtr context = this; - while (context) { - for (StatusTable::const_iterator iter = context->_status.begin(); iter != context->_status.end(); iter++) { - fn (iter->first, iter->second, data); - } - context = context->_parent; - } -} - - -//--------------------------------------------------------------------------- -// collect - -static void -marked_resItem_collector (constResItemPtr resItem, ResItemStatus status, void *data) -{ - CResItemList *rl = (CResItemList *)data; - rl->push_back (resItem); -} - - -CResItemList -ResolverContext::getMarkedResItems (void) const -{ - CResItemList rl; - - foreachMarkedResItem (marked_resItem_collector, &rl); - - return rl; -} - -//--------------------------------------------------------------------------- -// install - -typedef struct { - WorldPtr world; - MarkedResItemFn fn; - CResItemList *rl; - int count; -} InstallInfo; - -static void -install_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *data) -{ - InstallInfo *info = (InstallInfo *)data; - if (resItem_status_is_to_be_installed (status) - && ! resItem->isInstalled () - && info->world->findInstalledResItem (resItem) == NULL) { - - if (info->fn) info->fn (resItem, status, info->rl); - ++info->count; - } -} - - -int -ResolverContext::foreachInstall (MarkedResItemFn fn, void *data) const -{ - CResItemList *rl = (CResItemList *)data; - InstallInfo info = { world(), fn, rl, 0 }; - - foreachMarkedResItem (install_pkg_cb, (void *)&info); - - return info.count; -} - - -static void -context_resItem_collector (constResItemPtr resItem, ResItemStatus status, void *data) -{ - CResItemList *rl = (CResItemList *)data; - if (resItem_status_is_to_be_installed (status) - || (resItem_status_is_to_be_uninstalled (status) && resItem->isInstalled ())) { - rl->push_front (resItem); - } -} - - -CResItemList -ResolverContext::getInstalls (void) const -{ - CResItemList rl; - - foreachInstall (context_resItem_collector, (void *)&rl); - - return rl; -} - - -//--------------------------------------------------------------------------- -// upgrade - -typedef struct { - WorldPtr world; - MarkedResItemPairFn fn; - void *data; - ResolverContextPtr context; - int count; -} UpgradeInfo; - -static void -upgrade_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *data) -{ - UpgradeInfo *info = (UpgradeInfo *)data; - - constResItemPtr to_be_upgraded; - ResItemStatus tbu_status; - - if (resItem_status_is_to_be_installed (status) - && ! resItem->isInstalled ()) { - - to_be_upgraded = info->world->findInstalledResItem (resItem); - if (to_be_upgraded) { - tbu_status = info->context->getStatus (to_be_upgraded); - if (info->fn) { - info->fn (resItem, status, to_be_upgraded, tbu_status, info->data); - } - ++info->count; - } - } -} - - -int -ResolverContext::foreachUpgrade (MarkedResItemPairFn fn, void *data) -{ - UpgradeInfo info = { world(), fn, data, this, 0 }; - - foreachMarkedResItem (upgrade_pkg_cb, (void *)&info); - - return info.count; -} - - -static void -pair_resItem_collector (constResItemPtr resItem, ResItemStatus status, constResItemPtr old, ResItemStatus old_status, void *data) -{ - CResItemList *rl = (CResItemList *)data; - rl->push_back (resItem); -} - - -CResItemList -ResolverContext::getUpgrades (void) -{ - CResItemList rl; - - foreachUpgrade (pair_resItem_collector, (void *)&rl); - - return rl; -} - - -//--------------------------------------------------------------------------- -// uninstall - -typedef std::map UpgradeTable; - -typedef struct { - MarkedResItemFn fn; - CResItemList *rl; - UpgradeTable upgrade_hash; - int count; -} UninstallInfo; - -static void -uninstall_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *data) -{ - UninstallInfo *info = (UninstallInfo *)data; - - UpgradeTable::const_iterator pos = info->upgrade_hash.find(resItem->name()); - - if (resItem_status_is_to_be_uninstalled (status) - && pos == info->upgrade_hash.end()) { - if (info->fn) - info->fn (resItem, status, info->rl); - ++info->count; - } -} - -static void -build_upgrade_hash_cb (constResItemPtr resItem_add, ResItemStatus status_add, constResItemPtr resItem_del, ResItemStatus status_del, void *data) -{ - UpgradeTable *upgrade_hash = (UpgradeTable *)data; - (*upgrade_hash)[resItem_del->name()] = resItem_del; -} - - -int -ResolverContext::foreachUninstall (MarkedResItemFn fn, void *data) -{ - UninstallInfo info; // inits upgrade_hash - - info.fn = fn; - info.rl = (CResItemList *)data; - info.count = 0; - - foreachUpgrade (build_upgrade_hash_cb, (void *)&(info.upgrade_hash)); - foreachMarkedResItem (uninstall_pkg_cb, (void *)&info); - - return info.count; -} - - -CResItemList -ResolverContext::getUninstalls (void) -{ - CResItemList rl; - - foreachUninstall (context_resItem_collector, (void *)&rl); - - return rl; -} - - -//--------------------------------------------------------------------------- - -static void -install_count_cb (constResItemPtr resItem, ResItemStatus status, void *data) -{ - int *count = (int *)data; - if (! resItem->isInstalled ()) { - ++*count; - } -} - -int -ResolverContext::installCount (void) const -{ - int count = 0; - - foreachInstall (install_count_cb, (void *)&count); - - return count; -} - - -static void -uninstall_count_cb (constResItemPtr resItem, ResItemStatus status, void *data) -{ - int *count = (int *)data; - if (resItem->isInstalled ()) { - ++*count; - } -} - - -int -ResolverContext::uninstallCount (void) -{ - int count = 0; - - foreachUninstall (uninstall_count_cb, (void *)&count); - - return count; -} - - -int -ResolverContext::upgradeCount (void) -{ - return foreachUpgrade ((MarkedResItemPairFn)NULL, (void *)NULL); -} - - -//--------------------------------------------------------------------------- -// info - -void -ResolverContext::addInfo (ResolverInfoPtr info) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::addInfo(%s)\n", this, info->asString().c_str()); - _log.push_back (info); - - // _propagated_importance = false; - - if (info->error ()) { - - if (! _invalid) { - ResolverInfoPtr info = new ResolverInfoMisc (NULL, RESOLVER_INFO_PRIORITY_VERBOSE, "Marking this resolution attempt as invalid."); - info->flagAsError (); - _log.push_back (info); - } - - _invalid = true; - } -} - - -void -ResolverContext::addInfoString (constResItemPtr resItem, int priority, string msg) -{ -// if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext::addInfoString(%s) %s\n", resItem ? resItem->asString().c_str() : "", msg.c_str()); - ResolverInfoPtr info = new ResolverInfoMisc (resItem, priority, msg); - addInfo (info); -} - - -void -ResolverContext::addErrorString (constResItemPtr resItem, string msg) -{ - ResolverInfoPtr info = new ResolverInfoMisc (resItem, RESOLVER_INFO_PRIORITY_VERBOSE, msg); - info->flagAsError (); - addInfo (info); -} - - -//--------------------------------------------------------------------------- -// foreach info - -// We call a resItem mentioned by an error info an "error-resItem". -// We call a resItem mentioned by an important info an "important-resItem". -// -// The rules: -// (1) An info item that mentions an error-resItem is important. -// (2) An info item is about an important-resItem is important. - -static void -mark_important_info (InfoList & il) -{ - CResItemList error_list; // FIXME, a map is faster - - bool did_something; - int pass_num = 1; - - /* First of all, store all error-resItems in a list. */ - - for (InfoList::iterator iter = il.begin(); iter != il.end(); iter++) { - if ((*iter) != NULL // list items might be set to NULL - && (*iter)->error ()) { - constResItemPtr resItem = (*iter)->resItem(); - if (resItem != NULL) { - CResItemList::iterator pos; - for (pos = error_list.begin(); pos != error_list.end(); pos++) { - if (*pos == resItem) - break; - } - if (pos == error_list.end()) { - error_list.push_front (resItem); - } - } - - CResItemList resItems; - - constResolverInfoContainerPtr c = *iter; // check if it really is a container - if (c != NULL) resItems = c->resItems(); - - for (CResItemList::iterator res_iter = resItems.begin(); res_iter != resItems.end(); res_iter++) { - CResItemList::iterator pos; - for (pos = error_list.begin(); pos != error_list.end(); pos++) { - if (*pos == *iter) - break; - } - if (pos == error_list.end()) { - error_list.push_front (*res_iter); - } - } - } - } - - CResItemList important_list; // FIXME, hash is faster - - do { - ++pass_num; - assert (pass_num < 10000); - - did_something = false; - - for (InfoList::iterator iter = il.begin(); iter != il.end(); iter++) { - if ((*iter) != NULL // list items might be set to NULL - && (*iter)->important ()) { - bool should_be_important = false; - - for (CResItemList::const_iterator res_iter = error_list.begin(); res_iter != error_list.end() && ! should_be_important; res_iter++) { - constResolverInfoContainerPtr c = *iter; - if (c != NULL // check if it really is a container - && c->mentions (*res_iter)) { - should_be_important = true; - } - } - - for (CResItemList::const_iterator res_iter = important_list.begin(); res_iter != important_list.end() && ! should_be_important; res_iter++) { - if ((*iter)->isAbout (*res_iter)) { - should_be_important = true; - break; - } - } - - if (should_be_important) { - did_something = true; - (*iter)->flagAsImportant (); - CResItemList resItems; - constResolverInfoContainerPtr c = *iter; // check if it really is a container - if (c != NULL) resItems = c->resItems(); - for (CResItemList::iterator res_iter = resItems.begin(); res_iter != resItems.end(); res_iter++) { - CResItemList::iterator pos; - for (pos = important_list.begin(); pos != important_list.end(); pos++) { - if (*pos == *res_iter) - break; - } - if (pos == important_list.end()) { - important_list.push_front (*res_iter); - } - } - } - } - } - - } while (did_something); - -} - - -void -ResolverContext::foreachInfo (ResItemPtr resItem, int priority, ResolverInfoFn fn, void *data) -{ - InfoList info_list; - - ResolverContextPtr context = this; - - - // Assemble a list of copies of all of the info objects - while (context != NULL) { - for (InfoList::iterator iter = context->_log.begin(); iter != context->_log.end(); iter++) { - if ((resItem == NULL || (*iter)->resItem() == resItem) - && (*iter)->priority() >= priority) { - info_list.push_back ((*iter)->copy()); - } - } - context = context->_parent; - } -#if 0 - // Merge info objects - for (InfoList::iterator iter = info_list.begin(); iter != info_list.end(); iter++) { - - ResolverInfoPtr info1 = (*iter); - InfoList::iterator subiter = iter; - if (info1 != NULL) { - for (subiter++; subiter != info_list.end(); subiter++) { - ResolverInfoPtr info2 = *subiter; - if (info2 && info1->merge (info2)) { - *subiter = NULL; - } - } - } - } -#endif - mark_important_info (info_list); - - // Walk across the list of info objects and invoke our callback - - for (InfoList::iterator iter = info_list.begin(); iter != info_list.end(); iter++) { - if (*iter != NULL) { - fn (*iter, data); - } - } -} - - - -static void -get_info_foreach_cb (ResolverInfoPtr info, void *data) -{ - InfoList *il = (InfoList *)data; - - if (info->important ()) { - il->push_back (info); - } -} - - - -InfoList -ResolverContext::getInfo (void) -{ - InfoList il; - foreachInfo (NULL, -1, get_info_foreach_cb, (void *)&il); - return il; -} - - -//--------------------------------------------------------------------------- -// spew - -static void -spew_pkg_cb (constResItemPtr resItem, ResItemStatus status, void *unused) -{ - printf (" %s (%s)\n", resItem->asString().c_str(), ResolverContext::toString(status).c_str()); -} - - -void -spew_pkg2_cb (constResItemPtr resItem1, ResItemStatus status1, constResItemPtr resItem2, ResItemStatus status2, void *unused) -{ - const char *s1, *s2; - - s1 = resItem1->asString().c_str(); - s2 = resItem2->asString().c_str(); - - printf (" %s (%s) => %s (%s)\n", s2, ResolverContext::toString(status2).c_str(), s1, ResolverContext::toString(status1).c_str()); -} - - -void -ResolverContext::spew (void) -{ - printf ("TO INSTALL:\n"); - foreachInstall (spew_pkg_cb, NULL); - printf ("\n"); - - printf ("TO REMOVE:\n"); - foreachUninstall (spew_pkg_cb, NULL); - printf ("\n"); - - printf ("TO UPGRADE:\n"); - foreachUpgrade (spew_pkg2_cb, NULL); - printf ("\n"); -} - - -static void -spew_info_cb (ResolverInfoPtr info, void *unused) -{ - const char *msg = info->asString().c_str(); - if (info->error ()) printf ("[ERROR] "); - else if (info->important()) printf ("[>>>>>] "); - printf ("%s\n", msg); -} - - -void -ResolverContext::spewInfo (void) -{ - if (getenv ("RC_SPEW")) fprintf (stderr, "ResolverContext[%p]::spewInfo()\n", this); - foreachInfo (NULL, -1, spew_info_cb, NULL); -} - -//--------------------------------------------------------------------------- -// requirements - -typedef struct { - ResolverContextPtr context; - constSpecPtr dep; - bool flag; -} RequirementMetInfo; - - -static bool -requirement_met_cb (constResItemPtr resItem, constSpecPtr spec, void *data) -{ - RequirementMetInfo *info = (RequirementMetInfo *)data; - - // info->dep is set for resItem set children. If it is set, query the - // exact version only. - if ((info->dep == NULL || info->dep->equals(spec)) - && info->context->resItemIsPresent (resItem)) - { - info->flag = true; - } - -//fprintf (stderr, "requirement_met_cb(%s, %s) [info->dep %s] -> %s\n", resItem->asString().c_str(), spec->asString().c_str(), info->dep != NULL ? info->dep->asString().c_str() : "(none)", info->flag ? "true" : "false"); - return ! info->flag; -} - - -bool -ResolverContext::requirementIsMet (constDependencyPtr dependency, bool is_child) -{ - RequirementMetInfo info; - - info.context = this; - info.dep = is_child ? dependency : NULL; - info.flag = false; - - world()->foreachProvidingResItem (dependency, requirement_met_cb, (void *)&info); - - return info.flag; -} - - -//--------------------------------------------------------------------------- - -static bool -requirement_possible_cb (constResItemPtr resItem, constSpecPtr spec, void *data) -{ - RequirementMetInfo *info = (RequirementMetInfo *)data; - - ResItemStatus status = info->context->getStatus (resItem); - - if (! resItem_status_is_to_be_uninstalled (status) - || status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { - info->flag = true; - } - - return ! info->flag; -} - - -bool -ResolverContext::requirementIsPossible (constDependencyPtr dep) -{ - RequirementMetInfo info; - - info.context = this; - info.flag = false; - - world()->foreachProvidingResItem (dep, requirement_possible_cb, (void *)&info); - - return info.flag; -} - - -bool -ResolverContext::resItemIsPossible (constResItemPtr resItem) -{ - CDependencyList requires = resItem->requires(); - for (CDependencyList::iterator iter = requires.begin(); iter != requires.end(); iter++) { - if (! requirementIsPossible (*iter)) { - return false; - } - } - - return true; -} - -//--------------------------------------------------------------------------- - -typedef struct { - constSpecPtr spec; - bool flag; -} DupNameCheckInfo; - -static void -dup_name_check_cb (constResItemPtr resItem, ResItemStatus status, void *data) -{ - DupNameCheckInfo *info = (DupNameCheckInfo *)data; - if (! info->flag - && resItem_status_is_to_be_installed (status) - && info->spec->name() == resItem->name() - && !info->spec->equals(resItem)) { - info->flag = true; - } -} - -bool -ResolverContext::isParallelInstall (constResItemPtr resItem) -{ - DupNameCheckInfo info; - - info.spec = resItem; - info.flag = false; - foreachMarkedResItem (dup_name_check_cb, (void *)&info); - - return info.flag; -} - - -int -ResolverContext::getChannelPriority (constChannelPtr channel) const -{ - bool is_subscribed; - int priority; - - is_subscribed = channel->isSubscribed (); - priority = channel->getPriority (is_subscribed); - - return priority; -} - -//--------------------------------------------------------------------------- - -static int -num_cmp (double a, double b) -{ - return (b < a) - (a < b); -} - -static int -rev_num_cmp (double a, double b) -{ - return (a < b) - (b < a); -} - -static double -churn_factor (ResolverContextPtr a) -{ - return a->upgradeCount() + (2.0 * a->installCount ()) + (4.0 * a->uninstallCount ()); -} - -int -ResolverContext::partialCompare (ResolverContextPtr context) -{ - int cmp = 0; - if (this != context) { - - // High numbers are good... we don't want solutions containing low-priority channels. - cmp = num_cmp (_min_priority, context->_min_priority); - - if (cmp == 0) { - - // High numbers are bad. Less churn is better. - cmp = rev_num_cmp (churn_factor (this), churn_factor (context)); - - if (cmp == 0) { - - // High numbers are bad. Bigger #s means more penalties. - cmp = rev_num_cmp (_other_penalties, context->_other_penalties); - } - } - } - - return cmp; -} - -int -ResolverContext::compare (ResolverContextPtr context) -{ - int cmp; - - if (this == context) - return 0; - - cmp = partialCompare (context); - if (cmp) - return cmp; - - /* High numbers are bad. Smaller downloads are best. */ - cmp = rev_num_cmp (_download_size, context->_download_size); - if (cmp) - return cmp; - - /* High numbers are bad. Less disk space consumed is good. */ - cmp = rev_num_cmp (_install_size, context->_install_size); - if (cmp) - return cmp; - - return 0; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + typedef struct { + ResolverContextPtr context; + constSpecPtr dep; + bool flag; + } RequirementMetInfo; + + + static bool + requirement_met_cb (constResItemPtr resItem, constSpecPtr spec, void *data) + { + RequirementMetInfo *info = (RequirementMetInfo *)data; + + // info->dep is set for resItem set children. If it is set, query the + // exact version only. + if ((info->dep == NULL || info->dep->equals(spec)) + && info->context->resItemIsPresent (resItem)) + { + info->flag = true; + } + + //fprintf (stderr, "requirement_met_cb(%s, %s) [info->dep %s] -> %s\n", resItem->asString().c_str(), spec->asString().c_str(), info->dep != NULL ? info->dep->asString().c_str() : "(none)", info->flag ? "true" : "false"); + return ! info->flag; + } + + + bool + ResolverContext::requirementIsMet (constDependencyPtr dependency, bool is_child) + { + RequirementMetInfo info; + + info.context = this; + info.dep = is_child ? dependency : NULL; + info.flag = false; + + world()->foreachProvidingResItem (dependency, requirement_met_cb, (void *)&info); + + return info.flag; + } + + + //--------------------------------------------------------------------------- + + static bool + requirement_possible_cb (constResItemPtr resItem, constSpecPtr spec, void *data) + { + RequirementMetInfo *info = (RequirementMetInfo *)data; + + ResItemStatus status = info->context->getStatus (resItem); + + if (! resItem_status_is_to_be_uninstalled (status) + || status == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK) { + info->flag = true; + } + + return ! info->flag; + } + + + bool + ResolverContext::requirementIsPossible (constDependencyPtr dep) + { + RequirementMetInfo info; + + info.context = this; + info.flag = false; + + world()->foreachProvidingResItem (dep, requirement_possible_cb, (void *)&info); + + return info.flag; + } + + + bool + ResolverContext::resItemIsPossible (constResItemPtr resItem) + { + CDependencyList requires = resItem->requires(); + for (CDependencyList::iterator iter = requires.begin(); iter != requires.end(); iter++) { + if (! requirementIsPossible (*iter)) { + return false; + } + } + + return true; + } + + //--------------------------------------------------------------------------- + + typedef struct { + constSpecPtr spec; + bool flag; + } DupNameCheckInfo; + + static void + dup_name_check_cb (constResItemPtr resItem, ResItemStatus status, void *data) + { + DupNameCheckInfo *info = (DupNameCheckInfo *)data; + if (! info->flag + && resItem_status_is_to_be_installed (status) + && info->spec->name() == resItem->name() + && !info->spec->equals(resItem)) { + info->flag = true; + } + } + + bool + ResolverContext::isParallelInstall (constResItemPtr resItem) + { + DupNameCheckInfo info; + + info.spec = resItem; + info.flag = false; + foreachMarkedResItem (dup_name_check_cb, (void *)&info); + + return info.flag; + } + + + int + ResolverContext::getChannelPriority (constChannelPtr channel) const + { + bool is_subscribed; + int priority; + + is_subscribed = channel->isSubscribed (); + priority = channel->getPriority (is_subscribed); + + return priority; + } + + //--------------------------------------------------------------------------- + + static int + num_cmp (double a, double b) + { + return (b < a) - (a < b); + } + + static int + rev_num_cmp (double a, double b) + { + return (a < b) - (b < a); + } + + static double + churn_factor (ResolverContextPtr a) + { + return a->upgradeCount() + (2.0 * a->installCount ()) + (4.0 * a->uninstallCount ()); + } + + int + ResolverContext::partialCompare (ResolverContextPtr context) + { + int cmp = 0; + if (this != context) { + + // High numbers are good... we don't want solutions containing low-priority channels. + cmp = num_cmp (_min_priority, context->_min_priority); + + if (cmp == 0) { + + // High numbers are bad. Less churn is better. + cmp = rev_num_cmp (churn_factor (this), churn_factor (context)); + + if (cmp == 0) { + + // High numbers are bad. Bigger #s means more penalties. + cmp = rev_num_cmp (_other_penalties, context->_other_penalties); + } + } + } + + return cmp; + } + + int + ResolverContext::compare (ResolverContextPtr context) + { + int cmp; + + if (this == context) + return 0; + + cmp = partialCompare (context); + if (cmp) + return cmp; + + /* High numbers are bad. Smaller downloads are best. */ + cmp = rev_num_cmp (_download_size, context->_download_size); + if (cmp) + return cmp; + + /* High numbers are bad. Less disk space consumed is good. */ + cmp = rev_num_cmp (_install_size, context->_install_size); + if (cmp) + return cmp; + + return 0; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverContext.h b/zypp/solver/detail/ResolverContext.h index 3887d17..f8619e4 100644 --- a/zypp/solver/detail/ResolverContext.h +++ b/zypp/solver/detail/ResolverContext.h @@ -32,147 +32,159 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -typedef enum { - RESOLVABLE_STATUS_UNKNOWN = 0, - RESOLVABLE_STATUS_INSTALLED, - RESOLVABLE_STATUS_UNINSTALLED, - RESOLVABLE_STATUS_TO_BE_INSTALLED, - RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT, - RESOLVABLE_STATUS_TO_BE_UNINSTALLED, - RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE, - RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK -} ResItemStatus; - -#define resItem_status_is_to_be_installed(x) (((x) == RESOLVABLE_STATUS_TO_BE_INSTALLED) || ((x) == RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT)) -#define resItem_status_is_to_be_uninstalled(x) (((x) == RESOLVABLE_STATUS_TO_BE_UNINSTALLED) || ((x) == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE) || ((x) == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK)) - -typedef std::map StatusTable; -typedef std::list InfoList; - - -typedef void (*ResolverContextFn) (ResolverContextPtr ctx, void * data); -typedef void (*MarkedResItemFn) (constResItemPtr res, ResItemStatus status, void *data); -typedef void (*MarkedResItemPairFn) (constResItemPtr res1, ResItemStatus status1, constResItemPtr res2, ResItemStatus status2, void *data); - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverContext -class ResolverContext : public CountedRep { - REP_BODY(ResolverContext); - - private: - - ResolverContextPtr _parent; - - int _refs; - - WorldPtr _world; - StatusTable _status; - - // just a caching mechanism - constResItemPtr _last_checked_resItem; - ResItemStatus _last_checked_status; - - InfoList _log; - unsigned long long _download_size; - unsigned long long _install_size; - int _total_priority; - int _min_priority; - int _max_priority; - int _other_penalties; - constChannelPtr _current_channel; - bool _verifying; - bool _invalid; - - public: - ResolverContext (ResolverContextPtr parent = NULL); - virtual ~ResolverContext(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverContext & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverContext & context); - std::string asString (void ) const; - - static std::string toString (const ResItemStatus & status); - - // ---------------------------------- accessors - - WorldPtr world (void) const; // gets global world, if _world == NULL - void setWorld (WorldPtr world) { _world = world; } - - constChannelPtr currentChannel (void) const { return _current_channel; } - void setCurrentChannel (constChannelPtr channel) { _current_channel = channel; } - - unsigned long long downloadSize(void) const { return _download_size; } - unsigned long long installSize(void) const { return _install_size; } - int totalPriority (void) const { return _total_priority; } - int minPriority (void) const { return _min_priority; } - int maxPriority (void) const { return _max_priority; } - int otherPenalties (void) const { return _other_penalties; } - - bool isValid (void) const { return !_invalid; } - bool isInvalid (void) const { return _invalid; } - - bool verifying (void) const { return _verifying; } - void setVerifying (bool verifying) { _verifying = verifying; } - - // ---------------------------------- methods - - ResItemStatus getStatus (constResItemPtr res); // non-const, because its caching - void setStatus (constResItemPtr res, ResItemStatus status); - - bool installResItem (constResItemPtr resItem, bool is_soft, int other_penalty); - bool upgradeResItem (constResItemPtr new_resItem, constResItemPtr old_resItem, bool is_soft, int other_penalty); - bool uninstallResItem (constResItemPtr resItem, bool part_of_upgrade, bool due_to_obsolete, bool due_to_unlink); - - bool resItemIsPresent (constResItemPtr resItem); - bool resItemIsAbsent (constResItemPtr resItem); - - void foreachMarkedResItem (MarkedResItemFn fn, void *data) const; - CResItemList getMarkedResItems (void) const; - - int foreachInstall (MarkedResItemFn fn, void *data) const; - CResItemList getInstalls (void) const; - int installCount (void) const; - - int foreachUninstall (MarkedResItemFn fn, void *data); // non-const, calls foreachUpgrade - CResItemList getUninstalls (void); - int uninstallCount (void); - - int foreachUpgrade (MarkedResItemPairFn fn, void *data); // non-const, calls getStatus - CResItemList getUpgrades (void); - int upgradeCount (void); - - void addInfo (ResolverInfoPtr info); - void addInfoString (constResItemPtr resItem, int priority, std::string str); - void addErrorString (constResItemPtr resItem, std::string str); - - void foreachInfo (ResItemPtr resItem, int priority, ResolverInfoFn fn, void *data); - InfoList getInfo (void); - - void spew (void); - void spewInfo (void); - - bool requirementIsMet (constDependencyPtr dep, bool is_child); - bool requirementIsPossible (constDependencyPtr dep); - bool resItemIsPossible (constResItemPtr resItem); - bool isParallelInstall (constResItemPtr resItem); - - int getChannelPriority (constChannelPtr channel) const; - - int partialCompare (ResolverContextPtr context); // non-const, calls uninstall/upgrade Count - int compare (ResolverContextPtr context); -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef enum { + RESOLVABLE_STATUS_UNKNOWN = 0, + RESOLVABLE_STATUS_INSTALLED, + RESOLVABLE_STATUS_UNINSTALLED, + RESOLVABLE_STATUS_TO_BE_INSTALLED, + RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT, + RESOLVABLE_STATUS_TO_BE_UNINSTALLED, + RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE, + RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK + } ResItemStatus; + + #define resItem_status_is_to_be_installed(x) (((x) == RESOLVABLE_STATUS_TO_BE_INSTALLED) || ((x) == RESOLVABLE_STATUS_TO_BE_INSTALLED_SOFT)) + #define resItem_status_is_to_be_uninstalled(x) (((x) == RESOLVABLE_STATUS_TO_BE_UNINSTALLED) || ((x) == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_OBSOLETE) || ((x) == RESOLVABLE_STATUS_TO_BE_UNINSTALLED_DUE_TO_UNLINK)) + + typedef std::map StatusTable; + typedef std::list InfoList; + + + typedef void (*ResolverContextFn) (ResolverContextPtr ctx, void * data); + typedef void (*MarkedResItemFn) (constResItemPtr res, ResItemStatus status, void *data); + typedef void (*MarkedResItemPairFn) (constResItemPtr res1, ResItemStatus status1, constResItemPtr res2, ResItemStatus status2, void *data); + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverContext + class ResolverContext : public CountedRep { + REP_BODY(ResolverContext); + + private: + + ResolverContextPtr _parent; + + int _refs; + + WorldPtr _world; + StatusTable _status; + + // just a caching mechanism + constResItemPtr _last_checked_resItem; + ResItemStatus _last_checked_status; + + InfoList _log; + unsigned long long _download_size; + unsigned long long _install_size; + int _total_priority; + int _min_priority; + int _max_priority; + int _other_penalties; + constChannelPtr _current_channel; + bool _verifying; + bool _invalid; + + public: + ResolverContext (ResolverContextPtr parent = NULL); + virtual ~ResolverContext(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverContext & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverContext & context); + std::string asString (void ) const; + + static std::string toString (const ResItemStatus & status); + + // ---------------------------------- accessors + + WorldPtr world (void) const; // gets global world, if _world == NULL + void setWorld (WorldPtr world) { _world = world; } + + constChannelPtr currentChannel (void) const { return _current_channel; } + void setCurrentChannel (constChannelPtr channel) { _current_channel = channel; } + + unsigned long long downloadSize(void) const { return _download_size; } + unsigned long long installSize(void) const { return _install_size; } + int totalPriority (void) const { return _total_priority; } + int minPriority (void) const { return _min_priority; } + int maxPriority (void) const { return _max_priority; } + int otherPenalties (void) const { return _other_penalties; } + + bool isValid (void) const { return !_invalid; } + bool isInvalid (void) const { return _invalid; } + + bool verifying (void) const { return _verifying; } + void setVerifying (bool verifying) { _verifying = verifying; } + + // ---------------------------------- methods + + ResItemStatus getStatus (constResItemPtr res); // non-const, because its caching + void setStatus (constResItemPtr res, ResItemStatus status); + + bool installResItem (constResItemPtr resItem, bool is_soft, int other_penalty); + bool upgradeResItem (constResItemPtr new_resItem, constResItemPtr old_resItem, bool is_soft, int other_penalty); + bool uninstallResItem (constResItemPtr resItem, bool part_of_upgrade, bool due_to_obsolete, bool due_to_unlink); + + bool resItemIsPresent (constResItemPtr resItem); + bool resItemIsAbsent (constResItemPtr resItem); + + void foreachMarkedResItem (MarkedResItemFn fn, void *data) const; + CResItemList getMarkedResItems (void) const; + + int foreachInstall (MarkedResItemFn fn, void *data) const; + CResItemList getInstalls (void) const; + int installCount (void) const; + + int foreachUninstall (MarkedResItemFn fn, void *data); // non-const, calls foreachUpgrade + CResItemList getUninstalls (void); + int uninstallCount (void); + + int foreachUpgrade (MarkedResItemPairFn fn, void *data); // non-const, calls getStatus + CResItemList getUpgrades (void); + int upgradeCount (void); + + void addInfo (ResolverInfoPtr info); + void addInfoString (constResItemPtr resItem, int priority, std::string str); + void addErrorString (constResItemPtr resItem, std::string str); + + void foreachInfo (ResItemPtr resItem, int priority, ResolverInfoFn fn, void *data); + InfoList getInfo (void); + + void spew (void); + void spewInfo (void); + + bool requirementIsMet (constDependencyPtr dep, bool is_child); + bool requirementIsPossible (constDependencyPtr dep); + bool resItemIsPossible (constResItemPtr resItem); + bool isParallelInstall (constResItemPtr resItem); + + int getChannelPriority (constChannelPtr channel) const; + + int partialCompare (ResolverContextPtr context); // non-const, calls uninstall/upgrade Count + int compare (ResolverContextPtr context); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverContext_h diff --git a/zypp/solver/detail/ResolverContextPtr.h b/zypp/solver/detail/ResolverContextPtr.h index ffc2549..9cef771 100644 --- a/zypp/solver/detail/ResolverContextPtr.h +++ b/zypp/solver/detail/ResolverContextPtr.h @@ -23,18 +23,30 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverContextPtr -// CLASS NAME : constResolverContextPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(ResolverContext); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverContextPtr + // CLASS NAME : constResolverContextPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(ResolverContext); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverContextPtr_h diff --git a/zypp/solver/detail/ResolverInfo.cc b/zypp/solver/detail/ResolverInfo.cc index ee32ff9..16428bb 100644 --- a/zypp/solver/detail/ResolverInfo.cc +++ b/zypp/solver/detail/ResolverInfo.cc @@ -23,167 +23,179 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(ResolverInfo); - -//--------------------------------------------------------------------------- - -static struct { - ResolverInfoType type; - const char *str; -} type_str_table[] = { - { RESOLVER_INFO_TYPE_NEEDED_BY, "needed_by" }, - { RESOLVER_INFO_TYPE_CONFLICTS_WITH, "conflicts_with" }, - { RESOLVER_INFO_TYPE_OBSOLETES, "obsoletes" }, - { RESOLVER_INFO_TYPE_DEPENDS_ON, "depended_on" }, - { RESOLVER_INFO_TYPE_CHILD_OF, "child_of" }, - { RESOLVER_INFO_TYPE_MISSING_REQ, "missing_req" }, - { RESOLVER_INFO_TYPE_MISC, "misc" }, - { RESOLVER_INFO_TYPE_INVALID, "invalid" }, - { RESOLVER_INFO_TYPE_INVALID, NULL } -}; - -static const char * -info_type_to_string (ResolverInfoType type) -{ - int i; - - for (i = 0; type_str_table[i].str != NULL; ++i) { - if (type == type_str_table[i].type) - return type_str_table[i].str; - } - - return NULL; -} - - -ResolverInfoType -resolver_info_type_from_string (const char *str) -{ - int i; - - if (str == NULL) return RESOLVER_INFO_TYPE_INVALID; - - for (i = 0; type_str_table[i].str != NULL; ++i) { - if (strcasecmp (str, type_str_table[i].str) == 0) - return type_str_table[i].type; - } - - return RESOLVER_INFO_TYPE_INVALID; -} - -//--------------------------------------------------------------------------- - -string -ResolverInfo::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfo::toString ( const ResolverInfo & resolverinfo, bool full ) -{ - string res; - - if (full) { - res += "<"; - res += info_type_to_string (resolverinfo._type); - res += "> "; - } - if (resolverinfo._resItem != NULL) { - res += resolverinfo._resItem->asString(); - res += ": "; - } - - if (resolverinfo._error) res += " Error!"; - if (resolverinfo._important) res += " Important!"; - - return res; -} - - -ostream & -ResolverInfo::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfo & resolver) -{ - return os << resolver.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfo::ResolverInfo (ResolverInfoType type, constResItemPtr resItem, int priority) - : _type (type) - , _resItem (resItem) - , _priority (priority) - , _error (false) - , _important (false) -{ -} - - -ResolverInfo::~ResolverInfo() -{ -} - -//--------------------------------------------------------------------------- - -bool -ResolverInfo::merge (ResolverInfoPtr to_be_merged) -{ - if (to_be_merged == NULL) return false; - - if (_type != to_be_merged->_type - || _resItem != to_be_merged->_resItem) { - return false; - } - - return true; -} - -void -ResolverInfo::copy (constResolverInfoPtr from) -{ - _error = from->_error; - _important = from->_important; -} - - -ResolverInfoPtr -ResolverInfo::copy (void) const -{ - ResolverInfoPtr cpy = new ResolverInfo(_type, _resItem, _priority); - - cpy->copy (this); - - return cpy; -} - - -//--------------------------------------------------------------------------- - -bool -ResolverInfo::isAbout (constResItemPtr resItem) const -{ - if (_resItem == NULL) - return false; - - return _resItem->name() == resItem->name(); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(ResolverInfo); + + //--------------------------------------------------------------------------- + + static struct { + ResolverInfoType type; + const char *str; + } type_str_table[] = { + { RESOLVER_INFO_TYPE_NEEDED_BY, "needed_by" }, + { RESOLVER_INFO_TYPE_CONFLICTS_WITH, "conflicts_with" }, + { RESOLVER_INFO_TYPE_OBSOLETES, "obsoletes" }, + { RESOLVER_INFO_TYPE_DEPENDS_ON, "depended_on" }, + { RESOLVER_INFO_TYPE_CHILD_OF, "child_of" }, + { RESOLVER_INFO_TYPE_MISSING_REQ, "missing_req" }, + { RESOLVER_INFO_TYPE_MISC, "misc" }, + { RESOLVER_INFO_TYPE_INVALID, "invalid" }, + { RESOLVER_INFO_TYPE_INVALID, NULL } + }; + + static const char * + info_type_to_string (ResolverInfoType type) + { + int i; + + for (i = 0; type_str_table[i].str != NULL; ++i) { + if (type == type_str_table[i].type) + return type_str_table[i].str; + } + + return NULL; + } + + + ResolverInfoType + resolver_info_type_from_string (const char *str) + { + int i; + + if (str == NULL) return RESOLVER_INFO_TYPE_INVALID; + + for (i = 0; type_str_table[i].str != NULL; ++i) { + if (strcasecmp (str, type_str_table[i].str) == 0) + return type_str_table[i].type; + } + + return RESOLVER_INFO_TYPE_INVALID; + } + + //--------------------------------------------------------------------------- + + string + ResolverInfo::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfo::toString ( const ResolverInfo & resolverinfo, bool full ) + { + string res; + + if (full) { + res += "<"; + res += info_type_to_string (resolverinfo._type); + res += "> "; + } + if (resolverinfo._resItem != NULL) { + res += resolverinfo._resItem->asString(); + res += ": "; + } + + if (resolverinfo._error) res += " Error!"; + if (resolverinfo._important) res += " Important!"; + + return res; + } + + + ostream & + ResolverInfo::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfo & resolver) + { + return os << resolver.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfo::ResolverInfo (ResolverInfoType type, constResItemPtr resItem, int priority) + : _type (type) + , _resItem (resItem) + , _priority (priority) + , _error (false) + , _important (false) + { + } + + + ResolverInfo::~ResolverInfo() + { + } + + //--------------------------------------------------------------------------- + + bool + ResolverInfo::merge (ResolverInfoPtr to_be_merged) + { + if (to_be_merged == NULL) return false; + + if (_type != to_be_merged->_type + || _resItem != to_be_merged->_resItem) { + return false; + } + + return true; + } + + void + ResolverInfo::copy (constResolverInfoPtr from) + { + _error = from->_error; + _important = from->_important; + } + + + ResolverInfoPtr + ResolverInfo::copy (void) const + { + ResolverInfoPtr cpy = new ResolverInfo(_type, _resItem, _priority); + + cpy->copy (this); + + return cpy; + } + + + //--------------------------------------------------------------------------- + + bool + ResolverInfo::isAbout (constResItemPtr resItem) const + { + if (_resItem == NULL) + return false; + + return _resItem->name() == resItem->name(); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfo.h b/zypp/solver/detail/ResolverInfo.h index 6a6618d..3c28ee9 100644 --- a/zypp/solver/detail/ResolverInfo.h +++ b/zypp/solver/detail/ResolverInfo.h @@ -30,85 +30,96 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -typedef enum { - RESOLVER_INFO_TYPE_INVALID = 0, - RESOLVER_INFO_TYPE_NEEDED_BY, - RESOLVER_INFO_TYPE_CONFLICTS_WITH, - RESOLVER_INFO_TYPE_OBSOLETES, - RESOLVER_INFO_TYPE_DEPENDS_ON, - RESOLVER_INFO_TYPE_CHILD_OF, - RESOLVER_INFO_TYPE_MISSING_REQ, - RESOLVER_INFO_TYPE_MISC -} ResolverInfoType; - -#define RESOLVER_INFO_PRIORITY_USER 500 -#define RESOLVER_INFO_PRIORITY_VERBOSE 100 -#define RESOLVER_INFO_PRIORITY_DEBUGGING 0 - -typedef void (*ResolverInfoFn) (ResolverInfoPtr info, void *data); - -typedef std::list ResolverInfoList; - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfo - -class ResolverInfo : public CountedRep { - - REP_BODY(ResolverInfo); - - private: - - ResolverInfoType _type; - constResItemPtr _resItem; - int _priority; - - bool _error; - bool _important; - - protected: - - ResolverInfo (ResolverInfoType type, constResItemPtr resItem, int priority); - - public: - - virtual ~ResolverInfo(); - - void copy (constResolverInfoPtr from); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfo & context, bool full = false); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfo & context); - virtual std::string asString (void ) const; - - // ---------------------------------- accessors - - ResolverInfoType type (void) const { return _type; } - constResItemPtr resItem (void) const { return _resItem; } - int priority (void) const { return _priority; } - - int error (void) const { return _error; } - void flagAsError (void) { _error = true; } - int important (void) const { return _important; } - void flagAsImportant (void) { _important = true; } - - // ---------------------------------- methods - - bool merge (ResolverInfoPtr to_be_merged); - virtual ResolverInfoPtr copy (void) const; - - bool isAbout (constResItemPtr resItem) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef enum { + RESOLVER_INFO_TYPE_INVALID = 0, + RESOLVER_INFO_TYPE_NEEDED_BY, + RESOLVER_INFO_TYPE_CONFLICTS_WITH, + RESOLVER_INFO_TYPE_OBSOLETES, + RESOLVER_INFO_TYPE_DEPENDS_ON, + RESOLVER_INFO_TYPE_CHILD_OF, + RESOLVER_INFO_TYPE_MISSING_REQ, + RESOLVER_INFO_TYPE_MISC + } ResolverInfoType; + + #define RESOLVER_INFO_PRIORITY_USER 500 + #define RESOLVER_INFO_PRIORITY_VERBOSE 100 + #define RESOLVER_INFO_PRIORITY_DEBUGGING 0 + + typedef void (*ResolverInfoFn) (ResolverInfoPtr info, void *data); + + typedef std::list ResolverInfoList; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfo + + class ResolverInfo : public CountedRep { + + REP_BODY(ResolverInfo); + + private: + + ResolverInfoType _type; + constResItemPtr _resItem; + int _priority; + + bool _error; + bool _important; + + protected: + + ResolverInfo (ResolverInfoType type, constResItemPtr resItem, int priority); + + public: + + virtual ~ResolverInfo(); + + void copy (constResolverInfoPtr from); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfo & context, bool full = false); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfo & context); + virtual std::string asString (void ) const; + + // ---------------------------------- accessors + + ResolverInfoType type (void) const { return _type; } + constResItemPtr resItem (void) const { return _resItem; } + int priority (void) const { return _priority; } + + int error (void) const { return _error; } + void flagAsError (void) { _error = true; } + int important (void) const { return _important; } + void flagAsImportant (void) { _important = true; } + + // ---------------------------------- methods + + bool merge (ResolverInfoPtr to_be_merged); + virtual ResolverInfoPtr copy (void) const; + + bool isAbout (constResItemPtr resItem) const; + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfo_h diff --git a/zypp/solver/detail/ResolverInfoChildOf.cc b/zypp/solver/detail/ResolverInfoChildOf.cc index 86d8300..f0d79c6 100644 --- a/zypp/solver/detail/ResolverInfoChildOf.cc +++ b/zypp/solver/detail/ResolverInfoChildOf.cc @@ -23,77 +23,89 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoChildOf, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoChildOf::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoChildOf::toString ( const ResolverInfoChildOf & child) -{ - string res = "copy (this); - - return cpy; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoChildOf, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoChildOf::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoChildOf::toString ( const ResolverInfoChildOf & child) + { + string res = "copy (this); + + return cpy; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoChildOf.h b/zypp/solver/detail/ResolverInfoChildOf.h index 2d53c23..02c019f 100644 --- a/zypp/solver/detail/ResolverInfoChildOf.h +++ b/zypp/solver/detail/ResolverInfoChildOf.h @@ -25,42 +25,53 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoChildOf - -class ResolverInfoChildOf : public ResolverInfoContainer { - - REP_BODY(ResolverInfoChildOf); - - private: - - public: - - ResolverInfoChildOf (constResItemPtr resItem, constResItemPtr dependency); - virtual ~ResolverInfoChildOf(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoChildOf & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoChildOf & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - virtual ResolverInfoPtr copy (void) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoChildOf + + class ResolverInfoChildOf : public ResolverInfoContainer { + + REP_BODY(ResolverInfoChildOf); + + private: + + public: + + ResolverInfoChildOf (constResItemPtr resItem, constResItemPtr dependency); + virtual ~ResolverInfoChildOf(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoChildOf & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoChildOf & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + virtual ResolverInfoPtr copy (void) const; + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoChildOf_h diff --git a/zypp/solver/detail/ResolverInfoChildOfPtr.h b/zypp/solver/detail/ResolverInfoChildOfPtr.h index 067d9e0..a69ba1d 100644 --- a/zypp/solver/detail/ResolverInfoChildOfPtr.h +++ b/zypp/solver/detail/ResolverInfoChildOfPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoChildOfPtr -// CLASS NAME : constResolverInfoChildOfPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoChildOf, ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoChildOfPtr + // CLASS NAME : constResolverInfoChildOfPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoChildOf, ResolverInfo); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoChildOfPtr_h diff --git a/zypp/solver/detail/ResolverInfoConflictsWith.cc b/zypp/solver/detail/ResolverInfoConflictsWith.cc index e87a300..aca8e52 100644 --- a/zypp/solver/detail/ResolverInfoConflictsWith.cc +++ b/zypp/solver/detail/ResolverInfoConflictsWith.cc @@ -24,77 +24,88 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoConflictsWith, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoConflictsWith::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoConflictsWith::toString ( const ResolverInfoConflictsWith & with) -{ - string res; - - res += ResolverInfo::toString (with); - res += string ("conflicts with ") + with.resItemsToString(false); - - return res; -} - - -ostream & -ResolverInfoConflictsWith::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoConflictsWith & with) -{ - return os << with.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoConflictsWith::ResolverInfoConflictsWith (constResItemPtr resItem, constResItemPtr with) - : ResolverInfoContainer (RESOLVER_INFO_TYPE_CONFLICTS_WITH, resItem, RESOLVER_INFO_PRIORITY_USER, with) -{ -} - - -ResolverInfoConflictsWith::~ResolverInfoConflictsWith () -{ -} - - -//--------------------------------------------------------------------------- - -ResolverInfoPtr -ResolverInfoConflictsWith::copy (void) const -{ - ResolverInfoConflictsWithPtr cpy = new ResolverInfoConflictsWith(resItem(), NULL); - - ((ResolverInfoContainerPtr)cpy)->copy (this); - - return cpy; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoConflictsWith, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoConflictsWith::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoConflictsWith::toString ( const ResolverInfoConflictsWith & with) + { + string res; + + res += ResolverInfo::toString (with); + res += string ("conflicts with ") + with.resItemsToString(false); + + return res; + } + + + ostream & + ResolverInfoConflictsWith::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoConflictsWith & with) + { + return os << with.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoConflictsWith::ResolverInfoConflictsWith (constResItemPtr resItem, constResItemPtr with) + : ResolverInfoContainer (RESOLVER_INFO_TYPE_CONFLICTS_WITH, resItem, RESOLVER_INFO_PRIORITY_USER, with) + { + } + + + ResolverInfoConflictsWith::~ResolverInfoConflictsWith () + { + } + + + //--------------------------------------------------------------------------- + + ResolverInfoPtr + ResolverInfoConflictsWith::copy (void) const + { + ResolverInfoConflictsWithPtr cpy = new ResolverInfoConflictsWith(resItem(), NULL); + + ((ResolverInfoContainerPtr)cpy)->copy (this); + + return cpy; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoConflictsWith.h b/zypp/solver/detail/ResolverInfoConflictsWith.h index 729f2aa..6f902c7 100644 --- a/zypp/solver/detail/ResolverInfoConflictsWith.h +++ b/zypp/solver/detail/ResolverInfoConflictsWith.h @@ -25,42 +25,54 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoConflictsWith + + class ResolverInfoConflictsWith : public ResolverInfoContainer { + + REP_BODY(ResolverInfoConflictsWith); + + private: + + public: + + ResolverInfoConflictsWith (constResItemPtr resItem, constResItemPtr with); + virtual ~ResolverInfoConflictsWith(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoConflictsWith & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoConflictsWith & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + + // ---------------------------------- methods + + virtual ResolverInfoPtr copy (void) const; + }; -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoConflictsWith - -class ResolverInfoConflictsWith : public ResolverInfoContainer { - - REP_BODY(ResolverInfoConflictsWith); - - private: - - public: - - ResolverInfoConflictsWith (constResItemPtr resItem, constResItemPtr with); - virtual ~ResolverInfoConflictsWith(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoConflictsWith & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoConflictsWith & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - - // ---------------------------------- methods - - virtual ResolverInfoPtr copy (void) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoConflictsWith_h diff --git a/zypp/solver/detail/ResolverInfoConflictsWithPtr.h b/zypp/solver/detail/ResolverInfoConflictsWithPtr.h index 87ed3ce..ef6e062 100644 --- a/zypp/solver/detail/ResolverInfoConflictsWithPtr.h +++ b/zypp/solver/detail/ResolverInfoConflictsWithPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoConflictsWithPtr -// CLASS NAME : constResolverInfoConflictsWithPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoConflictsWith, ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoConflictsWithPtr + // CLASS NAME : constResolverInfoConflictsWithPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoConflictsWith, ResolverInfo); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoConflictsWithPtr_h diff --git a/zypp/solver/detail/ResolverInfoContainer.cc b/zypp/solver/detail/ResolverInfoContainer.cc index bf919b2..b0a48dd 100644 --- a/zypp/solver/detail/ResolverInfoContainer.cc +++ b/zypp/solver/detail/ResolverInfoContainer.cc @@ -23,179 +23,190 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoContainer, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoContainer::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoContainer::toString ( const ResolverInfoContainer & container ) -{ - string res = "asString(); - } - res += "'>"; - - return res; -} - - -ostream & -ResolverInfoContainer::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoContainer & container) -{ - return os << container.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoContainer::ResolverInfoContainer (ResolverInfoType type, constResItemPtr resItem, int priority, constResItemPtr child) - : ResolverInfo (type, resItem, priority) -{ - if (child != NULL) - _resItem_list.push_back (child); -} - - -ResolverInfoContainer::~ResolverInfoContainer () -{ -} - -//--------------------------------------------------------------------------- - -bool -ResolverInfoContainer::merge (ResolverInfoContainerPtr to_be_merged) -{ - bool res; - - res = ((ResolverInfoPtr)this)->merge ((ResolverInfoPtr)to_be_merged); - if (!res) return res; - - typedef std::map SeenTable; - SeenTable seen_packages; - - for (CResItemList::const_iterator iter = _resItem_list.begin(); iter != _resItem_list.end(); iter++) { - seen_packages[*iter] = true; - } - - CResItemList rl = to_be_merged->resItems(); - for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { - SeenTable::const_iterator pos = seen_packages.find(*iter); - if (pos == seen_packages.end()) { - _resItem_list.push_front (*iter); - seen_packages[*iter] = true; - } - } - - return true; -} - - -void -ResolverInfoContainer::copy (constResolverInfoContainerPtr from) -{ - ((ResolverInfoPtr)this)->copy(from); - - for (CResItemList::const_iterator iter = from->_resItem_list.begin(); iter != from->_resItem_list.end(); iter++) { - _resItem_list.push_back (*iter); - } -} - - -ResolverInfoPtr -ResolverInfoContainer::copy (void) const -{ - ResolverInfoContainerPtr cpy = new ResolverInfoContainer(type(), resItem(), priority()); - - cpy->copy (this); - - return cpy; -} - -//--------------------------------------------------------------------------- - -string -ResolverInfoContainer::resItemsToString (bool names_only) const -{ - string res; - - if (_resItem_list.empty()) - return res; - - res += " ["; - for (CResItemList::const_iterator iter = _resItem_list.begin(); iter != _resItem_list.end(); iter++) { - if (iter != _resItem_list.begin()) - res += ", "; - - res += (names_only ? (*iter)->name() : ((constSpecPtr)(*iter))->asString()); - } - res += "]"; - - return res; -} - - -bool -ResolverInfoContainer::mentions (constResItemPtr resItem) const -{ - if (isAbout(resItem)) - return true; - - // Search resItem_list for any mention of the resItem. - - for (CResItemList::const_iterator iter = _resItem_list.begin(); iter != _resItem_list.end(); iter++) { - if ((*iter)->name() == resItem->name()) { - return true; - } - } - - return false; -} - - -void -ResolverInfoContainer::addRelatedResItem (constResItemPtr resItem) -{ - if (!mentions(resItem)) { - _resItem_list.push_front (resItem); - } -} - - -void -ResolverInfoContainer::addRelatedResItemList (const CResItemList & resItems) -{ - for (CResItemList::const_iterator iter = resItems.begin(); iter != resItems.end(); iter++) { - _resItem_list.push_front (*iter); - } -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoContainer, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoContainer::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoContainer::toString ( const ResolverInfoContainer & container ) + { + string res = "asString(); + } + res += "'>"; + + return res; + } + + + ostream & + ResolverInfoContainer::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoContainer & container) + { + return os << container.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoContainer::ResolverInfoContainer (ResolverInfoType type, constResItemPtr resItem, int priority, constResItemPtr child) + : ResolverInfo (type, resItem, priority) + { + if (child != NULL) + _resItem_list.push_back (child); + } + + + ResolverInfoContainer::~ResolverInfoContainer () + { + } + + //--------------------------------------------------------------------------- + + bool + ResolverInfoContainer::merge (ResolverInfoContainerPtr to_be_merged) + { + bool res; + + res = ((ResolverInfoPtr)this)->merge ((ResolverInfoPtr)to_be_merged); + if (!res) return res; + + typedef std::map SeenTable; + SeenTable seen_packages; + + for (CResItemList::const_iterator iter = _resItem_list.begin(); iter != _resItem_list.end(); iter++) { + seen_packages[*iter] = true; + } + + CResItemList rl = to_be_merged->resItems(); + for (CResItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { + SeenTable::const_iterator pos = seen_packages.find(*iter); + if (pos == seen_packages.end()) { + _resItem_list.push_front (*iter); + seen_packages[*iter] = true; + } + } + + return true; + } + + + void + ResolverInfoContainer::copy (constResolverInfoContainerPtr from) + { + ((ResolverInfoPtr)this)->copy(from); + + for (CResItemList::const_iterator iter = from->_resItem_list.begin(); iter != from->_resItem_list.end(); iter++) { + _resItem_list.push_back (*iter); + } + } + + + ResolverInfoPtr + ResolverInfoContainer::copy (void) const + { + ResolverInfoContainerPtr cpy = new ResolverInfoContainer(type(), resItem(), priority()); + + cpy->copy (this); + + return cpy; + } + + //--------------------------------------------------------------------------- + + string + ResolverInfoContainer::resItemsToString (bool names_only) const + { + string res; + + if (_resItem_list.empty()) + return res; + + res += " ["; + for (CResItemList::const_iterator iter = _resItem_list.begin(); iter != _resItem_list.end(); iter++) { + if (iter != _resItem_list.begin()) + res += ", "; + + res += (names_only ? (*iter)->name() : ((constSpecPtr)(*iter))->asString()); + } + res += "]"; + + return res; + } + + + bool + ResolverInfoContainer::mentions (constResItemPtr resItem) const + { + if (isAbout(resItem)) + return true; + + // Search resItem_list for any mention of the resItem. + + for (CResItemList::const_iterator iter = _resItem_list.begin(); iter != _resItem_list.end(); iter++) { + if ((*iter)->name() == resItem->name()) { + return true; + } + } + + return false; + } + + + void + ResolverInfoContainer::addRelatedResItem (constResItemPtr resItem) + { + if (!mentions(resItem)) { + _resItem_list.push_front (resItem); + } + } + + + void + ResolverInfoContainer::addRelatedResItemList (const CResItemList & resItems) + { + for (CResItemList::const_iterator iter = resItems.begin(); iter != resItems.end(); iter++) { + _resItem_list.push_front (*iter); + } + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoContainer.h b/zypp/solver/detail/ResolverInfoContainer.h index cd53f04..646103a 100644 --- a/zypp/solver/detail/ResolverInfoContainer.h +++ b/zypp/solver/detail/ResolverInfoContainer.h @@ -29,58 +29,69 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoContainer - -class ResolverInfoContainer : public ResolverInfo { - - REP_BODY(ResolverInfoContainer); - - private: - - CResItemList _resItem_list; - - protected: - - ResolverInfoContainer (ResolverInfoType type, constResItemPtr resItem, int priority, constResItemPtr child = NULL); - - public: - virtual ~ResolverInfoContainer(); - - void copy (constResolverInfoContainerPtr from); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoContainer & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoContainer & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - CResItemList resItems (void) const { return _resItem_list; } - - // ---------------------------------- methods - - virtual bool merge (ResolverInfoContainerPtr to_be_merged); - virtual ResolverInfoPtr copy (void) const; - - std::string resItemsToString (bool names_only) const; - - bool mentions (constResItemPtr resItem) const; - void addRelatedResItem (constResItemPtr resItem); - void addRelatedResItemList (const CResItemList & resItems); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoContainer + + class ResolverInfoContainer : public ResolverInfo { + + REP_BODY(ResolverInfoContainer); + + private: + + CResItemList _resItem_list; + + protected: + + ResolverInfoContainer (ResolverInfoType type, constResItemPtr resItem, int priority, constResItemPtr child = NULL); + + public: + virtual ~ResolverInfoContainer(); + + void copy (constResolverInfoContainerPtr from); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoContainer & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoContainer & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + CResItemList resItems (void) const { return _resItem_list; } + + // ---------------------------------- methods + + virtual bool merge (ResolverInfoContainerPtr to_be_merged); + virtual ResolverInfoPtr copy (void) const; + + std::string resItemsToString (bool names_only) const; + + bool mentions (constResItemPtr resItem) const; + void addRelatedResItem (constResItemPtr resItem); + void addRelatedResItemList (const CResItemList & resItems); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoContainer_h diff --git a/zypp/solver/detail/ResolverInfoContainerPtr.h b/zypp/solver/detail/ResolverInfoContainerPtr.h index 9a71e38..6cf5c0d 100644 --- a/zypp/solver/detail/ResolverInfoContainerPtr.h +++ b/zypp/solver/detail/ResolverInfoContainerPtr.h @@ -24,18 +24,29 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoContainerPtr -// CLASS NAME : constResolverInfoContainerPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoContainer,ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoContainerPtr + // CLASS NAME : constResolverInfoContainerPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoContainer,ResolverInfo); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoContainerPtr_h diff --git a/zypp/solver/detail/ResolverInfoDependsOn.cc b/zypp/solver/detail/ResolverInfoDependsOn.cc index f4a36d4..ca069f8 100644 --- a/zypp/solver/detail/ResolverInfoDependsOn.cc +++ b/zypp/solver/detail/ResolverInfoDependsOn.cc @@ -24,77 +24,88 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoDependsOn, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoDependsOn::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoDependsOn::toString ( const ResolverInfoDependsOn & on) -{ - string res; - - res += ResolverInfo::toString (on); - res += string ("depended on ") + on.resItemsToString(false); - - return res; -} - - -ostream & -ResolverInfoDependsOn::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoDependsOn & on) -{ - return os << on.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoDependsOn::ResolverInfoDependsOn (constResItemPtr resItem, constResItemPtr on) - : ResolverInfoContainer (RESOLVER_INFO_TYPE_DEPENDS_ON, resItem, RESOLVER_INFO_PRIORITY_USER, on) -{ -} - - -ResolverInfoDependsOn::~ResolverInfoDependsOn () -{ -} - -//--------------------------------------------------------------------------- - -ResolverInfoPtr -ResolverInfoDependsOn::copy (void) const -{ - ResolverInfoDependsOnPtr cpy = new ResolverInfoDependsOn(resItem(), NULL); - - ((ResolverInfoContainerPtr)cpy)->copy (this); - - return cpy; -} - -//--------------------------------------------------------------------------- - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoDependsOn, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoDependsOn::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoDependsOn::toString ( const ResolverInfoDependsOn & on) + { + string res; + + res += ResolverInfo::toString (on); + res += string ("depended on ") + on.resItemsToString(false); + + return res; + } + + + ostream & + ResolverInfoDependsOn::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoDependsOn & on) + { + return os << on.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoDependsOn::ResolverInfoDependsOn (constResItemPtr resItem, constResItemPtr on) + : ResolverInfoContainer (RESOLVER_INFO_TYPE_DEPENDS_ON, resItem, RESOLVER_INFO_PRIORITY_USER, on) + { + } + + + ResolverInfoDependsOn::~ResolverInfoDependsOn () + { + } + + //--------------------------------------------------------------------------- + + ResolverInfoPtr + ResolverInfoDependsOn::copy (void) const + { + ResolverInfoDependsOnPtr cpy = new ResolverInfoDependsOn(resItem(), NULL); + + ((ResolverInfoContainerPtr)cpy)->copy (this); + + return cpy; + } + + //--------------------------------------------------------------------------- + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoDependsOn.h b/zypp/solver/detail/ResolverInfoDependsOn.h index 6645975..8a45d18 100644 --- a/zypp/solver/detail/ResolverInfoDependsOn.h +++ b/zypp/solver/detail/ResolverInfoDependsOn.h @@ -26,42 +26,55 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoDependsOn + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoDependsOn + + class ResolverInfoDependsOn : public ResolverInfoContainer { + + REP_BODY(ResolverInfoDependsOn); + + private: + + public: + + ResolverInfoDependsOn (constResItemPtr resItem, constResItemPtr on); + virtual ~ResolverInfoDependsOn(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoDependsOn & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoDependsOn & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + virtual ResolverInfoPtr copy (void) const; + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -class ResolverInfoDependsOn : public ResolverInfoContainer { - - REP_BODY(ResolverInfoDependsOn); - - private: - - public: - - ResolverInfoDependsOn (constResItemPtr resItem, constResItemPtr on); - virtual ~ResolverInfoDependsOn(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoDependsOn & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoDependsOn & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - virtual ResolverInfoPtr copy (void) const; - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ResolverInfoDependsOn_h diff --git a/zypp/solver/detail/ResolverInfoDependsOnPtr.h b/zypp/solver/detail/ResolverInfoDependsOnPtr.h index 6b90ada..e5a987b 100644 --- a/zypp/solver/detail/ResolverInfoDependsOnPtr.h +++ b/zypp/solver/detail/ResolverInfoDependsOnPtr.h @@ -24,18 +24,31 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoDependsOnPtr -// CLASS NAME : constResolverInfoDependsOnPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoDependsOn, ResolverInfo); + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoDependsOnPtr + // CLASS NAME : constResolverInfoDependsOnPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoDependsOn, ResolverInfo); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ResolverInfoDependsOnPtr_h diff --git a/zypp/solver/detail/ResolverInfoMisc.cc b/zypp/solver/detail/ResolverInfoMisc.cc index ed6ee58..640eed8 100644 --- a/zypp/solver/detail/ResolverInfoMisc.cc +++ b/zypp/solver/detail/ResolverInfoMisc.cc @@ -24,121 +24,132 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoMisc, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoMisc::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoMisc::toString ( const ResolverInfoMisc & misc) -{ - string res; - res += misc._msg; -#if 0 - res += " ["; - res += ResolverInfo::toString (misc, false); - res += "]"; -#endif - res += misc.resItemsToString(false); - if (!misc._action.empty()) { - res += string (", Action: ") + misc._action + "\n"; - } - if (!misc._trigger.empty()) { - res += string (", Trigger: ") + misc._trigger + "\n"; - } - - return res; -} - - -ostream & -ResolverInfoMisc::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoMisc & misc) -{ - return os << misc.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoMisc::ResolverInfoMisc (constResItemPtr resItem, int priority, const string & msg) - : ResolverInfoContainer (RESOLVER_INFO_TYPE_MISC, resItem, priority) - , _msg (msg) -{ -} - - -ResolverInfoMisc::~ResolverInfoMisc () -{ -} - -//--------------------------------------------------------------------------- - -bool -ResolverInfoMisc::merge (ResolverInfoPtr info) -{ - bool res; - ResolverInfoMiscPtr to_be_merged = info; - - res = ((ResolverInfoPtr)this)->merge ((ResolverInfoPtr)to_be_merged); - if (!res) return res; - - if (!_msg.empty() - && !to_be_merged->_msg.empty() - && _msg == to_be_merged->_msg) { - return true; - } - - return false; -} - - -ResolverInfoPtr -ResolverInfoMisc::copy (void) const -{ - ResolverInfoMiscPtr cpy = new ResolverInfoMisc(resItem(), priority(), _msg); - - ((ResolverInfoContainerPtr)cpy)->copy (this); - - return cpy; -} - -//--------------------------------------------------------------------------- - -void -ResolverInfoMisc::addAction (const std::string & action_msg) -{ - _action = action_msg; -} - - -void -ResolverInfoMisc::addTrigger (const std::string & trigger_msg) -{ - _trigger = trigger_msg; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoMisc, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoMisc::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoMisc::toString ( const ResolverInfoMisc & misc) + { + string res; + res += misc._msg; + #if 0 + res += " ["; + res += ResolverInfo::toString (misc, false); + res += "]"; + #endif + res += misc.resItemsToString(false); + if (!misc._action.empty()) { + res += string (", Action: ") + misc._action + "\n"; + } + if (!misc._trigger.empty()) { + res += string (", Trigger: ") + misc._trigger + "\n"; + } + + return res; + } + + + ostream & + ResolverInfoMisc::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoMisc & misc) + { + return os << misc.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoMisc::ResolverInfoMisc (constResItemPtr resItem, int priority, const string & msg) + : ResolverInfoContainer (RESOLVER_INFO_TYPE_MISC, resItem, priority) + , _msg (msg) + { + } + + + ResolverInfoMisc::~ResolverInfoMisc () + { + } + + //--------------------------------------------------------------------------- + + bool + ResolverInfoMisc::merge (ResolverInfoPtr info) + { + bool res; + ResolverInfoMiscPtr to_be_merged = info; + + res = ((ResolverInfoPtr)this)->merge ((ResolverInfoPtr)to_be_merged); + if (!res) return res; + + if (!_msg.empty() + && !to_be_merged->_msg.empty() + && _msg == to_be_merged->_msg) { + return true; + } + + return false; + } + + + ResolverInfoPtr + ResolverInfoMisc::copy (void) const + { + ResolverInfoMiscPtr cpy = new ResolverInfoMisc(resItem(), priority(), _msg); + + ((ResolverInfoContainerPtr)cpy)->copy (this); + + return cpy; + } + + //--------------------------------------------------------------------------- + + void + ResolverInfoMisc::addAction (const std::string & action_msg) + { + _action = action_msg; + } + + + void + ResolverInfoMisc::addTrigger (const std::string & trigger_msg) + { + _trigger = trigger_msg; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoMisc.h b/zypp/solver/detail/ResolverInfoMisc.h index e557623..d1ada17 100644 --- a/zypp/solver/detail/ResolverInfoMisc.h +++ b/zypp/solver/detail/ResolverInfoMisc.h @@ -26,50 +26,62 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoMisc - -class ResolverInfoMisc : public ResolverInfoContainer { - - REP_BODY(ResolverInfoMisc); - - private: - - std::string _msg; - std::string _action; - std::string _trigger; - - public: - - ResolverInfoMisc (constResItemPtr resItem, int priority, const std::string & msg); - virtual ~ResolverInfoMisc(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoMisc & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoMisc & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - virtual bool merge (ResolverInfoPtr to_be_merged); - virtual ResolverInfoPtr copy (void) const; - - void addAction (const std::string & action_msg); - void addTrigger (const std::string & trigger_msg); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoMisc + + class ResolverInfoMisc : public ResolverInfoContainer { + + REP_BODY(ResolverInfoMisc); + + private: + + std::string _msg; + std::string _action; + std::string _trigger; + + public: + + ResolverInfoMisc (constResItemPtr resItem, int priority, const std::string & msg); + virtual ~ResolverInfoMisc(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoMisc & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoMisc & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + virtual bool merge (ResolverInfoPtr to_be_merged); + virtual ResolverInfoPtr copy (void) const; + + void addAction (const std::string & action_msg); + void addTrigger (const std::string & trigger_msg); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoMisc_h diff --git a/zypp/solver/detail/ResolverInfoMiscPtr.h b/zypp/solver/detail/ResolverInfoMiscPtr.h index 7bb1321..bbf48a7 100644 --- a/zypp/solver/detail/ResolverInfoMiscPtr.h +++ b/zypp/solver/detail/ResolverInfoMiscPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoMiscPtr + // CLASS NAME : constResolverInfoMiscPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoMisc, ResolverInfo); -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoMiscPtr -// CLASS NAME : constResolverInfoMiscPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoMisc, ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoMiscPtr_h diff --git a/zypp/solver/detail/ResolverInfoMissingReq.cc b/zypp/solver/detail/ResolverInfoMissingReq.cc index 0f3770e..4a495ba 100644 --- a/zypp/solver/detail/ResolverInfoMissingReq.cc +++ b/zypp/solver/detail/ResolverInfoMissingReq.cc @@ -24,76 +24,88 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoMissingReq, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoMissingReq::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoMissingReq::toString ( const ResolverInfoMissingReq & missing) + { + string res; + + res += ResolverInfo::toString (missing); + res += string ("missing requirement ") + missing._missing_req->asString(); + + return res; + } + + + ostream & + ResolverInfoMissingReq::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoMissingReq & missing) + { + return os << missing.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoMissingReq::ResolverInfoMissingReq (constResItemPtr resItem, constDependencyPtr missing_req) + : ResolverInfo (RESOLVER_INFO_TYPE_MISSING_REQ, resItem, RESOLVER_INFO_PRIORITY_USER) + , _missing_req (missing_req) + { + } + + + ResolverInfoMissingReq::~ResolverInfoMissingReq () + { + } + + //--------------------------------------------------------------------------- + + ResolverInfoPtr + ResolverInfoMissingReq::copy (void) const + { + ResolverInfoMissingReqPtr cpy = new ResolverInfoMissingReq(resItem(), _missing_req); + + ((ResolverInfoPtr)cpy)->copy (this); + + return cpy; + } + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoMissingReq, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoMissingReq::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoMissingReq::toString ( const ResolverInfoMissingReq & missing) -{ - string res; - - res += ResolverInfo::toString (missing); - res += string ("missing requirement ") + missing._missing_req->asString(); - - return res; -} - - -ostream & -ResolverInfoMissingReq::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoMissingReq & missing) -{ - return os << missing.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoMissingReq::ResolverInfoMissingReq (constResItemPtr resItem, constDependencyPtr missing_req) - : ResolverInfo (RESOLVER_INFO_TYPE_MISSING_REQ, resItem, RESOLVER_INFO_PRIORITY_USER) - , _missing_req (missing_req) -{ -} - - -ResolverInfoMissingReq::~ResolverInfoMissingReq () -{ -} - -//--------------------------------------------------------------------------- - -ResolverInfoPtr -ResolverInfoMissingReq::copy (void) const -{ - ResolverInfoMissingReqPtr cpy = new ResolverInfoMissingReq(resItem(), _missing_req); - - ((ResolverInfoPtr)cpy)->copy (this); - - return cpy; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoMissingReq.h b/zypp/solver/detail/ResolverInfoMissingReq.h index 7f52c89..270d1c1 100644 --- a/zypp/solver/detail/ResolverInfoMissingReq.h +++ b/zypp/solver/detail/ResolverInfoMissingReq.h @@ -25,44 +25,56 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoMissingReq - -class ResolverInfoMissingReq : public ResolverInfo { - - REP_BODY(ResolverInfoMissingReq); - - private: - - constDependencyPtr _missing_req; - - public: - - ResolverInfoMissingReq (constResItemPtr resItem, constDependencyPtr missing_req); - virtual ~ResolverInfoMissingReq(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoMissingReq & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoMissingReq & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - virtual ResolverInfoPtr copy (void) const; - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoMissingReq + + class ResolverInfoMissingReq : public ResolverInfo { + + REP_BODY(ResolverInfoMissingReq); + + private: + + constDependencyPtr _missing_req; + + public: + + ResolverInfoMissingReq (constResItemPtr resItem, constDependencyPtr missing_req); + virtual ~ResolverInfoMissingReq(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoMissingReq & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoMissingReq & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + virtual ResolverInfoPtr copy (void) const; + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoMissingReq_h diff --git a/zypp/solver/detail/ResolverInfoMissingReqPtr.h b/zypp/solver/detail/ResolverInfoMissingReqPtr.h index c2cefae..b39463c 100644 --- a/zypp/solver/detail/ResolverInfoMissingReqPtr.h +++ b/zypp/solver/detail/ResolverInfoMissingReqPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoMissingReqPtr -// CLASS NAME : constResolverInfoMissingReqPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoMissingReq, ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoMissingReqPtr + // CLASS NAME : constResolverInfoMissingReqPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoMissingReq, ResolverInfo); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoMissingReqPtr_h diff --git a/zypp/solver/detail/ResolverInfoNeededBy.cc b/zypp/solver/detail/ResolverInfoNeededBy.cc index 3978b72..6bc3250 100644 --- a/zypp/solver/detail/ResolverInfoNeededBy.cc +++ b/zypp/solver/detail/ResolverInfoNeededBy.cc @@ -24,76 +24,87 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoNeededBy, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoNeededBy::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoNeededBy::toString ( const ResolverInfoNeededBy & by) -{ - string res; - - res += ResolverInfo::toString (by, false); - res += string (" needed by ") + by.resItemsToString(false); - - return res; -} - - -ostream & -ResolverInfoNeededBy::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoNeededBy & by) -{ - return os << by.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoNeededBy::ResolverInfoNeededBy (constResItemPtr resItem) - : ResolverInfoContainer (RESOLVER_INFO_TYPE_NEEDED_BY, resItem, RESOLVER_INFO_PRIORITY_USER, NULL) -{ -} - - -ResolverInfoNeededBy::~ResolverInfoNeededBy () -{ -} - -//--------------------------------------------------------------------------- - -ResolverInfoPtr -ResolverInfoNeededBy::copy (void) const -{ - ResolverInfoNeededByPtr cpy = new ResolverInfoNeededBy(resItem()); - - ((ResolverInfoContainerPtr)cpy)->copy (this); - - return cpy; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoNeededBy, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoNeededBy::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoNeededBy::toString ( const ResolverInfoNeededBy & by) + { + string res; + + res += ResolverInfo::toString (by, false); + res += string (" needed by ") + by.resItemsToString(false); + + return res; + } + + + ostream & + ResolverInfoNeededBy::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoNeededBy & by) + { + return os << by.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoNeededBy::ResolverInfoNeededBy (constResItemPtr resItem) + : ResolverInfoContainer (RESOLVER_INFO_TYPE_NEEDED_BY, resItem, RESOLVER_INFO_PRIORITY_USER, NULL) + { + } + + + ResolverInfoNeededBy::~ResolverInfoNeededBy () + { + } + + //--------------------------------------------------------------------------- + + ResolverInfoPtr + ResolverInfoNeededBy::copy (void) const + { + ResolverInfoNeededByPtr cpy = new ResolverInfoNeededBy(resItem()); + + ((ResolverInfoContainerPtr)cpy)->copy (this); + + return cpy; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoNeededBy.h b/zypp/solver/detail/ResolverInfoNeededBy.h index a636ecd..013b883 100644 --- a/zypp/solver/detail/ResolverInfoNeededBy.h +++ b/zypp/solver/detail/ResolverInfoNeededBy.h @@ -25,41 +25,53 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoNeededBy + + class ResolverInfoNeededBy : public ResolverInfoContainer { + + REP_BODY(ResolverInfoNeededBy); + + private: + + public: + + ResolverInfoNeededBy (constResItemPtr resItem); + virtual ~ResolverInfoNeededBy(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoNeededBy & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoNeededBy & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + virtual ResolverInfoPtr copy (void) const; + }; -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoNeededBy - -class ResolverInfoNeededBy : public ResolverInfoContainer { - - REP_BODY(ResolverInfoNeededBy); - - private: - - public: - - ResolverInfoNeededBy (constResItemPtr resItem); - virtual ~ResolverInfoNeededBy(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoNeededBy & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoNeededBy & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - virtual ResolverInfoPtr copy (void) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoNeededBy_h diff --git a/zypp/solver/detail/ResolverInfoNeededByPtr.h b/zypp/solver/detail/ResolverInfoNeededByPtr.h index ba884d0..0a030fe 100644 --- a/zypp/solver/detail/ResolverInfoNeededByPtr.h +++ b/zypp/solver/detail/ResolverInfoNeededByPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoNeededByPtr -// CLASS NAME : constResolverInfoNeededByPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoNeededBy, ResolverInfo); + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoNeededByPtr + // CLASS NAME : constResolverInfoNeededByPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoNeededBy, ResolverInfo); -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoNeededByPtr_h diff --git a/zypp/solver/detail/ResolverInfoObsoletes.cc b/zypp/solver/detail/ResolverInfoObsoletes.cc index 2f39ff1..1dca16c 100644 --- a/zypp/solver/detail/ResolverInfoObsoletes.cc +++ b/zypp/solver/detail/ResolverInfoObsoletes.cc @@ -24,76 +24,87 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ResolverInfoObsoletes, ResolverInfo); - -//--------------------------------------------------------------------------- - - -string -ResolverInfoObsoletes::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverInfoObsoletes::toString ( const ResolverInfoObsoletes & obsoletes) -{ - string res; - - res += ResolverInfo::toString (obsoletes); - res += string ("replaced by ") + obsoletes.resItemsToString(false); - - return res; -} - - -ostream & -ResolverInfoObsoletes::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverInfoObsoletes & obsoletes) -{ - return os << obsoletes.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverInfoObsoletes::ResolverInfoObsoletes (constResItemPtr resItem, constResItemPtr obsoletes) - : ResolverInfoContainer (RESOLVER_INFO_TYPE_OBSOLETES, resItem, RESOLVER_INFO_PRIORITY_USER, obsoletes) -{ -} - - -ResolverInfoObsoletes::~ResolverInfoObsoletes () -{ -} - -//--------------------------------------------------------------------------- - -ResolverInfoPtr -ResolverInfoObsoletes::copy (void) const -{ - ResolverInfoObsoletesPtr cpy = new ResolverInfoObsoletes(resItem(), NULL); - - ((ResolverInfoContainerPtr)cpy)->copy (this); - - return cpy; -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ResolverInfoObsoletes, ResolverInfo); + + //--------------------------------------------------------------------------- + + + string + ResolverInfoObsoletes::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverInfoObsoletes::toString ( const ResolverInfoObsoletes & obsoletes) + { + string res; + + res += ResolverInfo::toString (obsoletes); + res += string ("replaced by ") + obsoletes.resItemsToString(false); + + return res; + } + + + ostream & + ResolverInfoObsoletes::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverInfoObsoletes & obsoletes) + { + return os << obsoletes.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverInfoObsoletes::ResolverInfoObsoletes (constResItemPtr resItem, constResItemPtr obsoletes) + : ResolverInfoContainer (RESOLVER_INFO_TYPE_OBSOLETES, resItem, RESOLVER_INFO_PRIORITY_USER, obsoletes) + { + } + + + ResolverInfoObsoletes::~ResolverInfoObsoletes () + { + } + + //--------------------------------------------------------------------------- + + ResolverInfoPtr + ResolverInfoObsoletes::copy (void) const + { + ResolverInfoObsoletesPtr cpy = new ResolverInfoObsoletes(resItem(), NULL); + + ((ResolverInfoContainerPtr)cpy)->copy (this); + + return cpy; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverInfoObsoletes.h b/zypp/solver/detail/ResolverInfoObsoletes.h index 02e1f69..dfd0868 100644 --- a/zypp/solver/detail/ResolverInfoObsoletes.h +++ b/zypp/solver/detail/ResolverInfoObsoletes.h @@ -25,42 +25,52 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverInfoObsoletes - -class ResolverInfoObsoletes : public ResolverInfoContainer { - - REP_BODY(ResolverInfoObsoletes); - - private: - - public: - - ResolverInfoObsoletes (constResItemPtr resItem, constResItemPtr obsoletes); - virtual ~ResolverInfoObsoletes(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverInfoObsoletes & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverInfoObsoletes & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - virtual ResolverInfoPtr copy (void) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverInfoObsoletes + + class ResolverInfoObsoletes : public ResolverInfoContainer { + + REP_BODY(ResolverInfoObsoletes); + + private: + + public: + + ResolverInfoObsoletes (constResItemPtr resItem, constResItemPtr obsoletes); + virtual ~ResolverInfoObsoletes(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverInfoObsoletes & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverInfoObsoletes & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + virtual ResolverInfoPtr copy (void) const; + }; + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoObsoletes_h diff --git a/zypp/solver/detail/ResolverInfoObsoletesPtr.h b/zypp/solver/detail/ResolverInfoObsoletesPtr.h index b78b020..cc2a597 100644 --- a/zypp/solver/detail/ResolverInfoObsoletesPtr.h +++ b/zypp/solver/detail/ResolverInfoObsoletesPtr.h @@ -24,18 +24,31 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoObsoletesPtr + // CLASS NAME : constResolverInfoObsoletesPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ResolverInfoObsoletes, ResolverInfo); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoObsoletesPtr -// CLASS NAME : constResolverInfoObsoletesPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ResolverInfoObsoletes, ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ResolverInfoObsoletesPtr_h diff --git a/zypp/solver/detail/ResolverInfoPtr.h b/zypp/solver/detail/ResolverInfoPtr.h index 89a96da..476457f 100644 --- a/zypp/solver/detail/ResolverInfoPtr.h +++ b/zypp/solver/detail/ResolverInfoPtr.h @@ -23,18 +23,30 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverInfoPtr -// CLASS NAME : constResolverInfoPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(ResolverInfo); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverInfoPtr + // CLASS NAME : constResolverInfoPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(ResolverInfo); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _ResolverInfoPtr_h diff --git a/zypp/solver/detail/ResolverPtr.h b/zypp/solver/detail/ResolverPtr.h index 617c44e..d8b0f30 100644 --- a/zypp/solver/detail/ResolverPtr.h +++ b/zypp/solver/detail/ResolverPtr.h @@ -23,18 +23,30 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverPtr + // CLASS NAME : constResolverPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Resolver); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverPtr -// CLASS NAME : constResolverPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Resolver); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ResolverPtr_h diff --git a/zypp/solver/detail/ResolverQueue.cc b/zypp/solver/detail/ResolverQueue.cc index ff07750..16a5ec1 100644 --- a/zypp/solver/detail/ResolverQueue.cc +++ b/zypp/solver/detail/ResolverQueue.cc @@ -33,414 +33,426 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(ResolverQueue); - -//--------------------------------------------------------------------------- - - -//--------------------------------------------------------------------------- - -string -ResolverQueue::asString ( void ) const -{ - return toString (*this); -} - - -string -ResolverQueue::toString ( const ResolverQueue & resolverqueue ) -{ - string res; - - res += stringutil::form ("Context [%p]", (const void *)resolverqueue._context); - res += ", Items:\n\t"; - res += QueueItem::toString (resolverqueue._items, ",\n\t"); - - return res; -} - - -ostream & -ResolverQueue::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ResolverQueue & resolverqueue) -{ - return os << resolverqueue.asString(); -} - -//--------------------------------------------------------------------------- - -ResolverQueue::ResolverQueue (ResolverContextPtr context) - : _context (context) -{ - if (context == NULL) - _context = new ResolverContext(); -} - - -ResolverQueue::~ResolverQueue() -{ -} - -//--------------------------------------------------------------------------- - -void -ResolverQueue::addResItemToInstall (constResItemPtr resItem) -{ - QueueItemInstallPtr item; - - if (_context->resItemIsPresent (resItem)) { - printf ("%s is already installed", ((constSpecPtr)resItem)->asString().c_str()); - return; - } - - item = new QueueItemInstall (_context->world(), resItem); - item->setExplicitlyRequested (); - - addItem (item); -} - - -void -ResolverQueue::addResItemToRemove (constResItemPtr resItem, bool remove_only_mode) -{ - QueueItemUninstallPtr item; - - if (_context->resItemIsAbsent (resItem)) - return; - - item = new QueueItemUninstall (_context->world(), resItem, "user request"); - if (remove_only_mode) - item->setRemoveOnly (); - - item->setExplicitlyRequested (); - - addItem (item); -} - - -void -ResolverQueue::addResItemToVerify (constResItemPtr resItem) -{ - WorldPtr world; - - world = _context->world (); - - CDependencyList requires = resItem->requires(); - for (CDependencyList::const_iterator iter = requires.begin(); iter != requires.end(); iter++) { - QueueItemRequirePtr item = new QueueItemRequire (world, *iter); - item->addResItem (resItem); - addItem (item); - } - - CDependencyList conflicts = resItem->conflicts(); - for (CDependencyList::const_iterator iter = conflicts.begin(); iter != conflicts.end(); iter++) { - QueueItemConflictPtr item = new QueueItemConflict (world, *iter, resItem); - addItem (item); - } -} - - -void -ResolverQueue::addExtraDependency (constDependencyPtr dep) -{ - QueueItemRequirePtr item = new QueueItemRequire (_context->world(), dep); - addItem (item); -} - - -void -ResolverQueue::addExtraConflict (constDependencyPtr dep) -{ - QueueItemConflictPtr item = new QueueItemConflict (_context->world(), dep, NULL); - addItem (item); -} - - -void -ResolverQueue::addItem (QueueItemPtr item) -{ - _items.push_front (item); -} - - -bool -ResolverQueue::isInvalid () -{ - return _context->isInvalid(); -} - - -bool -ResolverQueue::containsOnlyBranches () -{ - for (QueueItemList::const_iterator iter = _items.begin(); iter != _items.end(); iter++) { - if (!(*iter)->isBranch()) - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- - -static int -itemlist_max_priority (const QueueItemList & qil) -{ - int max_priority = -1; - for (QueueItemList::const_iterator iter = qil.begin(); iter != qil.end(); iter++) { - if ((*iter)->priority() > max_priority) { - max_priority = (*iter)->priority(); - } - } - - return max_priority; -} - - - -bool -ResolverQueue::processOnce () -{ - QueueItemList new_items; - int max_priority; - bool did_something = false; - - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce(%s), %d items\n", asString().c_str(), (int) _items.size()); - while ( (max_priority = itemlist_max_priority (_items)) >= 0 - && _context->isValid () ) { - - bool did_something_recently = false; - - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce() inside loop\n"); - for (QueueItemList::iterator iter = _items.begin(); iter != _items.end() && _context->isValid();) { - QueueItemPtr item = *iter; - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "=====> 1st pass: [%s]\n", item->asString().c_str()); - QueueItemList::iterator next = iter; next++; - if (item && item->priority() == max_priority) { - if (item->process (_context, new_items)) { - did_something_recently = true; - } - _items.erase (iter); - } - iter = next; - } - - if (did_something_recently) { - did_something = true; - } - } - - _items = new_items; - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "%d items after first pass\n", (int) _items.size()); - - /* - Now make a second pass over the queue, removing any super-branches. - (If one branch contains all of the possible items of another branch, - the larger branch can be dropped. - */ - -// if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce() second pass\n"); - for (QueueItemList::iterator iter = _items.begin(); iter != _items.end();) { - QueueItemList::iterator next = iter; next++; - QueueItemPtr item = *iter; - - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "=====> 2nd pass: [%s]\n", item->asString().c_str()); - if (item->isBranch()) { - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce() is branch\n"); - QueueItemBranchPtr branch = (QueueItemBranchPtr)item; - for (QueueItemList::const_iterator iter2 = _items.begin(); iter2 != _items.end(); iter2++) { - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "Compare branch with [%s]\n", (*iter2)->asString().c_str()); - if (iter != iter2 - && branch->contains (*iter2)) { - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "Contained within, removing\n"); - _items.erase (iter); - break; - } - } - } - iter = next; - } - if (getenv ("QUEUE_SPEW")) fprintf (stderr, "did %sthing: %d items\n", did_something ? "some" : "no", (int)_items.size()); - - return did_something; -} - - -void -ResolverQueue::process () -{ - bool very_noisy; - - very_noisy = getenv ("RC_SPEW") != NULL; - - if (very_noisy) { - printf ("----- Processing -----\n"); - spew (); - } - - while (_context->isValid () - && ! isEmpty () - && processOnce ()) { - /* all of the work is in the conditional! */ - if (very_noisy) { - spew (); - } - } -} - - -//--------------------------------------------------------------------------- - -static ResolverQueuePtr -copy_queue_except_for_branch (ResolverQueuePtr queue, QueueItemPtr branch_item, QueueItemPtr subitem) -{ - ResolverContextPtr new_context; - ResolverQueuePtr new_queue; - - new_context = new ResolverContext (queue->context()); - new_queue = new ResolverQueue (new_context); - - QueueItemList qil = queue->items(); - for (QueueItemList::const_iterator iter = qil.begin(); iter != qil.end(); iter++) { - QueueItemPtr item = *iter; - QueueItemPtr new_item; - - if (item == branch_item) { - new_item = subitem->copy (); - - if (new_item->isInstall()) { - QueueItemInstallPtr install_item = (QueueItemInstallPtr)new_item; - - /* Penalties are negative priorities */ - int penalty; - penalty = - queue->context()->getChannelPriority (install_item->resItem()->channel()); - - install_item->setOtherPenalty (penalty); - } - - } else { - - new_item = item->copy (); - - } - - new_queue->addItem (new_item); - } - - return new_queue; -} - - -void -ResolverQueue::splitFirstBranch (ResolverQueueList & new_queues, ResolverQueueList & deferred_queues) -{ - QueueItemBranchPtr first_branch = NULL; - typedef std::map DeferTable; - DeferTable to_defer; - - for (QueueItemList::const_iterator iter = _items.begin(); iter != _items.end() && first_branch == NULL; iter++) { - QueueItemPtr item = *iter; - if (item->isBranch()) { - first_branch = (QueueItemBranchPtr)item; - } - } - - if (first_branch == NULL) - return; - - /* - Check for deferrable items: if we have two install items where the to-be-installed - resItems have the same name, then we will defer the lower-priority install if - one of the following is true: - (1) Both resItems have the same version - (2) The lower-priority channel is a previous version. - */ - - QueueItemList possible_items = first_branch->possibleItems(); - for (QueueItemList::const_iterator iter = possible_items.begin(); iter != possible_items.end(); iter++) { - QueueItemList::const_iterator iter2 = iter; - for (iter2++; iter2 != possible_items.end(); iter2++) { - QueueItemPtr item = *iter; - QueueItemPtr item2 = *iter2; - - if (item->isInstall() && item2->isInstall()) { - constResItemPtr r = ((QueueItemInstallPtr) item)->resItem(); - constResItemPtr r2 = ((QueueItemInstallPtr) item2)->resItem(); - constChannelPtr channel = r->channel(); - constChannelPtr channel2 = r2->channel(); - int priority, priority2; - - priority = channel->getPriority (channel->isSubscribed()); - priority2 = channel2->getPriority (channel2->isSubscribed()); - - if (priority != priority2 && r->name() == r2->name()) { - if (r->version() == r2->version() - || (priority < priority2 && GVersion.compare (r, r2) < 0) - || (priority > priority2 && GVersion.compare (r, r2) > 0)) { - - if (priority < priority2) - to_defer[item] = item; - else /* if (priority > priority2) */ - to_defer[item2] = item2; - } - } - } - } - } - - - for (QueueItemList::const_iterator iter = possible_items.begin(); iter != possible_items.end(); iter++) { - ResolverQueuePtr new_queue; - QueueItemPtr new_item = *iter; - - new_queue = copy_queue_except_for_branch (this, (QueueItemPtr) first_branch, new_item); - - DeferTable::const_iterator pos = to_defer.find (new_item); - if (pos != to_defer.end()) { - deferred_queues.push_back (new_queue); - } else { - new_queues.push_back (new_queue); - } - } - -} - - -void -ResolverQueue::spew () -{ - printf ("Resolver Queue: %s\n", _context->isInvalid() ? "INVALID" : ""); - - if (_items.empty()) { - - printf (" (empty)\n"); - - } else { - - for (QueueItemList::const_iterator iter = _items.begin(); iter != _items.end(); iter++) { - printf (" %s\n", (*iter)->asString().c_str()); - } - - } - - printf ("\n"); - fflush (stdout); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(ResolverQueue); + + //--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- + + string + ResolverQueue::asString ( void ) const + { + return toString (*this); + } + + + string + ResolverQueue::toString ( const ResolverQueue & resolverqueue ) + { + string res; + + res += stringutil::form ("Context [%p]", (const void *)resolverqueue._context); + res += ", Items:\n\t"; + res += QueueItem::toString (resolverqueue._items, ",\n\t"); + + return res; + } + + + ostream & + ResolverQueue::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ResolverQueue & resolverqueue) + { + return os << resolverqueue.asString(); + } + + //--------------------------------------------------------------------------- + + ResolverQueue::ResolverQueue (ResolverContextPtr context) + : _context (context) + { + if (context == NULL) + _context = new ResolverContext(); + } + + + ResolverQueue::~ResolverQueue() + { + } + + //--------------------------------------------------------------------------- + + void + ResolverQueue::addResItemToInstall (constResItemPtr resItem) + { + QueueItemInstallPtr item; + + if (_context->resItemIsPresent (resItem)) { + printf ("%s is already installed", ((constSpecPtr)resItem)->asString().c_str()); + return; + } + + item = new QueueItemInstall (_context->world(), resItem); + item->setExplicitlyRequested (); + + addItem (item); + } + + + void + ResolverQueue::addResItemToRemove (constResItemPtr resItem, bool remove_only_mode) + { + QueueItemUninstallPtr item; + + if (_context->resItemIsAbsent (resItem)) + return; + + item = new QueueItemUninstall (_context->world(), resItem, "user request"); + if (remove_only_mode) + item->setRemoveOnly (); + + item->setExplicitlyRequested (); + + addItem (item); + } + + + void + ResolverQueue::addResItemToVerify (constResItemPtr resItem) + { + WorldPtr world; + + world = _context->world (); + + CDependencyList requires = resItem->requires(); + for (CDependencyList::const_iterator iter = requires.begin(); iter != requires.end(); iter++) { + QueueItemRequirePtr item = new QueueItemRequire (world, *iter); + item->addResItem (resItem); + addItem (item); + } + + CDependencyList conflicts = resItem->conflicts(); + for (CDependencyList::const_iterator iter = conflicts.begin(); iter != conflicts.end(); iter++) { + QueueItemConflictPtr item = new QueueItemConflict (world, *iter, resItem); + addItem (item); + } + } + + + void + ResolverQueue::addExtraDependency (constDependencyPtr dep) + { + QueueItemRequirePtr item = new QueueItemRequire (_context->world(), dep); + addItem (item); + } + + + void + ResolverQueue::addExtraConflict (constDependencyPtr dep) + { + QueueItemConflictPtr item = new QueueItemConflict (_context->world(), dep, NULL); + addItem (item); + } + + + void + ResolverQueue::addItem (QueueItemPtr item) + { + _items.push_front (item); + } + + + bool + ResolverQueue::isInvalid () + { + return _context->isInvalid(); + } + + + bool + ResolverQueue::containsOnlyBranches () + { + for (QueueItemList::const_iterator iter = _items.begin(); iter != _items.end(); iter++) { + if (!(*iter)->isBranch()) + return false; + } + + return true; + } + + //--------------------------------------------------------------------------- + + static int + itemlist_max_priority (const QueueItemList & qil) + { + int max_priority = -1; + for (QueueItemList::const_iterator iter = qil.begin(); iter != qil.end(); iter++) { + if ((*iter)->priority() > max_priority) { + max_priority = (*iter)->priority(); + } + } + + return max_priority; + } + + + + bool + ResolverQueue::processOnce () + { + QueueItemList new_items; + int max_priority; + bool did_something = false; + + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce(%s), %d items\n", asString().c_str(), (int) _items.size()); + while ( (max_priority = itemlist_max_priority (_items)) >= 0 + && _context->isValid () ) { + + bool did_something_recently = false; + + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce() inside loop\n"); + for (QueueItemList::iterator iter = _items.begin(); iter != _items.end() && _context->isValid();) { + QueueItemPtr item = *iter; + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "=====> 1st pass: [%s]\n", item->asString().c_str()); + QueueItemList::iterator next = iter; next++; + if (item && item->priority() == max_priority) { + if (item->process (_context, new_items)) { + did_something_recently = true; + } + _items.erase (iter); + } + iter = next; + } + + if (did_something_recently) { + did_something = true; + } + } + + _items = new_items; + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "%d items after first pass\n", (int) _items.size()); + + /* + Now make a second pass over the queue, removing any super-branches. + (If one branch contains all of the possible items of another branch, + the larger branch can be dropped. + */ + + // if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce() second pass\n"); + for (QueueItemList::iterator iter = _items.begin(); iter != _items.end();) { + QueueItemList::iterator next = iter; next++; + QueueItemPtr item = *iter; + + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "=====> 2nd pass: [%s]\n", item->asString().c_str()); + if (item->isBranch()) { + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "ResolverQueue::processOnce() is branch\n"); + QueueItemBranchPtr branch = (QueueItemBranchPtr)item; + for (QueueItemList::const_iterator iter2 = _items.begin(); iter2 != _items.end(); iter2++) { + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "Compare branch with [%s]\n", (*iter2)->asString().c_str()); + if (iter != iter2 + && branch->contains (*iter2)) { + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "Contained within, removing\n"); + _items.erase (iter); + break; + } + } + } + iter = next; + } + if (getenv ("QUEUE_SPEW")) fprintf (stderr, "did %sthing: %d items\n", did_something ? "some" : "no", (int)_items.size()); + + return did_something; + } + + + void + ResolverQueue::process () + { + bool very_noisy; + + very_noisy = getenv ("RC_SPEW") != NULL; + + if (very_noisy) { + printf ("----- Processing -----\n"); + spew (); + } + + while (_context->isValid () + && ! isEmpty () + && processOnce ()) { + /* all of the work is in the conditional! */ + if (very_noisy) { + spew (); + } + } + } + + + //--------------------------------------------------------------------------- + + static ResolverQueuePtr + copy_queue_except_for_branch (ResolverQueuePtr queue, QueueItemPtr branch_item, QueueItemPtr subitem) + { + ResolverContextPtr new_context; + ResolverQueuePtr new_queue; + + new_context = new ResolverContext (queue->context()); + new_queue = new ResolverQueue (new_context); + + QueueItemList qil = queue->items(); + for (QueueItemList::const_iterator iter = qil.begin(); iter != qil.end(); iter++) { + QueueItemPtr item = *iter; + QueueItemPtr new_item; + + if (item == branch_item) { + new_item = subitem->copy (); + + if (new_item->isInstall()) { + QueueItemInstallPtr install_item = (QueueItemInstallPtr)new_item; + + /* Penalties are negative priorities */ + int penalty; + penalty = - queue->context()->getChannelPriority (install_item->resItem()->channel()); + + install_item->setOtherPenalty (penalty); + } + + } else { + + new_item = item->copy (); + + } + + new_queue->addItem (new_item); + } + + return new_queue; + } + + + void + ResolverQueue::splitFirstBranch (ResolverQueueList & new_queues, ResolverQueueList & deferred_queues) + { + QueueItemBranchPtr first_branch = NULL; + typedef std::map DeferTable; + DeferTable to_defer; + + for (QueueItemList::const_iterator iter = _items.begin(); iter != _items.end() && first_branch == NULL; iter++) { + QueueItemPtr item = *iter; + if (item->isBranch()) { + first_branch = (QueueItemBranchPtr)item; + } + } + + if (first_branch == NULL) + return; + + /* + Check for deferrable items: if we have two install items where the to-be-installed + resItems have the same name, then we will defer the lower-priority install if + one of the following is true: + (1) Both resItems have the same version + (2) The lower-priority channel is a previous version. + */ + + QueueItemList possible_items = first_branch->possibleItems(); + for (QueueItemList::const_iterator iter = possible_items.begin(); iter != possible_items.end(); iter++) { + QueueItemList::const_iterator iter2 = iter; + for (iter2++; iter2 != possible_items.end(); iter2++) { + QueueItemPtr item = *iter; + QueueItemPtr item2 = *iter2; + + if (item->isInstall() && item2->isInstall()) { + constResItemPtr r = ((QueueItemInstallPtr) item)->resItem(); + constResItemPtr r2 = ((QueueItemInstallPtr) item2)->resItem(); + constChannelPtr channel = r->channel(); + constChannelPtr channel2 = r2->channel(); + int priority, priority2; + + priority = channel->getPriority (channel->isSubscribed()); + priority2 = channel2->getPriority (channel2->isSubscribed()); + + if (priority != priority2 && r->name() == r2->name()) { + if (r->version() == r2->version() + || (priority < priority2 && GVersion.compare (r, r2) < 0) + || (priority > priority2 && GVersion.compare (r, r2) > 0)) { + + if (priority < priority2) + to_defer[item] = item; + else /* if (priority > priority2) */ + to_defer[item2] = item2; + } + } + } + } + } + + + for (QueueItemList::const_iterator iter = possible_items.begin(); iter != possible_items.end(); iter++) { + ResolverQueuePtr new_queue; + QueueItemPtr new_item = *iter; + + new_queue = copy_queue_except_for_branch (this, (QueueItemPtr) first_branch, new_item); + + DeferTable::const_iterator pos = to_defer.find (new_item); + if (pos != to_defer.end()) { + deferred_queues.push_back (new_queue); + } else { + new_queues.push_back (new_queue); + } + } + + } + + + void + ResolverQueue::spew () + { + printf ("Resolver Queue: %s\n", _context->isInvalid() ? "INVALID" : ""); + + if (_items.empty()) { + + printf (" (empty)\n"); + + } else { + + for (QueueItemList::const_iterator iter = _items.begin(); iter != _items.end(); iter++) { + printf (" %s\n", (*iter)->asString().c_str()); + } + + } + + printf ("\n"); + fflush (stdout); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ResolverQueue.h b/zypp/solver/detail/ResolverQueue.h index 5377f68..0cead07 100644 --- a/zypp/solver/detail/ResolverQueue.h +++ b/zypp/solver/detail/ResolverQueue.h @@ -33,66 +33,78 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef std::list ResolverQueueList; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResolverQueue + + class ResolverQueue : public CountedRep { + + REP_BODY(ResolverQueue); + + private: + + ResolverContextPtr _context; + QueueItemList _items; + + public: + ResolverQueue (ResolverContextPtr context = NULL); + virtual ~ResolverQueue(); + + // ---------------------------------- I/O + + static std::string toString (const ResolverQueue & context); + virtual std::ostream & dumpOn(std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream&, const ResolverQueue & context); + std::string asString (void ) const; + + // ---------------------------------- accessors + + ResolverContextPtr context (void) const { return _context; } + QueueItemList items(void) const { return _items; } + + // ---------------------------------- methods + + + void addResItemToInstall (constResItemPtr resItem); + void addResItemToRemove (constResItemPtr resItem, bool remove_only_mode); + void addResItemToVerify (constResItemPtr resItem); + void addExtraDependency (constDependencyPtr dep); + void addExtraConflict (constDependencyPtr dep); + void addItem (QueueItemPtr item); + + bool isEmpty () const { return _items.empty(); } + bool isInvalid (); + bool containsOnlyBranches (); + + bool processOnce (); + void process (); + + void splitFirstBranch (ResolverQueueList & new_queues, ResolverQueueList & deferred_queues); + + void spew (); + + }; + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -typedef std::list ResolverQueueList; - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ResolverQueue - -class ResolverQueue : public CountedRep { - - REP_BODY(ResolverQueue); - - private: - - ResolverContextPtr _context; - QueueItemList _items; - - public: - ResolverQueue (ResolverContextPtr context = NULL); - virtual ~ResolverQueue(); - - // ---------------------------------- I/O - - static std::string toString (const ResolverQueue & context); - virtual std::ostream & dumpOn(std::ostream & str ) const; - friend std::ostream& operator<<(std::ostream&, const ResolverQueue & context); - std::string asString (void ) const; - - // ---------------------------------- accessors - - ResolverContextPtr context (void) const { return _context; } - QueueItemList items(void) const { return _items; } - - // ---------------------------------- methods - - - void addResItemToInstall (constResItemPtr resItem); - void addResItemToRemove (constResItemPtr resItem, bool remove_only_mode); - void addResItemToVerify (constResItemPtr resItem); - void addExtraDependency (constDependencyPtr dep); - void addExtraConflict (constDependencyPtr dep); - void addItem (QueueItemPtr item); - - bool isEmpty () const { return _items.empty(); } - bool isInvalid (); - bool containsOnlyBranches (); - - bool processOnce (); - void process (); - - void splitFirstBranch (ResolverQueueList & new_queues, ResolverQueueList & deferred_queues); - - void spew (); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ResolverQueue_h diff --git a/zypp/solver/detail/ResolverQueuePtr.h b/zypp/solver/detail/ResolverQueuePtr.h index 296420d..da7c3f1 100644 --- a/zypp/solver/detail/ResolverQueuePtr.h +++ b/zypp/solver/detail/ResolverQueuePtr.h @@ -23,18 +23,31 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ResolverQueuePtr + // CLASS NAME : constResolverQueuePtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(ResolverQueue); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ResolverQueuePtr -// CLASS NAME : constResolverQueuePtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(ResolverQueue); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ResolverQueuePtr_h diff --git a/zypp/solver/detail/Section.cc b/zypp/solver/detail/Section.cc index 24cba9d..6ac53ce 100644 --- a/zypp/solver/detail/Section.cc +++ b/zypp/solver/detail/Section.cc @@ -25,175 +25,185 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -string -Section::asString ( void ) const -{ - return toString (*this); -} - - -string -Section::asUserString ( void ) const -{ - return toUserString (*this); -} - - -string -Section::toString ( const Section & section ) -{ - switch (section.section()) { - case SECTION_OFFICE: return ("office"); - case SECTION_IMAGING: return ("imaging"); - case SECTION_PIM: return ("pim"); - case SECTION_GAME: return ("game"); - case SECTION_MISC: return ("misc"); - case SECTION_MULTIMEDIA: return ("multimedia"); - case SECTION_INTERNET: return ("internet"); - case SECTION_UTIL: return ("util"); - case SECTION_SYSTEM: return ("system"); - case SECTION_DOC: return ("doc"); - case SECTION_DEVEL: return ("devel"); - case SECTION_DEVELUTIL: return ("develutil"); - case SECTION_LIBRARY: return ("library"); - case SECTION_XAPP: return ("xapp"); - default: - rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid section number %d\n", section.section()); - } - return ("misc"); -} - -string -Section::toUserString ( const Section & section ) -{ - switch (section.section()) { - case SECTION_OFFICE: return ("Productivity Applications"); - case SECTION_IMAGING: return ("Imaging"); - case SECTION_PIM: return ("Personal Information Management"); - case SECTION_GAME: return ("Games"); - case SECTION_MISC: return ("Miscellaneous"); - case SECTION_MULTIMEDIA: return ("Multimedia"); - case SECTION_INTERNET: return ("Internet Applications"); - case SECTION_UTIL: return ("Utilities"); - case SECTION_SYSTEM: return ("System Packages"); - case SECTION_DOC: return ("Documentation"); - case SECTION_DEVEL: return ("Development Packages"); - case SECTION_DEVELUTIL: return ("Development Utilities"); - case SECTION_LIBRARY: return ("Libraries"); - case SECTION_XAPP: return ("X Applications"); - default: - rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid section number %d\n", section.section()); - } - - return ("Miscellaneous"); -} - -ostream & -Section::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Section& section) -{ - return os << section.asString(); -} - -//--------------------------------------------------------------------------- - -Section::Section(const char *section_str) -{ - _section = SECTION_MISC; - - if (section_str != NULL) { - switch (*section_str) { - case 'd': - if (!strcmp (section_str, "develutil")) { - _section = SECTION_DEVELUTIL; - } - else if (!strcmp (section_str, "devel")) { - _section = SECTION_DEVEL; - } - else if (!strcmp (section_str, "doc")) { - _section = SECTION_DOC; - } - break; - case 'g': - if (!strcmp (section_str, "game")) { - _section = SECTION_GAME; - } - break; - case 'i': - if (!strcmp (section_str, "imaging")) { - _section = SECTION_IMAGING; - } - else if (!strcmp (section_str, "internet")) { - _section = SECTION_INTERNET; - } - break; - case 'l': - if (!strcmp (section_str, "library")) { - _section = SECTION_LIBRARY; - } - break; - case 'm': - if (!strcmp (section_str, "misc")) { - _section = SECTION_MISC; - } - else if (!strcmp (section_str, "multimedia")) { - _section = SECTION_MULTIMEDIA; - } - break; - case 'o': - if (!strcmp (section_str, "office")) { - _section = SECTION_OFFICE; - } - break; - case 'p': - if (!strcmp (section_str, "pim")) { - _section = SECTION_PIM; - } - break; - case 's': - if (!strcmp (section_str, "system")) { - _section = SECTION_SYSTEM; - } - break; - case 'u': - if (!strcmp (section_str, "util")) { - _section = SECTION_UTIL; - } - break; - case 'x': - if (!strcmp (section_str, "xapp")) { - _section = SECTION_XAPP; - } - break; - default: - rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid section name %s\n", section_str); - break; - } - } // if != NULL - -} - - -Section::~Section() -{ -} - - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + string + Section::asString ( void ) const + { + return toString (*this); + } + + + string + Section::asUserString ( void ) const + { + return toUserString (*this); + } + + + string + Section::toString ( const Section & section ) + { + switch (section.section()) { + case SECTION_OFFICE: return ("office"); + case SECTION_IMAGING: return ("imaging"); + case SECTION_PIM: return ("pim"); + case SECTION_GAME: return ("game"); + case SECTION_MISC: return ("misc"); + case SECTION_MULTIMEDIA: return ("multimedia"); + case SECTION_INTERNET: return ("internet"); + case SECTION_UTIL: return ("util"); + case SECTION_SYSTEM: return ("system"); + case SECTION_DOC: return ("doc"); + case SECTION_DEVEL: return ("devel"); + case SECTION_DEVELUTIL: return ("develutil"); + case SECTION_LIBRARY: return ("library"); + case SECTION_XAPP: return ("xapp"); + default: + rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid section number %d\n", section.section()); + } + return ("misc"); + } + + string + Section::toUserString ( const Section & section ) + { + switch (section.section()) { + case SECTION_OFFICE: return ("Productivity Applications"); + case SECTION_IMAGING: return ("Imaging"); + case SECTION_PIM: return ("Personal Information Management"); + case SECTION_GAME: return ("Games"); + case SECTION_MISC: return ("Miscellaneous"); + case SECTION_MULTIMEDIA: return ("Multimedia"); + case SECTION_INTERNET: return ("Internet Applications"); + case SECTION_UTIL: return ("Utilities"); + case SECTION_SYSTEM: return ("System Packages"); + case SECTION_DOC: return ("Documentation"); + case SECTION_DEVEL: return ("Development Packages"); + case SECTION_DEVELUTIL: return ("Development Utilities"); + case SECTION_LIBRARY: return ("Libraries"); + case SECTION_XAPP: return ("X Applications"); + default: + rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid section number %d\n", section.section()); + } + + return ("Miscellaneous"); + } + + ostream & + Section::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Section& section) + { + return os << section.asString(); + } + + //--------------------------------------------------------------------------- + + Section::Section(const char *section_str) + { + _section = SECTION_MISC; + + if (section_str != NULL) { + switch (*section_str) { + case 'd': + if (!strcmp (section_str, "develutil")) { + _section = SECTION_DEVELUTIL; + } + else if (!strcmp (section_str, "devel")) { + _section = SECTION_DEVEL; + } + else if (!strcmp (section_str, "doc")) { + _section = SECTION_DOC; + } + break; + case 'g': + if (!strcmp (section_str, "game")) { + _section = SECTION_GAME; + } + break; + case 'i': + if (!strcmp (section_str, "imaging")) { + _section = SECTION_IMAGING; + } + else if (!strcmp (section_str, "internet")) { + _section = SECTION_INTERNET; + } + break; + case 'l': + if (!strcmp (section_str, "library")) { + _section = SECTION_LIBRARY; + } + break; + case 'm': + if (!strcmp (section_str, "misc")) { + _section = SECTION_MISC; + } + else if (!strcmp (section_str, "multimedia")) { + _section = SECTION_MULTIMEDIA; + } + break; + case 'o': + if (!strcmp (section_str, "office")) { + _section = SECTION_OFFICE; + } + break; + case 'p': + if (!strcmp (section_str, "pim")) { + _section = SECTION_PIM; + } + break; + case 's': + if (!strcmp (section_str, "system")) { + _section = SECTION_SYSTEM; + } + break; + case 'u': + if (!strcmp (section_str, "util")) { + _section = SECTION_UTIL; + } + break; + case 'x': + if (!strcmp (section_str, "xapp")) { + _section = SECTION_XAPP; + } + break; + default: + rc_debug (RC_DEBUG_LEVEL_WARNING, "invalid section name %s\n", section_str); + break; + } + } // if != NULL + + } + + + Section::~Section() + { + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Section.h b/zypp/solver/detail/Section.h index e36c4ba..28279a9 100644 --- a/zypp/solver/detail/Section.h +++ b/zypp/solver/detail/Section.h @@ -27,77 +27,89 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Section -/** - * - **/ -class Section { - - private: - - typedef enum { - SECTION_OFFICE = 0, - SECTION_IMAGING, - SECTION_PIM, - SECTION_XAPP, - SECTION_GAME, - SECTION_MULTIMEDIA, - SECTION_INTERNET, - SECTION_UTIL, - SECTION_SYSTEM, - SECTION_DOC, - SECTION_LIBRARY, - SECTION_DEVEL, - SECTION_DEVELUTIL, - SECTION_MISC, - SECTION_LAST - } section_t; - - section_t _section; - - private: - section_t section () const { return _section; } - - public: - - Section(const char *section_str); - virtual ~Section(); - - // ---------------------------------- I/O - - static std::string toString ( const Section & section); - static std::string toUserString ( const Section & section); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Section & section); - - std::string asString ( void ) const; - std::string asUserString ( void ) const; - - // ---------------------------------- accessors - - // equality - bool operator==( const Section & section) const { - return _section == section.section(); - } - - // inequality - bool operator!=( const Section & section) const { - return !(*this == section); - } - -}; - -typedef Section * SectionPtr; -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Section + /** + * + **/ + class Section { + + private: + + typedef enum { + SECTION_OFFICE = 0, + SECTION_IMAGING, + SECTION_PIM, + SECTION_XAPP, + SECTION_GAME, + SECTION_MULTIMEDIA, + SECTION_INTERNET, + SECTION_UTIL, + SECTION_SYSTEM, + SECTION_DOC, + SECTION_LIBRARY, + SECTION_DEVEL, + SECTION_DEVELUTIL, + SECTION_MISC, + SECTION_LAST + } section_t; + + section_t _section; + + private: + section_t section () const { return _section; } + + public: + + Section(const char *section_str); + virtual ~Section(); + + // ---------------------------------- I/O + + static std::string toString ( const Section & section); + static std::string toUserString ( const Section & section); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Section & section); + + std::string asString ( void ) const; + std::string asUserString ( void ) const; + + // ---------------------------------- accessors + + // equality + bool operator==( const Section & section) const { + return _section == section.section(); + } + + // inequality + bool operator!=( const Section & section) const { + return !(*this == section); + } + + }; + + typedef Section * SectionPtr; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Section_h diff --git a/zypp/solver/detail/ServiceWorld.cc b/zypp/solver/detail/ServiceWorld.cc index 2967115..194dcea 100644 --- a/zypp/solver/detail/ServiceWorld.cc +++ b/zypp/solver/detail/ServiceWorld.cc @@ -21,61 +21,72 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(ServiceWorld, World); - -//--------------------------------------------------------------------------- - -string -ServiceWorld::asString ( void ) const -{ - return toString (*this); -} - - -string -ServiceWorld::toString ( const ServiceWorld & service ) -{ - return ""; -} - - -ostream & -ServiceWorld::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const ServiceWorld & service) -{ - return os << service.asString(); -} - -//--------------------------------------------------------------------------- - -ServiceWorld::ServiceWorld () - : StoreWorld (SERVICE_WORLD) -{ -} - - -ServiceWorld::~ServiceWorld() -{ - fprintf (stderr, "*** deleting service world[%p]: %s\n", this, World::toString(type()).c_str()); -} - -//--------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(ServiceWorld, World); + + //--------------------------------------------------------------------------- + + string + ServiceWorld::asString ( void ) const + { + return toString (*this); + } + + + string + ServiceWorld::toString ( const ServiceWorld & service ) + { + return ""; + } + + + ostream & + ServiceWorld::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const ServiceWorld & service) + { + return os << service.asString(); + } + + //--------------------------------------------------------------------------- + + ServiceWorld::ServiceWorld () + : StoreWorld (SERVICE_WORLD) + { + } + + + ServiceWorld::~ServiceWorld() + { + fprintf (stderr, "*** deleting service world[%p]: %s\n", this, World::toString(type()).c_str()); + } + + //--------------------------------------------------------------------------- + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ServiceWorld.h b/zypp/solver/detail/ServiceWorld.h index 7b5af73..891e835 100644 --- a/zypp/solver/detail/ServiceWorld.h +++ b/zypp/solver/detail/ServiceWorld.h @@ -29,60 +29,74 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// -typedef bool (*ServiceWorldAssembleFn) (ServiceWorldPtr service, void *error); // GError **error +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef bool (*ServiceWorldAssembleFn) (ServiceWorldPtr service, void *error); // GError **error + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ServiceWorld + + class ServiceWorld : public StoreWorld { + REP_BODY(ServiceWorld); + + private: + + char *_url; + char *_name; + char *_unique_id; + + bool _is_sticky; // if true, can't be unmounted + bool _is_invisible; // ... to users + bool _is_unsaved; // Never save into the services.xml file + bool _is_singleton; // only one such service at a time. FIXME: broken + + ServiceWorldAssembleFn _assemble_fn; + + public: + + ServiceWorld (); + virtual ~ServiceWorld(); + + // ---------------------------------- I/O + + static std::string toString (const ServiceWorld & section); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const ServiceWorld & section); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + char *url () const { return _url; } + char *name () const { return _name; } + void setName (const char *name) { _name = strdup (name); } + char *unique_id () const { return _unique_id; } + + // ---------------------------------- methods + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : ServiceWorld - -class ServiceWorld : public StoreWorld { - REP_BODY(ServiceWorld); - - private: - - char *_url; - char *_name; - char *_unique_id; - - bool _is_sticky; // if true, can't be unmounted - bool _is_invisible; // ... to users - bool _is_unsaved; // Never save into the services.xml file - bool _is_singleton; // only one such service at a time. FIXME: broken - - ServiceWorldAssembleFn _assemble_fn; - - public: - - ServiceWorld (); - virtual ~ServiceWorld(); - - // ---------------------------------- I/O - - static std::string toString (const ServiceWorld & section); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const ServiceWorld & section); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - char *url () const { return _url; } - char *name () const { return _name; } - void setName (const char *name) { _name = strdup (name); } - char *unique_id () const { return _unique_id; } - - // ---------------------------------- methods - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ServiceWorld_h diff --git a/zypp/solver/detail/ServiceWorldPtr.h b/zypp/solver/detail/ServiceWorldPtr.h index 99b1d18..e5e470e 100644 --- a/zypp/solver/detail/ServiceWorldPtr.h +++ b/zypp/solver/detail/ServiceWorldPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : ServiceWorldPtr + // CLASS NAME : constServiceWorldPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(ServiceWorld, World); + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : ServiceWorldPtr -// CLASS NAME : constServiceWorldPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(ServiceWorld, World); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _ServiceWorldPtr_h diff --git a/zypp/solver/detail/Spec.cc b/zypp/solver/detail/Spec.cc index 91f934f..593c612 100644 --- a/zypp/solver/detail/Spec.cc +++ b/zypp/solver/detail/Spec.cc @@ -24,204 +24,215 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(Spec); - -//--------------------------------------------------------------------------- - -UstringHash Name::_nameHash; -UstringHash Kind::_kindHash; -const Kind & Kind::Unknown = Kind(""); -const Kind & Kind::Package = Kind("package"); -const Kind & Kind::Patch = Kind("patch"); -const Kind & Kind::Script = Kind("script"); -const Kind & Kind::Message = Kind("message"); -const Kind & Kind::Selection = Kind("selection"); -const Kind & Kind::Product = Kind("product"); - -//--------------------------------------------------------------------------- - -string -Spec::asString ( bool full ) const -{ - return toString (*this, full); -} - - -string -Spec::toString ( const Spec & spec, bool full ) -{ - string res; - - if (full - || (spec.kind() != Kind::Package - && spec.kind() != Kind::Unknown)) { - res += spec.kind().asString(); - res += ":"; - } - - res += spec.name(); - - string ed = spec.edition()->asString (full); - if (!ed.empty()) { - res += "-"; - res += ed; - } - - return res; -} - - -ostream & -Spec::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Spec& spec) -{ - return os << spec.asString(); -} - -//--------------------------------------------------------------------------- - -Spec::Spec (const Kind & kind, const string & name, constEditionPtr edition) - : _kind (kind) - , _name (Name (name)) - , _edition (edition == NULL ? new Edition() : edition->copy()) -{ -} - - -Spec::Spec ( const Kind & kind, const string & name, int epoch, const string & version, const string & release, const Arch * arch) - : _kind (kind) - , _name (Name (name)) - , _edition (new Edition (epoch, version, release, arch)) -{ -} - - -Spec::Spec (constXmlNodePtr node) - : _kind (Kind::Unknown) -{ - fprintf (stderr, "Spec::Spec (constXmlNodePtr node)\nNot implemented\n"); - abort(); -} - - -Spec::~Spec() -{ -} - - -// needed during xml parsing (-> XmlParser) - -constSpecPtr -Spec::copy (void) const -{ - return new Spec (_kind, _name, _edition); -} - - -#if 0 -xmlNode * -rc_resItem_spec_to_xml_node (RCResItemSpec *spec) -{ - xmlNode *spec_node; - char buffer[128]; - - spec_node = xmlNewNode (NULL, "spec"); - - xmlNewTextChild (spec_node, NULL, "name", - g_quark_to_string (spec->nameq)); - - if (spec->has_epoch) { - g_snprintf (buffer, 128, "%d", spec->epoch); - xmlNewTextChild (spec_node, NULL, "epoch", buffer); - } - - xmlNewTextChild (spec_node, NULL, "version", spec->version); - - if (spec->release) - xmlNewTextChild (spec_node, NULL, "release", spec->release); - - xmlNewTextChild (spec_node, NULL, "arch", - rc_arch_to_string (spec->arch)); - - return spec_node; -} - -#endif - -//--------------------------------------------------------------------------- - - -HashValue -Spec::hash (void) const -{ - HashValue ret = _edition->epoch() + 1; - const char *spec_strs[3], *p; - int i; - - spec_strs[0] = _name.asString().c_str(); - spec_strs[1] = _edition->version().c_str(); - spec_strs[2] = _edition->release().c_str(); - - for (i = 0; i < 3; ++i) { - p = spec_strs[i]; - if (p) { - for (p += 1; *p != '\0'; ++p) { - ret = (ret << 5) - ret + *p; - } - } else { - ret = ret * 17; - } - } - - return ret; -} - - -const Spec * -Spec::findByName (const SpecList &speclist, const Name & name) const -{ - const Spec *spec = NULL; - for (SpecList::const_iterator iter = speclist.begin(); iter != speclist.end(); iter++) { - if ((*iter).name() == name) { - spec = &(*iter); - break; - } - } - return spec; -} - - -bool -Spec::match(constSpecPtr spec) const { - return ((_kind == spec->kind()) - && (_name == spec->name()) - && _edition->match (spec->edition())); -} - - -bool -Spec::equals(constSpecPtr spec) const { -//fprintf (stderr, "<%s> equals <%s>\n", asString(true).c_str(), spec->asString(true).c_str()); - return ((_kind == spec->kind()) - && (_name == spec->name()) - && _edition->equals(spec->edition())); -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(Spec); + + //--------------------------------------------------------------------------- + + UstringHash Name::_nameHash; + UstringHash Kind::_kindHash; + const Kind & Kind::Unknown = Kind(""); + const Kind & Kind::Package = Kind("package"); + const Kind & Kind::Patch = Kind("patch"); + const Kind & Kind::Script = Kind("script"); + const Kind & Kind::Message = Kind("message"); + const Kind & Kind::Selection = Kind("selection"); + const Kind & Kind::Product = Kind("product"); + + //--------------------------------------------------------------------------- + + string + Spec::asString ( bool full ) const + { + return toString (*this, full); + } + + + string + Spec::toString ( const Spec & spec, bool full ) + { + string res; + + if (full + || (spec.kind() != Kind::Package + && spec.kind() != Kind::Unknown)) { + res += spec.kind().asString(); + res += ":"; + } + + res += spec.name(); + + string ed = spec.edition()->asString (full); + if (!ed.empty()) { + res += "-"; + res += ed; + } + + return res; + } + + + ostream & + Spec::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Spec& spec) + { + return os << spec.asString(); + } + + //--------------------------------------------------------------------------- + + Spec::Spec (const Kind & kind, const string & name, constEditionPtr edition) + : _kind (kind) + , _name (Name (name)) + , _edition (edition == NULL ? new Edition() : edition->copy()) + { + } + + + Spec::Spec ( const Kind & kind, const string & name, int epoch, const string & version, const string & release, const Arch * arch) + : _kind (kind) + , _name (Name (name)) + , _edition (new Edition (epoch, version, release, arch)) + { + } + + + Spec::Spec (constXmlNodePtr node) + : _kind (Kind::Unknown) + { + fprintf (stderr, "Spec::Spec (constXmlNodePtr node)\nNot implemented\n"); + abort(); + } + + + Spec::~Spec() + { + } + + + // needed during xml parsing (-> XmlParser) + + constSpecPtr + Spec::copy (void) const + { + return new Spec (_kind, _name, _edition); + } + + + #if 0 + xmlNode * + rc_resItem_spec_to_xml_node (RCResItemSpec *spec) + { + xmlNode *spec_node; + char buffer[128]; + + spec_node = xmlNewNode (NULL, "spec"); + + xmlNewTextChild (spec_node, NULL, "name", + g_quark_to_string (spec->nameq)); + + if (spec->has_epoch) { + g_snprintf (buffer, 128, "%d", spec->epoch); + xmlNewTextChild (spec_node, NULL, "epoch", buffer); + } + + xmlNewTextChild (spec_node, NULL, "version", spec->version); + + if (spec->release) + xmlNewTextChild (spec_node, NULL, "release", spec->release); + + xmlNewTextChild (spec_node, NULL, "arch", + rc_arch_to_string (spec->arch)); + + return spec_node; + } + + #endif + + //--------------------------------------------------------------------------- + + + HashValue + Spec::hash (void) const + { + HashValue ret = _edition->epoch() + 1; + const char *spec_strs[3], *p; + int i; + + spec_strs[0] = _name.asString().c_str(); + spec_strs[1] = _edition->version().c_str(); + spec_strs[2] = _edition->release().c_str(); + + for (i = 0; i < 3; ++i) { + p = spec_strs[i]; + if (p) { + for (p += 1; *p != '\0'; ++p) { + ret = (ret << 5) - ret + *p; + } + } else { + ret = ret * 17; + } + } + + return ret; + } + + + const Spec * + Spec::findByName (const SpecList &speclist, const Name & name) const + { + const Spec *spec = NULL; + for (SpecList::const_iterator iter = speclist.begin(); iter != speclist.end(); iter++) { + if ((*iter).name() == name) { + spec = &(*iter); + break; + } + } + return spec; + } + + + bool + Spec::match(constSpecPtr spec) const { + return ((_kind == spec->kind()) + && (_name == spec->name()) + && _edition->match (spec->edition())); + } + + + bool + Spec::equals(constSpecPtr spec) const { + //fprintf (stderr, "<%s> equals <%s>\n", asString(true).c_str(), spec->asString(true).c_str()); + return ((_kind == spec->kind()) + && (_name == spec->name()) + && _edition->equals(spec->edition())); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Spec.h b/zypp/solver/detail/Spec.h index 1aa03b3..0650177 100644 --- a/zypp/solver/detail/Spec.h +++ b/zypp/solver/detail/Spec.h @@ -33,9 +33,15 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // @@ -89,89 +95,94 @@ class Kind : public Ustring { /////////////////////////////////////////////////////////////////// // -// CLASS NAME : Spec -/** - * - **/ - -class Spec : public CountedRep { - REP_BODY(Spec); - - private: - Kind _kind; - Name _name; - EditionPtr _edition; - - public: - typedef std::list SpecList; - - Spec( const Kind & kind, - const std::string & name, - int epoch = -1, - const std::string & version = "", - const std::string & release = "", - const Arch * arch = Arch::Unknown); - - Spec (const Kind & kind, const std::string & name, constEditionPtr edition); - - Spec (constXmlNodePtr node); - - virtual ~Spec(); - - // ---------------------------------- I/O - - const xmlNodePtr asXmlNode (const char *name) const; - - static std::string toString ( const Spec & spec, bool full = false ); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Spec& ); - - std::string asString ( bool full = false ) const; - - // ---------------------------------- accessors - - const std::string & version() const { return _edition->version(); } - void setVersion (const std::string & version) { _edition->setVersion (version); } - - const std::string & release() const { return _edition->release(); } - void setRelease (const std::string & release) { _edition->setRelease (release); } - - const int epoch() const { return _edition->epoch(); } - void setEpoch (int epoch) { _edition->setEpoch (epoch); } - bool hasEpoch() const { return _edition->hasEpoch(); } - - const Arch * arch() const { return _edition->arch(); } - void setArch (const Arch * arch) { _edition->setArch (arch); } - void setArch (const std::string & arch) { _edition->setArch (arch); } - - const Kind & kind() const { return _kind; } - void setKind (const Kind & kind) { _kind = kind; } - - const std::string name() const { return _name; } - void setName (const std::string & name) { _name = Name(name.c_str()); } - - constEditionPtr edition() const { return _edition; } - void setEdition (constEditionPtr edition) { _edition = edition->copy(); } - - // calculate hash - HashValue hash (void) const; - - // match operator - bool match(constSpecPtr spec) const; - bool equals (constSpecPtr spec) const; - - // find spec in SpecList by name - const Spec * findByName (const SpecList &speclist, const Name & name) const; - - // copy - - constSpecPtr copy (void) const; -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + // CLASS NAME : Spec + /** + * + **/ + + class Spec : public CountedRep { + REP_BODY(Spec); + + private: + Kind _kind; + Name _name; + EditionPtr _edition; + + public: + typedef std::list SpecList; + + Spec( const Kind & kind, + const std::string & name, + int epoch = -1, + const std::string & version = "", + const std::string & release = "", + const Arch * arch = Arch::Unknown); + + Spec (const Kind & kind, const std::string & name, constEditionPtr edition); + + Spec (constXmlNodePtr node); + + virtual ~Spec(); + + // ---------------------------------- I/O + + const xmlNodePtr asXmlNode (const char *name) const; + + static std::string toString ( const Spec & spec, bool full = false ); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Spec& ); + + std::string asString ( bool full = false ) const; + + // ---------------------------------- accessors + + const std::string & version() const { return _edition->version(); } + void setVersion (const std::string & version) { _edition->setVersion (version); } + + const std::string & release() const { return _edition->release(); } + void setRelease (const std::string & release) { _edition->setRelease (release); } + + const int epoch() const { return _edition->epoch(); } + void setEpoch (int epoch) { _edition->setEpoch (epoch); } + bool hasEpoch() const { return _edition->hasEpoch(); } + + const Arch * arch() const { return _edition->arch(); } + void setArch (const Arch * arch) { _edition->setArch (arch); } + void setArch (const std::string & arch) { _edition->setArch (arch); } + + const Kind & kind() const { return _kind; } + void setKind (const Kind & kind) { _kind = kind; } + + const std::string name() const { return _name; } + void setName (const std::string & name) { _name = Name(name.c_str()); } + + constEditionPtr edition() const { return _edition; } + void setEdition (constEditionPtr edition) { _edition = edition->copy(); } + + // calculate hash + HashValue hash (void) const; + + // match operator + bool match(constSpecPtr spec) const; + bool equals (constSpecPtr spec) const; + + // find spec in SpecList by name + const Spec * findByName (const SpecList &speclist, const Name & name) const; + + // copy + + constSpecPtr copy (void) const; + }; + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Spec_h diff --git a/zypp/solver/detail/SpecPtr.h b/zypp/solver/detail/SpecPtr.h index 328f1de..c46e282 100644 --- a/zypp/solver/detail/SpecPtr.h +++ b/zypp/solver/detail/SpecPtr.h @@ -23,18 +23,32 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : SpecPtr -// CLASS NAME : constSpecPtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(Spec); +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : SpecPtr + // CLASS NAME : constSpecPtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(Spec); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// #endif // _SpecPtr_h diff --git a/zypp/solver/detail/StoreWorld.cc b/zypp/solver/detail/StoreWorld.cc index 592fa38..10667bc 100644 --- a/zypp/solver/detail/StoreWorld.cc +++ b/zypp/solver/detail/StoreWorld.cc @@ -29,696 +29,708 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(StoreWorld, World); - -//--------------------------------------------------------------------------- - -string -StoreWorld::asString ( void ) const -{ - return toString (*this); -} - - -string -StoreWorld::toString ( const StoreWorld & storeworld ) -{ - string res (""); - - return res; -} - - -ostream & -StoreWorld::dumpOn (ostream & str) const -{ - str << asString(); - return str; -} - - -ostream & -operator<< (ostream & os, const StoreWorld & storeworld) -{ - return os << storeworld.asString(); -} - -//--------------------------------------------------------------------------- - -StoreWorld::StoreWorld (WorldType type) - : World (type) - , _resItem_kind(Kind::Unknown) -{ -} - - -StoreWorld::~StoreWorld() -{ - fprintf (stderr, "*** deleting store world[%p]: %s\n", this, World::toString(type()).c_str()); -} - - -//--------------------------------------------------------------------------- - -// Add/remove resItems - -bool -StoreWorld::addResItem (constResItemPtr resItem) -{ - ArchList compat_arch_list; - ResItemAndDependencyPtr r_and_d; - const char *package_name; - constChannelPtr channel; - int arch_score; - bool actually_added_package = false; - - if (resItem == NULL) return false; - - compat_arch_list = Arch::System->getCompatList(); -//fprintf (stderr, "Arch::System '%s' -> %d compats\n", Arch::System->asString().c_str(), (int) compat_arch_list.size()); - channel = resItem->channel (); - -// fprintf (stderr, "StoreWorld[%p]::addResItem(%s) [%s]\n", this, ((constSpecPtr)resItem)->asString().c_str(), channel?channel->name():"?"); - - arch_score = resItem->arch()->getCompatScore(compat_arch_list); - - /* Before we do anything, check to make sure that a resItem of the - same name isn't already in that channel. If there is a - duplicate, we keep the one with the most recent version number - and drop the other. - - This check only applies to resItems in a channel. We have - to allow for multiple installs. Grrrr... - */ - - if (!resItem->isInstalled ()) { // its not a system package - - constResItemPtr dup_res; - int dup_arch_score; - - /* Filter out resItems with totally incompatible arches */ - if (arch_score < 0) { - rc_debug (RC_DEBUG_LEVEL_DEBUG, "Ignoring resItem with incompatible arch: Arch '%s', %s", resItem->arch()->asString().c_str(), resItem->asString(true).c_str()); - goto finished; - } - - package_name = resItem->name().c_str(); - dup_res = findResItem (channel, package_name); - - /* This shouldn't happen (and would be caught by the check - below, because cmp will equal 0), but it never hurts to - check and produce a more explicit warning message. */ - - if (resItem == dup_res) { - rc_debug (RC_DEBUG_LEVEL_WARNING, "Ignoring re-add of resItem '%s'", package_name); - goto finished; - } - - if (dup_res != NULL) { - int cmp; - - cmp = GVersion.compare (resItem, dup_res); -//fprintf (stderr, "res: %s, dup_res %s, cmp %d\n", resItem->asString().c_str(), dup_res->asString().c_str(), cmp); - dup_arch_score = dup_res->arch()->getCompatScore(compat_arch_list); - - - /* If the resItem we are trying to add has a lower - version number, just ignore it. */ - - if (cmp < 0) { - rc_debug (RC_DEBUG_LEVEL_INFO, "Not adding resItem '%s'.\n\tA newer version is already in the channel.", resItem->asString().c_str()); - rc_debug (RC_DEBUG_LEVEL_INFO, "\t%s", dup_res->asString().c_str()); - goto finished; - } - - - /* If the version numbers are equal, we ignore the resItem to - add if it has a less-preferable arch. If both - resItems have the same version # and arch, we favor the - first resItem and just return. */ - - if (cmp == 0 && arch_score > dup_arch_score) { - rc_debug (RC_DEBUG_LEVEL_INFO, "Not adding resItem '%s'.\n\tAnother resItem with the same version but with a preferred arch is already in the channel.", resItem->asString().c_str()); - rc_debug (RC_DEBUG_LEVEL_INFO, "\t%s", dup_res->asString().c_str()); - goto finished; - } - - - /* Otherwise we throw out the old resItem and proceed with - adding the newer one. */ - - rc_debug (RC_DEBUG_LEVEL_INFO, "Replacing resItem '%s'.\n\tAnother resItem in the channel has the same name and a superior %s.", dup_res->asString().c_str(), cmp ? "version" : "arch"); - rc_debug (RC_DEBUG_LEVEL_INFO, "\t%s", resItem->asString().c_str()); - - removeResItem (dup_res); - } - } - - actually_added_package = true; - - if (channel && !channel->hidden()) { - touchResItemSequenceNumber (); - } - - /* StoreWorld all of our resItems in a hash by name. */ - _resItems_by_name.insert (ResItemTable::value_type (resItem->name(), resItem)); - - /* StoreWorld all of the resItem's provides in a hash by name. */ - for (CDependencyList::const_iterator i = resItem->provides().begin(); i != resItem->provides().end(); i++) { - r_and_d = new ResItemAndDependency (resItem, *i); - - _provides_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); - } - - /* StoreWorld all of the resItem's requires in a hash by name. */ - - for (CDependencyList::const_iterator i = resItem->requires().begin(); i != resItem->requires().end(); i++) { - r_and_d = new ResItemAndDependency (resItem, *i); - - _requires_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); - } - - /* "Recommends" are treated as requirements. */ -#warning Recommends are treated as requirements - - for (CDependencyList::const_iterator i = resItem->recommends().begin(); i != resItem->recommends().end(); i++) { - r_and_d = new ResItemAndDependency (resItem, *i); - - _requires_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); - } - - /* StoreWorld all of the resItem's conflicts in a hash by name. */ - - for (CDependencyList::const_iterator i = resItem->conflicts().begin(); i != resItem->conflicts().end(); i++) { - r_and_d = new ResItemAndDependency (resItem, *i); - _conflicts_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); - } - - finished: - - return actually_added_package; -} - - -void -StoreWorld::addResItemsFromList (const CResItemList & slist) -{ - for (CResItemList::const_iterator i = slist.begin(); i != slist.end(); i++) { - if (!addResItem (*i)) { - fprintf (stderr, "addResItem failed\n"); - break; - } - } - return; -} - -//--------------------------------------------------------------------------- - -static void -resItem_table_remove (ResItemTable & table, constResItemPtr resItem) -{ - const string name = resItem->name(); - for (ResItemTable::iterator pos = table.lower_bound(name); pos != table.upper_bound(name); pos++) { - constResItemPtr res = pos->second; - if (res == resItem) { - table.erase (pos); - break; - } - } - return; -} - - -static void -resItem_and_dependency_table_remove (ResItemAndDependencyTable & table, constResItemPtr resItem) -{ - const string name = resItem->name(); -// FIXME: this is inefficient but lower_bound can't to strcasecmp :-( -// for (ResItemAndDependencyTable::iterator pos = table.lower_bound(name); pos != table.upper_bound(name); pos++) { - for (ResItemAndDependencyTable::iterator pos = table.begin(); pos != table.end(); pos++) { - constResItemAndDependencyPtr r_and_d = pos->second; - if (r_and_d->resItem() == resItem) { - table.erase (pos); - break; - } - } - return; -} - -void -StoreWorld::removeResItem (constResItemPtr resItem) -{ - if (getenv("RC_SPEW")) fprintf (stderr, "StoreWorld::removeResItem (%s)\n", resItem->asString().c_str()); - - constChannelPtr channel = resItem->channel (); - - if (! (channel && channel->hidden ())) - touchResItemSequenceNumber (); - - resItem_and_dependency_table_remove (_provides_by_name, resItem); - resItem_and_dependency_table_remove (_requires_by_name, resItem); - resItem_and_dependency_table_remove (_conflicts_by_name, resItem); - - resItem_table_remove (_resItems_by_name, resItem); - - return; -} - - -void -StoreWorld::removeResItems (constChannelPtr channel) -{ - fprintf (stderr, "StoreWorld::removeResItems(%s) not implemented\n", channel->asString().c_str()); -} - - -void -StoreWorld::clear () -{ - fprintf (stderr, "StoreWorld::clear() not implemented\n"); -} - -//--------------------------------------------------------------------------- -// Single resItem queries - -static bool -installed_version_cb (constResItemPtr resItem, void *data) -{ - constResItemPtr *installed = (constResItemPtr *)data; - - if (resItem->isInstalled ()) { - *installed = resItem; - return false; - } - return true; -} - - -constResItemPtr -StoreWorld::findInstalledResItem (constResItemPtr resItem) -{ - constResItemPtr installed; - sync (); - - foreachResItemByName (resItem->name(), new Channel(CHANNEL_TYPE_ANY) /* is this right? */, installed_version_cb, &installed); - - return installed; -} - - -// -// findResItem -// @channel: A non-wildcard #Channel. -// @name: The name of a resItem. -// -// Searches the world for a resItem in the specified channel -// with the specified name. @channel must be an actual -// channel, not a wildcard. -// -// Return value: The matching resItem, or %NULL if no such -// resItem exists. -// - -constResItemPtr -StoreWorld::findResItem (constChannelPtr channel, const char *name) const -{ - syncConditional (channel); - for (ResItemTable::const_iterator pos = _resItems_by_name.lower_bound(name); pos != _resItems_by_name.upper_bound(name); pos++) { - constResItemPtr res = pos->second; - if (res->channel() == channel) { - return res; - } - } - return NULL; -} - - -constResItemPtr -StoreWorld::findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const -{ - fprintf (stderr, "StoreWorld::findResItemWithConstraint() not implemented\n"); - return 0; -} - - -ChannelPtr -StoreWorld::guessResItemChannel (constResItemPtr resItem) const -{ - fprintf (stderr, "StoreWorld::guessResItemChannel(%s) not implemented\n", ((constSpecPtr)resItem)->asString().c_str()); - return 0; -} - - -//----------------------------------------------------------------------------- -// foreach resItem - -typedef struct { - ChannelPtr channel; - CResItemFn callback; - void *data; - int count; - bool short_circuit; -} ForeachResItemInfo; - - -static void -foreach_resItem_cb (const string &name, constResItemPtr resItem, void *data) -{ - ForeachResItemInfo *info = (ForeachResItemInfo *)data; - - if (info->short_circuit) - return; - - /* FIXME: we should filter out dup uninstalled resItems. */ - - if (resItem && info->channel->equals(resItem->channel ())) { - if (info->callback) { - if (! info->callback (resItem, info->data)) - info->short_circuit = true; - } - ++info->count; - } -} - - -int -StoreWorld::foreachResItem (ChannelPtr channel, CResItemFn fn, void *data) -{ - return foreachResItemByName ("", channel, fn, data); -} - - -int -StoreWorld::foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data) -{ - if (name.empty()) { - - ForeachResItemInfo info; - - info.channel = channel; - info.callback = fn; - info.data = data; - info.count = 0; - info.short_circuit = false; - - for (ResItemTable::const_iterator iter = _resItems_by_name.begin(); iter != _resItems_by_name.end(); iter++) { - foreach_resItem_cb (iter->first, iter->second, (void *)&info); - } - - return info.short_circuit ? -1 : info.count; - } - - - ResItemTable installed; // FIXME: rc_resItem_spec_equal - int count = 0; - - for (ResItemTable::const_iterator iter = _resItems_by_name.lower_bound(name); iter != _resItems_by_name.upper_bound(name); iter++) { - constResItemPtr resItem = iter->second; - if (resItem->isInstalled()) { - const string str = ((constSpecPtr)resItem)->asString(); - installed.insert (ResItemTable::value_type(str,resItem)); - } - } - - for (ResItemTable::const_iterator iter = _resItems_by_name.lower_bound(name); iter != _resItems_by_name.upper_bound(name); iter++) { - constResItemPtr resItem = iter->second; - if (channel->equals (resItem->channel())) { - if (resItem->isInstalled() - || installed.find(((constSpecPtr)resItem)->asString()) == installed.end()) { - if (fn) { - if (! fn(resItem, data)) { - count = -1; - goto finished; - } - } - ++count; - } - } - } - -finished: - - return count; -} - - -int -StoreWorld::foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data) -{ - fprintf (stderr, "StoreWorld::foreachResItemByMatch () not implemented\n"); - return 0; -} - - -//----------------------------------------------------------------------------- -// iterater over resItems with dependency - -typedef std::map InstalledTable; - -int -StoreWorld::foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data) -{ - int count = 0; - InstalledTable installed; -//fprintf (stderr, "StoreWorld::foreachProvidingResItem(%s)\n", dep->asString().c_str()); - for (ResItemAndDependencyTable::const_iterator iter = _provides_by_name.lower_bound(dep->name()); iter != _provides_by_name.upper_bound(dep->name()); iter++) { - constResItemAndDependencyPtr r_and_d = iter->second; - constResItemPtr res = r_and_d->resItem(); -//fprintf (stderr, "StoreWorld::foreachProvidingResItem(): %s\n", res->asString(true).c_str()); - if (res != NULL && res->isInstalled ()) { - installed[res] = r_and_d; - } - } - - for (ResItemAndDependencyTable::const_iterator iter = _provides_by_name.lower_bound(dep->name()); iter != _provides_by_name.upper_bound(dep->name()); iter++) { - constResItemAndDependencyPtr r_and_d = iter->second; - - if (r_and_d && r_and_d->verifyRelation (dep)) { -//fprintf (stderr, "found: %s\n", r_and_d->resItem()->asString(true).c_str()); - /* If we have multiple identical resItems in RCWorld, - we want to only include the resItem that is installed and - skip the rest. */ - if (r_and_d->resItem()->isInstalled() - || installed.find(r_and_d->resItem()) == installed.end()) { - - if (fn) { - if (! fn(r_and_d->resItem(), r_and_d->dependency(), data)) { - count = -1; - goto finished; - } - } - ++count; - } - } - } - - finished: - - return count; -} - -int -StoreWorld::foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) -{ - int count = 0; - InstalledTable installed; - - - for (ResItemAndDependencyTable::const_iterator iter = _requires_by_name.lower_bound(dep->name()); iter != _requires_by_name.upper_bound(dep->name()); iter++) { - constResItemAndDependencyPtr r_and_d = iter->second; - constResItemPtr res = r_and_d->resItem(); - if (res != NULL && res->isInstalled ()) { -//fprintf (stderr, "is installed: %s\n", res->asString(true).c_str()); - installed[res] = r_and_d; - } - } - - for (ResItemAndDependencyTable::const_iterator iter = _requires_by_name.lower_bound(dep->name()); iter != _requires_by_name.upper_bound(dep->name()); iter++) { - constResItemAndDependencyPtr r_and_d = iter->second; - - if (r_and_d && r_and_d->dependency()->verifyRelation (dep)) { - - /* Skip dups if one of them in installed. */ - if (r_and_d->resItem()->isInstalled() - || installed.find(r_and_d->resItem()) == installed.end()) { - - if (fn) { - if (! fn(r_and_d->resItem(), r_and_d->dependency(), data)) { - count = -1; - goto finished; - } - } - ++count; - } - } - } - - finished: - - return count; -} - - -int -StoreWorld::foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) -{ - int count = 0; - InstalledTable installed; -//fprintf (stderr, "StoreWorld::foreachConflictingResItem (%s)\n", dep->name().c_str()); - for (ResItemAndDependencyTable::const_iterator iter = _conflicts_by_name.lower_bound(dep->name()); iter != _conflicts_by_name.upper_bound(dep->name()); iter++) { - constResItemAndDependencyPtr r_and_d = iter->second; - constResItemPtr res = r_and_d->resItem(); -//fprintf (stderr, "==> %s\n", res->asString().c_str()); - if (res != NULL && res->isInstalled ()) { - installed[res] = r_and_d; - } - } - - for (ResItemAndDependencyTable::const_iterator iter = _conflicts_by_name.lower_bound(dep->name()); iter != _conflicts_by_name.upper_bound(dep->name()); iter++) { - constResItemAndDependencyPtr r_and_d = iter->second; - - if (r_and_d) -//fprintf (stderr, "==> %s verify %s ? %s\n", r_and_d->asString().c_str(), dep->asString().c_str(), r_and_d->verifyRelation (dep) ? "Y" : "N"); - if (r_and_d && r_and_d->verifyRelation (dep)) { - - /* Skip dups if one of them in installed. */ - if (r_and_d->resItem()->isInstalled() - || installed.find(r_and_d->resItem()) == installed.end()) { - - if (fn) { - if (! fn(r_and_d->resItem(), r_and_d->dependency(), data)) { - count = -1; - goto finished; - } - } - ++count; - } - } - } - - finished: - - return count; -} - -//----------------------------------------------------------------------------- -// channel functions - -void -StoreWorld::addChannel (ChannelPtr channel) -{ - if (channel == NULL) return; - - channel->setWorld (this); - channel->setImmutable (true); - - _channels.push_back (channel); - - touchChannelSequenceNumber (); -} - - -void -StoreWorld::removeChannel (constChannelPtr channel) -{ - if (channel == NULL - || ! containsChannel (channel)) - return; - - removeResItems (channel); - - for (ChannelList::iterator iter = _channels.begin(); iter != _channels.end(); iter++) { - if ((*iter)->equals (channel)) { - _channels.erase (iter); - touchChannelSequenceNumber (); - break; - } - } -} - - -bool -StoreWorld::containsChannel (constChannelPtr channel) const -{ - for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { - if ((*iter)->equals (channel)) { - return true; - } - } - return false; -} - - -ChannelPtr -StoreWorld::getChannelByName (const char *channel_name) const -{ - if (channel_name == NULL - || *channel_name == 0) { - return NULL; - } - - for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { - if (strcasecmp ((*iter)->name(), channel_name) == 0) { - return *iter; - } - } - return NULL; -} - - -ChannelPtr -StoreWorld::getChannelByAlias (const char *alias) const -{ - if (alias == NULL - || *alias == 0) { - return NULL; - } - - for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { - if (strcasecmp ((*iter)->alias(), alias) == 0) { - return *iter; - } - } - return NULL; -} - - -ChannelPtr -StoreWorld::getChannelById (const char *channel_id) const -{ - if (channel_id == NULL - || *channel_id == 0) { - return NULL; - } - - for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { - if (strcasecmp ((*iter)->id(), channel_id) == 0) { - return *iter; - } - } - return NULL; -} - - -int -StoreWorld::foreachChannel (ChannelFn fn, void *data) const -{ - int count = 0; - for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { - if (!(*fn) (*iter, data)) - return -1; - count++; - } - return count; -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(StoreWorld, World); + + //--------------------------------------------------------------------------- + + string + StoreWorld::asString ( void ) const + { + return toString (*this); + } + + + string + StoreWorld::toString ( const StoreWorld & storeworld ) + { + string res (""); + + return res; + } + + + ostream & + StoreWorld::dumpOn (ostream & str) const + { + str << asString(); + return str; + } + + + ostream & + operator<< (ostream & os, const StoreWorld & storeworld) + { + return os << storeworld.asString(); + } + + //--------------------------------------------------------------------------- + + StoreWorld::StoreWorld (WorldType type) + : World (type) + , _resItem_kind(Kind::Unknown) + { + } + + + StoreWorld::~StoreWorld() + { + fprintf (stderr, "*** deleting store world[%p]: %s\n", this, World::toString(type()).c_str()); + } + + + //--------------------------------------------------------------------------- + + // Add/remove resItems + + bool + StoreWorld::addResItem (constResItemPtr resItem) + { + ArchList compat_arch_list; + ResItemAndDependencyPtr r_and_d; + const char *package_name; + constChannelPtr channel; + int arch_score; + bool actually_added_package = false; + + if (resItem == NULL) return false; + + compat_arch_list = Arch::System->getCompatList(); + //fprintf (stderr, "Arch::System '%s' -> %d compats\n", Arch::System->asString().c_str(), (int) compat_arch_list.size()); + channel = resItem->channel (); + + // fprintf (stderr, "StoreWorld[%p]::addResItem(%s) [%s]\n", this, ((constSpecPtr)resItem)->asString().c_str(), channel?channel->name():"?"); + + arch_score = resItem->arch()->getCompatScore(compat_arch_list); + + /* Before we do anything, check to make sure that a resItem of the + same name isn't already in that channel. If there is a + duplicate, we keep the one with the most recent version number + and drop the other. + + This check only applies to resItems in a channel. We have + to allow for multiple installs. Grrrr... + */ + + if (!resItem->isInstalled ()) { // its not a system package + + constResItemPtr dup_res; + int dup_arch_score; + + /* Filter out resItems with totally incompatible arches */ + if (arch_score < 0) { + rc_debug (RC_DEBUG_LEVEL_DEBUG, "Ignoring resItem with incompatible arch: Arch '%s', %s", resItem->arch()->asString().c_str(), resItem->asString(true).c_str()); + goto finished; + } + + package_name = resItem->name().c_str(); + dup_res = findResItem (channel, package_name); + + /* This shouldn't happen (and would be caught by the check + below, because cmp will equal 0), but it never hurts to + check and produce a more explicit warning message. */ + + if (resItem == dup_res) { + rc_debug (RC_DEBUG_LEVEL_WARNING, "Ignoring re-add of resItem '%s'", package_name); + goto finished; + } + + if (dup_res != NULL) { + int cmp; + + cmp = GVersion.compare (resItem, dup_res); + //fprintf (stderr, "res: %s, dup_res %s, cmp %d\n", resItem->asString().c_str(), dup_res->asString().c_str(), cmp); + dup_arch_score = dup_res->arch()->getCompatScore(compat_arch_list); + + + /* If the resItem we are trying to add has a lower + version number, just ignore it. */ + + if (cmp < 0) { + rc_debug (RC_DEBUG_LEVEL_INFO, "Not adding resItem '%s'.\n\tA newer version is already in the channel.", resItem->asString().c_str()); + rc_debug (RC_DEBUG_LEVEL_INFO, "\t%s", dup_res->asString().c_str()); + goto finished; + } + + + /* If the version numbers are equal, we ignore the resItem to + add if it has a less-preferable arch. If both + resItems have the same version # and arch, we favor the + first resItem and just return. */ + + if (cmp == 0 && arch_score > dup_arch_score) { + rc_debug (RC_DEBUG_LEVEL_INFO, "Not adding resItem '%s'.\n\tAnother resItem with the same version but with a preferred arch is already in the channel.", resItem->asString().c_str()); + rc_debug (RC_DEBUG_LEVEL_INFO, "\t%s", dup_res->asString().c_str()); + goto finished; + } + + + /* Otherwise we throw out the old resItem and proceed with + adding the newer one. */ + + rc_debug (RC_DEBUG_LEVEL_INFO, "Replacing resItem '%s'.\n\tAnother resItem in the channel has the same name and a superior %s.", dup_res->asString().c_str(), cmp ? "version" : "arch"); + rc_debug (RC_DEBUG_LEVEL_INFO, "\t%s", resItem->asString().c_str()); + + removeResItem (dup_res); + } + } + + actually_added_package = true; + + if (channel && !channel->hidden()) { + touchResItemSequenceNumber (); + } + + /* StoreWorld all of our resItems in a hash by name. */ + _resItems_by_name.insert (ResItemTable::value_type (resItem->name(), resItem)); + + /* StoreWorld all of the resItem's provides in a hash by name. */ + for (CDependencyList::const_iterator i = resItem->provides().begin(); i != resItem->provides().end(); i++) { + r_and_d = new ResItemAndDependency (resItem, *i); + + _provides_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); + } + + /* StoreWorld all of the resItem's requires in a hash by name. */ + + for (CDependencyList::const_iterator i = resItem->requires().begin(); i != resItem->requires().end(); i++) { + r_and_d = new ResItemAndDependency (resItem, *i); + + _requires_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); + } + + /* "Recommends" are treated as requirements. */ + #warning Recommends are treated as requirements + + for (CDependencyList::const_iterator i = resItem->recommends().begin(); i != resItem->recommends().end(); i++) { + r_and_d = new ResItemAndDependency (resItem, *i); + + _requires_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); + } + + /* StoreWorld all of the resItem's conflicts in a hash by name. */ + + for (CDependencyList::const_iterator i = resItem->conflicts().begin(); i != resItem->conflicts().end(); i++) { + r_and_d = new ResItemAndDependency (resItem, *i); + _conflicts_by_name.insert (ResItemAndDependencyTable::value_type (r_and_d->dependency()->name(), r_and_d)); + } + + finished: + + return actually_added_package; + } + + + void + StoreWorld::addResItemsFromList (const CResItemList & slist) + { + for (CResItemList::const_iterator i = slist.begin(); i != slist.end(); i++) { + if (!addResItem (*i)) { + fprintf (stderr, "addResItem failed\n"); + break; + } + } + return; + } + + //--------------------------------------------------------------------------- + + static void + resItem_table_remove (ResItemTable & table, constResItemPtr resItem) + { + const string name = resItem->name(); + for (ResItemTable::iterator pos = table.lower_bound(name); pos != table.upper_bound(name); pos++) { + constResItemPtr res = pos->second; + if (res == resItem) { + table.erase (pos); + break; + } + } + return; + } + + + static void + resItem_and_dependency_table_remove (ResItemAndDependencyTable & table, constResItemPtr resItem) + { + const string name = resItem->name(); + // FIXME: this is inefficient but lower_bound can't to strcasecmp :-( + // for (ResItemAndDependencyTable::iterator pos = table.lower_bound(name); pos != table.upper_bound(name); pos++) { + for (ResItemAndDependencyTable::iterator pos = table.begin(); pos != table.end(); pos++) { + constResItemAndDependencyPtr r_and_d = pos->second; + if (r_and_d->resItem() == resItem) { + table.erase (pos); + break; + } + } + return; + } + + void + StoreWorld::removeResItem (constResItemPtr resItem) + { + if (getenv("RC_SPEW")) fprintf (stderr, "StoreWorld::removeResItem (%s)\n", resItem->asString().c_str()); + + constChannelPtr channel = resItem->channel (); + + if (! (channel && channel->hidden ())) + touchResItemSequenceNumber (); + + resItem_and_dependency_table_remove (_provides_by_name, resItem); + resItem_and_dependency_table_remove (_requires_by_name, resItem); + resItem_and_dependency_table_remove (_conflicts_by_name, resItem); + + resItem_table_remove (_resItems_by_name, resItem); + + return; + } + + + void + StoreWorld::removeResItems (constChannelPtr channel) + { + fprintf (stderr, "StoreWorld::removeResItems(%s) not implemented\n", channel->asString().c_str()); + } + + + void + StoreWorld::clear () + { + fprintf (stderr, "StoreWorld::clear() not implemented\n"); + } + + //--------------------------------------------------------------------------- + // Single resItem queries + + static bool + installed_version_cb (constResItemPtr resItem, void *data) + { + constResItemPtr *installed = (constResItemPtr *)data; + + if (resItem->isInstalled ()) { + *installed = resItem; + return false; + } + return true; + } + + + constResItemPtr + StoreWorld::findInstalledResItem (constResItemPtr resItem) + { + constResItemPtr installed; + sync (); + + foreachResItemByName (resItem->name(), new Channel(CHANNEL_TYPE_ANY) /* is this right? */, installed_version_cb, &installed); + + return installed; + } + + + // + // findResItem + // @channel: A non-wildcard #Channel. + // @name: The name of a resItem. + // + // Searches the world for a resItem in the specified channel + // with the specified name. @channel must be an actual + // channel, not a wildcard. + // + // Return value: The matching resItem, or %NULL if no such + // resItem exists. + // + + constResItemPtr + StoreWorld::findResItem (constChannelPtr channel, const char *name) const + { + syncConditional (channel); + for (ResItemTable::const_iterator pos = _resItems_by_name.lower_bound(name); pos != _resItems_by_name.upper_bound(name); pos++) { + constResItemPtr res = pos->second; + if (res->channel() == channel) { + return res; + } + } + return NULL; + } + + + constResItemPtr + StoreWorld::findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const + { + fprintf (stderr, "StoreWorld::findResItemWithConstraint() not implemented\n"); + return 0; + } + + + ChannelPtr + StoreWorld::guessResItemChannel (constResItemPtr resItem) const + { + fprintf (stderr, "StoreWorld::guessResItemChannel(%s) not implemented\n", ((constSpecPtr)resItem)->asString().c_str()); + return 0; + } + + + //----------------------------------------------------------------------------- + // foreach resItem + + typedef struct { + ChannelPtr channel; + CResItemFn callback; + void *data; + int count; + bool short_circuit; + } ForeachResItemInfo; + + + static void + foreach_resItem_cb (const string &name, constResItemPtr resItem, void *data) + { + ForeachResItemInfo *info = (ForeachResItemInfo *)data; + + if (info->short_circuit) + return; + + /* FIXME: we should filter out dup uninstalled resItems. */ + + if (resItem && info->channel->equals(resItem->channel ())) { + if (info->callback) { + if (! info->callback (resItem, info->data)) + info->short_circuit = true; + } + ++info->count; + } + } + + + int + StoreWorld::foreachResItem (ChannelPtr channel, CResItemFn fn, void *data) + { + return foreachResItemByName ("", channel, fn, data); + } + + + int + StoreWorld::foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data) + { + if (name.empty()) { + + ForeachResItemInfo info; + + info.channel = channel; + info.callback = fn; + info.data = data; + info.count = 0; + info.short_circuit = false; + + for (ResItemTable::const_iterator iter = _resItems_by_name.begin(); iter != _resItems_by_name.end(); iter++) { + foreach_resItem_cb (iter->first, iter->second, (void *)&info); + } + + return info.short_circuit ? -1 : info.count; + } + + + ResItemTable installed; // FIXME: rc_resItem_spec_equal + int count = 0; + + for (ResItemTable::const_iterator iter = _resItems_by_name.lower_bound(name); iter != _resItems_by_name.upper_bound(name); iter++) { + constResItemPtr resItem = iter->second; + if (resItem->isInstalled()) { + const string str = ((constSpecPtr)resItem)->asString(); + installed.insert (ResItemTable::value_type(str,resItem)); + } + } + + for (ResItemTable::const_iterator iter = _resItems_by_name.lower_bound(name); iter != _resItems_by_name.upper_bound(name); iter++) { + constResItemPtr resItem = iter->second; + if (channel->equals (resItem->channel())) { + if (resItem->isInstalled() + || installed.find(((constSpecPtr)resItem)->asString()) == installed.end()) { + if (fn) { + if (! fn(resItem, data)) { + count = -1; + goto finished; + } + } + ++count; + } + } + } + + finished: + + return count; + } + + + int + StoreWorld::foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data) + { + fprintf (stderr, "StoreWorld::foreachResItemByMatch () not implemented\n"); + return 0; + } + + + //----------------------------------------------------------------------------- + // iterater over resItems with dependency + + typedef std::map InstalledTable; + + int + StoreWorld::foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data) + { + int count = 0; + InstalledTable installed; + //fprintf (stderr, "StoreWorld::foreachProvidingResItem(%s)\n", dep->asString().c_str()); + for (ResItemAndDependencyTable::const_iterator iter = _provides_by_name.lower_bound(dep->name()); iter != _provides_by_name.upper_bound(dep->name()); iter++) { + constResItemAndDependencyPtr r_and_d = iter->second; + constResItemPtr res = r_and_d->resItem(); + //fprintf (stderr, "StoreWorld::foreachProvidingResItem(): %s\n", res->asString(true).c_str()); + if (res != NULL && res->isInstalled ()) { + installed[res] = r_and_d; + } + } + + for (ResItemAndDependencyTable::const_iterator iter = _provides_by_name.lower_bound(dep->name()); iter != _provides_by_name.upper_bound(dep->name()); iter++) { + constResItemAndDependencyPtr r_and_d = iter->second; + + if (r_and_d && r_and_d->verifyRelation (dep)) { + //fprintf (stderr, "found: %s\n", r_and_d->resItem()->asString(true).c_str()); + /* If we have multiple identical resItems in RCWorld, + we want to only include the resItem that is installed and + skip the rest. */ + if (r_and_d->resItem()->isInstalled() + || installed.find(r_and_d->resItem()) == installed.end()) { + + if (fn) { + if (! fn(r_and_d->resItem(), r_and_d->dependency(), data)) { + count = -1; + goto finished; + } + } + ++count; + } + } + } + + finished: + + return count; + } + + int + StoreWorld::foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) + { + int count = 0; + InstalledTable installed; + + + for (ResItemAndDependencyTable::const_iterator iter = _requires_by_name.lower_bound(dep->name()); iter != _requires_by_name.upper_bound(dep->name()); iter++) { + constResItemAndDependencyPtr r_and_d = iter->second; + constResItemPtr res = r_and_d->resItem(); + if (res != NULL && res->isInstalled ()) { + //fprintf (stderr, "is installed: %s\n", res->asString(true).c_str()); + installed[res] = r_and_d; + } + } + + for (ResItemAndDependencyTable::const_iterator iter = _requires_by_name.lower_bound(dep->name()); iter != _requires_by_name.upper_bound(dep->name()); iter++) { + constResItemAndDependencyPtr r_and_d = iter->second; + + if (r_and_d && r_and_d->dependency()->verifyRelation (dep)) { + + /* Skip dups if one of them in installed. */ + if (r_and_d->resItem()->isInstalled() + || installed.find(r_and_d->resItem()) == installed.end()) { + + if (fn) { + if (! fn(r_and_d->resItem(), r_and_d->dependency(), data)) { + count = -1; + goto finished; + } + } + ++count; + } + } + } + + finished: + + return count; + } + + + int + StoreWorld::foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data) + { + int count = 0; + InstalledTable installed; + //fprintf (stderr, "StoreWorld::foreachConflictingResItem (%s)\n", dep->name().c_str()); + for (ResItemAndDependencyTable::const_iterator iter = _conflicts_by_name.lower_bound(dep->name()); iter != _conflicts_by_name.upper_bound(dep->name()); iter++) { + constResItemAndDependencyPtr r_and_d = iter->second; + constResItemPtr res = r_and_d->resItem(); + //fprintf (stderr, "==> %s\n", res->asString().c_str()); + if (res != NULL && res->isInstalled ()) { + installed[res] = r_and_d; + } + } + + for (ResItemAndDependencyTable::const_iterator iter = _conflicts_by_name.lower_bound(dep->name()); iter != _conflicts_by_name.upper_bound(dep->name()); iter++) { + constResItemAndDependencyPtr r_and_d = iter->second; + + if (r_and_d) + //fprintf (stderr, "==> %s verify %s ? %s\n", r_and_d->asString().c_str(), dep->asString().c_str(), r_and_d->verifyRelation (dep) ? "Y" : "N"); + if (r_and_d && r_and_d->verifyRelation (dep)) { + + /* Skip dups if one of them in installed. */ + if (r_and_d->resItem()->isInstalled() + || installed.find(r_and_d->resItem()) == installed.end()) { + + if (fn) { + if (! fn(r_and_d->resItem(), r_and_d->dependency(), data)) { + count = -1; + goto finished; + } + } + ++count; + } + } + } + + finished: + + return count; + } + + //----------------------------------------------------------------------------- + // channel functions + + void + StoreWorld::addChannel (ChannelPtr channel) + { + if (channel == NULL) return; + + channel->setWorld (this); + channel->setImmutable (true); + + _channels.push_back (channel); + + touchChannelSequenceNumber (); + } + + + void + StoreWorld::removeChannel (constChannelPtr channel) + { + if (channel == NULL + || ! containsChannel (channel)) + return; + + removeResItems (channel); + + for (ChannelList::iterator iter = _channels.begin(); iter != _channels.end(); iter++) { + if ((*iter)->equals (channel)) { + _channels.erase (iter); + touchChannelSequenceNumber (); + break; + } + } + } + + + bool + StoreWorld::containsChannel (constChannelPtr channel) const + { + for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { + if ((*iter)->equals (channel)) { + return true; + } + } + return false; + } + + + ChannelPtr + StoreWorld::getChannelByName (const char *channel_name) const + { + if (channel_name == NULL + || *channel_name == 0) { + return NULL; + } + + for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { + if (strcasecmp ((*iter)->name(), channel_name) == 0) { + return *iter; + } + } + return NULL; + } + + + ChannelPtr + StoreWorld::getChannelByAlias (const char *alias) const + { + if (alias == NULL + || *alias == 0) { + return NULL; + } + + for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { + if (strcasecmp ((*iter)->alias(), alias) == 0) { + return *iter; + } + } + return NULL; + } + + + ChannelPtr + StoreWorld::getChannelById (const char *channel_id) const + { + if (channel_id == NULL + || *channel_id == 0) { + return NULL; + } + + for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { + if (strcasecmp ((*iter)->id(), channel_id) == 0) { + return *iter; + } + } + return NULL; + } + + + int + StoreWorld::foreachChannel (ChannelFn fn, void *data) const + { + int count = 0; + for (ChannelList::const_iterator iter = _channels.begin(); iter != _channels.end(); iter++) { + if (!(*fn) (*iter, data)) + return -1; + count++; + } + return count; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/StoreWorld.h b/zypp/solver/detail/StoreWorld.h index 919857e..402cfa4 100644 --- a/zypp/solver/detail/StoreWorld.h +++ b/zypp/solver/detail/StoreWorld.h @@ -34,97 +34,107 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : StoreWorld - -class StoreWorld : public World { - REP_BODY(StoreWorld); - - private: - - int _freeze_count; - - ResItemTable _resItems_by_name; - ResItemAndDependencyTable _provides_by_name; - ResItemAndDependencyTable _requires_by_name; - ResItemAndDependencyTable _conflicts_by_name; - - PackmanPtr _packman; - Kind _resItem_kind; - - ChannelList _channels; - - public: - - StoreWorld (WorldType type = STORE_WORLD); - virtual ~StoreWorld(); - - // ---------------------------------- I/O - - static std::string toString (const StoreWorld & storeworld); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const StoreWorld & storeworld); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - virtual ChannelList channels () const { return _channels; } - - // ---------------------------------- methods - - // Add/remove resItems - - bool addResItem (constResItemPtr resItem); - void addResItemsFromList (const CResItemList & slist); - void removeResItem (constResItemPtr resItem); - void removeResItems (constChannelPtr channel); - void clear (); - - // Iterate over resItems - - virtual int foreachResItem (ChannelPtr channel, CResItemFn fn, void *data); - virtual int foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data); - virtual int foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data); - - // Iterate across provides or requirement - - virtual int foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data); - virtual int foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); - virtual int foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); - - // Channels - - void addChannel (ChannelPtr channel); - void removeChannel (constChannelPtr channel); - - virtual bool containsChannel (constChannelPtr channel) const; - - virtual ChannelPtr getChannelByName (const char *channel_name) const; - virtual ChannelPtr getChannelByAlias (const char *alias) const; - virtual ChannelPtr getChannelById (const char *channel_id) const; - - virtual int foreachChannel (ChannelFn fn, void *data) const; - - // Single resItem queries - - virtual constResItemPtr findInstalledResItem (constResItemPtr resItem); - virtual constResItemPtr findResItem (constChannelPtr channel, const char *name) const; - virtual constResItemPtr findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const; - virtual ChannelPtr guessResItemChannel (constResItemPtr resItem) const; - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : StoreWorld + + class StoreWorld : public World { + REP_BODY(StoreWorld); + + private: + + int _freeze_count; + + ResItemTable _resItems_by_name; + ResItemAndDependencyTable _provides_by_name; + ResItemAndDependencyTable _requires_by_name; + ResItemAndDependencyTable _conflicts_by_name; + + PackmanPtr _packman; + Kind _resItem_kind; + + ChannelList _channels; + + public: + + StoreWorld (WorldType type = STORE_WORLD); + virtual ~StoreWorld(); + + // ---------------------------------- I/O + + static std::string toString (const StoreWorld & storeworld); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const StoreWorld & storeworld); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + virtual ChannelList channels () const { return _channels; } + + // ---------------------------------- methods + + // Add/remove resItems + + bool addResItem (constResItemPtr resItem); + void addResItemsFromList (const CResItemList & slist); + void removeResItem (constResItemPtr resItem); + void removeResItems (constChannelPtr channel); + void clear (); + + // Iterate over resItems + + virtual int foreachResItem (ChannelPtr channel, CResItemFn fn, void *data); + virtual int foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *data); + virtual int foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *data); + + // Iterate across provides or requirement + + virtual int foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *data); + virtual int foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); + virtual int foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *data); + + // Channels + + void addChannel (ChannelPtr channel); + void removeChannel (constChannelPtr channel); + + virtual bool containsChannel (constChannelPtr channel) const; + + virtual ChannelPtr getChannelByName (const char *channel_name) const; + virtual ChannelPtr getChannelByAlias (const char *alias) const; + virtual ChannelPtr getChannelById (const char *channel_id) const; + + virtual int foreachChannel (ChannelFn fn, void *data) const; + + // Single resItem queries + + virtual constResItemPtr findInstalledResItem (constResItemPtr resItem); + virtual constResItemPtr findResItem (constChannelPtr channel, const char *name) const; + virtual constResItemPtr findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const; + virtual ChannelPtr guessResItemChannel (constResItemPtr resItem) const; + + }; + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _StoreWorld_h diff --git a/zypp/solver/detail/StoreWorldPtr.h b/zypp/solver/detail/StoreWorldPtr.h index 9d51da6..aed4eab 100644 --- a/zypp/solver/detail/StoreWorldPtr.h +++ b/zypp/solver/detail/StoreWorldPtr.h @@ -24,18 +24,31 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// CLASS NAME : StoreWorldPtr -// CLASS NAME : constStoreWorldPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(StoreWorld, World); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : StoreWorldPtr + // CLASS NAME : constStoreWorldPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(StoreWorld, World); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _StoreWorldPtr_h diff --git a/zypp/solver/detail/Subscription.cc b/zypp/solver/detail/Subscription.cc index 68cbcbb..5d4ee4e 100644 --- a/zypp/solver/detail/Subscription.cc +++ b/zypp/solver/detail/Subscription.cc @@ -32,361 +32,371 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -#define SUBSCRIPTION_PATH "/var/adm/zypp" -#define OLD_SUBSCRIPTION_PATH "/var/lib/rcd" -#define SUBSCRIPTION_NAME "/subscriptions.xml" - -#define DEFAULT_SUBSCRIPTION_FILE SUBSCRIPTION_PATH SUBSCRIPTION_NAME -#define OLD_SUBSCRIPTION_FILE OLD_SUBSCRIPTION_PATH SUBSCRIPTION_NAME - -/* Old subscriptions expire in 60 days */ -#define OLD_SUBSCRIPTION_EXPIRATION 60*24*60*60 - -SubscriptionList Subscription::subscriptions; -bool Subscription::subscriptions_changed = false; -const char *Subscription::subscription_file = DEFAULT_SUBSCRIPTION_FILE; - -//--------------------------------------------------------------------------- - -string -Subscription::asString ( void ) const -{ - return toString (*this); -} - - -string -Subscription::toString ( const Subscription & s) -{ - return ""; -} - -ostream & -Subscription::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Subscription & s) -{ - return os << s.asString(); -} - -//--------------------------------------------------------------------------- - - -void -Subscription::save (void) -{ - xmlDoc *doc; - xmlNode *root; - char buf[64]; - time_t now; - int save_retval; - - if (! subscriptions_changed) - return; - - time (&now); - - root = xmlNewNode (NULL, (const xmlChar*)"subscriptions"); - xmlNewProp (root, (const xmlChar*)"version", (const xmlChar*)"2.0"); - - doc = xmlNewDoc ((const xmlChar*)"1.0"); - xmlDocSetRootElement (doc, root); - - for (SubscriptionList::iterator iter = subscriptions.begin(); iter != subscriptions.end(); iter++) { - xmlNode *sub_node; - - Subscription *sub = *iter; - - /* Drop "old" (i.e. imported from 1.x) subscriptions that - we haven't seen for a while. */ - if (sub->_old) { - double elapsed = difftime (now, sub->_last_seen); - if (elapsed > OLD_SUBSCRIPTION_EXPIRATION) - continue; - } - - sub_node = xmlNewChild (root, NULL, (const xmlChar*)"channel", NULL); - - xmlNewProp (sub_node, (const xmlChar*)"id", (const xmlChar*)(sub->_channel_id.c_str())); - - snprintf (buf, sizeof (buf), "%ld", (long) sub->_last_seen); - xmlNewProp (sub_node, (const xmlChar*)"last_seen", (const xmlChar*)buf); - - if (sub->_old) - xmlNewProp (sub_node, (const xmlChar*)"old", (const xmlChar*)"1"); - } - - save_retval = xmlSaveFile (subscription_file, doc); - xmlFreeDoc (doc); - - if (save_retval > 0) { - /* Writing out the subscription file succeeded. */ - subscriptions_changed = false; - } else { - rc_debug (RC_DEBUG_LEVEL_WARNING, "Unable to save subscription data to '%s'", subscription_file); - rc_debug (RC_DEBUG_LEVEL_WARNING, "Subscription will not be saved!"); - } -} - - -void -Subscription::load_old_subscriptions (void) -{ - static bool tried_to_do_this_already = false; - xmlDoc *doc; - XmlNodePtr node; - - if (tried_to_do_this_already) - return; - tried_to_do_this_already = true; - - if (access (OLD_SUBSCRIPTION_FILE, R_OK) != 0) { - rc_debug (RC_DEBUG_LEVEL_WARNING, "Can't find rcd 1.x subscription file '%s'", OLD_SUBSCRIPTION_FILE); - return; - } - - doc = xmlParseFile (OLD_SUBSCRIPTION_FILE); - if (doc == NULL) { - rc_debug (RC_DEBUG_LEVEL_ERROR, "Can't parse rcd 1.x subscription file '%s'", OLD_SUBSCRIPTION_FILE); - return; - } - - node = new XmlNode (xmlDocGetRootElement (doc)); - - if (!node->equals("subscriptions")) { - rc_debug (RC_DEBUG_LEVEL_ERROR, "rcd 1.x subscription file '%s' is malformed", OLD_SUBSCRIPTION_FILE); - return; - } - - rc_debug (RC_DEBUG_LEVEL_INFO, "Importing rcd 1.x subscriptions."); - - node = node->children(); - - while (node != NULL) { - - if (node->equals ("channel")) { - const char *id_str; - - id_str = node->getProp ("channel_id"); - if (id_str && *id_str) { - - Subscription *sub = new Subscription (id_str); - sub->_old = true; - - subscriptions.push_back (sub); - } - } - - node = node->next(); - } - - /* If we've imported old subscriptions, we need to write them - out immediately into the new subscriptions file. */ - - subscriptions_changed = true; - save (); -} - - -void -Subscription::load (void) -{ - xmlDoc *doc; - XmlNodePtr node; - - if (access (subscription_file, R_OK) != 0) { - load_old_subscriptions (); - return; - } - - doc = xmlParseFile (subscription_file); - if (doc == NULL) { - rc_debug (RC_DEBUG_LEVEL_ERROR, "Can't parse subscription file '%s'", subscription_file); - return; - } - - node = new XmlNode (xmlDocGetRootElement (doc)); - - if (! node->equals ("subscriptions")) { - rc_debug (RC_DEBUG_LEVEL_ERROR, "Subscription file '%s' is malformed", subscription_file); - return; - } - - node = node->children(); - - while (node != NULL) { - - if (node->equals ("channel")) { - const char *id_str, *last_seen_str; - - id_str = node->getProp ("id"); - last_seen_str = node->getProp ("last_seen"); - - if (id_str && *id_str) { - Subscription *sub = new Subscription (id_str); - - if (last_seen_str) - sub->_last_seen = (time_t) atol (last_seen_str); - else - sub->_last_seen = time (NULL); - - sub->_old = node->getUnsignedIntValueDefault("old", 0); - - subscriptions.push_back (sub); - } - - free ((void *)id_str); - free ((void *)last_seen_str); - - } - - node = node->next(); - } - - xmlFreeDoc (doc); -} - -//--------------------------------------------------------------------------- - -bool -Subscription::match (constChannelPtr channel) -{ - bool match; - - /* Paranoia is the programmer's friend. */ - if (channel == NULL) return false; - if (channel->id() == NULL) return false; - - /* If this is an old (i.e. imported from 1.x) subscription, we - compare it against the channel id's tail. */ - - if (_old) { - const char *id = channel->legacyId (); - int len1, len2; - - if (!id) - return false; - - len1 = strlen (_channel_id.c_str()); - len2 = strlen (id); - - if (len1 > len2) - return false; - - /* If the tails match, mutate the Subscription into a - new-style subscription for that channel. */ - if (! strcmp (id + (len2 - len1), _channel_id.c_str())) { - _channel_id = channel->id (); - _old = false; - subscriptions_changed = true; - - return true; - } - - return false; - } - - match = (_channel_id == channel->id ()); - - if (match) { - time (&_last_seen); - } - - return match; -} - -//----------------------------------------------------------------------------- - -void -Subscription::setFile (const char *path) -{ - subscription_file = path; -} - - -bool -Subscription::status (constChannelPtr channel) -{ - if (subscriptions.empty()) - load (); - - if (channel == NULL) - return false; - - for (SubscriptionList::iterator iter = subscriptions.begin(); iter != subscriptions.end(); iter++) { - Subscription *sub = *iter; - if (sub->match (channel)) - return true; - } - - save (); - - return false; -} - - -void -Subscription::setStatus (constChannelPtr channel, bool subscribe_to_channel) -{ - bool currently_subscribed; - - if (channel == NULL) return; - - currently_subscribed = status (channel); - - if (currently_subscribed && !subscribe_to_channel) { - - /* Unsubscribe to the channel */ - for (SubscriptionList::iterator iter = subscriptions.begin(); iter != subscriptions.end(); iter++) { - Subscription *sub = *iter; - if (sub->match (channel)) { - subscriptions.erase (iter); - subscriptions_changed = true; - break; - } - } - - } else if (!currently_subscribed && subscribe_to_channel) { - - /* Subscribe to the channel */ - Subscription *sub; - sub = new Subscription (channel->id ()); - subscriptions.push_back(sub); - subscriptions_changed = true; - } - - save (); -} - -//--------------------------------------------------------------------------- - -Subscription::Subscription(const char *id) -{ - _channel_id = string (id); - _last_seen = time (NULL); - _old = false; -} - - -Subscription::~Subscription() -{ -} - - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + #define SUBSCRIPTION_PATH "/var/adm/zypp" + #define OLD_SUBSCRIPTION_PATH "/var/lib/rcd" + #define SUBSCRIPTION_NAME "/subscriptions.xml" + + #define DEFAULT_SUBSCRIPTION_FILE SUBSCRIPTION_PATH SUBSCRIPTION_NAME + #define OLD_SUBSCRIPTION_FILE OLD_SUBSCRIPTION_PATH SUBSCRIPTION_NAME + + /* Old subscriptions expire in 60 days */ + #define OLD_SUBSCRIPTION_EXPIRATION 60*24*60*60 + + SubscriptionList Subscription::subscriptions; + bool Subscription::subscriptions_changed = false; + const char *Subscription::subscription_file = DEFAULT_SUBSCRIPTION_FILE; + + //--------------------------------------------------------------------------- + + string + Subscription::asString ( void ) const + { + return toString (*this); + } + + + string + Subscription::toString ( const Subscription & s) + { + return ""; + } + + ostream & + Subscription::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Subscription & s) + { + return os << s.asString(); + } + + //--------------------------------------------------------------------------- + + + void + Subscription::save (void) + { + xmlDoc *doc; + xmlNode *root; + char buf[64]; + time_t now; + int save_retval; + + if (! subscriptions_changed) + return; + + time (&now); + + root = xmlNewNode (NULL, (const xmlChar*)"subscriptions"); + xmlNewProp (root, (const xmlChar*)"version", (const xmlChar*)"2.0"); + + doc = xmlNewDoc ((const xmlChar*)"1.0"); + xmlDocSetRootElement (doc, root); + + for (SubscriptionList::iterator iter = subscriptions.begin(); iter != subscriptions.end(); iter++) { + xmlNode *sub_node; + + Subscription *sub = *iter; + + /* Drop "old" (i.e. imported from 1.x) subscriptions that + we haven't seen for a while. */ + if (sub->_old) { + double elapsed = difftime (now, sub->_last_seen); + if (elapsed > OLD_SUBSCRIPTION_EXPIRATION) + continue; + } + + sub_node = xmlNewChild (root, NULL, (const xmlChar*)"channel", NULL); + + xmlNewProp (sub_node, (const xmlChar*)"id", (const xmlChar*)(sub->_channel_id.c_str())); + + snprintf (buf, sizeof (buf), "%ld", (long) sub->_last_seen); + xmlNewProp (sub_node, (const xmlChar*)"last_seen", (const xmlChar*)buf); + + if (sub->_old) + xmlNewProp (sub_node, (const xmlChar*)"old", (const xmlChar*)"1"); + } + + save_retval = xmlSaveFile (subscription_file, doc); + xmlFreeDoc (doc); + + if (save_retval > 0) { + /* Writing out the subscription file succeeded. */ + subscriptions_changed = false; + } else { + rc_debug (RC_DEBUG_LEVEL_WARNING, "Unable to save subscription data to '%s'", subscription_file); + rc_debug (RC_DEBUG_LEVEL_WARNING, "Subscription will not be saved!"); + } + } + + + void + Subscription::load_old_subscriptions (void) + { + static bool tried_to_do_this_already = false; + xmlDoc *doc; + XmlNodePtr node; + + if (tried_to_do_this_already) + return; + tried_to_do_this_already = true; + + if (access (OLD_SUBSCRIPTION_FILE, R_OK) != 0) { + rc_debug (RC_DEBUG_LEVEL_WARNING, "Can't find rcd 1.x subscription file '%s'", OLD_SUBSCRIPTION_FILE); + return; + } + + doc = xmlParseFile (OLD_SUBSCRIPTION_FILE); + if (doc == NULL) { + rc_debug (RC_DEBUG_LEVEL_ERROR, "Can't parse rcd 1.x subscription file '%s'", OLD_SUBSCRIPTION_FILE); + return; + } + + node = new XmlNode (xmlDocGetRootElement (doc)); + + if (!node->equals("subscriptions")) { + rc_debug (RC_DEBUG_LEVEL_ERROR, "rcd 1.x subscription file '%s' is malformed", OLD_SUBSCRIPTION_FILE); + return; + } + + rc_debug (RC_DEBUG_LEVEL_INFO, "Importing rcd 1.x subscriptions."); + + node = node->children(); + + while (node != NULL) { + + if (node->equals ("channel")) { + const char *id_str; + + id_str = node->getProp ("channel_id"); + if (id_str && *id_str) { + + Subscription *sub = new Subscription (id_str); + sub->_old = true; + + subscriptions.push_back (sub); + } + } + + node = node->next(); + } + + /* If we've imported old subscriptions, we need to write them + out immediately into the new subscriptions file. */ + + subscriptions_changed = true; + save (); + } + + + void + Subscription::load (void) + { + xmlDoc *doc; + XmlNodePtr node; + + if (access (subscription_file, R_OK) != 0) { + load_old_subscriptions (); + return; + } + + doc = xmlParseFile (subscription_file); + if (doc == NULL) { + rc_debug (RC_DEBUG_LEVEL_ERROR, "Can't parse subscription file '%s'", subscription_file); + return; + } + + node = new XmlNode (xmlDocGetRootElement (doc)); + + if (! node->equals ("subscriptions")) { + rc_debug (RC_DEBUG_LEVEL_ERROR, "Subscription file '%s' is malformed", subscription_file); + return; + } + + node = node->children(); + + while (node != NULL) { + + if (node->equals ("channel")) { + const char *id_str, *last_seen_str; + + id_str = node->getProp ("id"); + last_seen_str = node->getProp ("last_seen"); + + if (id_str && *id_str) { + Subscription *sub = new Subscription (id_str); + + if (last_seen_str) + sub->_last_seen = (time_t) atol (last_seen_str); + else + sub->_last_seen = time (NULL); + + sub->_old = node->getUnsignedIntValueDefault("old", 0); + + subscriptions.push_back (sub); + } + + free ((void *)id_str); + free ((void *)last_seen_str); + + } + + node = node->next(); + } + + xmlFreeDoc (doc); + } + + //--------------------------------------------------------------------------- + + bool + Subscription::match (constChannelPtr channel) + { + bool match; + + /* Paranoia is the programmer's friend. */ + if (channel == NULL) return false; + if (channel->id() == NULL) return false; + + /* If this is an old (i.e. imported from 1.x) subscription, we + compare it against the channel id's tail. */ + + if (_old) { + const char *id = channel->legacyId (); + int len1, len2; + + if (!id) + return false; + + len1 = strlen (_channel_id.c_str()); + len2 = strlen (id); + + if (len1 > len2) + return false; + + /* If the tails match, mutate the Subscription into a + new-style subscription for that channel. */ + if (! strcmp (id + (len2 - len1), _channel_id.c_str())) { + _channel_id = channel->id (); + _old = false; + subscriptions_changed = true; + + return true; + } + + return false; + } + + match = (_channel_id == channel->id ()); + + if (match) { + time (&_last_seen); + } + + return match; + } + + //----------------------------------------------------------------------------- + + void + Subscription::setFile (const char *path) + { + subscription_file = path; + } + + + bool + Subscription::status (constChannelPtr channel) + { + if (subscriptions.empty()) + load (); + + if (channel == NULL) + return false; + + for (SubscriptionList::iterator iter = subscriptions.begin(); iter != subscriptions.end(); iter++) { + Subscription *sub = *iter; + if (sub->match (channel)) + return true; + } + + save (); + + return false; + } + + + void + Subscription::setStatus (constChannelPtr channel, bool subscribe_to_channel) + { + bool currently_subscribed; + + if (channel == NULL) return; + + currently_subscribed = status (channel); + + if (currently_subscribed && !subscribe_to_channel) { + + /* Unsubscribe to the channel */ + for (SubscriptionList::iterator iter = subscriptions.begin(); iter != subscriptions.end(); iter++) { + Subscription *sub = *iter; + if (sub->match (channel)) { + subscriptions.erase (iter); + subscriptions_changed = true; + break; + } + } + + } else if (!currently_subscribed && subscribe_to_channel) { + + /* Subscribe to the channel */ + Subscription *sub; + sub = new Subscription (channel->id ()); + subscriptions.push_back(sub); + subscriptions_changed = true; + } + + save (); + } + + //--------------------------------------------------------------------------- + + Subscription::Subscription(const char *id) + { + _channel_id = string (id); + _last_seen = time (NULL); + _old = false; + } + + + Subscription::~Subscription() + { + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Subscription.h b/zypp/solver/detail/Subscription.h index c376799..7872dc3 100644 --- a/zypp/solver/detail/Subscription.h +++ b/zypp/solver/detail/Subscription.h @@ -30,62 +30,75 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Subscription - - -class Subscription; -typedef std::list SubscriptionList; - -class Subscription { - - private: - - static SubscriptionList subscriptions; - static bool subscriptions_changed; - static const char *subscription_file; - - std::string _channel_id; - time_t _last_seen; - bool _old; // subscription imported from an old-style subs file - - bool match (constChannelPtr channel); - static void save (void); - static void load (void); - static void load_old_subscriptions (void); - - public: - - Subscription (const char *id); - virtual ~Subscription(); - - // ---------------------------------- I/O - - static std::string toString ( const Subscription & section); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Subscription & section); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - void setFile (const char *file); - static bool status (constChannelPtr channel); - static void setStatus (constChannelPtr channel, bool channel_is_subscribed); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Subscription + + + class Subscription; + typedef std::list SubscriptionList; + + class Subscription { + + private: + + static SubscriptionList subscriptions; + static bool subscriptions_changed; + static const char *subscription_file; + + std::string _channel_id; + time_t _last_seen; + bool _old; // subscription imported from an old-style subs file + + bool match (constChannelPtr channel); + static void save (void); + static void load (void); + static void load_old_subscriptions (void); + + public: + + Subscription (const char *id); + virtual ~Subscription(); + + // ---------------------------------- I/O + + static std::string toString ( const Subscription & section); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Subscription & section); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + void setFile (const char *file); + static bool status (constChannelPtr channel); + static void setStatus (constChannelPtr channel, bool channel_is_subscribed); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Subscription_h diff --git a/zypp/solver/detail/UndumpWorld.cc b/zypp/solver/detail/UndumpWorld.cc index 25594ba..c75ce54 100644 --- a/zypp/solver/detail/UndumpWorld.cc +++ b/zypp/solver/detail/UndumpWorld.cc @@ -22,145 +22,155 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_DERIVED_POINTER(UndumpWorld, World); - -//--------------------------------------------------------------------------- - -string -UndumpWorld::asString ( void ) const -{ - return toString (*this); -} - - -string -UndumpWorld::toString ( const UndumpWorld & world ) -{ - return ""; -} - - -ostream & -UndumpWorld::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const UndumpWorld & world) -{ - return os << world.asString(); -} - -//--------------------------------------------------------------------------- - -UndumpWorld::UndumpWorld (const char *filename) - : StoreWorld (UNDUMP_WORLD) -{ - load (filename); -} - - -UndumpWorld::~UndumpWorld() -{ - fprintf (stderr, "*** deleting undump world[%p]: %s\n", this, World::toString(type()).c_str()); -} - -//--------------------------------------------------------------------------- - - -static bool -add_channel_cb (ChannelPtr channel, bool subscribed, void *data) -{ - UndumpWorld *undump = (UndumpWorld *)data; - - undump->addChannel (channel); - - if (!channel->system ()) { - undump->setSubscription (channel, subscribed); - } - - return true; -} - - -static bool -add_resItem_cb (constResItemPtr res, void *data) -{ - UndumpWorld *undump = (UndumpWorld *)data; - - undump->addResItem (res); - - return true; -} - - -static bool -add_lock_cb (constMatchPtr lock, void *data) -{ - UndumpWorld *undump = (UndumpWorld *)data; - - undump->addLock (lock); - - return true; -} - - -void -UndumpWorld::load (const char *filename) -{ - if (filename) { - extract_packages_from_undump_file (filename, add_channel_cb, add_resItem_cb, add_lock_cb, (void *)this); - } -} - - -void -UndumpWorld::setSubscription (constChannelPtr channel, bool subscribe) -{ -// if (getenv("RC_SPEW")) fprintf (stderr, "UndumpWorld::setSubscription (%s, %s)\n", channel->asString().c_str(), subscribe?"subscribe":"unsubscribe"); - for (ChannelSubscriptions::iterator i = _subscriptions.begin(); i != _subscriptions.end(); i++) { - if (*i == channel) { - if (!subscribe) { - _subscriptions.erase (i); - } - return; - } - } - - if (subscribe) { - _subscriptions.push_back (channel); - } - - return; -} - - -bool -UndumpWorld::isSubscribed (constChannelPtr channel) const -{ - for (ChannelSubscriptions::const_iterator i = _subscriptions.begin(); i != _subscriptions.end(); i++) { - if (*i == channel) { - if (getenv("RC_SPEW")) fprintf (stderr, "UndumpWorld::isSubscribed (%s) YES\n", channel->asString().c_str()); - return true; - } - } - - if (getenv("RC_SPEW")) fprintf (stderr, "UndumpWorld::isSubscribed (%s) NO\n", channel->asString().c_str()); - return false; -} - - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_DERIVED_POINTER(UndumpWorld, World); + + //--------------------------------------------------------------------------- + + string + UndumpWorld::asString ( void ) const + { + return toString (*this); + } + + + string + UndumpWorld::toString ( const UndumpWorld & world ) + { + return ""; + } + + + ostream & + UndumpWorld::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const UndumpWorld & world) + { + return os << world.asString(); + } + + //--------------------------------------------------------------------------- + + UndumpWorld::UndumpWorld (const char *filename) + : StoreWorld (UNDUMP_WORLD) + { + load (filename); + } + + + UndumpWorld::~UndumpWorld() + { + fprintf (stderr, "*** deleting undump world[%p]: %s\n", this, World::toString(type()).c_str()); + } + + //--------------------------------------------------------------------------- + + + static bool + add_channel_cb (ChannelPtr channel, bool subscribed, void *data) + { + UndumpWorld *undump = (UndumpWorld *)data; + + undump->addChannel (channel); + + if (!channel->system ()) { + undump->setSubscription (channel, subscribed); + } + + return true; + } + + + static bool + add_resItem_cb (constResItemPtr res, void *data) + { + UndumpWorld *undump = (UndumpWorld *)data; + + undump->addResItem (res); + + return true; + } + + + static bool + add_lock_cb (constMatchPtr lock, void *data) + { + UndumpWorld *undump = (UndumpWorld *)data; + + undump->addLock (lock); + + return true; + } + + + void + UndumpWorld::load (const char *filename) + { + if (filename) { + extract_packages_from_undump_file (filename, add_channel_cb, add_resItem_cb, add_lock_cb, (void *)this); + } + } + + + void + UndumpWorld::setSubscription (constChannelPtr channel, bool subscribe) + { + // if (getenv("RC_SPEW")) fprintf (stderr, "UndumpWorld::setSubscription (%s, %s)\n", channel->asString().c_str(), subscribe?"subscribe":"unsubscribe"); + for (ChannelSubscriptions::iterator i = _subscriptions.begin(); i != _subscriptions.end(); i++) { + if (*i == channel) { + if (!subscribe) { + _subscriptions.erase (i); + } + return; + } + } + + if (subscribe) { + _subscriptions.push_back (channel); + } + + return; + } + + + bool + UndumpWorld::isSubscribed (constChannelPtr channel) const + { + for (ChannelSubscriptions::const_iterator i = _subscriptions.begin(); i != _subscriptions.end(); i++) { + if (*i == channel) { + if (getenv("RC_SPEW")) fprintf (stderr, "UndumpWorld::isSubscribed (%s) YES\n", channel->asString().c_str()); + return true; + } + } + + if (getenv("RC_SPEW")) fprintf (stderr, "UndumpWorld::isSubscribed (%s) NO\n", channel->asString().c_str()); + return false; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/UndumpWorld.h b/zypp/solver/detail/UndumpWorld.h index 216ddcc..d31e236 100644 --- a/zypp/solver/detail/UndumpWorld.h +++ b/zypp/solver/detail/UndumpWorld.h @@ -30,49 +30,60 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : UndumpWorld - -class UndumpWorld : public StoreWorld { - REP_BODY(UndumpWorld); - - private: - - typedef std::list ChannelSubscriptions; - ChannelSubscriptions _subscriptions; - - public: - - UndumpWorld (const char *filename); - virtual ~UndumpWorld(); - - // ---------------------------------- I/O - - static std::string toString (const UndumpWorld & section); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const UndumpWorld & section); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - void load (const char *filename); - virtual bool isSubscribed (constChannelPtr channel) const; - virtual void setSubscription (constChannelPtr channel, bool is_subscribed); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : UndumpWorld + + class UndumpWorld : public StoreWorld { + REP_BODY(UndumpWorld); + + private: + + typedef std::list ChannelSubscriptions; + ChannelSubscriptions _subscriptions; + + public: + + UndumpWorld (const char *filename); + virtual ~UndumpWorld(); + + // ---------------------------------- I/O + + static std::string toString (const UndumpWorld & section); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const UndumpWorld & section); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + void load (const char *filename); + virtual bool isSubscribed (constChannelPtr channel) const; + virtual void setSubscription (constChannelPtr channel, bool is_subscribed); + + }; + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _UndumpWorld_h diff --git a/zypp/solver/detail/UndumpWorldPtr.h b/zypp/solver/detail/UndumpWorldPtr.h index e199378..b5075d8 100644 --- a/zypp/solver/detail/UndumpWorldPtr.h +++ b/zypp/solver/detail/UndumpWorldPtr.h @@ -24,18 +24,30 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : UndumpWorldPtr -// CLASS NAME : constUndumpWorldPtr -/////////////////////////////////////////////////////////////////// -DEFINE_DERIVED_POINTER(UndumpWorld, World); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : UndumpWorldPtr + // CLASS NAME : constUndumpWorldPtr + /////////////////////////////////////////////////////////////////// + DEFINE_DERIVED_POINTER(UndumpWorld, World); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _UndumpWorldPtr_h diff --git a/zypp/solver/detail/Version.cc b/zypp/solver/detail/Version.cc index f462ba4..2186e49 100644 --- a/zypp/solver/detail/Version.cc +++ b/zypp/solver/detail/Version.cc @@ -25,253 +25,263 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -Version GVersion; - -using namespace std; - -string -Version::asString ( void ) const -{ - return toString (*this); -} - - -string -Version::toString ( const Version & section ) -{ - return ""; -} - -ostream & -Version::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const Version& section) -{ - return os << section.asString(); -} - -//--------------------------------------------------------------------------- - -static EditionPtr -rpm_parse (const char *input) -{ - const char *vptr = NULL, *rptr = NULL; - - if (input == NULL || *input == 0) - return NULL; - - int epoch = -1; - const char *version; - const char *release; - const char *arch = ""; - - if ((vptr = strchr (input, ':'))) { - /* We -might- have an epoch here */ - char *endptr; - - epoch = strtoul (input, &endptr, 10); - - if (endptr != vptr) { - /* No epoch here, just a : in the version string */ - epoch = -1; - vptr = input; - } else { - vptr++; - } - } else { - vptr = input; - } - - if ((rptr = strchr (vptr, '-'))) { - char *v = strndup (vptr, rptr - vptr); - version = v; - release = rptr + 1; - } else { - version = vptr; - release = NULL; - } - - EditionPtr edition = new Edition(epoch, version, release, Arch::create(arch)); - - return edition; -} - - -/* This was stolen from RPM */ -/* And then slightly hacked on by me */ -/* And then hacked on more by me */ - -/* compare alpha and numeric segments of two versions */ -/* return 1: a is newer than b */ -/* 0: a and b are the same version */ -/* -1: b is newer than a */ -static int -vercmp (const char *a, const char *b) -{ - char oldch1, oldch2; - char * str1, * str2; - char * one, * two; - int rc; - int isnum; - unsigned int alen, blen; - - /* easy comparison to see if versions are identical */ - if (!strcmp(a, b)) return 0; - - alen = strlen (a); - blen = strlen (b); - - str1 = (char *)alloca(alen + 1); - str2 = (char *)alloca(blen + 1); - - strcpy(str1, a); - strcpy(str2, b); - - one = str1; - two = str2; - - /* loop through each version segment of str1 and str2 and compare them */ - while (*one && *two) { - while (*one && !isalnum(*one)) one++; - while (*two && !isalnum(*two)) two++; - - str1 = one; - str2 = two; - - /* grab first completely alpha or completely numeric segment */ - /* leave one and two pointing to the start of the alpha or numeric */ - /* segment and walk str1 and str2 to end of segment */ - if (isdigit(*str1)) { - while (*str1 && isdigit(*str1)) str1++; - while (*str2 && isdigit(*str2)) str2++; - isnum = 1; - } else { - while (*str1 && isalpha(*str1)) str1++; - while (*str2 && isalpha(*str2)) str2++; - isnum = 0; - } - - /* save character at the end of the alpha or numeric segment */ - /* so that they can be restored after the comparison */ - oldch1 = *str1; - *str1 = '\0'; - oldch2 = *str2; - *str2 = '\0'; - - /* This should only happen if someone is changing the string */ - /* behind our back. It should be a _very_ rare race condition */ - if (one == str1) return -1; /* arbitrary */ - - /* take care of the case where the two version segments are */ - /* different types: one numeric and one alpha */ - - /* Here's how we handle comparing numeric and non-numeric - * segments -- non-numeric (ximian.1) always sorts lower than - * numeric (0.ximian.6.1). */ - if (two == str2) - return (isnum ? 1 : -1); - - if (isnum) { - /* this used to be done by converting the digit segments */ - /* to ints using atoi() - it's changed because long */ - /* digit segments can overflow an int - this should fix that. */ - - /* throw away any leading zeros - it's a number, right? */ - while (*one == '0') one++; - while (*two == '0') two++; - - /* whichever number has more digits wins */ - if (strlen(one) > strlen(two)) return 1; - if (strlen(two) > strlen(one)) return -1; - } - - /* strcmp will return which one is greater - even if the two */ - /* segments are alpha or if they are numeric. don't return */ - /* if they are equal because there might be more segments to */ - /* compare */ - rc = strcmp(one, two); - if (rc) return rc; - - /* restore character that was replaced by null above */ - *str1 = oldch1; - one = str1; - *str2 = oldch2; - two = str2; - } - - /* this catches the case where all numeric and alpha segments have */ - /* compared identically but the segment sepparating characters were */ - /* different */ - if ((!*one) && (!*two)) return 0; - - /* whichever version still has characters left over wins */ - if (!*one) return -1; else return 1; -} - - -static int -rpm_compare (constSpecPtr spec1, constSpecPtr spec2) -{ - int rc = 0; - - assert (spec1 != NULL); - assert (spec2 != NULL); - - const string name1 = spec1->name(); - const string name2 = spec2->name(); - if (! (name1.empty() && name2.empty())) - { - rc = name1.compare (name2); - } - if (rc) return rc; - - if (spec1->epoch() >= 0 && spec2->epoch() >= 0) { - rc = spec1->epoch() - spec2->epoch(); - } else if (spec1->epoch() > 0) { - rc = 1; - } else if (spec2->epoch() > 0) { - rc = -1; - } - if (rc) return rc; - - rc = vercmp (spec1->version().c_str(), spec2->version().c_str()); - if (rc) return rc; - - const string rel1 = spec1->release(); - const string rel2 = spec2->release(); - if (!rel1.empty() && !rel2.empty()) { - rc = vercmp (rel1.c_str(), rel2.c_str()); - } - return rc; -} - -//--------------------------------------------------------------------------- - -Version::Version() - : _properties (VERSION_PROP_PROVIDE_ANY | VERSION_PROP_IGNORE_ABSENT_EPOCHS) - , _parse (rpm_parse) - , _compare (rpm_compare) -{ -} - - -Version::~Version() -{ -} - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + Version GVersion; + + using namespace std; + + string + Version::asString ( void ) const + { + return toString (*this); + } + + + string + Version::toString ( const Version & section ) + { + return ""; + } + + ostream & + Version::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const Version& section) + { + return os << section.asString(); + } + + //--------------------------------------------------------------------------- + + static EditionPtr + rpm_parse (const char *input) + { + const char *vptr = NULL, *rptr = NULL; + + if (input == NULL || *input == 0) + return NULL; + + int epoch = -1; + const char *version; + const char *release; + const char *arch = ""; + + if ((vptr = strchr (input, ':'))) { + /* We -might- have an epoch here */ + char *endptr; + + epoch = strtoul (input, &endptr, 10); + + if (endptr != vptr) { + /* No epoch here, just a : in the version string */ + epoch = -1; + vptr = input; + } else { + vptr++; + } + } else { + vptr = input; + } + + if ((rptr = strchr (vptr, '-'))) { + char *v = strndup (vptr, rptr - vptr); + version = v; + release = rptr + 1; + } else { + version = vptr; + release = NULL; + } + + EditionPtr edition = new Edition(epoch, version, release, Arch::create(arch)); + + return edition; + } + + + /* This was stolen from RPM */ + /* And then slightly hacked on by me */ + /* And then hacked on more by me */ + + /* compare alpha and numeric segments of two versions */ + /* return 1: a is newer than b */ + /* 0: a and b are the same version */ + /* -1: b is newer than a */ + static int + vercmp (const char *a, const char *b) + { + char oldch1, oldch2; + char * str1, * str2; + char * one, * two; + int rc; + int isnum; + unsigned int alen, blen; + + /* easy comparison to see if versions are identical */ + if (!strcmp(a, b)) return 0; + + alen = strlen (a); + blen = strlen (b); + + str1 = (char *)alloca(alen + 1); + str2 = (char *)alloca(blen + 1); + + strcpy(str1, a); + strcpy(str2, b); + + one = str1; + two = str2; + + /* loop through each version segment of str1 and str2 and compare them */ + while (*one && *two) { + while (*one && !isalnum(*one)) one++; + while (*two && !isalnum(*two)) two++; + + str1 = one; + str2 = two; + + /* grab first completely alpha or completely numeric segment */ + /* leave one and two pointing to the start of the alpha or numeric */ + /* segment and walk str1 and str2 to end of segment */ + if (isdigit(*str1)) { + while (*str1 && isdigit(*str1)) str1++; + while (*str2 && isdigit(*str2)) str2++; + isnum = 1; + } else { + while (*str1 && isalpha(*str1)) str1++; + while (*str2 && isalpha(*str2)) str2++; + isnum = 0; + } + + /* save character at the end of the alpha or numeric segment */ + /* so that they can be restored after the comparison */ + oldch1 = *str1; + *str1 = '\0'; + oldch2 = *str2; + *str2 = '\0'; + + /* This should only happen if someone is changing the string */ + /* behind our back. It should be a _very_ rare race condition */ + if (one == str1) return -1; /* arbitrary */ + + /* take care of the case where the two version segments are */ + /* different types: one numeric and one alpha */ + + /* Here's how we handle comparing numeric and non-numeric + * segments -- non-numeric (ximian.1) always sorts lower than + * numeric (0.ximian.6.1). */ + if (two == str2) + return (isnum ? 1 : -1); + + if (isnum) { + /* this used to be done by converting the digit segments */ + /* to ints using atoi() - it's changed because long */ + /* digit segments can overflow an int - this should fix that. */ + + /* throw away any leading zeros - it's a number, right? */ + while (*one == '0') one++; + while (*two == '0') two++; + + /* whichever number has more digits wins */ + if (strlen(one) > strlen(two)) return 1; + if (strlen(two) > strlen(one)) return -1; + } + + /* strcmp will return which one is greater - even if the two */ + /* segments are alpha or if they are numeric. don't return */ + /* if they are equal because there might be more segments to */ + /* compare */ + rc = strcmp(one, two); + if (rc) return rc; + + /* restore character that was replaced by null above */ + *str1 = oldch1; + one = str1; + *str2 = oldch2; + two = str2; + } + + /* this catches the case where all numeric and alpha segments have */ + /* compared identically but the segment sepparating characters were */ + /* different */ + if ((!*one) && (!*two)) return 0; + + /* whichever version still has characters left over wins */ + if (!*one) return -1; else return 1; + } + + + static int + rpm_compare (constSpecPtr spec1, constSpecPtr spec2) + { + int rc = 0; + + assert (spec1 != NULL); + assert (spec2 != NULL); + + const string name1 = spec1->name(); + const string name2 = spec2->name(); + if (! (name1.empty() && name2.empty())) + { + rc = name1.compare (name2); + } + if (rc) return rc; + + if (spec1->epoch() >= 0 && spec2->epoch() >= 0) { + rc = spec1->epoch() - spec2->epoch(); + } else if (spec1->epoch() > 0) { + rc = 1; + } else if (spec2->epoch() > 0) { + rc = -1; + } + if (rc) return rc; + + rc = vercmp (spec1->version().c_str(), spec2->version().c_str()); + if (rc) return rc; + + const string rel1 = spec1->release(); + const string rel2 = spec2->release(); + if (!rel1.empty() && !rel2.empty()) { + rc = vercmp (rel1.c_str(), rel2.c_str()); + } + return rc; + } + + //--------------------------------------------------------------------------- + + Version::Version() + : _properties (VERSION_PROP_PROVIDE_ANY | VERSION_PROP_IGNORE_ABSENT_EPOCHS) + , _parse (rpm_parse) + , _compare (rpm_compare) + { + } + + + Version::~Version() + { + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Version.h b/zypp/solver/detail/Version.h index e5af6e5..9d15878 100644 --- a/zypp/solver/detail/Version.h +++ b/zypp/solver/detail/Version.h @@ -28,86 +28,97 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : Version -/* - * Version properties: These exist to signal various parts of the - * world, packman, and dependency code of certain (mis)features of a - * packaging system. - * - * PROVIDE_ANY - An unversioned provide matches all versions. An - * unversioned provide translates into an RC_RELATION_ANY relation, which - * will meet any requirement for any version. (RPM) - * - * IGNORE_ABSENT_EPOCHS - If an epoch isn't specified in a requirement, - * it's ignored when verifying the provide. For example, if package "foo" - * requires "bar >= 2.0" then both "bar 21" and "bar 1:2.0" meet the - * requirement. (RPM) - * - * ALWAYS_VERIFY_RELEASE - When verifying relations, the release field is - * usually only compared when both the requirement specifies it. For - * example, a requirement of "foo > 2.0" would not be met by a package - * providing "foo 2.0-10", because the release field ("10") would be - * ignored and "2.0" is not greater than "2.0". When this property is - * set, however, the release field will always be compared, and the - * requirement in the previous example would be met, because "2.0-10" is - * greater than "2.0". (Debian) - * - */ - -#define VERSION_PROP_NONE (0) -#define VERSION_PROP_PROVIDE_ANY (1 << 0) -#define VERSION_PROP_IGNORE_ABSENT_EPOCHS (1 << 2) -#define VERSION_PROP_ALWAYS_VERIFY_RELEASE (1 << 4) - -class Version { - - private: - - unsigned int _properties; - - EditionPtr (*_parse)(const char *input); - - // compare uses SpecPtr and takes name into account - int (*_compare)(constSpecPtr a, constSpecPtr b); - - public: - - Version (); - virtual ~Version(); - - // ---------------------------------- I/O - - static std::string toString ( const Version & section); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream&, const Version & section); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - // ---------------------------------- methods - - // compare uses SpecPtr and takes name into account - int compare (constSpecPtr a, constSpecPtr b) const { return (*_compare) (a, b); } - - EditionPtr parse (const char *input) const { return (*_parse)(input); } - - bool hasProperty (unsigned int property) const { return (_properties & property) != 0; } - -}; - -extern Version GVersion; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Version + /* + * Version properties: These exist to signal various parts of the + * world, packman, and dependency code of certain (mis)features of a + * packaging system. + * + * PROVIDE_ANY - An unversioned provide matches all versions. An + * unversioned provide translates into an RC_RELATION_ANY relation, which + * will meet any requirement for any version. (RPM) + * + * IGNORE_ABSENT_EPOCHS - If an epoch isn't specified in a requirement, + * it's ignored when verifying the provide. For example, if package "foo" + * requires "bar >= 2.0" then both "bar 21" and "bar 1:2.0" meet the + * requirement. (RPM) + * + * ALWAYS_VERIFY_RELEASE - When verifying relations, the release field is + * usually only compared when both the requirement specifies it. For + * example, a requirement of "foo > 2.0" would not be met by a package + * providing "foo 2.0-10", because the release field ("10") would be + * ignored and "2.0" is not greater than "2.0". When this property is + * set, however, the release field will always be compared, and the + * requirement in the previous example would be met, because "2.0-10" is + * greater than "2.0". (Debian) + * + */ + + #define VERSION_PROP_NONE (0) + #define VERSION_PROP_PROVIDE_ANY (1 << 0) + #define VERSION_PROP_IGNORE_ABSENT_EPOCHS (1 << 2) + #define VERSION_PROP_ALWAYS_VERIFY_RELEASE (1 << 4) + + class Version { + + private: + + unsigned int _properties; + + EditionPtr (*_parse)(const char *input); + + // compare uses SpecPtr and takes name into account + int (*_compare)(constSpecPtr a, constSpecPtr b); + + public: + + Version (); + virtual ~Version(); + + // ---------------------------------- I/O + + static std::string toString ( const Version & section); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream&, const Version & section); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + // ---------------------------------- methods + + // compare uses SpecPtr and takes name into account + int compare (constSpecPtr a, constSpecPtr b) const { return (*_compare) (a, b); } + + EditionPtr parse (const char *input) const { return (*_parse)(input); } + + bool hasProperty (unsigned int property) const { return (_properties & property) != 0; } + + }; + + extern Version GVersion; + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _Version_h diff --git a/zypp/solver/detail/World.cc b/zypp/solver/detail/World.cc index 5314f85..c2a64c2 100644 --- a/zypp/solver/detail/World.cc +++ b/zypp/solver/detail/World.cc @@ -25,531 +25,543 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(World); - -WorldPtr World::GlobalWorld = NULL; - -//--------------------------------------------------------------------------- - -string -World::toString (WorldType type) -{ - switch (type) { - case PLAIN_WORLD: return "plain"; - case STORE_WORLD: return "store"; - case MULTI_WORLD: return "multi"; - case SERVICE_WORLD: return "service"; - case UNDUMP_WORLD: return "undump"; - case LOCALDIR_WORLD: return "localdir"; - case SYSTEM_WORLD: return "system"; - default: - break; - } - return "???"; -} - - -string -World::asString ( void ) const -{ - return toString (*this); -} - - -string -World::toString ( const World & world ) -{ - return ""; -} - - -ostream & -World::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const World & world) -{ - return os << world.asString(); -} - -//--------------------------------------------------------------------------- - -World::World (WorldType type) - : _type (type) -{ -// fprintf (stderr, "*** creating world[%p]: %s\n", this, toString(_type).c_str()); -} - - -World::~World() -{ -// fprintf (stderr, "*** deleting world[%p]: %s\n", this, toString(_type).c_str()); -} - -//--------------------------------------------------------------------------- -// sync/refresh functions - -bool -World::sync (void) const -{ - if (getenv("FIXME")) fprintf (stderr, "World::sync() not implemented\n"); - return false; -} - -bool -World::syncConditional (constChannelPtr channel) const -{ - if (getenv("FIXME")) fprintf (stderr, "World::syncConditional() not implemented\n"); - return false; -} - - -PendingPtr -World::refresh (void) -{ - if (getenv("FIXME")) fprintf (stderr, "World::refresh() not implemented\n"); - return 0; -} - -bool -World::hasRefresh (void) -{ - if (getenv("FIXME")) fprintf (stderr, "World::hasRefresh() not implemented\n"); - return false; -} - - -bool -World::isRefreshing (void) -{ - if (getenv("FIXME")) fprintf (stderr, "World::isRefreshing() not implemented\n"); - return false; -} - - - /* These functions are for World-implementers only! Don't call them! */ -void -World::refreshBegin (void) -{ - if (getenv("FIXME")) fprintf (stderr, "World::refreshBegin() not implemented\n"); - return; -} - -void -World::refreshComplete (void) -{ - if (getenv("FIXME")) fprintf (stderr, "World::refreshComplete() not implemented\n"); - return; -} - -//--------------------------------------------------------------------------- -// channels, subscriptions - -void -World::setSubscription (ChannelPtr channel, bool is_subscribed) -{ - bool curr_subs_status; - - if (channel == NULL) return; - -// if (getenv("RC_SPEW")) fprintf (stderr, "World::setSubscription (%s, %s)\n", channel->asString().c_str(), is_subscribed?"subscribe":"unsubscribe"); - - if (channel->system ()) { - fprintf (stderr, "Can't subscribe to system channel '%s'\n", channel->name ()); - return; - } - - curr_subs_status = isSubscribed (channel); - - Subscription::setStatus (channel, is_subscribed); - - if (curr_subs_status != isSubscribed (channel)) - touchSubscriptionSequenceNumber (); - - return; -} - - -bool -World::isSubscribed (constChannelPtr channel) const -{ - if (channel == NULL) return false; -// if (getenv("RC_SPEW")) fprintf (stderr, "World::isSubscribed (%s)\n", channel->asString().c_str()); - - if (channel->system ()) - return false; - - return Subscription::status (channel) ? true : false; -} - - - -//--------------------------------------------------------------------------- -// ResItem Locks - -typedef struct { - constResItemPtr resItem; - WorldPtr world; - bool is_locked; -} IsLockedInfo; - - -static bool -is_locked_cb (constMatchPtr match, void *data) -{ - IsLockedInfo *info = (IsLockedInfo *)data; - - if (match->test (info->resItem, info->world)) { - info->is_locked = true; - return false; - } - - return true; -} - - -bool -World::resItemIsLocked (constResItemPtr resItem) -{ - IsLockedInfo info; - - info.resItem = resItem; - info.world = this; - info.is_locked = false; - - foreachLock (is_locked_cb, &info); - - return info.is_locked; -} - - -//--------------------------------------------------------------------------- -// Transacting - -bool -World::canTransactResItem (constResItemPtr resItem) -{ - if (getenv("FIXME")) fprintf (stderr, "World::canTransactResItem() not implemented\n"); - return false; -} - -bool -World::transact (const ResItemList & installResItems, const ResItemList & remove_resItems, int flags) -{ - if (getenv("FIXME")) fprintf (stderr, "World::transact() not implemented\n"); - return false; -} - - -//--------------------------------------------------------------------------- -// XML serialization - -void -World::serialize (XmlNodePtr parent) -{ - if (getenv("FIXME")) fprintf (stderr, "World::serialize() not implemented\n"); - return; -} - -void -World::toFile (const char *filename) -{ - if (getenv("FIXME")) fprintf (stderr, "World::toFile() not implemented\n"); - return; -} - - -//--------------------------------------------------------------------------- -// Duplicating (primarily for atomic refreshes) - -WorldPtr -World::dup (void) -{ - if (getenv("FIXME")) fprintf (stderr, "World::dup() not implemented\n"); - return 0; -} - - -//--------------------------------------------------------------------------- -// only used for bindings - -void -World::setRefreshFunction (WorldRefreshFn refresh_fn) -{ - if (getenv("FIXME")) fprintf (stderr, "World::setRefreshFunction() not implemented\n"); - return; -} - - - -//----------------------------------------------------------------------------- -// Upgrades - -typedef struct { - constResItemPtr original_resItem; - CResItemFn fn; - void *data; - int count; - WorldPtr world; -} ForeachUpgradeInfo; - -static bool -foreach_upgrade_cb (constResItemPtr resItem, void *data) -{ - ForeachUpgradeInfo *info = (ForeachUpgradeInfo *)data; - int cmp; - - cmp = GVersion.compare (info->original_resItem, resItem); - - if (cmp >= 0) // original is already better - return true; - - if (info->world->resItemIsLocked (resItem)) - return true; - - if (info->fn) - info->fn (resItem, info->data); - ++info->count; - - return true; -} - - -// rc_world_foreach_upgrade: -// @world: An #RCWorld. -// @resItem: An #RCResItem. -// @channel: An #RCChannel or channel wildcard. -// @fn: A callback function. -// @user_data: Pointer passed to the callback function. -// -// Searchs @world for all resItems whose channel matches -// @channel and that are an upgrade for @resItem. -// (To be precise, an upgrade is a resItem with the same -// name as @resItem but with a greater version number.) -// -// Return value: The number of matching resItems -// that the callback functions was invoked on, or -// -1 in the case of an error. - -int -World::foreachUpgrade (constResItemPtr resItem, ChannelPtr channel, CResItemFn fn, void *data) -{ - ForeachUpgradeInfo info; - - syncConditional (channel); - - info.original_resItem = resItem; - info.fn = fn; - info.data = data; - info.count = 0; - info.world = this; - - foreachResItemByName (resItem->name(), channel, foreach_upgrade_cb, (void *)&info); - - return info.count; -} - - - -typedef struct { - WorldPtr world; - constResItemPtr system_resItem; - CResItemList best_upgrades; - bool subscribed_only; - ResItemPairFn fn; - void *data; - int count; -} SystemUpgradeInfo; - - -static bool -foreach_system_upgrade_cb (constResItemPtr upgrade, void *data) -{ - SystemUpgradeInfo *info = (SystemUpgradeInfo *)data; - constChannelPtr channel = upgrade->channel(); - int cmp; - - if (info->subscribed_only) { - if (!(channel && channel->isSubscribed ())) - return true; - } - - if (info->world->resItemIsLocked (upgrade)) - return true; - - if (info->best_upgrades.empty()) { - info->best_upgrades.push_back (upgrade); - } - else { - /* All the versions are equal, so picking the first is fine */ - constResItemPtr best_up = info->best_upgrades.front(); - - cmp = GVersion.compare (best_up, upgrade); - - if (cmp <= 0) { - /* We have a new best resItem... */ - info->best_upgrades.pop_front(); - info->best_upgrades.push_back (upgrade); - } - } - - return true; -} - - -static void -foreach_system_resItem_cb (const string & name, constResItemPtr resItem, SystemUpgradeInfo *info) -{ - info->system_resItem = resItem; - info->best_upgrades.clear(); - - /* If the resItem is excluded, skip it. */ - if (info->world->resItemIsLocked (info->system_resItem)) - return; - - info->world->foreachUpgrade (info->system_resItem, new Channel (CHANNEL_TYPE_NONSYSTEM), foreach_system_upgrade_cb, info); - - for (CResItemList::const_iterator iter = info->best_upgrades.begin(); iter != info->best_upgrades.end(); iter++) { - constResItemPtr upgrade = *iter; - - if (info->fn) - info->fn (info->system_resItem, upgrade, info->data); - - ++info->count; - } - - info->best_upgrades.clear(); -} - -typedef map UniqueTable; - -static bool -build_unique_table_cb (constResItemPtr resItem, void *data) -{ - UniqueTable *unique_table = (UniqueTable *)data; - - UniqueTable::const_iterator pos = unique_table->find (resItem->name()); - - if (pos != unique_table->end()) { - if (GVersion.compare (resItem, pos->second) <= 0) - return true; - } - - (*unique_table)[resItem->name()] = resItem; - - return true; -} - - -/** - * foreachSystemUpgrade: - * @world: An #RCWorld. - * @subscribed_only: if TRUE, only subscribed channels are used. - * @fn: A callback function. - * @user_data: Pointer to be passed to the callback function. - * - * Iterates across all system resItems in @world for which there - * exists an upgrade, and passes both the original resItem and - * the upgrade resItem to the callback function. - * - * Return value: The number of matching resItems that the callback - * function was invoked on, or -1 in case of an error. - **/ - -int -World::foreachSystemUpgrade (bool subscribed_only, ResItemPairFn fn, void *data) -{ - SystemUpgradeInfo info; - UniqueTable unique_table; - - /* rc_world_foreach_resItem calls rc_world_sync */ - - foreachResItem (new Channel (CHANNEL_TYPE_SYSTEM), build_unique_table_cb, &unique_table); - - info.world = this; - info.subscribed_only = subscribed_only; - info.fn = fn; - info.data = data; - info.count = 0; - - for (UniqueTable::const_iterator iter = unique_table.begin(); iter != unique_table.end(); iter++) { - foreach_system_resItem_cb (iter->first, iter->second, &info); - } - - return info.count; -} - - -PackageUpdateList -World::getUpgrades (constResItemPtr resItem, constChannelPtr channel) -{ - fprintf (stderr, "World::getUpgrades not implemented\n"); - return PackageUpdateList(); -} - -constResItemPtr -World::getBestUpgrade (constResItemPtr resItem, bool subscribed_only) -{ - fprintf (stderr, "World::getBestUpgrade not implemented\n"); - return 0; -} - - -//----------------------------------------------------------------------------- -// Locks - -int -World::foreachLock (MatchFn fn, void *data) const -{ - int count = 0; - - for (MatchList::const_iterator iter = _locks.begin(); iter != _locks.end(); iter++) { - if (! fn (*iter, data)) - return -1; - ++count; - } - - return count; -} - - -void -World::addLock (constMatchPtr lock) -{ - _locks.push_back (lock); -} - - -void -World::removeLock (constMatchPtr lock) -{ - for (MatchList::iterator iter = _locks.begin(); iter != _locks.end(); iter++) { - if (*iter == lock) { - _locks.erase (iter); - break; - } - } -} - - -void -World::clearLocks (void) -{ - _locks.clear(); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(World); + + WorldPtr World::GlobalWorld = NULL; + + //--------------------------------------------------------------------------- + + string + World::toString (WorldType type) + { + switch (type) { + case PLAIN_WORLD: return "plain"; + case STORE_WORLD: return "store"; + case MULTI_WORLD: return "multi"; + case SERVICE_WORLD: return "service"; + case UNDUMP_WORLD: return "undump"; + case LOCALDIR_WORLD: return "localdir"; + case SYSTEM_WORLD: return "system"; + default: + break; + } + return "???"; + } + + + string + World::asString ( void ) const + { + return toString (*this); + } + + + string + World::toString ( const World & world ) + { + return ""; + } + + + ostream & + World::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const World & world) + { + return os << world.asString(); + } + + //--------------------------------------------------------------------------- + + World::World (WorldType type) + : _type (type) + { + // fprintf (stderr, "*** creating world[%p]: %s\n", this, toString(_type).c_str()); + } + + + World::~World() + { + // fprintf (stderr, "*** deleting world[%p]: %s\n", this, toString(_type).c_str()); + } + + //--------------------------------------------------------------------------- + // sync/refresh functions + + bool + World::sync (void) const + { + if (getenv("FIXME")) fprintf (stderr, "World::sync() not implemented\n"); + return false; + } + + bool + World::syncConditional (constChannelPtr channel) const + { + if (getenv("FIXME")) fprintf (stderr, "World::syncConditional() not implemented\n"); + return false; + } + + + PendingPtr + World::refresh (void) + { + if (getenv("FIXME")) fprintf (stderr, "World::refresh() not implemented\n"); + return 0; + } + + bool + World::hasRefresh (void) + { + if (getenv("FIXME")) fprintf (stderr, "World::hasRefresh() not implemented\n"); + return false; + } + + + bool + World::isRefreshing (void) + { + if (getenv("FIXME")) fprintf (stderr, "World::isRefreshing() not implemented\n"); + return false; + } + + + /* These functions are for World-implementers only! Don't call them! */ + void + World::refreshBegin (void) + { + if (getenv("FIXME")) fprintf (stderr, "World::refreshBegin() not implemented\n"); + return; + } + + void + World::refreshComplete (void) + { + if (getenv("FIXME")) fprintf (stderr, "World::refreshComplete() not implemented\n"); + return; + } + + //--------------------------------------------------------------------------- + // channels, subscriptions + + void + World::setSubscription (ChannelPtr channel, bool is_subscribed) + { + bool curr_subs_status; + + if (channel == NULL) return; + + // if (getenv("RC_SPEW")) fprintf (stderr, "World::setSubscription (%s, %s)\n", channel->asString().c_str(), is_subscribed?"subscribe":"unsubscribe"); + + if (channel->system ()) { + fprintf (stderr, "Can't subscribe to system channel '%s'\n", channel->name ()); + return; + } + + curr_subs_status = isSubscribed (channel); + + Subscription::setStatus (channel, is_subscribed); + + if (curr_subs_status != isSubscribed (channel)) + touchSubscriptionSequenceNumber (); + + return; + } + + + bool + World::isSubscribed (constChannelPtr channel) const + { + if (channel == NULL) return false; + // if (getenv("RC_SPEW")) fprintf (stderr, "World::isSubscribed (%s)\n", channel->asString().c_str()); + + if (channel->system ()) + return false; + + return Subscription::status (channel) ? true : false; + } + + + + //--------------------------------------------------------------------------- + // ResItem Locks + + typedef struct { + constResItemPtr resItem; + WorldPtr world; + bool is_locked; + } IsLockedInfo; + + + static bool + is_locked_cb (constMatchPtr match, void *data) + { + IsLockedInfo *info = (IsLockedInfo *)data; + + if (match->test (info->resItem, info->world)) { + info->is_locked = true; + return false; + } + + return true; + } + + + bool + World::resItemIsLocked (constResItemPtr resItem) + { + IsLockedInfo info; + + info.resItem = resItem; + info.world = this; + info.is_locked = false; + + foreachLock (is_locked_cb, &info); + + return info.is_locked; + } + + + //--------------------------------------------------------------------------- + // Transacting + + bool + World::canTransactResItem (constResItemPtr resItem) + { + if (getenv("FIXME")) fprintf (stderr, "World::canTransactResItem() not implemented\n"); + return false; + } + + bool + World::transact (const ResItemList & installResItems, const ResItemList & remove_resItems, int flags) + { + if (getenv("FIXME")) fprintf (stderr, "World::transact() not implemented\n"); + return false; + } + + + //--------------------------------------------------------------------------- + // XML serialization + + void + World::serialize (XmlNodePtr parent) + { + if (getenv("FIXME")) fprintf (stderr, "World::serialize() not implemented\n"); + return; + } + + void + World::toFile (const char *filename) + { + if (getenv("FIXME")) fprintf (stderr, "World::toFile() not implemented\n"); + return; + } + + + //--------------------------------------------------------------------------- + // Duplicating (primarily for atomic refreshes) + + WorldPtr + World::dup (void) + { + if (getenv("FIXME")) fprintf (stderr, "World::dup() not implemented\n"); + return 0; + } + + + //--------------------------------------------------------------------------- + // only used for bindings + + void + World::setRefreshFunction (WorldRefreshFn refresh_fn) + { + if (getenv("FIXME")) fprintf (stderr, "World::setRefreshFunction() not implemented\n"); + return; + } + + + + //----------------------------------------------------------------------------- + // Upgrades + + typedef struct { + constResItemPtr original_resItem; + CResItemFn fn; + void *data; + int count; + WorldPtr world; + } ForeachUpgradeInfo; + + static bool + foreach_upgrade_cb (constResItemPtr resItem, void *data) + { + ForeachUpgradeInfo *info = (ForeachUpgradeInfo *)data; + int cmp; + + cmp = GVersion.compare (info->original_resItem, resItem); + + if (cmp >= 0) // original is already better + return true; + + if (info->world->resItemIsLocked (resItem)) + return true; + + if (info->fn) + info->fn (resItem, info->data); + ++info->count; + + return true; + } + + + // rc_world_foreach_upgrade: + // @world: An #RCWorld. + // @resItem: An #RCResItem. + // @channel: An #RCChannel or channel wildcard. + // @fn: A callback function. + // @user_data: Pointer passed to the callback function. + // + // Searchs @world for all resItems whose channel matches + // @channel and that are an upgrade for @resItem. + // (To be precise, an upgrade is a resItem with the same + // name as @resItem but with a greater version number.) + // + // Return value: The number of matching resItems + // that the callback functions was invoked on, or + // -1 in the case of an error. + + int + World::foreachUpgrade (constResItemPtr resItem, ChannelPtr channel, CResItemFn fn, void *data) + { + ForeachUpgradeInfo info; + + syncConditional (channel); + + info.original_resItem = resItem; + info.fn = fn; + info.data = data; + info.count = 0; + info.world = this; + + foreachResItemByName (resItem->name(), channel, foreach_upgrade_cb, (void *)&info); + + return info.count; + } + + + + typedef struct { + WorldPtr world; + constResItemPtr system_resItem; + CResItemList best_upgrades; + bool subscribed_only; + ResItemPairFn fn; + void *data; + int count; + } SystemUpgradeInfo; + + + static bool + foreach_system_upgrade_cb (constResItemPtr upgrade, void *data) + { + SystemUpgradeInfo *info = (SystemUpgradeInfo *)data; + constChannelPtr channel = upgrade->channel(); + int cmp; + + if (info->subscribed_only) { + if (!(channel && channel->isSubscribed ())) + return true; + } + + if (info->world->resItemIsLocked (upgrade)) + return true; + + if (info->best_upgrades.empty()) { + info->best_upgrades.push_back (upgrade); + } + else { + /* All the versions are equal, so picking the first is fine */ + constResItemPtr best_up = info->best_upgrades.front(); + + cmp = GVersion.compare (best_up, upgrade); + + if (cmp <= 0) { + /* We have a new best resItem... */ + info->best_upgrades.pop_front(); + info->best_upgrades.push_back (upgrade); + } + } + + return true; + } + + + static void + foreach_system_resItem_cb (const string & name, constResItemPtr resItem, SystemUpgradeInfo *info) + { + info->system_resItem = resItem; + info->best_upgrades.clear(); + + /* If the resItem is excluded, skip it. */ + if (info->world->resItemIsLocked (info->system_resItem)) + return; + + info->world->foreachUpgrade (info->system_resItem, new Channel (CHANNEL_TYPE_NONSYSTEM), foreach_system_upgrade_cb, info); + + for (CResItemList::const_iterator iter = info->best_upgrades.begin(); iter != info->best_upgrades.end(); iter++) { + constResItemPtr upgrade = *iter; + + if (info->fn) + info->fn (info->system_resItem, upgrade, info->data); + + ++info->count; + } + + info->best_upgrades.clear(); + } + + typedef map UniqueTable; + + static bool + build_unique_table_cb (constResItemPtr resItem, void *data) + { + UniqueTable *unique_table = (UniqueTable *)data; + + UniqueTable::const_iterator pos = unique_table->find (resItem->name()); + + if (pos != unique_table->end()) { + if (GVersion.compare (resItem, pos->second) <= 0) + return true; + } + + (*unique_table)[resItem->name()] = resItem; + + return true; + } + + + /** + * foreachSystemUpgrade: + * @world: An #RCWorld. + * @subscribed_only: if TRUE, only subscribed channels are used. + * @fn: A callback function. + * @user_data: Pointer to be passed to the callback function. + * + * Iterates across all system resItems in @world for which there + * exists an upgrade, and passes both the original resItem and + * the upgrade resItem to the callback function. + * + * Return value: The number of matching resItems that the callback + * function was invoked on, or -1 in case of an error. + **/ + + int + World::foreachSystemUpgrade (bool subscribed_only, ResItemPairFn fn, void *data) + { + SystemUpgradeInfo info; + UniqueTable unique_table; + + /* rc_world_foreach_resItem calls rc_world_sync */ + + foreachResItem (new Channel (CHANNEL_TYPE_SYSTEM), build_unique_table_cb, &unique_table); + + info.world = this; + info.subscribed_only = subscribed_only; + info.fn = fn; + info.data = data; + info.count = 0; + + for (UniqueTable::const_iterator iter = unique_table.begin(); iter != unique_table.end(); iter++) { + foreach_system_resItem_cb (iter->first, iter->second, &info); + } + + return info.count; + } + + + PackageUpdateList + World::getUpgrades (constResItemPtr resItem, constChannelPtr channel) + { + fprintf (stderr, "World::getUpgrades not implemented\n"); + return PackageUpdateList(); + } + + constResItemPtr + World::getBestUpgrade (constResItemPtr resItem, bool subscribed_only) + { + fprintf (stderr, "World::getBestUpgrade not implemented\n"); + return 0; + } + + + //----------------------------------------------------------------------------- + // Locks + + int + World::foreachLock (MatchFn fn, void *data) const + { + int count = 0; + + for (MatchList::const_iterator iter = _locks.begin(); iter != _locks.end(); iter++) { + if (! fn (*iter, data)) + return -1; + ++count; + } + + return count; + } + + + void + World::addLock (constMatchPtr lock) + { + _locks.push_back (lock); + } + + + void + World::removeLock (constMatchPtr lock) + { + for (MatchList::iterator iter = _locks.begin(); iter != _locks.end(); iter++) { + if (*iter == lock) { + _locks.erase (iter); + break; + } + } + } + + + void + World::clearLocks (void) + { + _locks.clear(); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/World.h b/zypp/solver/detail/World.h index 842a1a7..df985bc 100644 --- a/zypp/solver/detail/World.h +++ b/zypp/solver/detail/World.h @@ -36,219 +36,232 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { - -typedef std::list WorldList; - -class NameConflictInfo; - -////////////////////////////////////////////////////////////////// - -typedef enum { - PLAIN_WORLD = 0, - STORE_WORLD, - MULTI_WORLD, - SERVICE_WORLD, - UNDUMP_WORLD, - LOCALDIR_WORLD, - SYSTEM_WORLD -} WorldType; - -typedef bool (*WorldFn) (constWorldPtr world, void *user_data); -typedef PendingPtr (*WorldRefreshFn) (constWorldPtr world); - -#if 0 -typedef bool (*WorldSyncFn) (constWorldPtr world, constChannelPtr channel); -typedef PackmanPtr (*WorldPackmanFn) (constWorldPtr world, const Kind & kind); -typedef void (*WorldSpewFn) (constWorldPtr world, FILE *out); -typedef constWorldPtr (*WorldDupFn) (constWorldPtr world); - -typedef bool (*WorldCanTransactResItemFn) (constWorldPtr world, constResItemPtr resItem); -typedef bool (*WorldTransactFn) (constWorldPtr world, const ResItemList & install_resItems, const ResItemList & remove_resItems, int flags); - -typedef bool (*WorldGetSubscribedFn) (const World *world, constChannelPtr channel); -typedef void (*WorldSetSubscribedFn) (World *world, ChannelPtr channel, bool subs_status); - -typedef int (*WorldForeachChannelFn) (const World *world, ChannelFn callback, void *user_data); -typedef int (*WorldForeachLockFn) (constWorldPtr world, MatchFn callback, void *user_data); - -typedef void (*WorldAddLockFn) (constWorldPtr world, constMatchPtr lock); -typedef void (*WorldRemoveLockFn) (constWorldPtr world, constMatchPtr lock); -typedef void (*WorldClearLockFn) (constWorldPtr world); - -typedef int (*WorldForeachResItemFn) (constWorldPtr world, const char *name, constChannelPtr channel, ResItemFn callback, void *user_data); -typedef int (*WorldForeachPackageSpecFn) (constWorldPtr world, constDependencyPtr dep, ResItemAndSpecFn callback, void *user_data); -typedef int (*WorldForeachPackageDepFn) (constWorldPtr world, constDependencyPtr dep, ResItemAndDepFn callback, void *user_data); - -typedef void (*WorldSerializeFn) (constWorldPtr world, constXmlNodePtr root); -typedef void (*WorldUnserializeFn) (constWorldPtr world, constXmlNodePtr node); - -#endif - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : World - -class World : public CountedRep { - REP_BODY(World); - - private: - static WorldPtr GlobalWorld; - - WorldType _type; - - /* The sequence numbers gets incremented every - time the RCWorld is changed. */ - - unsigned int _seq_no_resItems; - unsigned int _seq_no_channels; - unsigned int _seq_no_subscriptions; - unsigned int _seq_no_locks; - - /* Every world needs to be able to store locks, so we provide a - place for that. Of course, derived classes are allowed to - provide their own exotic lock semantics by providing their - own *_lock_fn methods. */ - MatchList _lock_store; - - bool _refresh_pending; - - /* a bad hack to keep us from emitting signals while finalizing */ - bool _no_changed_signals; - - /* For unserialized worlds currently. If a world is read only, - you can not refresh or transact on it. */ - bool _read_only; - - MatchList _locks; - - public: - - World (WorldType type = PLAIN_WORLD); - virtual ~World(); - - // ---------------------------------- I/O - - static std::string toString (const World & section); - - static std::string toString (WorldType type); - - virtual std::ostream & dumpOn(std::ostream & str ) const; - - friend std::ostream& operator<<(std::ostream&, const World & section); - - std::string asString (void ) const; - - // ---------------------------------- accessors - - WorldType type() const { return _type; } - bool isPlainWorld () const { return _type == PLAIN_WORLD; } - bool isUndumpWorld () const { return _type == UNDUMP_WORLD; } - bool isMultiWorld () const { return _type == MULTI_WORLD; } - bool isServiceWorld () const { return _type == SERVICE_WORLD; } - - unsigned int resItemSequenceNumber (void) const { return _seq_no_resItems; } - unsigned int channelSequenceNumber (void) const { return _seq_no_channels; } - unsigned int subscriptionSequenceNumber (void) const { return _seq_no_subscriptions; } - unsigned int lockSequenceNumber (void) const { return _seq_no_locks; } - - void touchResItemSequenceNumber (void) { _seq_no_resItems++; } - void touchChannelSequenceNumber (void) { _seq_no_channels++; } - void touchSubscriptionSequenceNumber (void) { _seq_no_subscriptions++; } - void touchLockSequenceNumber (void) { _seq_no_locks++; } - - MatchList locks (void) const { return _lock_store; } - - // ---------------------------------- methods - - static void setGlobalWorld (MultiWorldPtr world) { GlobalWorld = world; } - static MultiWorldPtr globalWorld (void) { return GlobalWorld; } - - //RCPackman *get_packman (GType); - - bool sync (void) const; - virtual bool syncConditional (constChannelPtr channel) const; - PendingPtr refresh (void); - bool hasRefresh (void); - bool isRefreshing (void); - - /* These functions are for World-implementers only! Don't call them! */ - void refreshBegin (void); - void refreshComplete (void); - - virtual int foreachChannel (ChannelFn fn, void *user_data) const = 0; - - virtual void setSubscription (ChannelPtr channel, bool is_subscribed); - virtual bool isSubscribed (constChannelPtr channel) const; - - virtual ChannelList channels () const = 0; - virtual bool containsChannel (constChannelPtr channel) const = 0; - - virtual ChannelPtr getChannelByName (const char *channel_name) const = 0; - virtual ChannelPtr getChannelByAlias (const char *alias) const = 0; - virtual ChannelPtr getChannelById (const char *channel_id) const = 0; - - // ResItem Locks - - virtual int foreachLock (MatchFn fn, void *data) const; - - void addLock (constMatchPtr lock); - void removeLock (constMatchPtr lock); - void clearLocks (); - - bool resItemIsLocked (constResItemPtr resItem); - - // Single resItem queries - - virtual constResItemPtr findInstalledResItem (constResItemPtr resItem) = 0; - virtual constResItemPtr findResItem (constChannelPtr channel, const char *name) const = 0; - virtual constResItemPtr findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const = 0; - virtual ChannelPtr guessResItemChannel (constResItemPtr resItem) const = 0; - - // Iterate across resItems - - virtual int foreachResItem (ChannelPtr channel, CResItemFn fn, void *data) = 0; - virtual int foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *user_data) = 0; - virtual int foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *user_data) = 0; - - // Iterate across provides or requirement - - virtual int foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *user_data) = 0; - virtual int foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *user_data) = 0; - virtual int foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *user_data) = 0; - - // upgrades - - int foreachUpgrade (constResItemPtr resItem, ChannelPtr channel, CResItemFn fn, void *data); - PackageUpdateList getUpgrades (constResItemPtr resItem, constChannelPtr channel); - constResItemPtr getBestUpgrade (constResItemPtr resItem, bool subscribed_only); - int foreachSystemUpgrade (bool subscribed_only, ResItemPairFn fn, void *data); - - // provider - - bool getSingleProvider (constDependencyPtr dep, constChannelPtr channel, constResItemPtr *resItem); - - // Transacting - - bool canTransactResItem (constResItemPtr resItem); - bool transact (const ResItemList & installResItems, const ResItemList & remove_resItems, int flags); - - // XML serialization - - void serialize (XmlNodePtr parent); - void toFile (const char *filename); - - // Duplicating (primarily for atomic refreshes) - WorldPtr dup (void); - - // only used for bindings - void setRefreshFunction (WorldRefreshFn refresh_fn); - -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef std::list WorldList; + + class NameConflictInfo; + + ////////////////////////////////////////////////////////////////// + + typedef enum { + PLAIN_WORLD = 0, + STORE_WORLD, + MULTI_WORLD, + SERVICE_WORLD, + UNDUMP_WORLD, + LOCALDIR_WORLD, + SYSTEM_WORLD + } WorldType; + + typedef bool (*WorldFn) (constWorldPtr world, void *user_data); + typedef PendingPtr (*WorldRefreshFn) (constWorldPtr world); + + #if 0 + typedef bool (*WorldSyncFn) (constWorldPtr world, constChannelPtr channel); + typedef PackmanPtr (*WorldPackmanFn) (constWorldPtr world, const Kind & kind); + typedef void (*WorldSpewFn) (constWorldPtr world, FILE *out); + typedef constWorldPtr (*WorldDupFn) (constWorldPtr world); + + typedef bool (*WorldCanTransactResItemFn) (constWorldPtr world, constResItemPtr resItem); + typedef bool (*WorldTransactFn) (constWorldPtr world, const ResItemList & install_resItems, const ResItemList & remove_resItems, int flags); + + typedef bool (*WorldGetSubscribedFn) (const World *world, constChannelPtr channel); + typedef void (*WorldSetSubscribedFn) (World *world, ChannelPtr channel, bool subs_status); + + typedef int (*WorldForeachChannelFn) (const World *world, ChannelFn callback, void *user_data); + typedef int (*WorldForeachLockFn) (constWorldPtr world, MatchFn callback, void *user_data); + + typedef void (*WorldAddLockFn) (constWorldPtr world, constMatchPtr lock); + typedef void (*WorldRemoveLockFn) (constWorldPtr world, constMatchPtr lock); + typedef void (*WorldClearLockFn) (constWorldPtr world); + + typedef int (*WorldForeachResItemFn) (constWorldPtr world, const char *name, constChannelPtr channel, ResItemFn callback, void *user_data); + typedef int (*WorldForeachPackageSpecFn) (constWorldPtr world, constDependencyPtr dep, ResItemAndSpecFn callback, void *user_data); + typedef int (*WorldForeachPackageDepFn) (constWorldPtr world, constDependencyPtr dep, ResItemAndDepFn callback, void *user_data); + + typedef void (*WorldSerializeFn) (constWorldPtr world, constXmlNodePtr root); + typedef void (*WorldUnserializeFn) (constWorldPtr world, constXmlNodePtr node); + + #endif + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : World + + class World : public CountedRep { + REP_BODY(World); + + private: + static WorldPtr GlobalWorld; + + WorldType _type; + + /* The sequence numbers gets incremented every + time the RCWorld is changed. */ + + unsigned int _seq_no_resItems; + unsigned int _seq_no_channels; + unsigned int _seq_no_subscriptions; + unsigned int _seq_no_locks; + + /* Every world needs to be able to store locks, so we provide a + place for that. Of course, derived classes are allowed to + provide their own exotic lock semantics by providing their + own *_lock_fn methods. */ + MatchList _lock_store; + + bool _refresh_pending; + + /* a bad hack to keep us from emitting signals while finalizing */ + bool _no_changed_signals; + + /* For unserialized worlds currently. If a world is read only, + you can not refresh or transact on it. */ + bool _read_only; + + MatchList _locks; + + public: + + World (WorldType type = PLAIN_WORLD); + virtual ~World(); + + // ---------------------------------- I/O + + static std::string toString (const World & section); + + static std::string toString (WorldType type); + + virtual std::ostream & dumpOn(std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream&, const World & section); + + std::string asString (void ) const; + + // ---------------------------------- accessors + + WorldType type() const { return _type; } + bool isPlainWorld () const { return _type == PLAIN_WORLD; } + bool isUndumpWorld () const { return _type == UNDUMP_WORLD; } + bool isMultiWorld () const { return _type == MULTI_WORLD; } + bool isServiceWorld () const { return _type == SERVICE_WORLD; } + + unsigned int resItemSequenceNumber (void) const { return _seq_no_resItems; } + unsigned int channelSequenceNumber (void) const { return _seq_no_channels; } + unsigned int subscriptionSequenceNumber (void) const { return _seq_no_subscriptions; } + unsigned int lockSequenceNumber (void) const { return _seq_no_locks; } + + void touchResItemSequenceNumber (void) { _seq_no_resItems++; } + void touchChannelSequenceNumber (void) { _seq_no_channels++; } + void touchSubscriptionSequenceNumber (void) { _seq_no_subscriptions++; } + void touchLockSequenceNumber (void) { _seq_no_locks++; } + + MatchList locks (void) const { return _lock_store; } + + // ---------------------------------- methods + + static void setGlobalWorld (MultiWorldPtr world) { GlobalWorld = world; } + static MultiWorldPtr globalWorld (void) { return GlobalWorld; } + + //RCPackman *get_packman (GType); + + bool sync (void) const; + virtual bool syncConditional (constChannelPtr channel) const; + PendingPtr refresh (void); + bool hasRefresh (void); + bool isRefreshing (void); + + /* These functions are for World-implementers only! Don't call them! */ + void refreshBegin (void); + void refreshComplete (void); + + virtual int foreachChannel (ChannelFn fn, void *user_data) const = 0; + + virtual void setSubscription (ChannelPtr channel, bool is_subscribed); + virtual bool isSubscribed (constChannelPtr channel) const; + + virtual ChannelList channels () const = 0; + virtual bool containsChannel (constChannelPtr channel) const = 0; + + virtual ChannelPtr getChannelByName (const char *channel_name) const = 0; + virtual ChannelPtr getChannelByAlias (const char *alias) const = 0; + virtual ChannelPtr getChannelById (const char *channel_id) const = 0; + + // ResItem Locks + + virtual int foreachLock (MatchFn fn, void *data) const; + + void addLock (constMatchPtr lock); + void removeLock (constMatchPtr lock); + void clearLocks (); + + bool resItemIsLocked (constResItemPtr resItem); + + // Single resItem queries + + virtual constResItemPtr findInstalledResItem (constResItemPtr resItem) = 0; + virtual constResItemPtr findResItem (constChannelPtr channel, const char *name) const = 0; + virtual constResItemPtr findResItemWithConstraint (constChannelPtr channel, const char *name, constDependencyPtr constraint, bool is_and) const = 0; + virtual ChannelPtr guessResItemChannel (constResItemPtr resItem) const = 0; + + // Iterate across resItems + + virtual int foreachResItem (ChannelPtr channel, CResItemFn fn, void *data) = 0; + virtual int foreachResItemByName (const std::string & name, ChannelPtr channel, CResItemFn fn, void *user_data) = 0; + virtual int foreachResItemByMatch (constMatchPtr match, CResItemFn fn, void *user_data) = 0; + + // Iterate across provides or requirement + + virtual int foreachProvidingResItem (constDependencyPtr dep, ResItemAndSpecFn fn, void *user_data) = 0; + virtual int foreachRequiringResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *user_data) = 0; + virtual int foreachConflictingResItem (constDependencyPtr dep, ResItemAndDepFn fn, void *user_data) = 0; + + // upgrades + + int foreachUpgrade (constResItemPtr resItem, ChannelPtr channel, CResItemFn fn, void *data); + PackageUpdateList getUpgrades (constResItemPtr resItem, constChannelPtr channel); + constResItemPtr getBestUpgrade (constResItemPtr resItem, bool subscribed_only); + int foreachSystemUpgrade (bool subscribed_only, ResItemPairFn fn, void *data); + + // provider + + bool getSingleProvider (constDependencyPtr dep, constChannelPtr channel, constResItemPtr *resItem); + + // Transacting + + bool canTransactResItem (constResItemPtr resItem); + bool transact (const ResItemList & installResItems, const ResItemList & remove_resItems, int flags); + + // XML serialization + + void serialize (XmlNodePtr parent); + void toFile (const char *filename); + + // Duplicating (primarily for atomic refreshes) + WorldPtr dup (void); + + // only used for bindings + void setRefreshFunction (WorldRefreshFn refresh_fn); + + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _World_h diff --git a/zypp/solver/detail/WorldPtr.h b/zypp/solver/detail/WorldPtr.h index d18dd71..83896d7 100644 --- a/zypp/solver/detail/WorldPtr.h +++ b/zypp/solver/detail/WorldPtr.h @@ -23,18 +23,30 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// // CLASS NAME : WorldPtr // CLASS NAME : constWorldPtr /////////////////////////////////////////////////////////////////// DEFINE_BASE_POINTER(World); -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _WorldPtr_h diff --git a/zypp/solver/detail/XmlNode.cc b/zypp/solver/detail/XmlNode.cc index ea706b9..0ed3263 100644 --- a/zypp/solver/detail/XmlNode.cc +++ b/zypp/solver/detail/XmlNode.cc @@ -25,263 +25,275 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -IMPL_BASE_POINTER(XmlNode); - -//--------------------------------------------------------------------------- - -XmlNode::XmlNode (const xmlNodePtr node) - : _node(node) -{ -} - -XmlNode::XmlNode (const char *name) - : _node(xmlNewNode (NULL, (const xmlChar *)name)) -{ -} - -XmlNode::~XmlNode () -{ -} - -//--------------------------------------------------------------------------- - -string -XmlNode::asString ( void ) const -{ - return toString (*this); -} - - -string -XmlNode::toString ( const XmlNode & node ) -{ - return ""; -} - - -ostream & -XmlNode::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const XmlNode& node) -{ - return os << node.asString(); -} - -//--------------------------------------------------------------------------- - -const char * -XmlNode::getValue (const char *name, const char *deflt) const -{ - char *ret; - xmlChar *xml_s; - xmlNode *child; - - xml_s = xmlGetProp(_node, (const xmlChar *)name); -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) xmlGetProp '%s'\n", name, (char *)xml_s); - - if (xml_s) { - ret = strdup ((const char *)xml_s); - xmlFree (xml_s); - return ret; - } - - child = _node->xmlChildrenNode; - - while (child) { -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) child '%s'\n", name, (const char *)(child->name)); - if (strcasecmp((const char *)(child->name), name) == 0) { - xml_s = xmlNodeGetContent(child); -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) xmlNodeGetContent '%s'\n", name, (char *)xml_s); - if (xml_s) { - ret = strdup ((const char *)xml_s); - xmlFree (xml_s); - return ret; - } - } - child = child->next; - } - -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) NULL\n", name); - return deflt; -} - - -const char * -XmlNode::getProp (const char *name, const char *deflt) const -{ - xmlChar *ret; - char *gs; - - ret = xmlGetProp (_node, (const xmlChar *)name); -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getProp(%s) xmlGetProp '%s'\n", name, (char *)ret); - if (ret) { - gs = strdup ((const char *)ret); - xmlFree (ret); - return gs; - } - return deflt; -} - - -bool -XmlNode::getIntValue (const char *name, int *value) const -{ - const char *strval; - char *ret; - int z; - - strval = this->getValue (name, NULL); - if (!strval) { - return false; - } - - z = strtol (strval, &ret, 10); - if (*ret != '\0') { - free ((void *)strval); - return false; - } - - free ((void *)strval); - *value = z; - return true; -} - - -int -XmlNode::getIntValueDefault (const char *name, int def) const -{ - int z; - if (this->getIntValue (name, &z)) - return z; - else - return def; -} - - -unsigned int -XmlNode::getUnsignedIntValueDefault (const char *name, unsigned int def) const -{ - unsigned int z; - if (this->getUnsignedIntValue (name, &z)) - return z; - else - return def; -} - - -bool -XmlNode::getUnsignedIntValue (const char *name, unsigned int *value) const -{ - const char *strval; - char *ret; - int z; - - strval = this->getValue (name, NULL); - if (!strval) { - return false; - } - - z = strtoul (strval, &ret, 10); - if (*ret != '\0') { - free ((void *)strval); - return false; - } - - free ((void *)strval); - *value = z; - return true; -} - - -unsigned int -XmlNode::getUnsignedIntPropDefault (const char *name, unsigned int def) const -{ - xmlChar *buf; - unsigned int ret; - - buf = xmlGetProp (_node, (const xmlChar *)name); - - if (buf) { - ret = strtol ((const char *)buf, NULL, 10); - xmlFree (buf); - return (ret); - } else { - return (def); - } -} - - -const char * -XmlNode::getContent (void) const -{ - xmlChar *buf; - char *ret; - - buf = xmlNodeGetContent (_node); - - ret = strdup ((const char *)buf); - - xmlFree (buf); - - return (ret); -} - - -unsigned int -XmlNode::getUnsignedIntContentDefault (unsigned int def) const -{ - xmlChar *buf; - unsigned int ret; - - buf = xmlNodeGetContent (_node); - - if (buf) { - ret = strtol ((const char *)buf, NULL, 10); - xmlFree (buf); - return (ret); - } else { - return (def); - } -} - - -const XmlNodePtr -XmlNode::getNode (const char *name) const -{ - xmlNodePtr iter; - - for (iter = _node->xmlChildrenNode; iter; iter = iter->next) { - if (strcasecmp ((const char *)(iter->name), name) == 0) { - return new XmlNode (iter); - } - } - - return NULL; -} - - -//--------------------------------------------------------------------------- - - -void -XmlNode::addTextChild (const char *name, const char *content) -{ - xmlNewTextChild (_node, NULL, (const xmlChar *)name, (const xmlChar *)content); -} - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + IMPL_BASE_POINTER(XmlNode); + + //--------------------------------------------------------------------------- + + XmlNode::XmlNode (const xmlNodePtr node) + : _node(node) + { + } + + XmlNode::XmlNode (const char *name) + : _node(xmlNewNode (NULL, (const xmlChar *)name)) + { + } + + XmlNode::~XmlNode () + { + } + + //--------------------------------------------------------------------------- + + string + XmlNode::asString ( void ) const + { + return toString (*this); + } + + + string + XmlNode::toString ( const XmlNode & node ) + { + return ""; + } + + + ostream & + XmlNode::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const XmlNode& node) + { + return os << node.asString(); + } + + //--------------------------------------------------------------------------- + + const char * + XmlNode::getValue (const char *name, const char *deflt) const + { + char *ret; + xmlChar *xml_s; + xmlNode *child; + + xml_s = xmlGetProp(_node, (const xmlChar *)name); + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) xmlGetProp '%s'\n", name, (char *)xml_s); + + if (xml_s) { + ret = strdup ((const char *)xml_s); + xmlFree (xml_s); + return ret; + } + + child = _node->xmlChildrenNode; + + while (child) { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) child '%s'\n", name, (const char *)(child->name)); + if (strcasecmp((const char *)(child->name), name) == 0) { + xml_s = xmlNodeGetContent(child); + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) xmlNodeGetContent '%s'\n", name, (char *)xml_s); + if (xml_s) { + ret = strdup ((const char *)xml_s); + xmlFree (xml_s); + return ret; + } + } + child = child->next; + } + + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getValue(%s) NULL\n", name); + return deflt; + } + + + const char * + XmlNode::getProp (const char *name, const char *deflt) const + { + xmlChar *ret; + char *gs; + + ret = xmlGetProp (_node, (const xmlChar *)name); + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlNode::getProp(%s) xmlGetProp '%s'\n", name, (char *)ret); + if (ret) { + gs = strdup ((const char *)ret); + xmlFree (ret); + return gs; + } + return deflt; + } + + + bool + XmlNode::getIntValue (const char *name, int *value) const + { + const char *strval; + char *ret; + int z; + + strval = this->getValue (name, NULL); + if (!strval) { + return false; + } + + z = strtol (strval, &ret, 10); + if (*ret != '\0') { + free ((void *)strval); + return false; + } + + free ((void *)strval); + *value = z; + return true; + } + + + int + XmlNode::getIntValueDefault (const char *name, int def) const + { + int z; + if (this->getIntValue (name, &z)) + return z; + else + return def; + } + + + unsigned int + XmlNode::getUnsignedIntValueDefault (const char *name, unsigned int def) const + { + unsigned int z; + if (this->getUnsignedIntValue (name, &z)) + return z; + else + return def; + } + + + bool + XmlNode::getUnsignedIntValue (const char *name, unsigned int *value) const + { + const char *strval; + char *ret; + int z; + + strval = this->getValue (name, NULL); + if (!strval) { + return false; + } + + z = strtoul (strval, &ret, 10); + if (*ret != '\0') { + free ((void *)strval); + return false; + } + + free ((void *)strval); + *value = z; + return true; + } + + + unsigned int + XmlNode::getUnsignedIntPropDefault (const char *name, unsigned int def) const + { + xmlChar *buf; + unsigned int ret; + + buf = xmlGetProp (_node, (const xmlChar *)name); + + if (buf) { + ret = strtol ((const char *)buf, NULL, 10); + xmlFree (buf); + return (ret); + } else { + return (def); + } + } + + + const char * + XmlNode::getContent (void) const + { + xmlChar *buf; + char *ret; + + buf = xmlNodeGetContent (_node); + + ret = strdup ((const char *)buf); + + xmlFree (buf); + + return (ret); + } + + + unsigned int + XmlNode::getUnsignedIntContentDefault (unsigned int def) const + { + xmlChar *buf; + unsigned int ret; + + buf = xmlNodeGetContent (_node); + + if (buf) { + ret = strtol ((const char *)buf, NULL, 10); + xmlFree (buf); + return (ret); + } else { + return (def); + } + } + + + const XmlNodePtr + XmlNode::getNode (const char *name) const + { + xmlNodePtr iter; + + for (iter = _node->xmlChildrenNode; iter; iter = iter->next) { + if (strcasecmp ((const char *)(iter->name), name) == 0) { + return new XmlNode (iter); + } + } + + return NULL; + } + + + //--------------------------------------------------------------------------- + + + void + XmlNode::addTextChild (const char *name, const char *content) + { + xmlNewTextChild (_node, NULL, (const xmlChar *)name, (const xmlChar *)content); + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/XmlNode.h b/zypp/solver/detail/XmlNode.h index 0d001bd..e09f078 100644 --- a/zypp/solver/detail/XmlNode.h +++ b/zypp/solver/detail/XmlNode.h @@ -31,9 +31,15 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // @@ -98,9 +104,16 @@ class XmlNode : public CountedRep void addTextChild (const char *name, const char *content); }; -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + #endif // _XmlNode_h diff --git a/zypp/solver/detail/XmlNodePtr.h b/zypp/solver/detail/XmlNodePtr.h index 7020c0b..452b17d 100644 --- a/zypp/solver/detail/XmlNodePtr.h +++ b/zypp/solver/detail/XmlNodePtr.h @@ -24,17 +24,30 @@ #include /////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// CLASS NAME : XmlNodePtr -// CLASS NAME : constXmlNodePtr -/////////////////////////////////////////////////////////////////// -DEFINE_BASE_POINTER(XmlNode); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp +namespace zypp +{ ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + namespace solver + { /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : XmlNodePtr + // CLASS NAME : constXmlNodePtr + /////////////////////////////////////////////////////////////////// + DEFINE_BASE_POINTER(XmlNode); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// +};// namespace zypp /////////////////////////////////////////////////////////////////// #endif // _XmlNodePtr_h diff --git a/zypp/solver/detail/XmlParser.cc b/zypp/solver/detail/XmlParser.cc index 164d232..8d06fd3 100644 --- a/zypp/solver/detail/XmlParser.cc +++ b/zypp/solver/detail/XmlParser.cc @@ -22,7 +22,6 @@ #include #include #include - #include #include #include @@ -31,801 +30,812 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -//--------------------------------------------------------------------------- - -static DependencyPtr -parse_dep_attrs(bool *is_obsolete, const xmlChar **attrs) -{ - int i; - bool op_present = false; - /* Temporary variables dependent upon the presense of an 'op' attribute */ - const char *name = NULL; - int epoch = -1; - string version; - string release; - string arch; - Relation relation = Relation::Any; - - *is_obsolete = false; - - for (i = 0; attrs[i]; i++) { - const char *attr = (const char *)attrs[i++]; - const char *value = (const char *)attrs[i]; - - if (!strcasecmp(attr, "name")) name = value; - else if (!strcasecmp(attr, "op")) { op_present = true; relation = Relation::parse(value); } - else if (!strcasecmp(attr, "epoch")) epoch = atoi (value); - else if (!strcasecmp(attr, "version")) version = value; - else if (!strcasecmp(attr, "release")) release = value; - else if (!strcasecmp(attr, "arch")) arch = value; - else if (!strcasecmp (attr, "obsoletes")) *is_obsolete = true; - else { - if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Unknown attribute: %s = %s", attr, value); - } - - } - - /* FIXME: should get Channel from XML */ - /* FIXME: should get Kind from XML */ - return new Dependency (name, relation, Kind::Package, new Channel(CHANNEL_TYPE_ANY), epoch, version, release, Arch::create(arch)); -} - - -//--------------------------------------------------------------------------- -// SAX callbacks - -static void -sax_start_document(void *ptr) -{ - XmlParser *ctx = (XmlParser *)ptr; - if (ctx->processing()) return; - -// if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Start document"); - - ctx->setProcessing (true); -} - - -static void -sax_end_document(void *ptr) -{ - XmlParser *ctx = (XmlParser *)ptr; - if (!ctx->processing()) return; - -// if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* End document"); - - ctx->setProcessing (false); -} - - -static void -sax_start_element(void *ptr, const xmlChar *name, const xmlChar **attrs) -{ - XmlParser *ctx = (XmlParser *)ptr; - - ctx->releaseBuffer(); - -#if 0 -// if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Start element (%s)", (const char *)name); - - if (attrs) { - for (int i = 0; attrs[i]; i += 2) { - if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, " - Attribute (%s=%s)", (const char *)attrs[i], (const char *)attrs[i+1]); - } - } -#endif - if (!strcmp((const char *)name, "channel") || !strcmp((const char *)name, "subchannel")) { - /* Unneeded container tags. Ignore */ - return; - } - - return ctx->startElement ((const char *)name, attrs); - -} - - -static void -sax_end_element(void *ptr, const xmlChar *name) -{ - XmlParser *ctx = (XmlParser *)ptr; - -// if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* End element (%s)", (const char *)name); - - if (!strcmp((const char *)name, "channel") || !strcmp((const char *)name, "subchannel")) { - /* Unneeded container tags. Ignore */ - name = NULL; - } - - return ctx->endElement ((const char *)name); -} - - -static void -sax_characters(void *ptr, const xmlChar *ch, int len) -{ - XmlParser *ctx = (XmlParser *)ptr; - - ctx->toBuffer ((const char *)ch, len); - return; -} - - -static void -sax_warning(void *ptr, const char *msg, ...) -{ - va_list args; - char tmp[2048]; - - va_start(args, msg); - - if (vsnprintf(tmp, 2048, msg, args) >= 2048) fprintf (stderr, "vsnprintf overflow\n"); - rc_debug (RC_DEBUG_LEVEL_WARNING, "* SAX Warning: %s", tmp); - - va_end(args); -} - - -static void -sax_error(void *ptr, const char *msg, ...) -{ - va_list args; - char tmp[2048]; - - va_start(args, msg); - - if (vsnprintf(tmp, 2048, msg, args) >= 2048) fprintf (stderr, "vsnprintf overflow\n"); - rc_debug (RC_DEBUG_LEVEL_ERROR, "* SAX Error: %s", tmp); - - va_end(args); -} - - -static xmlSAXHandler sax_handler = { - NULL, /* internalSubset */ - NULL, /* isStandalone */ - NULL, /* hasInternalSubset */ - NULL, /* hasExternalSubset */ - NULL, /* resolveEntity */ - NULL, /* getEntity */ - NULL, /* entityDecl */ - NULL, /* notationDecl */ - NULL, /* attributeDecl */ - NULL, /* elementDecl */ - NULL, /* unparsedEntityDecl */ - NULL, /* setDocumentLocator */ - sax_start_document, /* startDocument */ - sax_end_document, /* endDocument */ - sax_start_element, /* startElement */ - sax_end_element, /* endElement */ - NULL, /* reference */ - sax_characters, /* characters */ - NULL, /* ignorableWhitespace */ - NULL, /* processingInstruction */ - NULL, /* comment */ - sax_warning, /* warning */ - sax_error, /* error */ - sax_error /* fatalError */ -}; - -//--------------------------------------------------------------------------- - -XmlParser::XmlParser (constChannelPtr channel) - : _channel (channel) - , _processing (false) - , _xml_context (NULL) - , _state (PARSER_TOPLEVEL) - , _current_package (NULL) - , _current_update (NULL) - , _toplevel_dep_list (NULL) - , _current_dep_list (NULL) - , _text_buffer (NULL) - , _text_buffer_size (0) -{ -// if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Context created (%p)", this); -} - - -XmlParser::~XmlParser() -{ - releaseBuffer (); -} - -//--------------------------------------------------------------------------- - -string -XmlParser::asString ( void ) const -{ - return toString (*this); -} - - -string -XmlParser::toString ( const XmlParser & context ) -{ - return ""; -} - - -ostream & -XmlParser::dumpOn( ostream & str ) const -{ - str << asString(); - return str; -} - - -ostream& -operator<<( ostream& os, const XmlParser& context) -{ - return os << context.asString(); -} - -//--------------------------------------------------------------------------- - -void -XmlParser::toBuffer (const char *data, size_t size) -{ - _text_buffer = (char *)realloc (_text_buffer, _text_buffer_size + size + 1); - strncpy (_text_buffer + _text_buffer_size, (char *)data, size); - _text_buffer_size += size; - _text_buffer[_text_buffer_size] = 0; - -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser[%p]::toBuffer(%.32s...,%ld)\n", this, data, (long)size); -} - - -void -XmlParser::releaseBuffer () -{ - if (_text_buffer) - free (_text_buffer); - _text_buffer = NULL; - _text_buffer_size = 0; -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser[%p]::releaseBuffer()\n", this); -} - - -void -XmlParser::parseChunk(const char *xmlbuf, size_t size) -{ - if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::parseChunk(%.32s...,%ld)\n", xmlbuf, (long)size); - - xmlSubstituteEntitiesDefault(true); - - if (!_xml_context) { - _xml_context = xmlCreatePushParserCtxt(&sax_handler, this, NULL, 0, NULL); - } - - xmlParseChunk(_xml_context, xmlbuf, size, 0); -} - - -PackageList -XmlParser::done() -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::done()\n"); - - if (_processing) - xmlParseChunk(_xml_context, NULL, 0, 1); - - if (_xml_context) - xmlFreeParserCtxt(_xml_context); - - if (_current_package) { - fprintf (stderr, "Incomplete package lost\n"); - } - - if (_current_update) { - fprintf (stderr, "Incomplete update lost"); - } - - return _all_packages; -} - - -//--------------------------------------------------------------------------- -// Parser state callbacks - -void -XmlParser::startElement(const char *name, const xmlChar **attrs) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::startElement(%s)\n", name); - - switch (_state) { - case PARSER_TOPLEVEL: - toplevelStart(name, attrs); - break; - case PARSER_PACKAGE: - packageStart(name, attrs); - break; - case PARSER_HISTORY: - historyStart(name, attrs); - break; - case PARSER_DEP: - dependencyStart(name, attrs); - break; - default: - break; - } - - return; -} - - -void -XmlParser::endElement(const char *name) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::endElement(%s)\n", name); - - if (name != NULL) { // sax_end_element might set name to NULL - switch (_state) { - case PARSER_PACKAGE: - packageEnd(name); - break; - case PARSER_HISTORY: - historyEnd(name); - break; - case PARSER_UPDATE: - updateEnd(name); - break; - case PARSER_DEP: - dependencyEnd(name); - break; - default: - break; - } - } - - releaseBuffer(); - - return; -} - - -void -XmlParser::toplevelStart(const char * name, const xmlChar **attrs) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::toplevelStart(%s)\n", name); - - if (!strcmp(name, "package")) { - assert(_current_package == NULL); - - _state = PARSER_PACKAGE; - - _current_package = new Package(_channel); - _current_requires.clear(); - _current_provides.clear(); - _current_conflicts.clear(); - _current_children.clear(); - _current_recommends.clear(); - _current_suggests.clear(); - _current_obsoletes.clear(); - - } - else { - if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s at toplevel", (const char *)name); - } -} - - -void -XmlParser::packageStart(const char * name, const xmlChar **attrs) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageStart(%s)\n", name); - - assert(_current_package != NULL); - - /* Only care about the containers here */ - if (!strcmp((const char *)name, "history")) { - _state = PARSER_HISTORY; - } - else if (!strcmp (name, "deps")) { - /* - * We can get a tag surrounding the actual package - * dependency sections (requires, provides, conflicts, etc). - * In this case, we'll just ignore this tag quietly. - */ - } - else if (!strcmp(name, "requires")) { - _state = PARSER_DEP; - _current_dep_list = _toplevel_dep_list = &_current_requires; - } - else if (!strcmp(name, "recommends")) { - _state = PARSER_DEP; - _current_dep_list = _toplevel_dep_list = &_current_recommends; - } - else if (!strcmp(name, "suggests")) { - _state = PARSER_DEP; - _current_dep_list = _toplevel_dep_list = &_current_suggests; - } - else if (!strcmp(name, "conflicts")) { - bool is_obsolete = false; - int i; - - _state = PARSER_DEP; - - for (i = 0; attrs && attrs[i] && !is_obsolete; i += 2) { - - if (!strcasecmp ((const char *)(attrs[i]), "obsoletes")) - is_obsolete = true; - } - - if (is_obsolete) - _current_dep_list = _toplevel_dep_list = &_current_obsoletes; - else { - _current_dep_list = _toplevel_dep_list = &_current_conflicts; - } - } - else if (!strcmp(name, "obsoletes")) { - _state = PARSER_DEP; - _current_dep_list = _toplevel_dep_list = &_current_obsoletes; - } - else if (!strcmp(name, "provides")) { - _state = PARSER_DEP; - _current_dep_list = _toplevel_dep_list = &_current_provides; - } - else if (!strcmp(name, "children")) { - _state = PARSER_DEP; - _current_dep_list = _toplevel_dep_list = &_current_children; - } - else { -// if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in package start", name); - } -} - - -void -XmlParser::historyStart(const char * name, const xmlChar **attrs) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::historyStart(%s)\n", name); - - assert(_current_package != NULL); - - if (!strcmp(name, "update")) { - assert(_current_update == NULL); - - _current_update = new PackageUpdate(_current_package->name()); - - _state = PARSER_UPDATE; - } - else { - if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in history", name); - } -} - - -void -XmlParser::dependencyStart(const char *name, const xmlChar **attrs) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::dependencyStart(%s)\n", name); - - if (!strcmp(name, "dep")) { - DependencyPtr dep; - bool is_obsolete; - - dep = parse_dep_attrs(&is_obsolete, attrs); - - if (is_obsolete) - _current_obsoletes.push_back (dep); - else { - _current_dep_list->push_back (dep); - } - } - else if (!strcmp(name, "or")) - _current_dep_list = new CDependencyList; - else { - if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in dependency", name); - } -} - - -//--------------------------------------------------------------------------- - - -void -XmlParser::packageEnd(const char *name) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s)\n", name); - - assert(_current_package != NULL); - - if (!strcmp(name, "package")) { - PackageUpdatePtr update; - - /* If possible, grab the version info from the most recent update. - * Otherwise, try to find where the package provides itself and use - * that version info. - */ - update = _current_package->getLatestUpdate(); - - if (update) { - _current_package->setName (update->name()); - _current_package->setKind (update->kind()); - _current_package->setEdition (update->edition()); - _current_package->setFileSize (update->packageSize()); - _current_package->setInstalledSize (update->installedSize()); - } - else { - for (CDependencyList::const_iterator iter = _current_provides.begin(); iter != _current_provides.end(); iter++) { - if ((*iter)->relation().isEqual() - && ((*iter)->name() == _current_package->name())) - { - _current_package->setKind ((*iter)->kind()); - _current_package->setEdition ((*iter)->edition()); - break; - } - } - } - - /* Hack for the old XML */ - if (_current_package->arch()->isUnknown()) { - _current_package->setArch (Arch::System); - } - - // check if we provide ourselfs properly - - CDependencyList::const_iterator piter; - for (piter = _current_provides.begin(); piter != _current_provides.end(); piter++) { - if ((*piter)->relation().isEqual() - && ((*piter)->name() == _current_package->name())) - { - break; - } - } - - if (piter == _current_provides.end()) { // no self provide found, construct one - constDependencyPtr selfdep = new Dependency (_current_package->name(), Relation::Equal, _current_package->kind(), _current_package->channel(), _current_package->edition()); -//if (getenv ("RC_SPEW")) fprintf (stderr, "Adding self-provide [%s]\n", selfdep->asString().c_str()); - _current_provides.push_front (selfdep); - } - - _current_package->setRequires (_current_requires); - _current_package->setProvides (_current_provides); - _current_package->setConflicts (_current_conflicts); - _current_package->setObsoletes (_current_obsoletes); - _current_package->setSuggests (_current_suggests); - _current_package->setRecommends (_current_recommends); - - _all_packages.push_back (_current_package); - - if (getenv ("RC_SPEW")) fprintf (stderr, "%s\n", _current_package->asString(true).c_str()); - if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd done: '%s'\n", _current_package->asString(true).c_str()); -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd now %ld packages\n", _all_packages.size()); - _current_package = NULL; - _state = PARSER_TOPLEVEL; - } - else if (!strcmp(name, "name")) { _current_package->setName (strstrip (_text_buffer)); - } else if (!strcmp(name, "pretty_name")) { _current_package->setPrettyName (strstrip (_text_buffer)); - } else if (!strcmp(name, "summary")) { _current_package->setSummary (strstrip (_text_buffer)); - } else if (!strcmp(name, "description")) { _current_package->setDescription (strstrip (_text_buffer)); - } else if (!strcmp(name, "section")) { _current_package->setSection (new Section(strstrip (_text_buffer))); - } else if (!strcmp(name, "arch")) { _current_package->setArch (strstrip (_text_buffer)); - } else if (!strcmp(name, "filesize")) { _current_package->setFileSize (atoi(_text_buffer)); - } else if (!strcmp(name, "installedsize")) { _current_package->setInstalledSize (atoi(_text_buffer)); - } else if (!strcmp(name, "install_only")) { _current_package->setInstallOnly (true); - } else if (!strcmp(name, "package_set")) { _current_package->setPackageSet (true); - } else { - if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s) unknown\n", name); - } - -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s) done\n", name); - - releaseBuffer(); -} - - -void -XmlParser::historyEnd(const char *name) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::historyEnd(%s)\n", name); - assert(_current_package != NULL); - - if (!strcmp(name, "history")) { - assert(_current_update == NULL); - - _state = PARSER_PACKAGE; - } -} - - -void -XmlParser::updateEnd(const char *name) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::updateEnd(%s)\n", name); - - constChannelPtr channel; - const char *url_prefix = NULL; - - assert(_current_package != NULL); - assert(_current_update != NULL); - - channel = _current_package->channel(); - - if (channel != NULL) { - url_prefix = channel->filePath (); - } - - if (!strcmp(name, "update")) { - _current_package->addUpdate(_current_update); - - _current_update = NULL; - _state = PARSER_HISTORY; - - } else if (!strcmp(name, "epoch")) { _current_update->setEpoch (atoi(_text_buffer)); - } else if (!strcmp(name, "version")) { _current_update->setVersion (strstrip (_text_buffer)); - } else if (!strcmp(name, "release")) { _current_update->setRelease (strstrip (_text_buffer)); - } else if (!strcmp(name, "arch")) { _current_update->setArch (strstrip (_text_buffer)); - } else if (!strcmp(name, "filename")) { - strstrip (_text_buffer); - if (url_prefix) { - _current_update->setPackageUrl (maybe_merge_paths(url_prefix, _text_buffer)); - } - else { - _current_update->setPackageUrl (_text_buffer); - } - } else if (!strcmp(name, "filesize")) { _current_update->setPackageSize (atoi(_text_buffer)); - } else if (!strcmp(name, "installedsize")) { _current_update->setInstalledSize (atoi (_text_buffer)); - } else if (!strcmp(name, "signaturename")) { - strstrip (_text_buffer); - if (url_prefix) { - _current_update->setSignatureUrl (maybe_merge_paths(url_prefix, _text_buffer)); - } - else { - _current_update->setSignatureUrl (_text_buffer); - } - } else if (!strcmp(name, "signaturesize")) { _current_update->setSignatureSize (atoi (_text_buffer)); - } else if (!strcmp(name, "md5sum")) { _current_update->setMd5sum (strstrip (_text_buffer)); - } else if (!strcmp(name, "importance")) { _current_update->setImportance (new Importance (strstrip (_text_buffer))); - } else if (!strcmp(name, "description")) { _current_update->setDescription (strstrip (_text_buffer)); - } else if (!strcmp(name, "hid")) { _current_update->setHid (atoi(_text_buffer)); - } else if (!strcmp (name, "license")) { _current_update->setLicense (strstrip (_text_buffer)); - } else { - fprintf (stderr, "XmlParser::updateEnd(%s) unknown\n", name); - } - -// if (_current_update != NULL && getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::updateEnd(%s) => '%s'\n", name, _current_update->asString().c_str()); - - releaseBuffer(); - -} - - -void -XmlParser::dependencyEnd(const char *name) -{ -// if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::dependencyEnd(%s)\n", name); - - if (!strcmp(name, "or")) { - OrDependencyPtr or_dep = OrDependency::fromDependencyList (*_current_dep_list); - DependencyPtr dep = new Dependency (or_dep); - - (*_current_dep_list).clear(); - - (*_toplevel_dep_list).push_back (dep); - _current_dep_list = _toplevel_dep_list; - } - else if (!strcmp(name, "dep")) { - /* We handled everything we needed for dep in start */ - } - else { - /* All of the dep lists (requires, provides, etc.) */ - _toplevel_dep_list = NULL; - _current_dep_list = NULL; - _state = PARSER_PACKAGE; - } -} - - - -//=================================================================================================================== - -#if 0 -//--------------------------------------------------------------------------- - -/* ------ */ - - -static RCResItemDep * -rc_xml_node_to_resItem_dep_internal (const xmlNode *node) -{ - gchar *name = NULL, *version = NULL, *release = NULL; - gboolean has_epoch = false; - guint32 epoch = 0; - RCResItemRelation relation; - RCResItemDep *dep; - - gchar *tmp; - - if (g_strcasecmp (node->name, "dep")) { - return (NULL); - } - - name = xml_get_prop (node, "name"); - tmp = xml_get_prop (node, "op"); - if (tmp) { - relation = rc_resItem_relation_from_string (tmp); - - has_epoch = xml_get_guint32_value (node, "epoch", &epoch); - - version = xml_get_prop (node, "version"); - release = xml_get_prop (node, "release"); - } else { - relation = RC_RELATION_ANY; - } - - /* FIXME: should get channel from XML */ - dep = rc_resItem_dep_new (name, has_epoch, epoch, version, release, - relation, RC_TYPE_RESOLVABLE, RC_CHANNEL_ANY, - false, false); - - g_free (tmp); - g_free (name); - g_free (version); - g_free (release); - - return dep; -} /* rc_xml_node_to_resItem_dep_internal */ - -RCResItemDep * -rc_xml_node_to_resItem_dep (const xmlNode *node) -{ - RCResItemDep *dep = NULL; - - if (!g_strcasecmp (node->name, "dep")) { - dep = rc_xml_node_to_resItem_dep_internal (node); - return (dep); - } else if (!g_strcasecmp (node->name, "or")) { - RCResItemDepSList *or_dep_slist = NULL; - RCDepOr *or; - xmlNode *iter = node->xmlChildrenNode; - - while (iter) { - if (iter->type == XML_ELEMENT_NODE) { - or_dep_slist = g_slist_append( - or_dep_slist, - rc_xml_node_to_resItem_dep_internal (iter)); - } - - iter = iter->next; - } - - or = rc_dep_or_new (or_dep_slist); - dep = rc_dep_or_new_provide (or); - } - - return (dep); -} /* rc_xml_node_to_resItem_dep */ - -/* ------ */ - -/* This hack cleans 8-bit characters out of a string. This is a very - problematic "solution" to the problem of non-UTF-8 package info. */ -static gchar * -sanitize_string (const char *str) -{ - gchar *dup = g_strdup (str); - gchar *c; - - return dup; - - if (dup) { - for (c = dup; *c; ++c) { - if ((guint)*c > 0x7f) - *c = '_'; - } - } - - return dup; -} - -#endif - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + //--------------------------------------------------------------------------- + + static DependencyPtr + parse_dep_attrs(bool *is_obsolete, const xmlChar **attrs) + { + int i; + bool op_present = false; + /* Temporary variables dependent upon the presense of an 'op' attribute */ + const char *name = NULL; + int epoch = -1; + string version; + string release; + string arch; + Relation relation = Relation::Any; + + *is_obsolete = false; + + for (i = 0; attrs[i]; i++) { + const char *attr = (const char *)attrs[i++]; + const char *value = (const char *)attrs[i]; + + if (!strcasecmp(attr, "name")) name = value; + else if (!strcasecmp(attr, "op")) { op_present = true; relation = Relation::parse(value); } + else if (!strcasecmp(attr, "epoch")) epoch = atoi (value); + else if (!strcasecmp(attr, "version")) version = value; + else if (!strcasecmp(attr, "release")) release = value; + else if (!strcasecmp(attr, "arch")) arch = value; + else if (!strcasecmp (attr, "obsoletes")) *is_obsolete = true; + else { + if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Unknown attribute: %s = %s", attr, value); + } + + } + + /* FIXME: should get Channel from XML */ + /* FIXME: should get Kind from XML */ + return new Dependency (name, relation, Kind::Package, new Channel(CHANNEL_TYPE_ANY), epoch, version, release, Arch::create(arch)); + } + + + //--------------------------------------------------------------------------- + // SAX callbacks + + static void + sax_start_document(void *ptr) + { + XmlParser *ctx = (XmlParser *)ptr; + if (ctx->processing()) return; + + // if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Start document"); + + ctx->setProcessing (true); + } + + + static void + sax_end_document(void *ptr) + { + XmlParser *ctx = (XmlParser *)ptr; + if (!ctx->processing()) return; + + // if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* End document"); + + ctx->setProcessing (false); + } + + + static void + sax_start_element(void *ptr, const xmlChar *name, const xmlChar **attrs) + { + XmlParser *ctx = (XmlParser *)ptr; + + ctx->releaseBuffer(); + + #if 0 + // if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Start element (%s)", (const char *)name); + + if (attrs) { + for (int i = 0; attrs[i]; i += 2) { + if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, " - Attribute (%s=%s)", (const char *)attrs[i], (const char *)attrs[i+1]); + } + } + #endif + if (!strcmp((const char *)name, "channel") || !strcmp((const char *)name, "subchannel")) { + /* Unneeded container tags. Ignore */ + return; + } + + return ctx->startElement ((const char *)name, attrs); + + } + + + static void + sax_end_element(void *ptr, const xmlChar *name) + { + XmlParser *ctx = (XmlParser *)ptr; + + // if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* End element (%s)", (const char *)name); + + if (!strcmp((const char *)name, "channel") || !strcmp((const char *)name, "subchannel")) { + /* Unneeded container tags. Ignore */ + name = NULL; + } + + return ctx->endElement ((const char *)name); + } + + + static void + sax_characters(void *ptr, const xmlChar *ch, int len) + { + XmlParser *ctx = (XmlParser *)ptr; + + ctx->toBuffer ((const char *)ch, len); + return; + } + + + static void + sax_warning(void *ptr, const char *msg, ...) + { + va_list args; + char tmp[2048]; + + va_start(args, msg); + + if (vsnprintf(tmp, 2048, msg, args) >= 2048) fprintf (stderr, "vsnprintf overflow\n"); + rc_debug (RC_DEBUG_LEVEL_WARNING, "* SAX Warning: %s", tmp); + + va_end(args); + } + + + static void + sax_error(void *ptr, const char *msg, ...) + { + va_list args; + char tmp[2048]; + + va_start(args, msg); + + if (vsnprintf(tmp, 2048, msg, args) >= 2048) fprintf (stderr, "vsnprintf overflow\n"); + rc_debug (RC_DEBUG_LEVEL_ERROR, "* SAX Error: %s", tmp); + + va_end(args); + } + + + static xmlSAXHandler sax_handler = { + NULL, /* internalSubset */ + NULL, /* isStandalone */ + NULL, /* hasInternalSubset */ + NULL, /* hasExternalSubset */ + NULL, /* resolveEntity */ + NULL, /* getEntity */ + NULL, /* entityDecl */ + NULL, /* notationDecl */ + NULL, /* attributeDecl */ + NULL, /* elementDecl */ + NULL, /* unparsedEntityDecl */ + NULL, /* setDocumentLocator */ + sax_start_document, /* startDocument */ + sax_end_document, /* endDocument */ + sax_start_element, /* startElement */ + sax_end_element, /* endElement */ + NULL, /* reference */ + sax_characters, /* characters */ + NULL, /* ignorableWhitespace */ + NULL, /* processingInstruction */ + NULL, /* comment */ + sax_warning, /* warning */ + sax_error, /* error */ + sax_error /* fatalError */ + }; + + //--------------------------------------------------------------------------- + + XmlParser::XmlParser (constChannelPtr channel) + : _channel (channel) + , _processing (false) + , _xml_context (NULL) + , _state (PARSER_TOPLEVEL) + , _current_package (NULL) + , _current_update (NULL) + , _toplevel_dep_list (NULL) + , _current_dep_list (NULL) + , _text_buffer (NULL) + , _text_buffer_size (0) + { + // if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Context created (%p)", this); + } + + + XmlParser::~XmlParser() + { + releaseBuffer (); + } + + //--------------------------------------------------------------------------- + + string + XmlParser::asString ( void ) const + { + return toString (*this); + } + + + string + XmlParser::toString ( const XmlParser & context ) + { + return ""; + } + + + ostream & + XmlParser::dumpOn( ostream & str ) const + { + str << asString(); + return str; + } + + + ostream& + operator<<( ostream& os, const XmlParser& context) + { + return os << context.asString(); + } + + //--------------------------------------------------------------------------- + + void + XmlParser::toBuffer (const char *data, size_t size) + { + _text_buffer = (char *)realloc (_text_buffer, _text_buffer_size + size + 1); + strncpy (_text_buffer + _text_buffer_size, (char *)data, size); + _text_buffer_size += size; + _text_buffer[_text_buffer_size] = 0; + + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser[%p]::toBuffer(%.32s...,%ld)\n", this, data, (long)size); + } + + + void + XmlParser::releaseBuffer () + { + if (_text_buffer) + free (_text_buffer); + _text_buffer = NULL; + _text_buffer_size = 0; + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser[%p]::releaseBuffer()\n", this); + } + + + void + XmlParser::parseChunk(const char *xmlbuf, size_t size) + { + if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::parseChunk(%.32s...,%ld)\n", xmlbuf, (long)size); + + xmlSubstituteEntitiesDefault(true); + + if (!_xml_context) { + _xml_context = xmlCreatePushParserCtxt(&sax_handler, this, NULL, 0, NULL); + } + + xmlParseChunk(_xml_context, xmlbuf, size, 0); + } + + + PackageList + XmlParser::done() + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::done()\n"); + + if (_processing) + xmlParseChunk(_xml_context, NULL, 0, 1); + + if (_xml_context) + xmlFreeParserCtxt(_xml_context); + + if (_current_package) { + fprintf (stderr, "Incomplete package lost\n"); + } + + if (_current_update) { + fprintf (stderr, "Incomplete update lost"); + } + + return _all_packages; + } + + + //--------------------------------------------------------------------------- + // Parser state callbacks + + void + XmlParser::startElement(const char *name, const xmlChar **attrs) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::startElement(%s)\n", name); + + switch (_state) { + case PARSER_TOPLEVEL: + toplevelStart(name, attrs); + break; + case PARSER_PACKAGE: + packageStart(name, attrs); + break; + case PARSER_HISTORY: + historyStart(name, attrs); + break; + case PARSER_DEP: + dependencyStart(name, attrs); + break; + default: + break; + } + + return; + } + + + void + XmlParser::endElement(const char *name) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::endElement(%s)\n", name); + + if (name != NULL) { // sax_end_element might set name to NULL + switch (_state) { + case PARSER_PACKAGE: + packageEnd(name); + break; + case PARSER_HISTORY: + historyEnd(name); + break; + case PARSER_UPDATE: + updateEnd(name); + break; + case PARSER_DEP: + dependencyEnd(name); + break; + default: + break; + } + } + + releaseBuffer(); + + return; + } + + + void + XmlParser::toplevelStart(const char * name, const xmlChar **attrs) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::toplevelStart(%s)\n", name); + + if (!strcmp(name, "package")) { + assert(_current_package == NULL); + + _state = PARSER_PACKAGE; + + _current_package = new Package(_channel); + _current_requires.clear(); + _current_provides.clear(); + _current_conflicts.clear(); + _current_children.clear(); + _current_recommends.clear(); + _current_suggests.clear(); + _current_obsoletes.clear(); + + } + else { + if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s at toplevel", (const char *)name); + } + } + + + void + XmlParser::packageStart(const char * name, const xmlChar **attrs) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageStart(%s)\n", name); + + assert(_current_package != NULL); + + /* Only care about the containers here */ + if (!strcmp((const char *)name, "history")) { + _state = PARSER_HISTORY; + } + else if (!strcmp (name, "deps")) { + /* + * We can get a tag surrounding the actual package + * dependency sections (requires, provides, conflicts, etc). + * In this case, we'll just ignore this tag quietly. + */ + } + else if (!strcmp(name, "requires")) { + _state = PARSER_DEP; + _current_dep_list = _toplevel_dep_list = &_current_requires; + } + else if (!strcmp(name, "recommends")) { + _state = PARSER_DEP; + _current_dep_list = _toplevel_dep_list = &_current_recommends; + } + else if (!strcmp(name, "suggests")) { + _state = PARSER_DEP; + _current_dep_list = _toplevel_dep_list = &_current_suggests; + } + else if (!strcmp(name, "conflicts")) { + bool is_obsolete = false; + int i; + + _state = PARSER_DEP; + + for (i = 0; attrs && attrs[i] && !is_obsolete; i += 2) { + + if (!strcasecmp ((const char *)(attrs[i]), "obsoletes")) + is_obsolete = true; + } + + if (is_obsolete) + _current_dep_list = _toplevel_dep_list = &_current_obsoletes; + else { + _current_dep_list = _toplevel_dep_list = &_current_conflicts; + } + } + else if (!strcmp(name, "obsoletes")) { + _state = PARSER_DEP; + _current_dep_list = _toplevel_dep_list = &_current_obsoletes; + } + else if (!strcmp(name, "provides")) { + _state = PARSER_DEP; + _current_dep_list = _toplevel_dep_list = &_current_provides; + } + else if (!strcmp(name, "children")) { + _state = PARSER_DEP; + _current_dep_list = _toplevel_dep_list = &_current_children; + } + else { + // if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in package start", name); + } + } + + + void + XmlParser::historyStart(const char * name, const xmlChar **attrs) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::historyStart(%s)\n", name); + + assert(_current_package != NULL); + + if (!strcmp(name, "update")) { + assert(_current_update == NULL); + + _current_update = new PackageUpdate(_current_package->name()); + + _state = PARSER_UPDATE; + } + else { + if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in history", name); + } + } + + + void + XmlParser::dependencyStart(const char *name, const xmlChar **attrs) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::dependencyStart(%s)\n", name); + + if (!strcmp(name, "dep")) { + DependencyPtr dep; + bool is_obsolete; + + dep = parse_dep_attrs(&is_obsolete, attrs); + + if (is_obsolete) + _current_obsoletes.push_back (dep); + else { + _current_dep_list->push_back (dep); + } + } + else if (!strcmp(name, "or")) + _current_dep_list = new CDependencyList; + else { + if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in dependency", name); + } + } + + + //--------------------------------------------------------------------------- + + + void + XmlParser::packageEnd(const char *name) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s)\n", name); + + assert(_current_package != NULL); + + if (!strcmp(name, "package")) { + PackageUpdatePtr update; + + /* If possible, grab the version info from the most recent update. + * Otherwise, try to find where the package provides itself and use + * that version info. + */ + update = _current_package->getLatestUpdate(); + + if (update) { + _current_package->setName (update->name()); + _current_package->setKind (update->kind()); + _current_package->setEdition (update->edition()); + _current_package->setFileSize (update->packageSize()); + _current_package->setInstalledSize (update->installedSize()); + } + else { + for (CDependencyList::const_iterator iter = _current_provides.begin(); iter != _current_provides.end(); iter++) { + if ((*iter)->relation().isEqual() + && ((*iter)->name() == _current_package->name())) + { + _current_package->setKind ((*iter)->kind()); + _current_package->setEdition ((*iter)->edition()); + break; + } + } + } + + /* Hack for the old XML */ + if (_current_package->arch()->isUnknown()) { + _current_package->setArch (Arch::System); + } + + // check if we provide ourselfs properly + + CDependencyList::const_iterator piter; + for (piter = _current_provides.begin(); piter != _current_provides.end(); piter++) { + if ((*piter)->relation().isEqual() + && ((*piter)->name() == _current_package->name())) + { + break; + } + } + + if (piter == _current_provides.end()) { // no self provide found, construct one + constDependencyPtr selfdep = new Dependency (_current_package->name(), Relation::Equal, _current_package->kind(), _current_package->channel(), _current_package->edition()); + //if (getenv ("RC_SPEW")) fprintf (stderr, "Adding self-provide [%s]\n", selfdep->asString().c_str()); + _current_provides.push_front (selfdep); + } + + _current_package->setRequires (_current_requires); + _current_package->setProvides (_current_provides); + _current_package->setConflicts (_current_conflicts); + _current_package->setObsoletes (_current_obsoletes); + _current_package->setSuggests (_current_suggests); + _current_package->setRecommends (_current_recommends); + + _all_packages.push_back (_current_package); + + if (getenv ("RC_SPEW")) fprintf (stderr, "%s\n", _current_package->asString(true).c_str()); + if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd done: '%s'\n", _current_package->asString(true).c_str()); + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd now %ld packages\n", _all_packages.size()); + _current_package = NULL; + _state = PARSER_TOPLEVEL; + } + else if (!strcmp(name, "name")) { _current_package->setName (strstrip (_text_buffer)); + } else if (!strcmp(name, "pretty_name")) { _current_package->setPrettyName (strstrip (_text_buffer)); + } else if (!strcmp(name, "summary")) { _current_package->setSummary (strstrip (_text_buffer)); + } else if (!strcmp(name, "description")) { _current_package->setDescription (strstrip (_text_buffer)); + } else if (!strcmp(name, "section")) { _current_package->setSection (new Section(strstrip (_text_buffer))); + } else if (!strcmp(name, "arch")) { _current_package->setArch (strstrip (_text_buffer)); + } else if (!strcmp(name, "filesize")) { _current_package->setFileSize (atoi(_text_buffer)); + } else if (!strcmp(name, "installedsize")) { _current_package->setInstalledSize (atoi(_text_buffer)); + } else if (!strcmp(name, "install_only")) { _current_package->setInstallOnly (true); + } else if (!strcmp(name, "package_set")) { _current_package->setPackageSet (true); + } else { + if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s) unknown\n", name); + } + + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s) done\n", name); + + releaseBuffer(); + } + + + void + XmlParser::historyEnd(const char *name) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::historyEnd(%s)\n", name); + assert(_current_package != NULL); + + if (!strcmp(name, "history")) { + assert(_current_update == NULL); + + _state = PARSER_PACKAGE; + } + } + + + void + XmlParser::updateEnd(const char *name) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::updateEnd(%s)\n", name); + + constChannelPtr channel; + const char *url_prefix = NULL; + + assert(_current_package != NULL); + assert(_current_update != NULL); + + channel = _current_package->channel(); + + if (channel != NULL) { + url_prefix = channel->filePath (); + } + + if (!strcmp(name, "update")) { + _current_package->addUpdate(_current_update); + + _current_update = NULL; + _state = PARSER_HISTORY; + + } else if (!strcmp(name, "epoch")) { _current_update->setEpoch (atoi(_text_buffer)); + } else if (!strcmp(name, "version")) { _current_update->setVersion (strstrip (_text_buffer)); + } else if (!strcmp(name, "release")) { _current_update->setRelease (strstrip (_text_buffer)); + } else if (!strcmp(name, "arch")) { _current_update->setArch (strstrip (_text_buffer)); + } else if (!strcmp(name, "filename")) { + strstrip (_text_buffer); + if (url_prefix) { + _current_update->setPackageUrl (maybe_merge_paths(url_prefix, _text_buffer)); + } + else { + _current_update->setPackageUrl (_text_buffer); + } + } else if (!strcmp(name, "filesize")) { _current_update->setPackageSize (atoi(_text_buffer)); + } else if (!strcmp(name, "installedsize")) { _current_update->setInstalledSize (atoi (_text_buffer)); + } else if (!strcmp(name, "signaturename")) { + strstrip (_text_buffer); + if (url_prefix) { + _current_update->setSignatureUrl (maybe_merge_paths(url_prefix, _text_buffer)); + } + else { + _current_update->setSignatureUrl (_text_buffer); + } + } else if (!strcmp(name, "signaturesize")) { _current_update->setSignatureSize (atoi (_text_buffer)); + } else if (!strcmp(name, "md5sum")) { _current_update->setMd5sum (strstrip (_text_buffer)); + } else if (!strcmp(name, "importance")) { _current_update->setImportance (new Importance (strstrip (_text_buffer))); + } else if (!strcmp(name, "description")) { _current_update->setDescription (strstrip (_text_buffer)); + } else if (!strcmp(name, "hid")) { _current_update->setHid (atoi(_text_buffer)); + } else if (!strcmp (name, "license")) { _current_update->setLicense (strstrip (_text_buffer)); + } else { + fprintf (stderr, "XmlParser::updateEnd(%s) unknown\n", name); + } + + // if (_current_update != NULL && getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::updateEnd(%s) => '%s'\n", name, _current_update->asString().c_str()); + + releaseBuffer(); + + } + + + void + XmlParser::dependencyEnd(const char *name) + { + // if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::dependencyEnd(%s)\n", name); + + if (!strcmp(name, "or")) { + OrDependencyPtr or_dep = OrDependency::fromDependencyList (*_current_dep_list); + DependencyPtr dep = new Dependency (or_dep); + + (*_current_dep_list).clear(); + + (*_toplevel_dep_list).push_back (dep); + _current_dep_list = _toplevel_dep_list; + } + else if (!strcmp(name, "dep")) { + /* We handled everything we needed for dep in start */ + } + else { + /* All of the dep lists (requires, provides, etc.) */ + _toplevel_dep_list = NULL; + _current_dep_list = NULL; + _state = PARSER_PACKAGE; + } + } + + + + //=================================================================================================================== + + #if 0 + //--------------------------------------------------------------------------- + + /* ------ */ + + + static RCResItemDep * + rc_xml_node_to_resItem_dep_internal (const xmlNode *node) + { + gchar *name = NULL, *version = NULL, *release = NULL; + gboolean has_epoch = false; + guint32 epoch = 0; + RCResItemRelation relation; + RCResItemDep *dep; + + gchar *tmp; + + if (g_strcasecmp (node->name, "dep")) { + return (NULL); + } + + name = xml_get_prop (node, "name"); + tmp = xml_get_prop (node, "op"); + if (tmp) { + relation = rc_resItem_relation_from_string (tmp); + + has_epoch = xml_get_guint32_value (node, "epoch", &epoch); + + version = xml_get_prop (node, "version"); + release = xml_get_prop (node, "release"); + } else { + relation = RC_RELATION_ANY; + } + + /* FIXME: should get channel from XML */ + dep = rc_resItem_dep_new (name, has_epoch, epoch, version, release, + relation, RC_TYPE_RESOLVABLE, RC_CHANNEL_ANY, + false, false); + + g_free (tmp); + g_free (name); + g_free (version); + g_free (release); + + return dep; + } /* rc_xml_node_to_resItem_dep_internal */ + + RCResItemDep * + rc_xml_node_to_resItem_dep (const xmlNode *node) + { + RCResItemDep *dep = NULL; + + if (!g_strcasecmp (node->name, "dep")) { + dep = rc_xml_node_to_resItem_dep_internal (node); + return (dep); + } else if (!g_strcasecmp (node->name, "or")) { + RCResItemDepSList *or_dep_slist = NULL; + RCDepOr *or; + xmlNode *iter = node->xmlChildrenNode; + + while (iter) { + if (iter->type == XML_ELEMENT_NODE) { + or_dep_slist = g_slist_append( + or_dep_slist, + rc_xml_node_to_resItem_dep_internal (iter)); + } + + iter = iter->next; + } + + or = rc_dep_or_new (or_dep_slist); + dep = rc_dep_or_new_provide (or); + } + + return (dep); + } /* rc_xml_node_to_resItem_dep */ + + /* ------ */ + + /* This hack cleans 8-bit characters out of a string. This is a very + problematic "solution" to the problem of non-UTF-8 package info. */ + static gchar * + sanitize_string (const char *str) + { + gchar *dup = g_strdup (str); + gchar *c; + + return dup; + + if (dup) { + for (c = dup; *c; ++c) { + if ((guint)*c > 0x7f) + *c = '_'; + } + } + + return dup; + } + + #endif + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/XmlParser.h b/zypp/solver/detail/XmlParser.h index a128df1..4a41052 100644 --- a/zypp/solver/detail/XmlParser.h +++ b/zypp/solver/detail/XmlParser.h @@ -32,109 +32,122 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////// -// -// CLASS NAME : XmlParser - -class XmlParser -{ - public: - enum _XmlParserState { - PARSER_TOPLEVEL = 0, - PARSER_PACKAGE, - PARSER_HISTORY, - PARSER_UPDATE, - PARSER_DEP, - }; - typedef enum _XmlParserState XmlParserState; - - private: - constChannelPtr _channel; - bool _processing; - xmlParserCtxtPtr _xml_context; - XmlParserState _state; - - PackageList _all_packages; - - /* Temporary state */ - PackagePtr _current_package; - CDependencyList _current_requires; - CDependencyList _current_provides; - CDependencyList _current_conflicts; - CDependencyList _current_children; - CDependencyList _current_recommends; - CDependencyList _current_suggests; - CDependencyList _current_obsoletes; - PackageUpdatePtr _current_update; - - // these point to one of the above lists during dependency parsing - CDependencyList *_toplevel_dep_list; - CDependencyList *_current_dep_list; - - char *_text_buffer; - size_t _text_buffer_size; - - protected: - void setState (XmlParserState state) { _state = state; } - - public: - - XmlParser (constChannelPtr channel); - virtual ~XmlParser(); - - // ---------------------------------- I/O - - static std::string toString ( const XmlParser & parser); - - virtual std::ostream & dumpOn( std::ostream & str ) const; - - friend std::ostream& operator<<( std::ostream & str, const XmlParser & parser); - - std::string asString ( void ) const; - - // ---------------------------------- accessors - - bool processing() const { return _processing; } - void setProcessing (bool processing) { _processing = processing; } - - XmlParserState state (void) const { return _state; } - -#if 0 // are they needed ? - constChannelPtr channel() const { return _channel; } - void setChannel (constChannelPtr channel) { _channel = channel; } - - xmlParserCtxtPtr xmlContext() const { return _xml_context; } - void setXmlContext (xmlParserCtxtPtr xml_context) { _xml_context = xml_context; } -#endif - // ---------------------------------- methods - - void toBuffer (const char *data, size_t size); - void releaseBuffer (void); // free _text_buffer - - void startElement(const char *name, const xmlChar **attrs); - void endElement(const char *name); - - void toplevelStart(const char *name, const xmlChar **attrs); - void packageStart(const char *name, const xmlChar **attrs); - void historyStart(const char *name, const xmlChar **attrs); - void dependencyStart(const char *name, const xmlChar **attrs); - - void updateEnd(const char *name); - void packageEnd(const char *name); - void historyEnd(const char *name); - void dependencyEnd(const char *name); - - void parseChunk (const char *xmlbuf, size_t size); - PackageList done (void); -}; - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : XmlParser + + class XmlParser + { + public: + enum _XmlParserState { + PARSER_TOPLEVEL = 0, + PARSER_PACKAGE, + PARSER_HISTORY, + PARSER_UPDATE, + PARSER_DEP, + }; + typedef enum _XmlParserState XmlParserState; + + private: + constChannelPtr _channel; + bool _processing; + xmlParserCtxtPtr _xml_context; + XmlParserState _state; + + PackageList _all_packages; + + /* Temporary state */ + PackagePtr _current_package; + CDependencyList _current_requires; + CDependencyList _current_provides; + CDependencyList _current_conflicts; + CDependencyList _current_children; + CDependencyList _current_recommends; + CDependencyList _current_suggests; + CDependencyList _current_obsoletes; + PackageUpdatePtr _current_update; + + // these point to one of the above lists during dependency parsing + CDependencyList *_toplevel_dep_list; + CDependencyList *_current_dep_list; + + char *_text_buffer; + size_t _text_buffer_size; + + protected: + void setState (XmlParserState state) { _state = state; } + + public: + + XmlParser (constChannelPtr channel); + virtual ~XmlParser(); + + // ---------------------------------- I/O + + static std::string toString ( const XmlParser & parser); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream & str, const XmlParser & parser); + + std::string asString ( void ) const; + + // ---------------------------------- accessors + + bool processing() const { return _processing; } + void setProcessing (bool processing) { _processing = processing; } + + XmlParserState state (void) const { return _state; } + + #if 0 // are they needed ? + constChannelPtr channel() const { return _channel; } + void setChannel (constChannelPtr channel) { _channel = channel; } + + xmlParserCtxtPtr xmlContext() const { return _xml_context; } + void setXmlContext (xmlParserCtxtPtr xml_context) { _xml_context = xml_context; } + #endif + // ---------------------------------- methods + + void toBuffer (const char *data, size_t size); + void releaseBuffer (void); // free _text_buffer + + void startElement(const char *name, const xmlChar **attrs); + void endElement(const char *name); + + void toplevelStart(const char *name, const xmlChar **attrs); + void packageStart(const char *name, const xmlChar **attrs); + void historyStart(const char *name, const xmlChar **attrs); + void dependencyStart(const char *name, const xmlChar **attrs); + + void updateEnd(const char *name); + void packageEnd(const char *name); + void historyEnd(const char *name); + void dependencyEnd(const char *name); + + void parseChunk (const char *xmlbuf, size_t size); + PackageList done (void); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif // _XmlParser_h diff --git a/zypp/solver/detail/extract.cc b/zypp/solver/detail/extract.cc index f04e821..156d0d8 100644 --- a/zypp/solver/detail/extract.cc +++ b/zypp/solver/detail/extract.cc @@ -29,922 +29,934 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - - -int -extract_packages_from_xml_node (XmlNodePtr node, ChannelPtr channel, CResItemFn callback, void *data) -{ - PackagePtr package; - int count = 0; - - if (getenv ("RC_SPEW_XML")) fprintf (stderr, "extract_packages_from_xml_node ()\n"); - // search the 'package' node - - while (node && !node->equals("package")) { - if (!node->isElement()) { - node = node->next(); - continue; - } - - node = node->children(); - } - - // extract the 'package' node, if found - - while (node) { - if (node->equals("package")) { - package = new Package (node, channel); - if (package) { - if (getenv ("RC_SPEW")) fprintf (stderr, "%s\n", package->asString(true).c_str()); - bool ok = true; - if (callback) - ok = callback (package, data); - if (! ok) - return -1; - ++count; - } - } - node = node->next(); - } - - return count; -} - - -int -extract_packages_from_helix_buffer (const char *buf, size_t len, ChannelPtr channel, CResItemFn callback, void *data) -{ - unsigned int count = 0; - PackageList packages; - - if (getenv ("RC_SPEW_XML")) fprintf (stderr, "extract_packages_from_helix_buffer(%.32s...,%ld,...)\n", buf, (long)len); - - if (buf == NULL || len == 0) - return 0; - - XmlParser parser (channel); - parser.parseChunk (buf, len); - packages = parser.done (); - - if (packages.empty()) - return 0; - - count = packages.size(); - - if (getenv ("RC_SPEW_XML")) fprintf (stderr, "extract_packages_from_helix_buffer: parsed %d packages\n", count); - - if (callback != NULL) { - for (PackageList::iterator iter = packages.begin(); iter != packages.end(); iter++) { - callback (*iter, data); - } - } - - return count; -} - - -int -extract_packages_from_helix_file (const string & filename, ChannelPtr channel, CResItemFn callback, void *data) -{ - Buffer *buf; - int count; - - if (filename.empty()) - return -1; - - buf = buffer_map_file (filename); - if (buf == NULL) - return -1; - - count = extract_packages_from_helix_buffer ((const char *)(buf->data), buf->size, channel, callback, data); - - buffer_unmap_file (buf); - - return count; -} - - -int -extract_packages_from_undump_buffer (const char *buf, size_t len, ChannelAndSubscribedFn channel_callback, CResItemFn resItem_callback, MatchFn lock_callback, void *data) -{ - xmlDoc *doc; - XmlNodePtr dump_node; - ChannelPtr system_channel = NULL; - ChannelPtr current_channel = NULL; - XmlNodePtr channel_node; - int count = 0; - - doc = parse_xml_from_buffer (buf, len); - if (doc == NULL) - return -1; - - dump_node = new XmlNode (xmlDocGetRootElement (doc)); - if (dump_node == NULL) - return -1; - - if (!dump_node->equals("world")) { - debug (DEBUG_LEVEL_WARNING, "Unrecognized top-level node for undump: '%s'", dump_node->name()); - return -1; - } - - channel_node = dump_node->children(); - - while (channel_node != NULL) { - - if (channel_node->equals("locks")) { - XmlNodePtr lock_node = channel_node->children(); - - while (lock_node) { - MatchPtr lock; - - lock = new Match (lock_node); - - if (lock_callback) - lock_callback (lock, data); - - lock_node = lock_node->next(); - } - - } else if (channel_node->equals("system_packages")) { - - int subcount; - - if (!system_channel) { - system_channel = new Channel ("@system", "System Packages", "@system", "System Packages"); - system_channel->setSystem (true); - system_channel->setHidden (true); - } - - if (channel_callback) { - channel_callback (system_channel, false, data); - } - - subcount = extract_packages_from_xml_node (channel_node, system_channel, resItem_callback, data); - - if (subcount < 0) { - /* Do something clever */ - fprintf (stderr, "No packages found\n"); - abort (); - } - - count += subcount; - - } else if (channel_node->equals("channel")) { - - int subscribed; - current_channel = new Channel (channel_node, &subscribed, (World *)data); - - if (channel_callback) { - channel_callback (current_channel, subscribed != 0, data); - } - - if (resItem_callback) { - int subcount; - subcount = extract_packages_from_xml_node (channel_node, current_channel, resItem_callback, data); - if (subcount < 0) { - /* FIXME: do something clever */ - fprintf (stderr, "No packages found\n"); - abort (); - } - count += subcount; - } - } - - channel_node = channel_node->next(); - } - - xmlFreeDoc (doc); - - return count; -} - - -int -extract_packages_from_undump_file (const string & filename, ChannelAndSubscribedFn channel_callback, CResItemFn resItem_callback, MatchFn lock_callback, void *data) -{ - Buffer *buf; - int count; - - if (filename.empty()) - return -1; - - buf = buffer_map_file (filename); - if (buf == NULL) - return -1; - - count = extract_packages_from_undump_buffer ((const char *)(buf->data), buf->size, channel_callback, resItem_callback, lock_callback, data); - - buffer_unmap_file (buf); - - return count; -} - -#if 0 -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -static ResItemPtr -fill_debian_package (const char *buf, const char *url_prefix, int *off) -{ - const char *ibuf; - RCPackageUpdate *up = NULL; - ResItemPtr r; - ResItemList requires, provides, conflicts, suggests, recommends; - - up = rc_package_update_new (); - - ibuf = buf; - while (1) { - char *key; - GString *value = NULL; - const char *p; - int ind; - - /* Linebreaks indicate the end of a package block. */ - if (*ibuf == '\0' || *ibuf == '\n') break; - - p = strchr (ibuf, ':'); - - /* Something bad happened, we're supposed to have a colon. */ - if (!p) break; - - /* Copy the name of the key and lowercase it */ - key = g_ascii_strdown (ibuf, p - ibuf); - - /* Move past the colon and any spaces */ - ibuf = p; - while (*ibuf && (*ibuf == ':' || *ibuf == ' ')) ibuf++; - - ind = 0; - while ((p = strchr (ibuf, '\n'))) { - if (!value) - value = g_string_new (""); - - g_string_append_len (value, ibuf, p - ibuf); - ind += p - ibuf; - - ibuf = p; - - /* Move past the newline */ - ibuf++; - - /* Check to see if this is a continuation of the previous line */ - if (*ibuf == ' ') { - /* It is. Move past the space */ - ibuf++; - - /* - * This is a hack. Description is special because it's - * intended to be multiline and user-visible. So if we're - * dealing with description, add a newline. - */ - - if (strncmp (key, "description", - strlen ("description")) == 0) { - g_string_append_c (value, '\n'); - - /* - * A period on a line by itself indicates that it - * should be a blank line. A newline will follow the - * period, so we'll just skip over it. - */ - if (*ibuf == '.') - ibuf++; - } - } - else { - /* It isn't. Break out. */ - break; - } - } - - if (!strncmp (key, "package", strlen ("package"))) { - rc_resItem_spec_set_name (RC_RESOLVABLE_SPEC (pkg), value->str); - } else if (!strncmp (key, "installed-size", - strlen ("installed-size"))) { - up->installed_size = strtoul (value->str, NULL, 10) * 1024; - } else if (!strncmp (key, "size", strlen ("size"))) { - up->package_size = strtoul(value->str, NULL, 10); - } else if (!strncmp (key, "description", strlen ("description"))) { - char *newline; - - /* - * We only want the first line for the summary, and all the - * other lines for the description. - */ - - newline = strchr (value->str, '\n'); - if (!newline) { - pkg->summary = strdup (value->str); - pkg->description = g_strconcat (value->str, "\n", NULL); - } - else { - pkg->summary = g_strndup (value->str, newline - value->str); - pkg->description = g_strconcat (newline + 1, "\n", NULL); - } - } else if (!strncmp (key, "version", strlen ("version"))) { - RCResItemSpec *spec = RC_RESOLVABLE_SPEC (pkg); - rc_version_parse (value->str, spec); - } else if (!strncmp (key, "section", strlen ("section"))) { - pkg->section = rc_debman_section_to_package_section (value->str); - } else if (!strncmp (key, "depends", strlen ("depends"))) { - requires = g_slist_concat ( - requires, - rc_debman_fill_depends (value->str, false)); - } else if (!strncmp (key, "recommends", strlen ("recommends"))) { - recommends = g_slist_concat ( - recommends, - rc_debman_fill_depends (value->str, false)); - } else if (!strncmp (key, "suggests", strlen ("suggests"))) { - suggests = g_slist_concat ( - suggests, - rc_debman_fill_depends (value->str, false)); - } else if (!strncmp (key, "pre-depends", strlen ("pre-depends"))) { - requires = g_slist_concat ( - requires, - rc_debman_fill_depends (value->str, true)); - } else if (!strncmp (key, "conflicts", strlen ("conflicts"))) { - conflicts = g_slist_concat ( - conflicts, - rc_debman_fill_depends (value->str, false)); - } else if (!strncmp (key, "provides", strlen ("provides"))) { - provides = g_slist_concat ( - provides, - rc_debman_fill_depends (value->str, false)); - } else if (!strncmp (key, "filename", strlen ("filename"))) { - /* Build a new update with just this version */ - if (url_prefix) { - up->package_url = g_strconcat (url_prefix, "/", - value->str, - NULL); - } else { - up->package_url = strdup (value->str); - } - } else if (!strncmp (key, "md5sum", strlen ("md5sum"))) { - up->md5sum = strdup (value->str); - } else if (!strncmp (key, "architecture", strlen ("architecture"))) { - rc_resItem_spec_set_arch (RC_RESOLVABLE_SPEC (pkg), rc_arch_from_string (value->str)); - } - - g_string_free (value, true); - } - - up->importance = RC_IMPORTANCE_SUGGESTED; - up->description = strdup ("Upstream Debian release"); - rc_resItem_spec_copy (rc_package_update_get_spec(up), RC_RESOLVABLE_SPEC (pkg)); - rc_package_add_update (pkg, up); - - r = RC_RESOLVABLE (pkg); - - /* Make sure to provide myself, for the dep code! */ - provides = g_slist_append (provides, rc_resItem_dep_new_from_spec - (RC_RESOLVABLE_SPEC (pkg), - RC_RELATION_EQUAL, - RC_TYPE_PACKAGE, - rc_resItem_get_channel (r), - false, false)); - - rc_resItem_set_requires (r, requires); - rc_resItem_set_provides (r, provides); - rc_resItem_set_conflicts (r, conflicts); - rc_resItem_set_obsoletes (r, NULL); - rc_resItem_set_suggests (r, suggests); - rc_resItem_set_recommends(r, recommends); - /* returns the number of characters we processed */ - return ibuf - buf; -} - -#endif - -int -extract_packages_from_debian_buffer (const char *buf, size_t len, ChannelPtr channel, CResItemFn callback, void *data) -{ - const char *pos; - int count = 0; - - /* Keep looking for a "Package: " */ - pos = buf; -#if 0 - while ((pos = strstr (pos, "Package: ")) != NULL) { - int off; - - /* All debian packages "have" epochs */ - ResItemPtr resItem = fill_debian_package (iter, channel->getFilePath (), &off); - - resItem->setEpoch (0); - resItem->setArch (Arch::Noarch); - resItem->setChannel (channel); - - if (callback) - callback (resItem, data); - - ++count; - - iter += off; - } -#endif - return count; -} - - -int -extract_packages_from_debian_file (const string & filename, ChannelPtr channel, CResItemFn callback, void *data) -{ - Buffer *buf; - int count; - - if (filename.empty()) - return -1; - - buf = buffer_map_file (filename); - if (buf == NULL) - return -1; - - count = extract_packages_from_debian_buffer ((const char *)(buf->data), buf->size, channel, callback, data); - buffer_unmap_file (buf); - - return count; -} - -#if 0 -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -PackagePtr -extract_yum_package (const guint8 *data, size_t len, - RCPackman *packman, char *url) -{ -#ifndef ENABLE_RPM - /* We can't support yum without rpm support */ - debug (RC_DEBUG_LEVEL_ERROR, "RPM support is not enabled"); - return NULL; -#else - RCRpmman *rpmman; - Header h; - PackagePtr p; - RCPackageUpdate *pu; - char *tmpc; - int typ, n; - - g_return_val_if_fail (packman != NULL, NULL); - - if (!g_type_is_a (G_TYPE_FROM_INSTANCE (packman), RC_TYPE_RPMMAN)) { - debug (RC_DEBUG_LEVEL_ERROR, - "yum support is not available on non-RPM systems"); - return NULL; - } - - rpmman = RC_RPMMAN (packman); - - h = rpmman->headerLoad (data); - - if (h == NULL) { - debug (RC_DEBUG_LEVEL_ERROR, - "Unable to get header from headerCopyLoad!"); - return NULL; - } - - rpmman->headerGetEntry (h, RPMTAG_ARCH, &typ, (void **) &tmpc, &n); - - p = rc_package_new (); - - rc_rpmman_read_header (rpmman, h, p); - rc_rpmman_depends_fill (rpmman, h, p, true); - - pu = rc_package_update_new (); - rc_resItem_spec_copy (rc_package_update_get_spec (pu), RC_RESOLVABLE_SPEC (p)); - pu->importance = RC_IMPORTANCE_SUGGESTED; - pu->description = strdup ("No information available."); - pu->package_url = url; - - p->history = g_slist_append (p->history, pu); - - rpmman->headerFree (h); - - return p; -#endif -} - -int -extract_packages_from_aptrpm_buffer (const guint8 *data, size_t len, - RCPackman *packman, - ChannelPtr channel, - CResItemFn callback, - void * user_data) -{ -#ifndef ENABLE_RPM - /* We can't support apt-rpm without rpm support */ - debug (RC_DEBUG_LEVEL_ERROR, "RPM support is not enabled"); - return -1; -#else - RCRpmman *rpmman; - int count = 0; - const int hdrmagic_len = 8; - const char *hdrmagic; - const guint8 *cur_ptr; - RCResItemSpec *spec; - - - g_return_val_if_fail (packman != NULL, -1); - - if (!g_type_is_a (G_TYPE_FROM_INSTANCE (packman), RC_TYPE_RPMMAN)) { - debug (RC_DEBUG_LEVEL_ERROR, - "apt-rpm support is not available on non-RPM systems"); - return -1; - } - - rpmman = RC_RPMMAN (packman); - - if (len < hdrmagic_len) { - debug (RC_DEBUG_LEVEL_ERROR, - "Data is too small to possibly be correct"); - return 0; - } - - /* - * The apt-rpm pkglist files are a set of rpm headers, each prefixed - * with the header magic, one right after the other. If opened on disk, - * they can be iterated using headerRead(). Since we have an in-memory - * buffer, we use headerCopyLoad to read them. We could, potentially, - * use headerLoad(); but I'm unsure as to what happens when headerFree - * is called on a Header returned from headerLoad. It may be a small - * memory savings to do so. - */ - - /* Skip the inital RPM header magic */ - hdrmagic = data; - cur_ptr = data + hdrmagic_len; - - while (cur_ptr != NULL) { - Header h; - PackagePtr p; - RCPackageUpdate *pu; - int bytesleft, i; - char *tmpc; - int typ, n; - char *archstr; - - h = rpmman->headerLoad (cur_ptr); - - if (h == NULL) { - debug (RC_DEBUG_LEVEL_ERROR, - "Unable to get header from headerCopyLoad!"); - return 0; - } - - rpmman->headerGetEntry (h, RPMTAG_ARCH, &typ, (void **) &tmpc, &n); - - if (n && typ == RPM_STRING_TYPE) - archstr = tmpc; - else { - debug (RC_DEBUG_LEVEL_WARNING, "No arch available!"); - goto cleanup; - } - - p = rc_package_new (); - - rc_rpmman_read_header (rpmman, h, p); - rc_rpmman_depends_fill (rpmman, h, p, true); - - rc_resItem_set_channel (RC_RESOLVABLE (p), channel); - - pu = rc_package_update_new (); - rc_resItem_spec_copy (rc_package_update_get_spec (pu), RC_RESOLVABLE_SPEC (p)); - pu->importance = RC_IMPORTANCE_SUGGESTED; - pu->description = strdup ("No information available."); - - /* Build a filename from the spec */ - spec = RC_RESOLVABLE_SPEC (p); - pu->package_url = strdup_printf ("%s/%s-%s-%s.%s.rpm", - rc_channel_get_file_path (channel), - rc_resItem_spec_get_name (spec), - rc_resItem_spec_get_version (spec), - rc_resItem_spec_get_release (spec), - archstr); - - p->history = g_slist_append (p->history, pu); - - if (callback) - callback ((RCResItem *) p, user_data); - - g_object_unref (p); - - ++count; - - cleanup: - rpmman->headerFree (h); - - /* This chunk of ugly could be removed if a) memmem() was portable; - * or b) if rpmlib didn't suck, and I could figure out how much - * data it read from the buffer. - */ - bytesleft = len - (cur_ptr - data); - for (i = 0; i < bytesleft - hdrmagic_len; i++) { - if (memcmp (cur_ptr + i, hdrmagic, hdrmagic_len) == 0) { - /* We found a match */ - cur_ptr = cur_ptr + i + hdrmagic_len; - break; - } - } - - if (i >= bytesleft - hdrmagic_len) { - /* No match was found */ - cur_ptr = NULL; - } - } - - return count; -#endif -} - -int -extract_packages_from_aptrpm_file (const char *filename, - RCPackman *packman, - ChannelPtr channel, - CResItemFn callback, - void * user_data) -{ - WorldPtr world = *((WorldPtr *)data); - RCBuffer *buf; - int count; - - g_return_val_if_fail (filename != NULL, -1); - g_return_val_if_fail (packman != NULL, -1); - - buf = rc_buffer_map_file (filename); - if (buf == NULL) - return -1; - - count = extract_packages_from_aptrpm_buffer (buf->data, buf->size, - packman, channel, - callback, user_data); - - rc_buffer_unmap_file (buf); - - return count; -} - -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -static void -package_into_hash (PackagePtr pkg, GHashTable *hash) -{ - void * nameq; - PackagePtr hashed_pkg; - - nameq = GINT_TO_POINTER (RC_RESOLVABLE_SPEC (pkg)->nameq); - hashed_pkg = g_hash_table_lookup (hash, nameq); - if (hashed_pkg == NULL) { - g_hash_table_insert (hash, nameq, g_object_ref (pkg)); - } else if (rc_version_compare (RC_RESOLVABLE_SPEC (pkg), - RC_RESOLVABLE_SPEC (hashed_pkg)) > 0) { - g_hash_table_replace (hash, nameq, g_object_ref (pkg)); - g_object_unref (hashed_pkg); - } -} - -static bool -hash_recurse_cb (PackagePtr pkg, void * user_data) -{ - GHashTable *hash = user_data; - package_into_hash (pkg, hash); - return true; -} - -struct HashIterInfo { - CResItemFn callback; - void * user_data; - int count; -}; - -static void -hash_iter_cb (void * key, void * val, void * user_data) -{ - RCResItem *r = val; - struct HashIterInfo *info = user_data; - - if (info->callback) - info->callback (r, info->user_data); - - g_object_unref (r); - ++info->count; -} - - -static void -add_fake_history (PackagePtr pkg) -{ - RCPackageUpdate *up; - - up = rc_package_update_new (); - rc_resItem_spec_copy ((RCResItemSpec *) up, - RC_RESOLVABLE_SPEC (pkg)); - up->importance = RC_IMPORTANCE_SUGGESTED; - rc_package_add_update (pkg, up); -} - -typedef struct { - CResItemFn user_callback; - void * user_data; - const gchar *path; -} PackagesFromDirInfo; - -static bool -packages_from_dir_cb (PackagePtr package, void * user_data) -{ - PackagesFromDirInfo *info = user_data; - RCPackageUpdate *update; - - /* Set package path */ - update = rc_package_get_latest_update (package); - if (update && update->package_url) - package->package_filename = g_build_path (G_DIR_SEPARATOR_S, - info->path, - update->package_url, - NULL); - if (info->user_callback) - return info->user_callback ((RCResItem *)package, info->user_data); - - return true; -} - -int -extract_packages_from_directory (const char *path, - ChannelPtr channel, - RCPackman *packman, - bool recursive, - CResItemFn callback, - void * user_data) -{ - WorldPtr world = *((WorldPtr *)data); - GDir *dir; - GHashTable *hash; - struct HashIterInfo info; - const char *filename; - char *magic; - bool distro_magic, pkginfo_magic; - - g_return_val_if_fail (path && *path, -1); - g_return_val_if_fail (channel != NULL, -1); - - /* - Check for magic files that indicate how to treat the - directory. The files aren't read -- it is sufficient that - they exist. - */ - - magic = g_strconcat (path, "/RC_SKIP", NULL); - if (g_file_test (magic, G_FILE_TEST_EXISTS)) { - g_free (magic); - return 0; - } - g_free (magic); - - magic = g_strconcat (path, "/RC_RECURSIVE", NULL); - if (g_file_test (magic, G_FILE_TEST_EXISTS)) - recursive = true; - g_free (magic); - - magic = g_strconcat (path, "/RC_BY_DISTRO", NULL); - distro_magic = g_file_test (magic, G_FILE_TEST_EXISTS); - g_free (magic); - - pkginfo_magic = true; - magic = g_strconcat (path, "/RC_IGNORE_PKGINFO", NULL); - if (g_file_test (magic, G_FILE_TEST_EXISTS)) - pkginfo_magic = false; - g_free (magic); - - /* If distro_magic is set, we search for packages in two - subdirectories of path: path/distro-target (i.e. - path/redhat-9-i386) and path/x-cross. - */ - -#if 0 - if (distro_magic) { - char *distro_path, *cross_distro_path; - bool found_distro_magic = false; - int count = 0, c; - - distro_path = g_strconcat (path, "/", rc_distro_get_target (), NULL); - if (g_file_test (distro_path, G_FILE_TEST_IS_DIR)) { - found_distro_magic = true; - - c = extract_packages_from_directory (distro_path, - channel, packman, - callback, user_data); - if (c >= 0) - count += c; - } - - cross_distro_path = g_strconcat (path, "/x-distro", NULL); - if (g_file_test (cross_distro_path, G_FILE_TEST_IS_DIR)) { - c = extract_packages_from_directory (cross_distro_path, - channel, packman, - callback, user_data); - if (c >= 0) - count += c; - } - - g_free (cross_distro_path); - g_free (distro_path); - - return count; - } -#endif - - /* If pkginfo_magic is set and if a packageinfo.xml or - packageinfo.xml.gz file exists in the directory, use it - instead of just scanning the files in the directory - looking for packages. */ - - if (pkginfo_magic) { - int i, count; - gchar *pkginfo_path = NULL; - const gchar *pkginfo[] = { "packageinfo.xml", - "packageinfo.xml.gz", - NULL }; - - for (i = 0; pkginfo[i]; i++) { - pkginfo_path = g_build_path (G_DIR_SEPARATOR_S, path, pkginfo[i], NULL); - if (g_file_test (pkginfo_path, G_FILE_TEST_EXISTS)) - break; - - g_free (pkginfo_path); - pkginfo_path = NULL; - } - - if (pkginfo_path) { - PackagesFromDirInfo info; - - info.user_callback = callback; - info.user_data = user_data; - info.path = path; - - count = extract_packages_from_helix_file (pkginfo_path, channel, packages_from_dir_cb, &info); - g_free (pkginfo_path); - return count; - } - } - - dir = g_dir_open (path, 0, NULL); - if (dir == NULL) - return -1; - - hash = g_hash_table_new (NULL, NULL); - - while ( (filename = g_dir_read_name (dir)) ) { - gchar *file_path; - - file_path = g_strconcat (path, "/", filename, NULL); - - if (recursive && g_file_test (file_path, G_FILE_TEST_IS_DIR)) { - extract_packages_from_directory (file_path, - channel, - packman, - true, - hash_recurse_cb, - hash); - } else if (g_file_test (file_path, G_FILE_TEST_IS_REGULAR)) { - PackagePtr pkg; - - pkg = rc_packman_query_file (packman, file_path, true); - if (pkg != NULL) { - rc_resItem_set_channel (RC_RESOLVABLE (pkg), channel); - pkg->package_filename = strdup (file_path); - pkg->local_package = false; - add_fake_history (pkg); - package_into_hash (pkg, hash); - g_object_unref (pkg); - } - } - - g_free (file_path); - } - - g_dir_close (dir); - - info.callback = callback; - info.user_data = user_data; - info.count = 0; - - /* Walk across the hash and: - 1) Invoke the callback on each package - 2) Unref each package - */ - g_hash_table_foreach (hash, hash_iter_cb, &info); - - g_hash_table_destroy (hash); - - return info.count; -} -#endif - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + + int + extract_packages_from_xml_node (XmlNodePtr node, ChannelPtr channel, CResItemFn callback, void *data) + { + PackagePtr package; + int count = 0; + + if (getenv ("RC_SPEW_XML")) fprintf (stderr, "extract_packages_from_xml_node ()\n"); + // search the 'package' node + + while (node && !node->equals("package")) { + if (!node->isElement()) { + node = node->next(); + continue; + } + + node = node->children(); + } + + // extract the 'package' node, if found + + while (node) { + if (node->equals("package")) { + package = new Package (node, channel); + if (package) { + if (getenv ("RC_SPEW")) fprintf (stderr, "%s\n", package->asString(true).c_str()); + bool ok = true; + if (callback) + ok = callback (package, data); + if (! ok) + return -1; + ++count; + } + } + node = node->next(); + } + + return count; + } + + + int + extract_packages_from_helix_buffer (const char *buf, size_t len, ChannelPtr channel, CResItemFn callback, void *data) + { + unsigned int count = 0; + PackageList packages; + + if (getenv ("RC_SPEW_XML")) fprintf (stderr, "extract_packages_from_helix_buffer(%.32s...,%ld,...)\n", buf, (long)len); + + if (buf == NULL || len == 0) + return 0; + + XmlParser parser (channel); + parser.parseChunk (buf, len); + packages = parser.done (); + + if (packages.empty()) + return 0; + + count = packages.size(); + + if (getenv ("RC_SPEW_XML")) fprintf (stderr, "extract_packages_from_helix_buffer: parsed %d packages\n", count); + + if (callback != NULL) { + for (PackageList::iterator iter = packages.begin(); iter != packages.end(); iter++) { + callback (*iter, data); + } + } + + return count; + } + + + int + extract_packages_from_helix_file (const string & filename, ChannelPtr channel, CResItemFn callback, void *data) + { + Buffer *buf; + int count; + + if (filename.empty()) + return -1; + + buf = buffer_map_file (filename); + if (buf == NULL) + return -1; + + count = extract_packages_from_helix_buffer ((const char *)(buf->data), buf->size, channel, callback, data); + + buffer_unmap_file (buf); + + return count; + } + + + int + extract_packages_from_undump_buffer (const char *buf, size_t len, ChannelAndSubscribedFn channel_callback, CResItemFn resItem_callback, MatchFn lock_callback, void *data) + { + xmlDoc *doc; + XmlNodePtr dump_node; + ChannelPtr system_channel = NULL; + ChannelPtr current_channel = NULL; + XmlNodePtr channel_node; + int count = 0; + + doc = parse_xml_from_buffer (buf, len); + if (doc == NULL) + return -1; + + dump_node = new XmlNode (xmlDocGetRootElement (doc)); + if (dump_node == NULL) + return -1; + + if (!dump_node->equals("world")) { + debug (DEBUG_LEVEL_WARNING, "Unrecognized top-level node for undump: '%s'", dump_node->name()); + return -1; + } + + channel_node = dump_node->children(); + + while (channel_node != NULL) { + + if (channel_node->equals("locks")) { + XmlNodePtr lock_node = channel_node->children(); + + while (lock_node) { + MatchPtr lock; + + lock = new Match (lock_node); + + if (lock_callback) + lock_callback (lock, data); + + lock_node = lock_node->next(); + } + + } else if (channel_node->equals("system_packages")) { + + int subcount; + + if (!system_channel) { + system_channel = new Channel ("@system", "System Packages", "@system", "System Packages"); + system_channel->setSystem (true); + system_channel->setHidden (true); + } + + if (channel_callback) { + channel_callback (system_channel, false, data); + } + + subcount = extract_packages_from_xml_node (channel_node, system_channel, resItem_callback, data); + + if (subcount < 0) { + /* Do something clever */ + fprintf (stderr, "No packages found\n"); + abort (); + } + + count += subcount; + + } else if (channel_node->equals("channel")) { + + int subscribed; + current_channel = new Channel (channel_node, &subscribed, (World *)data); + + if (channel_callback) { + channel_callback (current_channel, subscribed != 0, data); + } + + if (resItem_callback) { + int subcount; + subcount = extract_packages_from_xml_node (channel_node, current_channel, resItem_callback, data); + if (subcount < 0) { + /* FIXME: do something clever */ + fprintf (stderr, "No packages found\n"); + abort (); + } + count += subcount; + } + } + + channel_node = channel_node->next(); + } + + xmlFreeDoc (doc); + + return count; + } + + + int + extract_packages_from_undump_file (const string & filename, ChannelAndSubscribedFn channel_callback, CResItemFn resItem_callback, MatchFn lock_callback, void *data) + { + Buffer *buf; + int count; + + if (filename.empty()) + return -1; + + buf = buffer_map_file (filename); + if (buf == NULL) + return -1; + + count = extract_packages_from_undump_buffer ((const char *)(buf->data), buf->size, channel_callback, resItem_callback, lock_callback, data); + + buffer_unmap_file (buf); + + return count; + } + + #if 0 + /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + + static ResItemPtr + fill_debian_package (const char *buf, const char *url_prefix, int *off) + { + const char *ibuf; + RCPackageUpdate *up = NULL; + ResItemPtr r; + ResItemList requires, provides, conflicts, suggests, recommends; + + up = rc_package_update_new (); + + ibuf = buf; + while (1) { + char *key; + GString *value = NULL; + const char *p; + int ind; + + /* Linebreaks indicate the end of a package block. */ + if (*ibuf == '\0' || *ibuf == '\n') break; + + p = strchr (ibuf, ':'); + + /* Something bad happened, we're supposed to have a colon. */ + if (!p) break; + + /* Copy the name of the key and lowercase it */ + key = g_ascii_strdown (ibuf, p - ibuf); + + /* Move past the colon and any spaces */ + ibuf = p; + while (*ibuf && (*ibuf == ':' || *ibuf == ' ')) ibuf++; + + ind = 0; + while ((p = strchr (ibuf, '\n'))) { + if (!value) + value = g_string_new (""); + + g_string_append_len (value, ibuf, p - ibuf); + ind += p - ibuf; + + ibuf = p; + + /* Move past the newline */ + ibuf++; + + /* Check to see if this is a continuation of the previous line */ + if (*ibuf == ' ') { + /* It is. Move past the space */ + ibuf++; + + /* + * This is a hack. Description is special because it's + * intended to be multiline and user-visible. So if we're + * dealing with description, add a newline. + */ + + if (strncmp (key, "description", + strlen ("description")) == 0) { + g_string_append_c (value, '\n'); + + /* + * A period on a line by itself indicates that it + * should be a blank line. A newline will follow the + * period, so we'll just skip over it. + */ + if (*ibuf == '.') + ibuf++; + } + } + else { + /* It isn't. Break out. */ + break; + } + } + + if (!strncmp (key, "package", strlen ("package"))) { + rc_resItem_spec_set_name (RC_RESOLVABLE_SPEC (pkg), value->str); + } else if (!strncmp (key, "installed-size", + strlen ("installed-size"))) { + up->installed_size = strtoul (value->str, NULL, 10) * 1024; + } else if (!strncmp (key, "size", strlen ("size"))) { + up->package_size = strtoul(value->str, NULL, 10); + } else if (!strncmp (key, "description", strlen ("description"))) { + char *newline; + + /* + * We only want the first line for the summary, and all the + * other lines for the description. + */ + + newline = strchr (value->str, '\n'); + if (!newline) { + pkg->summary = strdup (value->str); + pkg->description = g_strconcat (value->str, "\n", NULL); + } + else { + pkg->summary = g_strndup (value->str, newline - value->str); + pkg->description = g_strconcat (newline + 1, "\n", NULL); + } + } else if (!strncmp (key, "version", strlen ("version"))) { + RCResItemSpec *spec = RC_RESOLVABLE_SPEC (pkg); + rc_version_parse (value->str, spec); + } else if (!strncmp (key, "section", strlen ("section"))) { + pkg->section = rc_debman_section_to_package_section (value->str); + } else if (!strncmp (key, "depends", strlen ("depends"))) { + requires = g_slist_concat ( + requires, + rc_debman_fill_depends (value->str, false)); + } else if (!strncmp (key, "recommends", strlen ("recommends"))) { + recommends = g_slist_concat ( + recommends, + rc_debman_fill_depends (value->str, false)); + } else if (!strncmp (key, "suggests", strlen ("suggests"))) { + suggests = g_slist_concat ( + suggests, + rc_debman_fill_depends (value->str, false)); + } else if (!strncmp (key, "pre-depends", strlen ("pre-depends"))) { + requires = g_slist_concat ( + requires, + rc_debman_fill_depends (value->str, true)); + } else if (!strncmp (key, "conflicts", strlen ("conflicts"))) { + conflicts = g_slist_concat ( + conflicts, + rc_debman_fill_depends (value->str, false)); + } else if (!strncmp (key, "provides", strlen ("provides"))) { + provides = g_slist_concat ( + provides, + rc_debman_fill_depends (value->str, false)); + } else if (!strncmp (key, "filename", strlen ("filename"))) { + /* Build a new update with just this version */ + if (url_prefix) { + up->package_url = g_strconcat (url_prefix, "/", + value->str, + NULL); + } else { + up->package_url = strdup (value->str); + } + } else if (!strncmp (key, "md5sum", strlen ("md5sum"))) { + up->md5sum = strdup (value->str); + } else if (!strncmp (key, "architecture", strlen ("architecture"))) { + rc_resItem_spec_set_arch (RC_RESOLVABLE_SPEC (pkg), rc_arch_from_string (value->str)); + } + + g_string_free (value, true); + } + + up->importance = RC_IMPORTANCE_SUGGESTED; + up->description = strdup ("Upstream Debian release"); + rc_resItem_spec_copy (rc_package_update_get_spec(up), RC_RESOLVABLE_SPEC (pkg)); + rc_package_add_update (pkg, up); + + r = RC_RESOLVABLE (pkg); + + /* Make sure to provide myself, for the dep code! */ + provides = g_slist_append (provides, rc_resItem_dep_new_from_spec + (RC_RESOLVABLE_SPEC (pkg), + RC_RELATION_EQUAL, + RC_TYPE_PACKAGE, + rc_resItem_get_channel (r), + false, false)); + + rc_resItem_set_requires (r, requires); + rc_resItem_set_provides (r, provides); + rc_resItem_set_conflicts (r, conflicts); + rc_resItem_set_obsoletes (r, NULL); + rc_resItem_set_suggests (r, suggests); + rc_resItem_set_recommends(r, recommends); + /* returns the number of characters we processed */ + return ibuf - buf; + } + + #endif + + int + extract_packages_from_debian_buffer (const char *buf, size_t len, ChannelPtr channel, CResItemFn callback, void *data) + { + const char *pos; + int count = 0; + + /* Keep looking for a "Package: " */ + pos = buf; + #if 0 + while ((pos = strstr (pos, "Package: ")) != NULL) { + int off; + + /* All debian packages "have" epochs */ + ResItemPtr resItem = fill_debian_package (iter, channel->getFilePath (), &off); + + resItem->setEpoch (0); + resItem->setArch (Arch::Noarch); + resItem->setChannel (channel); + + if (callback) + callback (resItem, data); + + ++count; + + iter += off; + } + #endif + return count; + } + + + int + extract_packages_from_debian_file (const string & filename, ChannelPtr channel, CResItemFn callback, void *data) + { + Buffer *buf; + int count; + + if (filename.empty()) + return -1; + + buf = buffer_map_file (filename); + if (buf == NULL) + return -1; + + count = extract_packages_from_debian_buffer ((const char *)(buf->data), buf->size, channel, callback, data); + buffer_unmap_file (buf); + + return count; + } + + #if 0 + /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + + PackagePtr + extract_yum_package (const guint8 *data, size_t len, + RCPackman *packman, char *url) + { + #ifndef ENABLE_RPM + /* We can't support yum without rpm support */ + debug (RC_DEBUG_LEVEL_ERROR, "RPM support is not enabled"); + return NULL; + #else + RCRpmman *rpmman; + Header h; + PackagePtr p; + RCPackageUpdate *pu; + char *tmpc; + int typ, n; + + g_return_val_if_fail (packman != NULL, NULL); + + if (!g_type_is_a (G_TYPE_FROM_INSTANCE (packman), RC_TYPE_RPMMAN)) { + debug (RC_DEBUG_LEVEL_ERROR, + "yum support is not available on non-RPM systems"); + return NULL; + } + + rpmman = RC_RPMMAN (packman); + + h = rpmman->headerLoad (data); + + if (h == NULL) { + debug (RC_DEBUG_LEVEL_ERROR, + "Unable to get header from headerCopyLoad!"); + return NULL; + } + + rpmman->headerGetEntry (h, RPMTAG_ARCH, &typ, (void **) &tmpc, &n); + + p = rc_package_new (); + + rc_rpmman_read_header (rpmman, h, p); + rc_rpmman_depends_fill (rpmman, h, p, true); + + pu = rc_package_update_new (); + rc_resItem_spec_copy (rc_package_update_get_spec (pu), RC_RESOLVABLE_SPEC (p)); + pu->importance = RC_IMPORTANCE_SUGGESTED; + pu->description = strdup ("No information available."); + pu->package_url = url; + + p->history = g_slist_append (p->history, pu); + + rpmman->headerFree (h); + + return p; + #endif + } + + int + extract_packages_from_aptrpm_buffer (const guint8 *data, size_t len, + RCPackman *packman, + ChannelPtr channel, + CResItemFn callback, + void * user_data) + { + #ifndef ENABLE_RPM + /* We can't support apt-rpm without rpm support */ + debug (RC_DEBUG_LEVEL_ERROR, "RPM support is not enabled"); + return -1; + #else + RCRpmman *rpmman; + int count = 0; + const int hdrmagic_len = 8; + const char *hdrmagic; + const guint8 *cur_ptr; + RCResItemSpec *spec; + + + g_return_val_if_fail (packman != NULL, -1); + + if (!g_type_is_a (G_TYPE_FROM_INSTANCE (packman), RC_TYPE_RPMMAN)) { + debug (RC_DEBUG_LEVEL_ERROR, + "apt-rpm support is not available on non-RPM systems"); + return -1; + } + + rpmman = RC_RPMMAN (packman); + + if (len < hdrmagic_len) { + debug (RC_DEBUG_LEVEL_ERROR, + "Data is too small to possibly be correct"); + return 0; + } + + /* + * The apt-rpm pkglist files are a set of rpm headers, each prefixed + * with the header magic, one right after the other. If opened on disk, + * they can be iterated using headerRead(). Since we have an in-memory + * buffer, we use headerCopyLoad to read them. We could, potentially, + * use headerLoad(); but I'm unsure as to what happens when headerFree + * is called on a Header returned from headerLoad. It may be a small + * memory savings to do so. + */ + + /* Skip the inital RPM header magic */ + hdrmagic = data; + cur_ptr = data + hdrmagic_len; + + while (cur_ptr != NULL) { + Header h; + PackagePtr p; + RCPackageUpdate *pu; + int bytesleft, i; + char *tmpc; + int typ, n; + char *archstr; + + h = rpmman->headerLoad (cur_ptr); + + if (h == NULL) { + debug (RC_DEBUG_LEVEL_ERROR, + "Unable to get header from headerCopyLoad!"); + return 0; + } + + rpmman->headerGetEntry (h, RPMTAG_ARCH, &typ, (void **) &tmpc, &n); + + if (n && typ == RPM_STRING_TYPE) + archstr = tmpc; + else { + debug (RC_DEBUG_LEVEL_WARNING, "No arch available!"); + goto cleanup; + } + + p = rc_package_new (); + + rc_rpmman_read_header (rpmman, h, p); + rc_rpmman_depends_fill (rpmman, h, p, true); + + rc_resItem_set_channel (RC_RESOLVABLE (p), channel); + + pu = rc_package_update_new (); + rc_resItem_spec_copy (rc_package_update_get_spec (pu), RC_RESOLVABLE_SPEC (p)); + pu->importance = RC_IMPORTANCE_SUGGESTED; + pu->description = strdup ("No information available."); + + /* Build a filename from the spec */ + spec = RC_RESOLVABLE_SPEC (p); + pu->package_url = strdup_printf ("%s/%s-%s-%s.%s.rpm", + rc_channel_get_file_path (channel), + rc_resItem_spec_get_name (spec), + rc_resItem_spec_get_version (spec), + rc_resItem_spec_get_release (spec), + archstr); + + p->history = g_slist_append (p->history, pu); + + if (callback) + callback ((RCResItem *) p, user_data); + + g_object_unref (p); + + ++count; + + cleanup: + rpmman->headerFree (h); + + /* This chunk of ugly could be removed if a) memmem() was portable; + * or b) if rpmlib didn't suck, and I could figure out how much + * data it read from the buffer. + */ + bytesleft = len - (cur_ptr - data); + for (i = 0; i < bytesleft - hdrmagic_len; i++) { + if (memcmp (cur_ptr + i, hdrmagic, hdrmagic_len) == 0) { + /* We found a match */ + cur_ptr = cur_ptr + i + hdrmagic_len; + break; + } + } + + if (i >= bytesleft - hdrmagic_len) { + /* No match was found */ + cur_ptr = NULL; + } + } + + return count; + #endif + } + + int + extract_packages_from_aptrpm_file (const char *filename, + RCPackman *packman, + ChannelPtr channel, + CResItemFn callback, + void * user_data) + { + WorldPtr world = *((WorldPtr *)data); + RCBuffer *buf; + int count; + + g_return_val_if_fail (filename != NULL, -1); + g_return_val_if_fail (packman != NULL, -1); + + buf = rc_buffer_map_file (filename); + if (buf == NULL) + return -1; + + count = extract_packages_from_aptrpm_buffer (buf->data, buf->size, + packman, channel, + callback, user_data); + + rc_buffer_unmap_file (buf); + + return count; + } + + /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + + static void + package_into_hash (PackagePtr pkg, GHashTable *hash) + { + void * nameq; + PackagePtr hashed_pkg; + + nameq = GINT_TO_POINTER (RC_RESOLVABLE_SPEC (pkg)->nameq); + hashed_pkg = g_hash_table_lookup (hash, nameq); + if (hashed_pkg == NULL) { + g_hash_table_insert (hash, nameq, g_object_ref (pkg)); + } else if (rc_version_compare (RC_RESOLVABLE_SPEC (pkg), + RC_RESOLVABLE_SPEC (hashed_pkg)) > 0) { + g_hash_table_replace (hash, nameq, g_object_ref (pkg)); + g_object_unref (hashed_pkg); + } + } + + static bool + hash_recurse_cb (PackagePtr pkg, void * user_data) + { + GHashTable *hash = user_data; + package_into_hash (pkg, hash); + return true; + } + + struct HashIterInfo { + CResItemFn callback; + void * user_data; + int count; + }; + + static void + hash_iter_cb (void * key, void * val, void * user_data) + { + RCResItem *r = val; + struct HashIterInfo *info = user_data; + + if (info->callback) + info->callback (r, info->user_data); + + g_object_unref (r); + ++info->count; + } + + + static void + add_fake_history (PackagePtr pkg) + { + RCPackageUpdate *up; + + up = rc_package_update_new (); + rc_resItem_spec_copy ((RCResItemSpec *) up, + RC_RESOLVABLE_SPEC (pkg)); + up->importance = RC_IMPORTANCE_SUGGESTED; + rc_package_add_update (pkg, up); + } + + typedef struct { + CResItemFn user_callback; + void * user_data; + const gchar *path; + } PackagesFromDirInfo; + + static bool + packages_from_dir_cb (PackagePtr package, void * user_data) + { + PackagesFromDirInfo *info = user_data; + RCPackageUpdate *update; + + /* Set package path */ + update = rc_package_get_latest_update (package); + if (update && update->package_url) + package->package_filename = g_build_path (G_DIR_SEPARATOR_S, + info->path, + update->package_url, + NULL); + if (info->user_callback) + return info->user_callback ((RCResItem *)package, info->user_data); + + return true; + } + + int + extract_packages_from_directory (const char *path, + ChannelPtr channel, + RCPackman *packman, + bool recursive, + CResItemFn callback, + void * user_data) + { + WorldPtr world = *((WorldPtr *)data); + GDir *dir; + GHashTable *hash; + struct HashIterInfo info; + const char *filename; + char *magic; + bool distro_magic, pkginfo_magic; + + g_return_val_if_fail (path && *path, -1); + g_return_val_if_fail (channel != NULL, -1); + + /* + Check for magic files that indicate how to treat the + directory. The files aren't read -- it is sufficient that + they exist. + */ + + magic = g_strconcat (path, "/RC_SKIP", NULL); + if (g_file_test (magic, G_FILE_TEST_EXISTS)) { + g_free (magic); + return 0; + } + g_free (magic); + + magic = g_strconcat (path, "/RC_RECURSIVE", NULL); + if (g_file_test (magic, G_FILE_TEST_EXISTS)) + recursive = true; + g_free (magic); + + magic = g_strconcat (path, "/RC_BY_DISTRO", NULL); + distro_magic = g_file_test (magic, G_FILE_TEST_EXISTS); + g_free (magic); + + pkginfo_magic = true; + magic = g_strconcat (path, "/RC_IGNORE_PKGINFO", NULL); + if (g_file_test (magic, G_FILE_TEST_EXISTS)) + pkginfo_magic = false; + g_free (magic); + + /* If distro_magic is set, we search for packages in two + subdirectories of path: path/distro-target (i.e. + path/redhat-9-i386) and path/x-cross. + */ + + #if 0 + if (distro_magic) { + char *distro_path, *cross_distro_path; + bool found_distro_magic = false; + int count = 0, c; + + distro_path = g_strconcat (path, "/", rc_distro_get_target (), NULL); + if (g_file_test (distro_path, G_FILE_TEST_IS_DIR)) { + found_distro_magic = true; + + c = extract_packages_from_directory (distro_path, + channel, packman, + callback, user_data); + if (c >= 0) + count += c; + } + + cross_distro_path = g_strconcat (path, "/x-distro", NULL); + if (g_file_test (cross_distro_path, G_FILE_TEST_IS_DIR)) { + c = extract_packages_from_directory (cross_distro_path, + channel, packman, + callback, user_data); + if (c >= 0) + count += c; + } + + g_free (cross_distro_path); + g_free (distro_path); + + return count; + } + #endif + + /* If pkginfo_magic is set and if a packageinfo.xml or + packageinfo.xml.gz file exists in the directory, use it + instead of just scanning the files in the directory + looking for packages. */ + + if (pkginfo_magic) { + int i, count; + gchar *pkginfo_path = NULL; + const gchar *pkginfo[] = { "packageinfo.xml", + "packageinfo.xml.gz", + NULL }; + + for (i = 0; pkginfo[i]; i++) { + pkginfo_path = g_build_path (G_DIR_SEPARATOR_S, path, pkginfo[i], NULL); + if (g_file_test (pkginfo_path, G_FILE_TEST_EXISTS)) + break; + + g_free (pkginfo_path); + pkginfo_path = NULL; + } + + if (pkginfo_path) { + PackagesFromDirInfo info; + + info.user_callback = callback; + info.user_data = user_data; + info.path = path; + + count = extract_packages_from_helix_file (pkginfo_path, channel, packages_from_dir_cb, &info); + g_free (pkginfo_path); + return count; + } + } + + dir = g_dir_open (path, 0, NULL); + if (dir == NULL) + return -1; + + hash = g_hash_table_new (NULL, NULL); + + while ( (filename = g_dir_read_name (dir)) ) { + gchar *file_path; + + file_path = g_strconcat (path, "/", filename, NULL); + + if (recursive && g_file_test (file_path, G_FILE_TEST_IS_DIR)) { + extract_packages_from_directory (file_path, + channel, + packman, + true, + hash_recurse_cb, + hash); + } else if (g_file_test (file_path, G_FILE_TEST_IS_REGULAR)) { + PackagePtr pkg; + + pkg = rc_packman_query_file (packman, file_path, true); + if (pkg != NULL) { + rc_resItem_set_channel (RC_RESOLVABLE (pkg), channel); + pkg->package_filename = strdup (file_path); + pkg->local_package = false; + add_fake_history (pkg); + package_into_hash (pkg, hash); + g_object_unref (pkg); + } + } + + g_free (file_path); + } + + g_dir_close (dir); + + info.callback = callback; + info.user_data = user_data; + info.count = 0; + + /* Walk across the hash and: + 1) Invoke the callback on each package + 2) Unref each package + */ + g_hash_table_foreach (hash, hash_iter_cb, &info); + + g_hash_table_destroy (hash); + + return info.count; + } + #endif + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/extract.h b/zypp/solver/detail/extract.h index 867ee1a..14eb8f8 100644 --- a/zypp/solver/detail/extract.h +++ b/zypp/solver/detail/extract.h @@ -37,32 +37,42 @@ #include #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - - -int extract_packages_from_helix_buffer (const char data[], size_t len, ChannelPtr channel, CResItemFn callback, void *data); -int extract_packages_from_helix_file (const std::string & filename, ChannelPtr channel, CResItemFn callback, void *data); - -int extract_packages_from_xml_node (constXmlNodePtr node, ChannelPtr channel, ResItemFn callback, void *data); - -int extract_packages_from_debian_buffer (const char *data, size_t len, ChannelPtr channel, CResItemFn callback, void *data); -int extract_packages_from_debian_file (const std::string & filename, ChannelPtr channel, CResItemFn callback, void *data); - -PackagePtr extract_yum_package (const char *data, size_t len, PackmanPtr packman, const std::string & url); - -int extract_packages_from_aptrpm_buffer (const char *data, size_t len, PackmanPtr packman, ChannelPtr channel, ResItemFn callback, void *data); -int extract_packages_from_aptrpm_file (const std::string & filename, PackmanPtr packman, ChannelPtr channel, ResItemFn callback, void *data); - -int extract_packages_from_undump_buffer (const char *data, size_t len, ChannelAndSubscribedFn channel_callback, CResItemFn package_callback, MatchFn lock_callback, void *data); -int extract_packages_from_undump_file (const std::string & filename, ChannelAndSubscribedFn channel_callback, CResItemFn package_callback, MatchFn lock_callback, void *data); - -int extract_packages_from_directory (const std::string & path, ChannelPtr channel, PackmanPtr packman, bool recursive, ResItemFn callback, void *data); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// - +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + int extract_packages_from_helix_buffer (const char data[], size_t len, ChannelPtr channel, CResItemFn callback, void *data); + int extract_packages_from_helix_file (const std::string & filename, ChannelPtr channel, CResItemFn callback, void *data); + + int extract_packages_from_xml_node (constXmlNodePtr node, ChannelPtr channel, ResItemFn callback, void *data); + + int extract_packages_from_debian_buffer (const char *data, size_t len, ChannelPtr channel, CResItemFn callback, void *data); + int extract_packages_from_debian_file (const std::string & filename, ChannelPtr channel, CResItemFn callback, void *data); + + PackagePtr extract_yum_package (const char *data, size_t len, PackmanPtr packman, const std::string & url); + + int extract_packages_from_aptrpm_buffer (const char *data, size_t len, PackmanPtr packman, ChannelPtr channel, ResItemFn callback, void *data); + int extract_packages_from_aptrpm_file (const std::string & filename, PackmanPtr packman, ChannelPtr channel, ResItemFn callback, void *data); + + int extract_packages_from_undump_buffer (const char *data, size_t len, ChannelAndSubscribedFn channel_callback, CResItemFn package_callback, MatchFn lock_callback, void *data); + int extract_packages_from_undump_file (const std::string & filename, ChannelAndSubscribedFn channel_callback, CResItemFn package_callback, MatchFn lock_callback, void *data); + + int extract_packages_from_directory (const std::string & path, ChannelPtr channel, PackmanPtr packman, bool recursive, ResItemFn callback, void *data); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// #endif /* __EXTRACT_H__ */ diff --git a/zypp/solver/detail/utils.cc b/zypp/solver/detail/utils.cc index b7510f8..588fc97 100644 --- a/zypp/solver/detail/utils.cc +++ b/zypp/solver/detail/utils.cc @@ -41,646 +41,656 @@ #include -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -using namespace std; - -//--------------------------------------------------------------------------- -// string stuff - -/* Like g_strstrip(), only returns NULL on an empty string */ -char * -strstrip (const char *str) -{ - const char *start; - const char *end; - - if (str == NULL) - return ""; - - start = str; - while (isblank (*start)) { - start++; - } - - end = start + strlen (start) - 1; - while (end > start - && isblank (*end)) { - end--; - } - - if (start > end) { // empty string - return NULL; - } - - if (start > str - || *(end+1) != 0) { // we stripped at least one blank somewhere - return strndup (start, end - start + 1); - } - return strdup (str); // no blanks stripped -} - - -//--------------------------------------------------------------------------- -// url and path stuff - -char * -maybe_merge_paths(const char *parent_path, const char *child_path) -{ - /* Child path is NULL, so we return a dup of the parent path. - Ex: maybe_merge_paths("/foo", NULL) => "/foo" */ - if (!child_path) - return strdup(parent_path); - - /* Child path is a fully qualified URL, so we return a dup of it. - Ex: maybe_merge_paths("/foo", "http://www.ximian.com") => - "http://www.ximian.com" - - OR - - Child path is an absolute path, so we just return a dup of it. - Ex: maybe_merge_paths("/foo", "/bar/baz") => "/bar/baz" */ - - if (url_is_absolute(child_path) || child_path[0] == '/') - return strdup(child_path); - - /* Child path is a relative path, so we tack child path onto the end of - parent path. - Ex: maybe_merge_paths("/foo", "bar/baz") => "/foo/bar/baz" */ - - char *s = (char *)malloc (strlen (parent_path) + strlen (child_path) + 1 + 1); // +1 for /, +1 for \0 - strcpy (s, parent_path); - - if (parent_path[strlen(parent_path) - 1] != '/') - strcat (s, "/"); - - strcat (s, child_path); - - return s; -} - - -bool -url_is_absolute (const char *url) -{ - if (strncasecmp (url, "http:", 5) == 0 || - strncasecmp (url, "https:", 6) == 0 || - strncasecmp (url, "ftp:", 4) == 0 || - strncasecmp (url, "cd:", 3) == 0 || - strncasecmp (url, "dvd:", 4) == 0 || - strncasecmp (url, "dir:", 4) == 0 || - strncasecmp (url, "file:", 5) == 0) - { - return true; - } - - return false; -} - - -//--------------------------------------------------------------------------- -// compress/uncompress stuff - -/* - * Magic gunzipping goodness - */ - -/* - * Count number of bytes to skip at start of buf - */ -static int gz_magic[2] = {0x1f, 0x8b}; -/* gzip flag byte */ -#define GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define GZ_HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define GZ_COMMENT 0x10 /* bit 4 set: file comment present */ -#define GZ_RESERVED 0xE0 /* bits 5..7: reserved */ - -static int -count_gzip_header (const unsigned char *buf, unsigned int input_length) -{ - int method, flags; - const unsigned char *s = buf; - unsigned int left_len = input_length; - - if (left_len < 4) return -1; - if (*s++ != gz_magic[0] || *s++ != gz_magic[1]) { - return -2; - } - - method = *s++; - flags = *s++; - left_len -= 4; - - if (method != Z_DEFLATED || (flags & GZ_RESERVED) != 0) { - /* If it's not deflated, or the reserved isn't 0 */ - return -3; - } - - /* Skip time, xflags, OS code */ - if (left_len < 6) return -4; - s += 6; - left_len -= 6; - - if (flags & GZ_EXTRA_FIELD) { - unsigned int len; - if (left_len < 2) return -5; - len = (unsigned int)(*s++); - len += ((unsigned int)(*s++)) << 8; - if (left_len < len) return -6; - s += len; - left_len -= len; - } - - /* Skip filename */ - if (flags & GZ_ORIG_NAME) { - while (--left_len != 0 && *s++ != '\0') ; - if (left_len == 0) return -7; - } - /* Skip comment */ - if (flags & GZ_COMMENT) { - while (--left_len != 0 && *s++ != '\0') ; - if (left_len == 0) return -7; - } - /* Skip CRC */ - if (flags & GZ_HEAD_CRC) { - if (left_len < 2) return -7; - s += 2; - left_len -= 2; - } - - return input_length - left_len; -} - - -int -gunzip_memory (const unsigned char *input_buffer, unsigned int input_length, ByteArray **out_ba) -{ - z_stream zs; - char *outbuf = NULL; - ByteArray *ba = NULL; - int zret; - - int gzip_hdr; - - if (input_buffer == NULL) return -1; - if (input_length == 0) return -2; - if (out_ba == NULL) return -3; - - ba = (ByteArray *)malloc (sizeof (ByteArray)); - ba->data = NULL; - ba->len = 0; - - gzip_hdr = count_gzip_header (input_buffer, input_length); - if (gzip_hdr < 0) - return -1; - - zs.next_in = (unsigned char *) input_buffer + gzip_hdr; - zs.avail_in = input_length - gzip_hdr; - zs.zalloc = NULL; - zs.zfree = NULL; - zs.opaque = NULL; - -#define OUTBUFSIZE 10000 - outbuf = (char *)malloc (OUTBUFSIZE); - zs.next_out = (Bytef *)outbuf; - zs.avail_out = OUTBUFSIZE; - - /* Negative inflateinit is magic to tell zlib that there is no - * zlib header */ - inflateInit2 (&zs, -MAX_WBITS); - - while (1) { - zret = inflate (&zs, Z_SYNC_FLUSH); - if (zret != Z_OK && zret != Z_STREAM_END) - break; - - ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); - memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); - ba->len += (OUTBUFSIZE - zs.avail_out); - - zs.next_out = (Bytef *)outbuf; - zs.avail_out = OUTBUFSIZE; - - if (zret == Z_STREAM_END) - break; - } - - inflateEnd (&zs); - free ((void *)outbuf); - - if (zret != Z_STREAM_END) { - fprintf (stderr, "libz inflate failed! (%d)", zret); - free (ba->data); - free (ba); - ba = NULL; - } else { - zret = 0; - } - - *out_ba = ba; - return zret; -} - - -int -gzip_memory (const char *input_buffer, unsigned int input_length, ByteArray **out_ba) -{ - z_stream zs; - char *outbuf = NULL; - ByteArray *ba = NULL; - int zret; - - if (input_buffer == NULL) return -1; - if (input_length == 0) return -2; - if (out_ba == NULL) return -3; - - ba = (ByteArray *)malloc (sizeof (ByteArray)); - ba->data = NULL; - ba->len = 0; - - zs.next_in = (unsigned char *) input_buffer; - zs.avail_in = input_length; - zs.zalloc = NULL; - zs.zfree = NULL; - zs.opaque = NULL; - - outbuf = (char *)malloc (OUTBUFSIZE); - zs.next_out = (Bytef *)outbuf; - zs.avail_out = OUTBUFSIZE; - - deflateInit (&zs, Z_DEFAULT_COMPRESSION); - - while (1) { - if (zs.avail_in) - zret = deflate (&zs, Z_SYNC_FLUSH); - else - zret = deflate (&zs, Z_FINISH); - - if (zret != Z_OK && zret != Z_STREAM_END) - break; - - ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); - memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); - ba->len += (OUTBUFSIZE - zs.avail_out); - - zs.next_out = (Bytef *)outbuf; - zs.avail_out = OUTBUFSIZE; - - if (zret == Z_STREAM_END) - break; - } - - deflateEnd (&zs); - free ((void *)outbuf); - - if (zret != Z_STREAM_END) { - fprintf (stderr, "libz deflate failed! (%d)", zret); - free (ba->data); - free (ba); - ba = NULL; - } else { - zret = 0; - } - - *out_ba = ba; - return zret; -} /* gzip_memory */ - - -bool -memory_looks_gzipped (const unsigned char *buffer) -{ - if (buffer == NULL) - return false; - - /* This is from RFC 1952 */ - - return buffer[0] == gz_magic[0] /* ID1 */ - && buffer[1] == gz_magic[1]; /* ID2 */ -} - -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -static char bz2_magic[3] = { 'B', 'Z', 'h' }; - -int -bunzip2_memory (const unsigned char *input_buffer, unsigned int input_length, ByteArray **out_ba) -{ -#ifndef HAVE_BZ2 - - fprintf (stderr, "bz2 support not compiled in"); - *out_ba = NULL; - - return -1; - -#else - - bz_stream bzs; - ByteArray *ba; - char *outbuf; - int bzret; - - if (input_buffer == NULL) return -1; - if (input_length == 0) return -2; - if (out_ba == NULL) return -3; - - ba = (ByteArray *)malloc (sizeof (ByteArray)); - ba->data = NULL; - ba->len = 0; - - bzs.next_in = (unsigned char *) input_buffer; - bzs.avail_in = input_length; - bzs.bzalloc = NULL; - bzs.bzfree = NULL; - bzs.opaque = NULL; - - outbuf = (char *)malloc (OUTBUFSIZE); - bzs.next_out = (Bytef *)outbuf; - bzs.avail_out = OUTBUFSIZE; - - BZ2_bzDecompressInit (&bzs, 1, 0); - - while (1) { - bzret = BZ2_bzDecompress (&bzs); - if (bzret != BZ_OK && bzret != BZ_STREAM_END) - break; - - ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); - memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); - ba->len += (OUTBUFSIZE - zs.avail_out); - - bzs.next_out = (Bytef *)outbuf; - bzs.avail_out = OUTBUFSIZE; - - if (bzret == BZ_STREAM_END) - break; - - if (bzs.avail_in == 0) { - /* The data is incomplete */ - bzret = -1; - break; - } - } - - BZ2_bzDecompressEnd (&bzs); - free ((void *)outbuf); - - if (bzret != BZ_STREAM_END) { - fprintf (stderr, "libbzip2 decompress failed (%d)", bzret); - free (ba->data); - free (ba); - ba = NULL; - } else { - bzret = 0; - } - - *out_ba = ba; - return bzret; -#endif -} - - -int -bzip2_memory (const char *input_buffer, unsigned int input_length, ByteArray **out_ba) -{ -#ifndef HAVE_BZ2 - - fprintf (stderr, "bz2 support not compiled in"); - *out_ba = NULL; - - return -1; - -#else - - bz_stream bzs; - ByteArray *ba; - char *outbuf; - int bzret; - - if (input_buffer == NULL) return -1; - if (input_length == 0) return -2; - if (out_ba == NULL) return -3; - - ba = (ByteArray *)malloc (sizeof (ByteArray)); - ba->data = NULL; - ba->len = 0; - - bzs.next_in = (unsigned char *) input_buffer; - bzs.avail_in = input_length; - bzs.bzalloc = NULL; - bzs.bzfree = NULL; - bzs.opaque = NULL; - - outbuf = (char *)malloc (OUTBUFSIZE); - bzs.next_out = (Bytef *)outbuf; - bzs.avail_out = OUTBUFSIZE; - - BZ2_bzCompressInit (&bzs, 5, 1, 0); - - while (1) { - if (bzs.avail_in) - bzret = BZ2_bzCompress (&bzs, BZ_RUN); - else - bzret = BZ2_bzCompress (&bzs, BZ_FINISH); - - if (bzret != BZ_OK && bzret != BZ_STREAM_END) - break; - - ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); - memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); - ba->len += (OUTBUFSIZE - zs.avail_out); - - bzs.next_out = (Bytef *)outbuf; - bzs.avail_out = OUTBUFSIZE; - - if (bzret == BZ_STREAM_END) - break; - } - - BZ2_bzCompressEnd (&bzs); - free ((void *)outbuf); - - if (bzret != BZ_STREAM_END) { - fprintf (stderr, "bz2 compress failed! (%d)", bzret); - free (ba->data); - free (ba); - ba = NULL; - } else { - bzret = 0; - } - - *out_ba = ba; - return bzret; -#endif -} - - -bool -memory_looks_bzip2ed (const unsigned char *buffer) -{ - if (buffer == NULL) - return false; - - return buffer[0] == bz2_magic[0] - && buffer[1] == bz2_magic[1] - && buffer[2] == bz2_magic[2]; -} - -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ - -int -uncompress_memory (const unsigned char *input_buffer, unsigned int input_length, ByteArray **out_ba) -{ - if (input_length > 2 && memory_looks_bzip2ed (input_buffer)) - return bunzip2_memory (input_buffer, input_length, out_ba); - else if (input_length > 3 && memory_looks_gzipped (input_buffer)) - return gunzip_memory (input_buffer, input_length, out_ba); - else - return -1; -} - -bool -memory_looks_compressed (const unsigned char *buffer, size_t size) -{ -#ifdef HAVE_BZ2 - if (size > 2 && memory_looks_bzip2ed (buffer)) - return true; -#endif - - if (size > 4 && memory_looks_gzipped (buffer)) - return true; - - return false; -} - -//--------------------------------------------------------------------------- -// I/O stuff - -/* - * This just allows reading from the buffer for now. It could be extended to - * do writing if necessary. - */ - -Buffer * -buffer_map_file (const string & filename) -{ - struct stat s; - int fd; - unsigned char *data; - Buffer *buf = NULL; - - if (filename.empty()) - return NULL; - - if (stat(filename.c_str(), &s) < 0) - return NULL; - - fd = open(filename.c_str(), O_RDONLY); - - if (fd < 0) - return NULL; - - data = (unsigned char *)mmap(NULL, s.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); - - close (fd); - - if (data == MAP_FAILED) - return NULL; - - /* Transparently uncompress */ - if (memory_looks_compressed (data, s.st_size)) { - ByteArray *byte_array = NULL; - - if (uncompress_memory (data, s.st_size, &byte_array)) { - debug (RC_DEBUG_LEVEL_WARNING, "Uncompression of '%s' failed", filename.c_str()); - } else { - buf = (Buffer *)malloc(sizeof (Buffer)); - buf->data = byte_array->data; - buf->size = byte_array->len; - buf->is_mmapped = false; - } - - munmap (data, s.st_size); - - if (byte_array) { - free (byte_array); - } - - } else { - buf = (Buffer *)malloc(sizeof (Buffer)); - buf->data = (byte *)data; - buf->size = s.st_size; - buf->is_mmapped = true; - } - - return buf; -} /* buffer_map_file */ - -void -buffer_unmap_file (Buffer *buf) -{ - if (buf == NULL) return; - - if (buf->is_mmapped) - munmap (buf->data, buf->size); - else - free (buf->data); - - free (buf); -} - -//--------------------------------------------------------------------------- -// XML stuff - -xmlDoc * -parse_xml_from_buffer (const char *input_buffer, size_t input_length) -{ - xmlDoc *doc = NULL; - - if (input_buffer == NULL) return NULL; - - if (input_length > 3 && memory_looks_gzipped ((const unsigned char *)input_buffer)) { - ByteArray *buf; - - if (uncompress_memory ((const unsigned char *)input_buffer, input_length, &buf)) { - return NULL; - } - doc = xmlParseMemory ((const char *)(buf->data), buf->len); - free (buf->data); - free (buf); - } else { - doc = xmlParseMemory (input_buffer, input_length); - } - - return doc; -} - - -xmlDoc * -parse_xml_from_file (const string & filename) -{ - Buffer *buf; - xmlDoc *doc = NULL; - - if (filename.empty()) return NULL; - - buf = buffer_map_file (filename); - if (buf) { - doc = xmlParseMemory ((const char *)(buf->data), buf->size); - buffer_unmap_file (buf); - } - - return doc; -} - - - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + using namespace std; + + //--------------------------------------------------------------------------- + // string stuff + + /* Like g_strstrip(), only returns NULL on an empty string */ + char * + strstrip (const char *str) + { + const char *start; + const char *end; + + if (str == NULL) + return ""; + + start = str; + while (isblank (*start)) { + start++; + } + + end = start + strlen (start) - 1; + while (end > start + && isblank (*end)) { + end--; + } + + if (start > end) { // empty string + return NULL; + } + + if (start > str + || *(end+1) != 0) { // we stripped at least one blank somewhere + return strndup (start, end - start + 1); + } + return strdup (str); // no blanks stripped + } + + + //--------------------------------------------------------------------------- + // url and path stuff + + char * + maybe_merge_paths(const char *parent_path, const char *child_path) + { + /* Child path is NULL, so we return a dup of the parent path. + Ex: maybe_merge_paths("/foo", NULL) => "/foo" */ + if (!child_path) + return strdup(parent_path); + + /* Child path is a fully qualified URL, so we return a dup of it. + Ex: maybe_merge_paths("/foo", "http://www.ximian.com") => + "http://www.ximian.com" + + OR + + Child path is an absolute path, so we just return a dup of it. + Ex: maybe_merge_paths("/foo", "/bar/baz") => "/bar/baz" */ + + if (url_is_absolute(child_path) || child_path[0] == '/') + return strdup(child_path); + + /* Child path is a relative path, so we tack child path onto the end of + parent path. + Ex: maybe_merge_paths("/foo", "bar/baz") => "/foo/bar/baz" */ + + char *s = (char *)malloc (strlen (parent_path) + strlen (child_path) + 1 + 1); // +1 for /, +1 for \0 + strcpy (s, parent_path); + + if (parent_path[strlen(parent_path) - 1] != '/') + strcat (s, "/"); + + strcat (s, child_path); + + return s; + } + + + bool + url_is_absolute (const char *url) + { + if (strncasecmp (url, "http:", 5) == 0 || + strncasecmp (url, "https:", 6) == 0 || + strncasecmp (url, "ftp:", 4) == 0 || + strncasecmp (url, "cd:", 3) == 0 || + strncasecmp (url, "dvd:", 4) == 0 || + strncasecmp (url, "dir:", 4) == 0 || + strncasecmp (url, "file:", 5) == 0) + { + return true; + } + + return false; + } + + + //--------------------------------------------------------------------------- + // compress/uncompress stuff + + /* + * Magic gunzipping goodness + */ + + /* + * Count number of bytes to skip at start of buf + */ + static int gz_magic[2] = {0x1f, 0x8b}; + /* gzip flag byte */ + #define GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ + #define GZ_HEAD_CRC 0x02 /* bit 1 set: header CRC present */ + #define GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ + #define GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */ + #define GZ_COMMENT 0x10 /* bit 4 set: file comment present */ + #define GZ_RESERVED 0xE0 /* bits 5..7: reserved */ + + static int + count_gzip_header (const unsigned char *buf, unsigned int input_length) + { + int method, flags; + const unsigned char *s = buf; + unsigned int left_len = input_length; + + if (left_len < 4) return -1; + if (*s++ != gz_magic[0] || *s++ != gz_magic[1]) { + return -2; + } + + method = *s++; + flags = *s++; + left_len -= 4; + + if (method != Z_DEFLATED || (flags & GZ_RESERVED) != 0) { + /* If it's not deflated, or the reserved isn't 0 */ + return -3; + } + + /* Skip time, xflags, OS code */ + if (left_len < 6) return -4; + s += 6; + left_len -= 6; + + if (flags & GZ_EXTRA_FIELD) { + unsigned int len; + if (left_len < 2) return -5; + len = (unsigned int)(*s++); + len += ((unsigned int)(*s++)) << 8; + if (left_len < len) return -6; + s += len; + left_len -= len; + } + + /* Skip filename */ + if (flags & GZ_ORIG_NAME) { + while (--left_len != 0 && *s++ != '\0') ; + if (left_len == 0) return -7; + } + /* Skip comment */ + if (flags & GZ_COMMENT) { + while (--left_len != 0 && *s++ != '\0') ; + if (left_len == 0) return -7; + } + /* Skip CRC */ + if (flags & GZ_HEAD_CRC) { + if (left_len < 2) return -7; + s += 2; + left_len -= 2; + } + + return input_length - left_len; + } + + + int + gunzip_memory (const unsigned char *input_buffer, unsigned int input_length, ByteArray **out_ba) + { + z_stream zs; + char *outbuf = NULL; + ByteArray *ba = NULL; + int zret; + + int gzip_hdr; + + if (input_buffer == NULL) return -1; + if (input_length == 0) return -2; + if (out_ba == NULL) return -3; + + ba = (ByteArray *)malloc (sizeof (ByteArray)); + ba->data = NULL; + ba->len = 0; + + gzip_hdr = count_gzip_header (input_buffer, input_length); + if (gzip_hdr < 0) + return -1; + + zs.next_in = (unsigned char *) input_buffer + gzip_hdr; + zs.avail_in = input_length - gzip_hdr; + zs.zalloc = NULL; + zs.zfree = NULL; + zs.opaque = NULL; + + #define OUTBUFSIZE 10000 + outbuf = (char *)malloc (OUTBUFSIZE); + zs.next_out = (Bytef *)outbuf; + zs.avail_out = OUTBUFSIZE; + + /* Negative inflateinit is magic to tell zlib that there is no + * zlib header */ + inflateInit2 (&zs, -MAX_WBITS); + + while (1) { + zret = inflate (&zs, Z_SYNC_FLUSH); + if (zret != Z_OK && zret != Z_STREAM_END) + break; + + ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); + memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); + ba->len += (OUTBUFSIZE - zs.avail_out); + + zs.next_out = (Bytef *)outbuf; + zs.avail_out = OUTBUFSIZE; + + if (zret == Z_STREAM_END) + break; + } + + inflateEnd (&zs); + free ((void *)outbuf); + + if (zret != Z_STREAM_END) { + fprintf (stderr, "libz inflate failed! (%d)", zret); + free (ba->data); + free (ba); + ba = NULL; + } else { + zret = 0; + } + + *out_ba = ba; + return zret; + } + + + int + gzip_memory (const char *input_buffer, unsigned int input_length, ByteArray **out_ba) + { + z_stream zs; + char *outbuf = NULL; + ByteArray *ba = NULL; + int zret; + + if (input_buffer == NULL) return -1; + if (input_length == 0) return -2; + if (out_ba == NULL) return -3; + + ba = (ByteArray *)malloc (sizeof (ByteArray)); + ba->data = NULL; + ba->len = 0; + + zs.next_in = (unsigned char *) input_buffer; + zs.avail_in = input_length; + zs.zalloc = NULL; + zs.zfree = NULL; + zs.opaque = NULL; + + outbuf = (char *)malloc (OUTBUFSIZE); + zs.next_out = (Bytef *)outbuf; + zs.avail_out = OUTBUFSIZE; + + deflateInit (&zs, Z_DEFAULT_COMPRESSION); + + while (1) { + if (zs.avail_in) + zret = deflate (&zs, Z_SYNC_FLUSH); + else + zret = deflate (&zs, Z_FINISH); + + if (zret != Z_OK && zret != Z_STREAM_END) + break; + + ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); + memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); + ba->len += (OUTBUFSIZE - zs.avail_out); + + zs.next_out = (Bytef *)outbuf; + zs.avail_out = OUTBUFSIZE; + + if (zret == Z_STREAM_END) + break; + } + + deflateEnd (&zs); + free ((void *)outbuf); + + if (zret != Z_STREAM_END) { + fprintf (stderr, "libz deflate failed! (%d)", zret); + free (ba->data); + free (ba); + ba = NULL; + } else { + zret = 0; + } + + *out_ba = ba; + return zret; + } /* gzip_memory */ + + + bool + memory_looks_gzipped (const unsigned char *buffer) + { + if (buffer == NULL) + return false; + + /* This is from RFC 1952 */ + + return buffer[0] == gz_magic[0] /* ID1 */ + && buffer[1] == gz_magic[1]; /* ID2 */ + } + + /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + + static char bz2_magic[3] = { 'B', 'Z', 'h' }; + + int + bunzip2_memory (const unsigned char *input_buffer, unsigned int input_length, ByteArray **out_ba) + { + #ifndef HAVE_BZ2 + + fprintf (stderr, "bz2 support not compiled in"); + *out_ba = NULL; + + return -1; + + #else + + bz_stream bzs; + ByteArray *ba; + char *outbuf; + int bzret; + + if (input_buffer == NULL) return -1; + if (input_length == 0) return -2; + if (out_ba == NULL) return -3; + + ba = (ByteArray *)malloc (sizeof (ByteArray)); + ba->data = NULL; + ba->len = 0; + + bzs.next_in = (unsigned char *) input_buffer; + bzs.avail_in = input_length; + bzs.bzalloc = NULL; + bzs.bzfree = NULL; + bzs.opaque = NULL; + + outbuf = (char *)malloc (OUTBUFSIZE); + bzs.next_out = (Bytef *)outbuf; + bzs.avail_out = OUTBUFSIZE; + + BZ2_bzDecompressInit (&bzs, 1, 0); + + while (1) { + bzret = BZ2_bzDecompress (&bzs); + if (bzret != BZ_OK && bzret != BZ_STREAM_END) + break; + + ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); + memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); + ba->len += (OUTBUFSIZE - zs.avail_out); + + bzs.next_out = (Bytef *)outbuf; + bzs.avail_out = OUTBUFSIZE; + + if (bzret == BZ_STREAM_END) + break; + + if (bzs.avail_in == 0) { + /* The data is incomplete */ + bzret = -1; + break; + } + } + + BZ2_bzDecompressEnd (&bzs); + free ((void *)outbuf); + + if (bzret != BZ_STREAM_END) { + fprintf (stderr, "libbzip2 decompress failed (%d)", bzret); + free (ba->data); + free (ba); + ba = NULL; + } else { + bzret = 0; + } + + *out_ba = ba; + return bzret; + #endif + } + + + int + bzip2_memory (const char *input_buffer, unsigned int input_length, ByteArray **out_ba) + { + #ifndef HAVE_BZ2 + + fprintf (stderr, "bz2 support not compiled in"); + *out_ba = NULL; + + return -1; + + #else + + bz_stream bzs; + ByteArray *ba; + char *outbuf; + int bzret; + + if (input_buffer == NULL) return -1; + if (input_length == 0) return -2; + if (out_ba == NULL) return -3; + + ba = (ByteArray *)malloc (sizeof (ByteArray)); + ba->data = NULL; + ba->len = 0; + + bzs.next_in = (unsigned char *) input_buffer; + bzs.avail_in = input_length; + bzs.bzalloc = NULL; + bzs.bzfree = NULL; + bzs.opaque = NULL; + + outbuf = (char *)malloc (OUTBUFSIZE); + bzs.next_out = (Bytef *)outbuf; + bzs.avail_out = OUTBUFSIZE; + + BZ2_bzCompressInit (&bzs, 5, 1, 0); + + while (1) { + if (bzs.avail_in) + bzret = BZ2_bzCompress (&bzs, BZ_RUN); + else + bzret = BZ2_bzCompress (&bzs, BZ_FINISH); + + if (bzret != BZ_OK && bzret != BZ_STREAM_END) + break; + + ba->data = (byte *)realloc (ba->data, ba->len + (OUTBUFSIZE - zs.avail_out)); + memcpy (ba->data + ba->len, outbuf, OUTBUFSIZE - zs.avail_out); + ba->len += (OUTBUFSIZE - zs.avail_out); + + bzs.next_out = (Bytef *)outbuf; + bzs.avail_out = OUTBUFSIZE; + + if (bzret == BZ_STREAM_END) + break; + } + + BZ2_bzCompressEnd (&bzs); + free ((void *)outbuf); + + if (bzret != BZ_STREAM_END) { + fprintf (stderr, "bz2 compress failed! (%d)", bzret); + free (ba->data); + free (ba); + ba = NULL; + } else { + bzret = 0; + } + + *out_ba = ba; + return bzret; + #endif + } + + + bool + memory_looks_bzip2ed (const unsigned char *buffer) + { + if (buffer == NULL) + return false; + + return buffer[0] == bz2_magic[0] + && buffer[1] == bz2_magic[1] + && buffer[2] == bz2_magic[2]; + } + + /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + + int + uncompress_memory (const unsigned char *input_buffer, unsigned int input_length, ByteArray **out_ba) + { + if (input_length > 2 && memory_looks_bzip2ed (input_buffer)) + return bunzip2_memory (input_buffer, input_length, out_ba); + else if (input_length > 3 && memory_looks_gzipped (input_buffer)) + return gunzip_memory (input_buffer, input_length, out_ba); + else + return -1; + } + + bool + memory_looks_compressed (const unsigned char *buffer, size_t size) + { + #ifdef HAVE_BZ2 + if (size > 2 && memory_looks_bzip2ed (buffer)) + return true; + #endif + + if (size > 4 && memory_looks_gzipped (buffer)) + return true; + + return false; + } + + //--------------------------------------------------------------------------- + // I/O stuff + + /* + * This just allows reading from the buffer for now. It could be extended to + * do writing if necessary. + */ + + Buffer * + buffer_map_file (const string & filename) + { + struct stat s; + int fd; + unsigned char *data; + Buffer *buf = NULL; + + if (filename.empty()) + return NULL; + + if (stat(filename.c_str(), &s) < 0) + return NULL; + + fd = open(filename.c_str(), O_RDONLY); + + if (fd < 0) + return NULL; + + data = (unsigned char *)mmap(NULL, s.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + + close (fd); + + if (data == MAP_FAILED) + return NULL; + + /* Transparently uncompress */ + if (memory_looks_compressed (data, s.st_size)) { + ByteArray *byte_array = NULL; + + if (uncompress_memory (data, s.st_size, &byte_array)) { + debug (RC_DEBUG_LEVEL_WARNING, "Uncompression of '%s' failed", filename.c_str()); + } else { + buf = (Buffer *)malloc(sizeof (Buffer)); + buf->data = byte_array->data; + buf->size = byte_array->len; + buf->is_mmapped = false; + } + + munmap (data, s.st_size); + + if (byte_array) { + free (byte_array); + } + + } else { + buf = (Buffer *)malloc(sizeof (Buffer)); + buf->data = (byte *)data; + buf->size = s.st_size; + buf->is_mmapped = true; + } + + return buf; + } /* buffer_map_file */ + + void + buffer_unmap_file (Buffer *buf) + { + if (buf == NULL) return; + + if (buf->is_mmapped) + munmap (buf->data, buf->size); + else + free (buf->data); + + free (buf); + } + + //--------------------------------------------------------------------------- + // XML stuff + + xmlDoc * + parse_xml_from_buffer (const char *input_buffer, size_t input_length) + { + xmlDoc *doc = NULL; + + if (input_buffer == NULL) return NULL; + + if (input_length > 3 && memory_looks_gzipped ((const unsigned char *)input_buffer)) { + ByteArray *buf; + + if (uncompress_memory ((const unsigned char *)input_buffer, input_length, &buf)) { + return NULL; + } + doc = xmlParseMemory ((const char *)(buf->data), buf->len); + free (buf->data); + free (buf); + } else { + doc = xmlParseMemory (input_buffer, input_length); + } + + return doc; + } + + + xmlDoc * + parse_xml_from_file (const string & filename) + { + Buffer *buf; + xmlDoc *doc = NULL; + + if (filename.empty()) return NULL; + + buf = buffer_map_file (filename); + if (buf) { + doc = xmlParseMemory ((const char *)(buf->data), buf->size); + buffer_unmap_file (buf); + } + + return doc; + } + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/utils.h b/zypp/solver/detail/utils.h index 1a70cd3..6b381e1 100644 --- a/zypp/solver/detail/utils.h +++ b/zypp/solver/detail/utils.h @@ -28,40 +28,51 @@ #include #include #include - -/////////////////////////////////////////////////////////////////// -namespace zypp { -////////////////////////////////////////////////////////////////// - -typedef unsigned char byte; - -char *strstrip (const char *str); -char *maybe_merge_paths(const char *parent_path, const char *child_path); -bool url_is_absolute (const char *url); - - -typedef struct { - byte *data; - size_t len; -} ByteArray; - -// An easy way to map files. If we map a compressed file, -// it will be magically uncompressed for us. - -typedef struct { - byte *data; - size_t size; - bool is_mmapped; -} Buffer; - -Buffer *buffer_map_file (const std::string & filename); -void buffer_unmap_file (Buffer *buffer); - - -xmlDoc *parse_xml_from_buffer (const char *input_buffer, size_t input_length); -xmlDoc *parse_xml_from_file (const std::string & filename); - -/////////////////////////////////////////////////////////////////// -}; // namespace zypp -/////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + typedef unsigned char byte; + + char *strstrip (const char *str); + char *maybe_merge_paths(const char *parent_path, const char *child_path); + bool url_is_absolute (const char *url); + + + typedef struct { + byte *data; + size_t len; + } ByteArray; + + // An easy way to map files. If we map a compressed file, + // it will be magically uncompressed for us. + + typedef struct { + byte *data; + size_t size; + bool is_mmapped; + } Buffer; + + Buffer *buffer_map_file (const std::string & filename); + void buffer_unmap_file (Buffer *buffer); + + + xmlDoc *parse_xml_from_buffer (const char *input_buffer, size_t input_length); + xmlDoc *parse_xml_from_file (const std::string & filename); + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/testsuite/deptestomatic_multi.cc b/zypp/solver/testsuite/deptestomatic_multi.cc index 6cac0ea..2f0c774 100644 --- a/zypp/solver/testsuite/deptestomatic_multi.cc +++ b/zypp/solver/testsuite/deptestomatic_multi.cc @@ -50,7 +50,7 @@ int assertOutput( const char* output) using namespace std; -using namespace zypp; +using namespace zypp::solver::detail; static MultiWorldPtr world = NULL; diff --git a/zypp/solver/testsuite/edition_single.cc b/zypp/solver/testsuite/edition_single.cc index c2ae01a..77a7aec 100644 --- a/zypp/solver/testsuite/edition_single.cc +++ b/zypp/solver/testsuite/edition_single.cc @@ -24,7 +24,7 @@ #include using namespace std; -using namespace zypp; +using namespace zypp::solver::detail; //--------------------------------------------------------------------------- diff --git a/zypp/solver/testsuite/spec_single.cc b/zypp/solver/testsuite/spec_single.cc index 75bd6a3..e5dd362 100644 --- a/zypp/solver/testsuite/spec_single.cc +++ b/zypp/solver/testsuite/spec_single.cc @@ -24,7 +24,7 @@ #include using namespace std; -using namespace zypp; +using namespace zypp::solver::detail; bool emptySpec (void) diff --git a/zypp/solver/testsuite/utils_single.cc b/zypp/solver/testsuite/utils_single.cc index b31f260..6930c05 100644 --- a/zypp/solver/testsuite/utils_single.cc +++ b/zypp/solver/testsuite/utils_single.cc @@ -1,7 +1,7 @@ #include #include -using namespace zypp; +using namespace zypp::solver::detail; int main (int argc, char *argv[])