- 'what-provides' command added (fate #302148)
authorJan Kupec <jkupec@suse.cz>
Thu, 17 Apr 2008 15:50:02 +0000 (15:50 +0000)
committerJan Kupec <jkupec@suse.cz>
Thu, 17 Apr 2008 15:50:02 +0000 (15:50 +0000)
src/zypper-command.cc
src/zypper-command.h
src/zypper-misc.cc
src/zypper-misc.h
src/zypper-search.cc
src/zypper-search.h
src/zypper-utils.cc
src/zypper-utils.h
src/zypper.cc

index 83adbe3..c603059 100644 (file)
@@ -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;
index a7ba59e..6a1384f 100644 (file)
@@ -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,
index 3db5dc2..a688de5 100644 (file)
@@ -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<EDITION>]
-    // transform to NAME[ OP <EDITION>] (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<bool,const zypp::PoolItem&> (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<bool,const zypp::PoolItem&> (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?
index 57ae33c..2a38726 100644 (file)
@@ -11,6 +11,7 @@
 #define ZMART_MISC_H
 
 #include <string>
+
 #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.
index dce16e6..8f2fb11 100644 (file)
@@ -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:
index dbdc742..44a130d 100644 (file)
@@ -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_*/
index a8ae4c7..98fb24e 100644 (file)
@@ -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<EDITION>]
+  // transform to NAME[ OP <EDITION>] (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();
+}
index c2f90b5..76986e4 100644 (file)
@@ -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){
index 58bd3b4..8a79ba6 100644 (file)
@@ -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) <capability>\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) <capability>\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) <capability>\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: