From 2c863b69ce9efb38ebe74a4394ebce0c72c4054c Mon Sep 17 00:00:00 2001 From: Jan Kupec Date: Thu, 17 Apr 2008 15:50:02 +0000 Subject: [PATCH] - 'what-provides' command added (fate #302148) --- src/zypper-command.cc | 6 +++ src/zypper-command.h | 6 +++ src/zypper-misc.cc | 120 ++------------------------------------------------ src/zypper-misc.h | 3 +- src/zypper-search.cc | 18 ++++++++ src/zypper-search.h | 3 ++ src/zypper-utils.cc | 50 ++++++++++++++++++++- src/zypper-utils.h | 8 +++- src/zypper.cc | 82 +++++++++++++++++++++++++++++++++- 9 files changed, 175 insertions(+), 121 deletions(-) diff --git a/src/zypper-command.cc b/src/zypper-command.cc index 83adbe3..c603059 100644 --- a/src/zypper-command.cc +++ b/src/zypper-command.cc @@ -38,6 +38,9 @@ const ZypperCommand ZypperCommand::PACKAGES(ZypperCommand::PACKAGES_e); const ZypperCommand ZypperCommand::PATCHES(ZypperCommand::PATCHES_e); const ZypperCommand ZypperCommand::PATTERNS(ZypperCommand::PATTERNS_e); const ZypperCommand ZypperCommand::PRODUCTS(ZypperCommand::PRODUCTS_e); +const ZypperCommand ZypperCommand::WHAT_PROVIDES(ZypperCommand::WHAT_PROVIDES_e); +//const ZypperCommand ZypperCommand::WHAT_REQUIRES(ZypperCommand::WHAT_REQUIRES_e); +//const ZypperCommand ZypperCommand::WHAT_CONFLICTS(ZypperCommand::WHAT_CONFLICTS_e); const ZypperCommand ZypperCommand::XML_LIST_UPDATES_PATCHES(ZypperCommand::XML_LIST_UPDATES_PATCHES_e); const ZypperCommand ZypperCommand::ADD_LOCK(ZypperCommand::ADD_LOCK_e); @@ -87,6 +90,9 @@ ZypperCommand::Command ZypperCommand::parse(const std::string & strval_r) _table["patches"] = _table["pch"] = ZypperCommand::PATCHES_e; _table["patterns"] = _table["pt"] = ZypperCommand::PATTERNS_e; _table["products"] = _table["pd"] = ZypperCommand::PRODUCTS_e; + _table["what-provides"] = _table["wp"] = ZypperCommand::WHAT_PROVIDES_e; + //_table["what-requires"] = _table["wr"] = ZypperCommand::WHAT_REQUIRES_e; + //_table["what-conflicts"] = _table["wc"] = ZypperCommand::WHAT_CONFLICTS_e; _table["xml-updates"] = _table["xu"] = ZypperCommand::XML_LIST_UPDATES_PATCHES_e; _table["addlock"] = _table["al"] = _table["lock-add"] = _table["la"] = ZypperCommand::ADD_LOCK_e; diff --git a/src/zypper-command.h b/src/zypper-command.h index a7ba59e..6a1384f 100644 --- a/src/zypper-command.h +++ b/src/zypper-command.h @@ -33,6 +33,9 @@ struct ZypperCommand static const ZypperCommand PATCHES; static const ZypperCommand PATTERNS; static const ZypperCommand PRODUCTS; + static const ZypperCommand WHAT_PROVIDES; + //static const ZypperCommand WHAT_REQUIRES; + //static const ZypperCommand WHAT_CONFLICTS; static const ZypperCommand XML_LIST_UPDATES_PATCHES; static const ZypperCommand ADD_LOCK; @@ -79,6 +82,9 @@ struct ZypperCommand PATCHES_e, PATTERNS_e, PRODUCTS_e, + WHAT_PROVIDES_e, + //WHAT_REQUIRES_e, + //WHAT_CONFLICTS_e, XML_LIST_UPDATES_PATCHES_e, ADD_LOCK_e, diff --git a/src/zypper-misc.cc b/src/zypper-misc.cc index 3db5dc2..a688de5 100644 --- a/src/zypper-misc.cc +++ b/src/zypper-misc.cc @@ -50,7 +50,7 @@ static bool confirm_licenses(Zypper & zypper); // converts a user-supplied kind to a zypp kind object // returns an empty one if not recognized -ResObject::Kind string_to_kind (const string &skind) +ResKind string_to_kind (const string &skind) { ResObject::Kind empty; string lskind = str::toLower (skind); @@ -126,120 +126,6 @@ bool ProvideProcess::operator()( const PoolItem& provider ) return true; } -/** - * Stops iterations on first item and stores edition of the found item. - * - * If no item has been found, the \ref found variable is set to false. - */ -struct VersionGetter -{ - Edition edition; - bool found; - - VersionGetter() : found(false) {} - - bool operator()(const zypp::PoolItem& item) - { - edition = item.resolvable()->edition(); - found = true; - return false; // don't iterate further - } -}; - -/** - * Stops iterations on first item having revision newer than edition passed in - * contructor. Stores the edition of the found item. - * - * If no item has been found, the \ref found variable is set to false. - */ -struct NewerVersionGetter -{ - const Edition & old_edition; - Edition edition; - bool found; - - NewerVersionGetter(const Edition & edition) : old_edition(edition), found(false) {} - - bool operator()(const zypp::PoolItem& item) - { - if (item.resolvable()->edition() > old_edition) - { - edition = item.resolvable()->edition(); - found = true; - return false; // don't iterate further - } - - return true; - } -}; - -// on error print a message and return noCap -static Capability safe_parse_cap (Zypper & zypper, - const ResObject::Kind &kind, const string & capstr) -{ - Capability cap; - try { - // expect named caps as NAME[OP] - // transform to NAME[ OP ] (add spaces) - string new_capstr = capstr; - DBG << "capstr: " << capstr << endl; - string::size_type op_pos = capstr.find_first_of("<>="); - if (op_pos != string::npos) - { - new_capstr.insert(op_pos, " "); - DBG << "new capstr: " << new_capstr << endl; - op_pos = new_capstr.find_first_not_of("<>=", op_pos + 1); - if (op_pos != string::npos && new_capstr.size() > op_pos) - { - new_capstr.insert(op_pos, " "); - DBG << "new capstr: " << new_capstr << endl; - } - } - // if we are about to install stuff and - // if this is not a candidate for a versioned capability, take it like - // a package name and check if it is already installed - else if (zypper.command() == ZypperCommand::INSTALL) - { - using namespace zypp::functor; - using namespace zypp::resfilter; - - // get the installed version - VersionGetter vg; - invokeOnEach( - God->pool().byIdentBegin(kind, capstr), - God->pool().byIdentEnd(kind,capstr), - ByInstalled(), - functorRef (vg)); - // installed found - if (vg.found) - { - // check for newer version of that resolvable - NewerVersionGetter nvg(vg.edition); - invokeOnEach( - God->pool().byIdentBegin(kind, capstr), - God->pool().byIdentEnd(kind,capstr), - not_c(ByInstalled()), - functorRef (nvg)); - // newer version found - if (nvg.found) - { - DBG << "installed resolvable named " << capstr - << " found, changing capability to " << new_capstr << endl; - new_capstr = capstr + " > " + vg.edition.asString(); - } - } - } - cap = Capability( new_capstr.c_str(), kind ); - } - catch (const Exception& e) { - //! \todo check this handling (should we fail or set a special exit code?) - ZYPP_CAUGHT(e); - zypper.out().error(boost::str( - format(_("Cannot parse capability '%s'.")) % capstr)); - } - return cap; -} - // this does only resolvables with this _name_. // we could also act on _provides_ // TODO edition, arch @@ -578,7 +464,7 @@ void install_remove(Zypper & zypper, DBG << "trying: " << trythis << endl; - Capability cap = safe_parse_cap (zypper, kind, trythis); + Capability cap = safe_parse_cap (zypper, trythis, kind); sat::WhatProvides q(cap); if (!q.empty()) @@ -612,7 +498,7 @@ void install_remove(Zypper & zypper, // try by capability - Capability cap = safe_parse_cap (zypper, kind, str); + Capability cap = safe_parse_cap (zypper, str, kind); sat::WhatProvides q(cap); // is there a provider for the requested capability? diff --git a/src/zypper-misc.h b/src/zypper-misc.h index 57ae33c..2a38726 100644 --- a/src/zypper-misc.h +++ b/src/zypper-misc.h @@ -11,6 +11,7 @@ #define ZMART_MISC_H #include + #include "zypp/ResKind.h" #include "zypp/PoolItem.h" @@ -19,7 +20,7 @@ #include "zypper-utils.h" -zypp::ResObject::Kind string_to_kind (const std::string &skind); +zypp::ResKind string_to_kind (const std::string & skind); /** * Run the solver. diff --git a/src/zypper-search.cc b/src/zypper-search.cc index dce16e6..8f2fb11 100644 --- a/src/zypper-search.cc +++ b/src/zypper-search.cc @@ -257,6 +257,24 @@ void list_products(Zypper & zypper) cout << tbl; } + +void list_what_provides(Zypper & zypper, const string & str) +{ + Capability cap = safe_parse_cap (zypper, /*kind,*/ str); + sat::WhatProvides q(cap); + + // is there a provider for the requested capability? + if (q.empty()) + { + zypper.out().info(str::form(_("No providers of '%s' found."), str.c_str())); + return; + } + + Table t; + invokeOnEach(q.selectableBegin(), q.selectableEnd(), FillSearchTableSolvable(t) ); + cout << t; +} + // Local Variables: // c-basic-offset: 2 // End: diff --git a/src/zypper-search.h b/src/zypper-search.h index dbdc742..44a130d 100644 --- a/src/zypper-search.h +++ b/src/zypper-search.h @@ -170,4 +170,7 @@ void list_packages(Zypper & zypper); /** List all products with specific info in specified repos */ void list_products(Zypper & zypper); +/** List all providers of given capability */ +void list_what_provides(Zypper & zypper, const std::string & capstr); + #endif /*ZYPPERSEARCH_H_*/ diff --git a/src/zypper-utils.cc b/src/zypper-utils.cc index a8ae4c7..98fb24e 100644 --- a/src/zypper-utils.cc +++ b/src/zypper-utils.cc @@ -8,6 +8,7 @@ #include "zypp/base/Logger.h" #include "zypp/media/MediaManager.h" #include "zypp/parser/xml_escape_parser.hpp" +#include "zypp/Capability.h" #include "zypper.h" #include "zypper-main.h" @@ -62,10 +63,15 @@ void report_a_bug (Out & out) void report_too_many_arguments(const string & specific_help) { + report_too_many_arguments(Zypper::instance()->out(), specific_help); +} + +void report_too_many_arguments(Out & out, const string & specific_help) +{ //! \todo make this more explanatory, e.g. "Ingoring arg1 arg2. This command does not take arguments. See %s for more information." ostringstream s; s << _("Usage") << ':' << endl << specific_help; - Zypper::instance()->out().error(_("Too many arguments."), s.str()); + out.error(_("Too many arguments."), s.str()); } // ---------------------------------------------------------------------------- @@ -304,3 +310,45 @@ std::string & indent(std::string & text, int columns) text.insert(0, string(columns, ' ')); return text; } + +static string preparse_cap_str(const string & capstr) +{ + // expect versioned caps as NAME[OP] + // transform to NAME[ OP ] (add spaces) + string new_capstr = capstr; + DBG << "capstr: " << capstr << endl; + string::size_type op_pos = capstr.find_first_of("<>="); + if (op_pos != string::npos) + { + new_capstr.insert(op_pos, " "); + DBG << "new capstr: " << new_capstr << endl; + op_pos = new_capstr.find_first_not_of("<>=", op_pos + 1); + if (op_pos != string::npos && new_capstr.size() > op_pos) + { + new_capstr.insert(op_pos, " "); + DBG << "new capstr: " << new_capstr << endl; + } + } + + return new_capstr; +} + +Capability safe_parse_cap (Zypper & zypper, + const string & capstr, + const ResKind & kind) +{ + try + { + if (kind == ResKind::nokind) + return Capability(preparse_cap_str(capstr)); + else + return Capability(preparse_cap_str(capstr), kind); + } + catch (const Exception& e) + { + //! \todo check this handling (should we fail or set a special exit code?) + ZYPP_CAUGHT(e); + zypper.out().error(str::form(_("Cannot parse capability '%s'."), capstr.c_str())); + } + return Capability(); +} diff --git a/src/zypper-utils.h b/src/zypper-utils.h index c2f90b5..76986e4 100644 --- a/src/zypper-utils.h +++ b/src/zypper-utils.h @@ -19,7 +19,8 @@ std::string readline_getline(); void report_a_bug (Out & out); /** Say that too many arguments have been specified */ -void report_too_many_arguments(const std::string & specific_help); +void report_too_many_arguments(const std::string & specific_help); // deprecated +void report_too_many_arguments(Out & out, const std::string & specific_help); /** Say the specified option has no effect */ void report_dummy_option(Out & out, const std::string & longoption_str); @@ -69,6 +70,11 @@ std::string xml_encode(const std::string & text); std::string & indent(std::string & text, int columns); +zypp::Capability safe_parse_cap (Zypper & zypper, + const std::string & capstr, + const zypp::ResKind & kind = zypp::ResKind::nokind); + + //comparator for RepoInfo set class RepoInfoAliasComparator{ public: bool operator()(const zypp::RepoInfo &a, const zypp::RepoInfo& b){ diff --git a/src/zypper.cc b/src/zypper.cc index 58bd3b4..8a79ba6 100644 --- a/src/zypper.cc +++ b/src/zypper.cc @@ -203,6 +203,9 @@ void print_main_help(Zypper & zypper) "\tpackages, pa\t\tList all available packages.\n" "\tpatterns, pt\t\tList all available patterns.\n" "\tproducts, pd\t\tList all available products.\n" + "\twhat-provides, wp\tList packages providing specified capability.\n" + //"\twhat-requires, wr\tList packages requiring specified capability.\n" + //"\twhat-conflicts, wc\tList packages conflicting with specified capability.\n" ); static string help_lock_commands = _("\tPackage Locks:\n" @@ -1462,6 +1465,57 @@ void Zypper::processCommandOptions() break; } + case ZypperCommand::WHAT_PROVIDES_e: + { + static struct option options[] = { + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + specific_options = options; + _command_help = _( + "what-provides (wp) \n" + "\n" + "List all packages providing the specified capability.\n" + "\n" + "This command has no additional options.\n" + ); + break; + } +/* + case ZypperCommand::WHAT_REQUIRES_e: + { + static struct option options[] = { + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + specific_options = options; + _command_help = _( + "what-requires (wr) \n" + "\n" + "List all packages requiring the specified capability.\n" + "\n" + "This command has no additional options.\n" + ); + break; + } + + case ZypperCommand::WHAT_CONFLICTS_e: + { + static struct option options[] = { + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + specific_options = options; + _command_help = _( + "what-conflicts (wc) \n" + "\n" + "List all packages conflicting with the specified capability.\n" + "\n" + "This command has no additional options.\n" + ); + break; + } +*/ case ZypperCommand::MOO_e: { static struct option moo_options[] = { @@ -2370,7 +2424,7 @@ void Zypper::doCommand() break; } - // --------------------------( patches )------------------------------------ + // --------------------------( misc queries )-------------------------------- case ZypperCommand::PATCHES_e: case ZypperCommand::PATTERNS_e: @@ -2405,6 +2459,32 @@ void Zypper::doCommand() break; } + case ZypperCommand::WHAT_PROVIDES_e: + { + if (runningHelp()) { out().info(_command_help, Out::QUIET); return; } + + if (_arguments.empty()) + report_required_arg_missing(out(), _command_help); + else if (_arguments.size() > 1) + report_too_many_arguments(out(), _command_help); + + init_target(*this); + init_repos(*this); + if (exitCode() != ZYPPER_EXIT_OK) + return; + load_resolvables(*this); + + switch (command().toEnum()) + { + case ZypperCommand::WHAT_PROVIDES_e: + list_what_provides(*this, _arguments[0]); + break; + default:; + } + + break; + } + // --------------------------( list updates )------------------------------- case ZypperCommand::LIST_UPDATES_e: -- 2.7.4