Imported Upstream version 1.11.60 89/109389/1 upstream/1.11.60
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Jan 2017 05:29:33 +0000 (14:29 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Jan 2017 05:29:34 +0000 (14:29 +0900)
Change-Id: I96d0c4e734e8ade7053b35602f81ab594fc76dba
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
13 files changed:
VERSION.cmake
package/zypper.changes
src/Table.cc
src/Table.h
src/Zypper.cc
src/callbacks/keyring.h
src/callbacks/rpm.h
src/locks.cc
src/output/Out.cc
src/output/Out.h
src/output/xmlout.rnc
src/repos.cc
zypper.spec.cmake

index b3d2e77..096a9ed 100644 (file)
@@ -34,7 +34,7 @@
 #
 SET(VERSION_MAJOR "1")
 SET(VERSION_MINOR "11")
-SET(VERSION_PATCH "59")
+SET(VERSION_PATCH "60")
 
-# LAST RELEASED: 1.11.59
+# LAST RELEASED: 1.11.60
 #=======
index 8ee31da..8eefbb0 100644 (file)
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Fri Dec 16 11:48:19 CET 2016 - ma@suse.de
+
+- locks: add parsable XML output (bsc#985390)
+- BuildRequires:  libzypp-devel >= 14.45.0
+- version 1.11.60
+
+-------------------------------------------------------------------
 Wed Nov 23 08:47:56 CET 2016 - ma@suse.de
 
 - Do not warn about processes using deleted files when using --root
index f2d8644..6f58cb6 100644 (file)
@@ -48,10 +48,6 @@ TableRow & TableRow::addDetail(const string& s)
   return *this;
 }
 
-unsigned int TableRow::cols( void ) const {
-  return _columns.size();
-}
-
 // 1st implementation: no width calculation, just tabs
 void TableRow::dumbDumpTo (ostream &stream) const {
   bool seen_first = false;
@@ -215,9 +211,10 @@ Table & Table::add (const TableRow& tr) {
   return *this;
 }
 
-Table & Table::setHeader (const TableHeader& tr) {
-  _has_header = true;
+Table & Table::setHeader( const TableHeader & tr )
+{
   _header = tr;
+  _has_header = !_header.empty();
   return *this;
 }
 
index 1ae3f29..c2fefd8 100644 (file)
@@ -66,8 +66,15 @@ public:
   TableRow & addDetail( const _Tp & val_r )
   { return addDetail( zypp::str::asString( val_r ) ); }
 
+  bool empty() const
+  { return _columns.empty(); }
+
   // return number of columns
-  unsigned int cols( void ) const;
+  unsigned size() const
+  { return _columns.size(); }
+
+  unsigned cols() const
+  { return size(); }
 
   //! tab separated output
   void dumbDumpTo (ostream &stream) const;
index 7913763..2759e08 100644 (file)
@@ -97,11 +97,11 @@ namespace {
 
   inline std::string legacyCLI( const std::string & old_r, const std::string & new_r, bool global_r = false )
   {
-    return boost::str( boost::formatNAC( global_r
-                                        ? _("Legacy commandline option %1% detected. Please use global option %2% instead.")
-                                        : _("Legacy commandline option %1% detected. Please use %2% instead.") )
-                    % old_r
-                    % new_r );
+    return str::FormatNAC( global_r
+                        ? _("Legacy commandline option %1% detected. Please use global option %2% instead.")
+                        : _("Legacy commandline option %1% detected. Please use %2% instead.") )
+                        % old_r
+                        % new_r;
   }
 
   inline std::string dashdash( std::string optname_r )
index d03a8bd..7e72980 100644 (file)
@@ -328,11 +328,11 @@ namespace zypp
        std::string unblock( found.substr( 0, 4 ) );
 
        zypper.out().gap();
-       // translators: !!! BOOST STYLE PLACEHOLDERS ( %N% - reorder and multiple occurance is OK )
+       // translators: !!! BOOST STYLE PLACEHOLDERS ( %N% - reorder and multiple occurrence is OK )
        // translators: %1%      - a file name
        // translators: %2%      - full path name
-       // translators: %3%, %4% - checksum strings (>60 chars), please keep them alligned
-       zypper.out().warning( boost::formatNAC(_(
+       // translators: %3%, %4% - checksum strings (>60 chars), please keep them aligned
+       zypper.out().warning( str::FormatNAC(_(
                "Digest verification failed for file '%1%'\n"
                "[%2%]\n"
                "\n"
@@ -350,9 +350,9 @@ namespace zypp
        );
        zypper.out().gap();
 
-       // translators: !!! BOOST STYLE PLACEHOLDERS ( %N% - reorder and multiple occurance is OK )
+       // translators: !!! BOOST STYLE PLACEHOLDERS ( %N% - reorder and multiple occurrence is OK )
        // translators: %1%      - abbreviated checksum (4 chars)
-       zypper.out().info( boost::formatNAC(_(
+       zypper.out().info( str::FormatNAC(_(
                "However if you made certain that the file with checksum '%1%..' is secure, correct\n"
                "and should be used within this operation, enter the first 4 characters of the checksum\n"
                "to unblock using this file on your own risk. Empty input will discard the file.\n" ) )
index b7cdf66..5be5d18 100644 (file)
@@ -32,71 +32,65 @@ namespace out
   ///////////////////////////////////////////////////////////////////
   struct FileConflictsListFormater
   {
-    typedef out::DefaultGapedListLayout ListLayout;
+    typedef out::DefaultGapedListLayout NormalLayout;
 
-    struct XmlFormater
-    {
-      std::string operator()( const sat::FileConflicts::Conflict & val_r ) const
-      { str::Str str; dumpAsXmlOn( str.stream(), val_r ); return str; }
-    };
+    std::string xmlListElement( const sat::FileConflicts::Conflict & val_r ) const
+    { str::Str str; dumpAsXmlOn( str.stream(), val_r ); return str; }
 
-    std::string operator()( const sat::FileConflicts::Conflict & val_r ) const
+    std::string listElement( const sat::FileConflicts::Conflict & val_r ) const
     { return asUserString( val_r ); }
   };
   ///////////////////////////////////////////////////////////////////
 
-  /** \relates SolvableListFormater Conversion to sat::Solvable */
-  template <class _Tp>
-  sat::Solvable asSolvable( const _Tp & val_r )
-  { return sat::asSolvable( val_r ); }
-
-  sat::Solvable asSolvable( int val_r )                // e.g. satQueues use int as SolvabeId
-  { return sat::Solvable( val_r ); }
-
   ///////////////////////////////////////////////////////////////////
   /// \class SolvableListFormater
   /// \brief Printing Solvable based types in List (legacy format used in summary)
   ///////////////////////////////////////////////////////////////////
   struct SolvableListFormater
   {
-    typedef out::CompressedListLayout ListLayout;
+    typedef out::CompressedListLayout NormalLayout;
 
-    struct XmlFormater
-    {
-      template <class _Tp>
-      std::string operator()( const _Tp & val_r ) const
-      { return operator()( makeResObject( asSolvable( val_r ) ) ); }
+    template <class Tp_>
+    std::string xmlListElement( const Tp_ & val_r ) const
+    { return xmlListElement( makeResObject( asSolvable( val_r ) ) ); }
 
-      std::string operator()( ResObject::Ptr val_r, ResObject::Ptr old_r = nullptr ) const
+    std::string xmlListElement( const ResObject::Ptr & val_r ) const
+    {
+      str::Str ret;
+      ret << "<solvable";
+      ret << " type=\""        << val_r->kind() << "\"";
+      ret << " name=\""        << val_r->name() << "\"";
+      ret << " edition=\""     << val_r->edition() << "\"";
+      ret << " arch=\""        << val_r->arch() << "\"";
       {
-       str::Str ret;
-       ret << "<solvable";
-       ret << " type=\""       << val_r->kind() << "\"";
-       ret << " name=\""       << val_r->name() << "\"";
-       ret << " edition=\""    << val_r->edition() << "\"";
-       ret << " arch=\""       << val_r->arch() << "\"";
-       {
-         const std::string & text( val_r->summary() );
-         if ( ! text.empty() )
-           ret << " summary=\"" << xml::escape( text ) << "\"";
-       }
-       {
-         const std::string & text( val_r->description() );
-         if ( ! text.empty() )
-           ret << ">\n" << "<description>" << xml::escape( text ) << "</description>" << "</solvable>";
-         else
-           ret << "/>";
-       }
-       return ret;
+       const std::string & text( val_r->summary() );
+       if ( ! text.empty() )
+         ret << " summary=\"" << xml::escape( text ) << "\"";
+      }
+      {
+       const std::string & text( val_r->description() );
+       if ( ! text.empty() )
+         ret << ">\n" << "<description>" << xml::escape( text ) << "</description>" << "</solvable>";
+       else
+         ret << "/>";
       }
-    };
+      return ret;
+    }
 
-    template <class _Tp>
-    std::string operator()( const _Tp & val_r ) const
-    { return operator()( makeResObject( asSolvable( val_r ) ) ); }
+    template <class Tp>
+    std::string listElement( const Tp & val_r ) const
+    { return listElement( makeResObject( asSolvable( val_r ) ) ); }
 
-    std::string operator()( ResObject::Ptr val_r, ResObject::Ptr old_r = nullptr ) const
+    std::string listElement( const ResObject::Ptr & val_r ) const
     { return val_r->ident().asString(); }
+
+  private:
+    template <class Tp_>
+    static sat::Solvable asSolvable( const Tp_ & val_r )
+    { return sat::asSolvable( val_r ); }
+
+    static sat::Solvable asSolvable( int val_r )               // e.g. satQueues use int as SolvabeId
+    { return sat::Solvable( val_r ); }
   };
 
 } // namespace out
@@ -392,7 +386,7 @@ struct FindFileConflictstReportReceiver : public zypp::callback::ReceiveReport<z
 
       if ( ! noFilelist_r.empty() )    // warning
       {
-       out.warning( boost::formatNAC(
+       out.warning( str::FormatNAC(
                       // TranslatorExplanation %1%(commandline option)
                       _("Checking for file conflicts requires not installed packages to be downloaded in advance "
                         "in order to access their file lists. See option '%1%' in the zypper manual page for details.")
index 31e4c46..3286f72 100644 (file)
 using namespace zypp;
 
 ///////////////////////////////////////////////////////////////////
-namespace
+namespace out
 {
-  inline std::string get_string_for_table( const std::set<std::string> & attrvals )
+  struct LocksTableFormater : public TableFormater
   {
-    std::string ret;
-    if ( attrvals.empty() )
-      ret = _("(any)");
-    else if ( attrvals.size() > 1 )
-      ret = _("(multiple)");
-    else
-      ret = *attrvals.begin();
-    return ret;
-  }
-
-  inline int compareByN( const sat::Solvable & lhs, const sat::Solvable & rhs )        // from zypp::sat::
-  {
-    int res = 0;
-    if ( lhs != rhs )
+  private:
+    /** LESS compare for MatchDetails */
+    struct MatchDetailCompare
     {
-      if ( (res = lhs.kind().compare( rhs.kind() )) == 0 )
-       res = lhs.name().compare( rhs.name() );
-    }
-    return res;
-  }
-
-  inline std::string getLockDetails( const PoolQuery & q )
-  {
-    if ( q.empty() )
-      return "";
+      bool operator()( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
+      { return( doComapre( lhs, rhs ) < 0 ); }
 
-    PropertyTable p;
-    {
-      struct DoCompare
+      int doComapre( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
       {
-       int operator()( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
-       { return( doComapre( lhs, rhs ) < 0 ); }
-
-       int doComapre( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
-       {
-         // return zypp::sat::compareByNVRA( lhs, rhs );
-         // do N(<) A(>) VR(>)
-         int res = compareByN( lhs, rhs );                     // ascending  l<r
-         if ( res == 0 )
-           res = rhs.arch().compare( lhs.arch() );             // descending r<l
+       // do N(<) A(>) VR(>)
+       int res = sat::compareByN( lhs, rhs );                  // ascending  l<r
+       if ( res == 0 )
+         res = rhs.arch().compare( lhs.arch() );               // descending r<l
          if ( res == 0 )
            res = rhs.edition().compare( lhs.edition() );       // descending r<l
-         if ( res == 0 )
-           res = lhs.repository().asUserString().compare( rhs.repository().asUserString() );   // ascending  l<r
-         return res;
-       }
-      };
-      std::set<sat::Solvable,DoCompare> i;
-      std::set<sat::Solvable,DoCompare> a;
-      for ( const auto & solv : q )
-      { (solv.isSystem()?i:a).insert( solv ); }
-
-      std::vector<std::string> names;
-      names.reserve( std::max( i.size(), a.size() ) );
-
-      if ( ! i.empty() )
-      {
-       //names.clear();
-       for ( const auto & solv : i )
-       { names.push_back( solv.asUserString() ); }
-       // translators: property name; short; used like "Name: value"
-       p.add( _("Keep installed"), names );
+           if ( res == 0 )
+             res = lhs.repository().asUserString().compare( rhs.repository().asUserString() ); // ascending  l<r
+             return res;
       }
-      if ( ! a.empty() )
+    };
+    /** Ordered MatchDetails */
+    typedef std::set<sat::Solvable,MatchDetailCompare> MatchDetails;
+
+    /** MatchDetail representation */
+    struct MatchDetailFormater
+    {
+      std::string xmlListElement( const sat::Solvable & match_r ) const
       {
-       names.clear();
-       for ( const auto & solv : a )
-       { names.push_back( solv.asUserString() ); }
-       // translators: property name; short; used like "Name: value"
-       p.add( _("Do not install"), names );
+       str::Str str;
+       {
+         xmlout::Node lock( str.stream(), "match", {
+           { "kind",           match_r.kind()  },
+           { "name",           match_r.name()  },
+           { "edition",        match_r.edition()       },
+           { "arch",           match_r.arch()  },
+           { "installed",      match_r.isSystem()      },
+           { "repo",           match_r.repository().alias()    },
+         } );
+       }
+       return str;
       }
-    }
-    return str::Str() << p;
-  }
+    };
 
-} //namespace
-///////////////////////////////////////////////////////////////////
+  public:
+    std::string xmlListElement( const PoolQuery & q_r ) const
+    {
+      str::Str str;
+      // <lock>
+      {
+       ++_i;
+       xmlout::Node lock( str.stream(), "lock", { { "number", _i } } );
 
-void list_locks(Zypper & zypper)
-{
-  shared_ptr<ListLocksOptions> listLocksOptions = zypper.commandOptionsOrDefaultAs<ListLocksOptions>();
+       // <name> (solvable_name)
+       for ( const std::string & val : q_r.attribute( sat::SolvAttr::name ) )
+       { *xmlout::Node( *lock, "name" ) << val; }
+       // <name> (query_string)
+       for ( const std::string & val : q_r.strings() )
+       { *xmlout::Node( *lock, "name" ) << val; }
 
-  bool withSolvables = listLocksOptions->_withSolvables;
-  bool withMatches = withSolvables||listLocksOptions->_withMatches;
+       // <type>
+       for ( const ResKind & kind : q_r.kinds() )
+       { *xmlout::Node( *lock, "type" ) << kind; }
 
-  try
-  {
-    Locks & locks = Locks::instance();
-    locks.read( Pathname::assertprefix( zypper.globalOpts().root_dir, ZConfig::instance().locksFile() ) );
+       // <repo>
+       for ( const std::string & repo : q_r.repos() )
+       { *xmlout::Node( *lock, "repo" ) << repo; }
 
-    Table t;
+       if ( _withMatches )
+       {
+         // <matches>
+         xmlout::Node matches( *lock, "matches", xmlout::Node::optionalContent, { { "size", q_r.size() } } );
+         if ( _withSolvables && !q_r.empty() )
+         {
+           MatchDetails d;
+           getLockDetails( q_r, d );
+           xmlWriteContainer( *matches, d, MatchDetailFormater() );
+         }
+       }
+      }
+      return str;
+    }
 
-    TableHeader th;
-    th << "#" << _("Name");
-    if ( withMatches )
-      th << _("Matches");
-    if (zypper.globalOpts().is_rug_compatible)
-      th << _("Repository") << _("Importance");
-    else
+    TableHeader header() const
+    {
+      TableHeader th;
+      th << "#" << _("Name");
+      if ( _withMatches )
+       th << _("Matches");
       th << _("Type") << _("Repository");
+      return th;
+    }
 
-    t << th;
-
-    unsigned i = 0;
-    for ( const PoolQuery & q : locks )
+    TableRow row( const PoolQuery & q_r ) const
     {
       TableRow tr;
-      ++i;
 
       // #
-      tr << str::numstring( i );
+      ++_i;
+      tr << str::numstring( _i );
 
-      // name
-      const PoolQuery::StrContainer & nameStings( q.attribute( sat::SolvAttr::name ) );
-      const PoolQuery::StrContainer & globalStrings( q.strings() );
+      // Name
+      const PoolQuery::StrContainer & nameStings( q_r.attribute( sat::SolvAttr::name ) );
+      const PoolQuery::StrContainer & globalStrings( q_r.strings() );
 
       if ( nameStings.size() + globalStrings.size() > 1 )
         // translators: locks table value
@@ -147,51 +135,103 @@ void list_locks(Zypper & zypper)
         tr << *nameStings.begin();
 
       // opt Matches
-      if ( withMatches )
-       tr << q.size();
+      if ( _withMatches )
+       tr << q_r.size();
 
+      // Type
       std::set<std::string> strings;
-      if (zypper.globalOpts().is_rug_compatible)
-      {
-        // repository
-        copy(q.repos().begin(), q.repos().end(), inserter(strings, strings.end()));
-        tr << get_string_for_table(strings);
-        // importance
-        tr << _("(any)");
-      }
-      else
-      {
-       // type
-       for ( const ResKind & kind : q.kinds() )
-         strings.insert( kind.asString() );
-       tr << get_string_for_table( strings );
-
-       // repo
-       strings.clear();
-       copy( q.repos().begin(), q.repos().end(), inserter(strings, strings.end()) );
-       tr << get_string_for_table( strings );
-      }
-      
-      // opt Solvables
-      if ( withSolvables )
+      for ( const ResKind & kind : q_r.kinds() )
+       strings.insert( kind.asString() );
+      tr << get_string_for_table( strings );
+
+      // Repository
+      strings.clear();
+      copy( q_r.repos().begin(), q_r.repos().end(), inserter(strings, strings.end()) );
+      tr << get_string_for_table( strings );
+
+      // opt Solvables as detail
+      if ( _withSolvables && !q_r.empty() )
       {
-       tr.addDetail( getLockDetails( q ) );
+       MatchDetails i;
+       MatchDetails a;
+       getLockDetails( q_r, i, a );
+
+       PropertyTable p;
+       {
+         std::vector<std::string> names;
+         names.reserve( std::max( i.size(), a.size() ) );
+         if ( ! i.empty() )
+         {
+           //names.clear();
+           for ( const auto & solv : i )
+           { names.push_back( solv.asUserString() ); }
+           // translators: property name; short; used like "Name: value"
+           p.add( _("Keep installed"), names );
+         }
+         if ( ! a.empty() )
+         {
+           names.clear();
+           for ( const auto & solv : a )
+           { names.push_back( solv.asUserString() ); }
+           // translators: property name; short; used like "Name: value"
+           p.add( _("Do not install"), names );
+         }
+       }
+       tr.addDetail( str::Str() << p );
       }
+      return tr;
+    }
+
+    LocksTableFormater( shared_ptr<ListLocksOptions> listLocksOptions_r )
+    : _withSolvables( listLocksOptions_r->_withSolvables )
+    , _withMatches( _withSolvables || listLocksOptions_r->_withMatches )
+    {}
 
-      t << tr;
+  private:
+    static std::string get_string_for_table( const std::set<std::string> & attrvals_r )
+    {
+      std::string ret;
+      if ( attrvals_r.empty() )
+       ret = _("(any)");
+      else if ( attrvals_r.size() > 1 )
+       ret = _("(multiple)");
+      else
+       ret = *attrvals_r.begin();
+      return ret;
     }
 
-    if (t.empty())
-      zypper.out().info(_("There are no package locks defined."));
-    else
-      cout << t;
+    static void getLockDetails( const PoolQuery & q_r, MatchDetails & i_r, MatchDetails & a_r )
+    { for ( const auto & solv : q_r ) { (solv.isSystem()?i_r:a_r).insert( solv ); } }
+
+    static void getLockDetails( const PoolQuery & q_r, MatchDetails & d_r )
+    { getLockDetails( q_r, d_r, d_r ); }
+
+  private:
+    bool _withSolvables        :1;     //< include match details (implies _withMatches)
+    bool _withMatches  :1;     //< include number of matches
+    mutable unsigned _i = 0;   //< Lock Number
+  };
+} //namespace out
+///////////////////////////////////////////////////////////////////
+
+void list_locks( Zypper & zypper )
+{
+  Locks & locks( Locks::instance() );
+  try
+  {
+    locks.read( Pathname::assertprefix( zypper.globalOpts().root_dir, ZConfig::instance().locksFile() ) );
   }
-  catch(const Exception & e)
+  catch( const Exception & e )
   {
-    ZYPP_CAUGHT(e);
-    zypper.out().error(e, _("Error reading the locks file:"));
-    zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
+    throw( Out::Error( ZYPPER_EXIT_ERR_ZYPP, _("Error reading the locks file:"), e ) );
   }
+
+  // show result
+  Out & out( zypper.out() );
+  out.gap();
+  out.table( "locks", locks.empty() ? _("There are no package locks defined.") : "",
+            locks, out::LocksTableFormater( zypper.commandOptionsOrDefaultAs<ListLocksOptions>() ) );
+  out.gap();
 }
 
 template <typename Target, typename Source>
index 3a5f3f7..72fb530 100644 (file)
 
 #include "Zypper.h"
 
+///////////////////////////////////////////////////////////////////
+namespace out
+{
+  unsigned defaultTermwidth()
+  { return Zypper::instance()->out().termwidth(); }
+} // namespace out
+///////////////////////////////////////////////////////////////////
+
 ////////////////////////////////////////////////////////////////////////////////
 //     class TermLine
 ////////////////////////////////////////////////////////////////////////////////
@@ -129,3 +137,19 @@ int Out::Error::report( Zypper & zypper_r ) const
     zypper_r.setExitCode( _exitcode );
   return zypper_r.exitCode();
 }
+
+std::string Out::Error::combine( std::string && msg_r, const zypp::Exception & ex_r )
+{
+  if ( msg_r.empty() )
+  {
+    msg_r = combine( ex_r );
+  }
+  else
+  {
+    msg_r += "\n";
+    msg_r += combine( ex_r );
+  }
+  return std::move(msg_r);
+}
+std::string Out::Error::combine( const zypp::Exception & ex_r )
+{ return Zypper::instance()->out().zyppExceptionReport( ex_r ); }
index 0126571..9b83dee 100644 (file)
 #include "utils/richtext.h"
 #include "output/prompt.h"
 
+inline char * asYesNo( bool val_r ) { return val_r ? _("Yes") : _("No"); }
+#include "Table.h"
+#define OSD ColorStream( std::cout, ColorContext::OSDEBUG )
+
 using namespace zypp;
 
-class Table;
 class Zypper;
 
-#define OSD ColorStream( std::cout, ColorContext::OSDEBUG )
-
-inline char * asYesNo( bool val_r )
-{ return val_r ? _("Yes") : _("No"); }
-
 ///////////////////////////////////////////////////////////////////
 namespace out
 {
   static constexpr unsigned termwidthUnlimited = 0u;
+  unsigned defaultTermwidth(); // Zypper::instance()->out().termwidth()
 } // namespace out
 ///////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////
 namespace out
 {
-  /** \relates ListFormater NORMAL representation of types in lists [no default] */
-  template <class _Tp>
-  std::string asListElement( const _Tp & val_r );
-
-  /** \relates ListFormater XML representation of types in lists [no default] */
-  template <class _Tp>
-  std::string asXmlListElement( const _Tp & val_r );
-
   ///////////////////////////////////////////////////////////////////
   /// \class ListLayout
   /// \brief Basic list layout
@@ -59,6 +50,8 @@ namespace out
   ///////////////////////////////////////////////////////////////////
   struct ListLayout
   {
+    template <class TFormater> struct Writer;
+
     ListLayout( bool singleline_r, bool wrapline_r, bool gaped_r, unsigned indent_r )
     : _singleline( singleline_r )
     , _wrapline( wrapline_r )
@@ -76,6 +69,7 @@ namespace out
     template <bool _Singleline, bool _Wrapline, bool _Gaped, unsigned _Indent>
     struct ListLayoutInit : public ListLayout { ListLayoutInit() : ListLayout( _Singleline, _Wrapline, _Gaped, _Indent ) {} };
   }
+
   typedef detail::ListLayoutInit<true, false,false, 0U>        XmlListLayout;
   typedef detail::ListLayoutInit<true, true, false, 0U>        DefaultListLayout;      ///< one element per line, no indent
   typedef detail::ListLayoutInit<true, true, true,  0U>        DefaultGapedListLayout; ///< one element per line, no indent, gaped
@@ -84,29 +78,102 @@ namespace out
   typedef detail::ListLayoutInit<false,true, false, 2U>        CompressedListLayout;   ///< multiple elements per line, indented
 
   ///////////////////////////////////////////////////////////////////
-  /// \class ListFormater
-  /// \brief Default representation of types in Lists [asListElement|asXmlListElement]
+  /// \class TableLayout
+  /// \brief Basic table layout
   ///////////////////////////////////////////////////////////////////
-  struct ListFormater
+  struct TableLayout
   {
-    typedef DefaultListLayout ListLayout;      //< ListLayout for NORMAL lists
+    template <class TFormater> struct Writer;
+  };
 
-    struct XmlFormater                         //< XML representation of element
-    {
-      template <class _Tp>
-      std::string operator()( const _Tp & val_r ) const
-      { return asXmlListElement( val_r ); }
-    };
+  typedef TableLayout  DefaultTableLayout;     ///< Simple Table
+
+  ///////////////////////////////////////////////////////////////////
+  // Either specialize per Type or define a custom Formater:
 
-    template <class _Tp>                       //< NORMAL representation of element
-    std::string operator()( const _Tp & val_r ) const
+  /** \relates XmlFormater XML representation of types [no default] */
+  template <class Tp>
+  std::string asXmlListElement( const Tp & val_r );
+  inline std::string asXmlListElement( const std::string & val_r ){ return val_r; }
+  inline std::string asXmlListElement( const char * val_r )    { return val_r; }
+
+  /** \relates ListFormater NORMAL representation of types in lists [no default] */
+  template <class Tp>
+  std::string asListElement( const Tp & val_r );
+  inline std::string asListElement( const std::string & val_r )        { return val_r; }
+  inline std::string asListElement( const char * val_r )       { return val_r; }
+
+  /** \relates TableFormater NORMAL representation of types as TableHeader [no default] */
+  template <class Tp = void>
+  TableHeader asTableHeader();
+
+  template <>
+  inline TableHeader asTableHeader<void>()
+  { return TableHeader(); }
+
+  /** \relates TableFormater NORMAL representation of types as TableRow [no default] */
+  template <class Tp>
+  TableRow asTableRow( const Tp & val_r );
+
+  ///////////////////////////////////////////////////////////////////
+  /// \class XmlFormater
+  /// \brief XML representation of types in container [asXmlListElement]
+  ///////////////////////////////////////////////////////////////////
+  struct XmlFormater
+  {
+    template <class Tp>
+    std::string xmlListElement( const Tp & val_r ) const//< XML representation of element
+    { return asXmlListElement( val_r ); }
+  };
+
+  ///////////////////////////////////////////////////////////////////
+  /// \class ListFormater
+  /// \brief Default representation of types in Lists [asListElement]
+  ///////////////////////////////////////////////////////////////////
+  struct ListFormater : public XmlFormater
+  {
+    typedef DefaultListLayout  NormalLayout;           //< ListLayout for NORMAL lists
+
+    template <class Tp>
+    std::string listElement( const Tp & val_r ) const  //< NORMAL representation of list element
     { return asListElement( val_r ); }
+  };
+
+  ///////////////////////////////////////////////////////////////////
+  /// \class TableFormater
+  /// \brief Special list formater writing a Table [asTableHeader|asTableRow]
+  ///////////////////////////////////////////////////////////////////
+  struct TableFormater : public XmlFormater
+  {
+    typedef DefaultTableLayout NormalLayout;           //< NORMAL layout as Table
 
-    std::string operator()( const std::string & val_r ) const
-    { return val_r; }
+    TableHeader header() const                         //< TableHeader for TableRow representation
+    { return asTableHeader<>(); }
+
+    template <class Tp>                                        //< Representation as TableRow
+    TableRow row( const Tp & val_r ) const
+    { return asTableRow( val_r ); }
+  };
 
-    std::string operator()( const char * val_r ) const
-    { return val_r; }
+  ///////////////////////////////////////////////////////////////////
+  /// \class XmlFormaterAdaptor
+  /// \brief Adaptor mapping xmlListElement->listElement for container XML output
+  ///////////////////////////////////////////////////////////////////
+   /** Adaptor */
+  template <class TFormater>
+  struct XmlFormaterAdaptor
+  {
+    typedef XmlListLayout      NormalLayout;           //< Layout as XML list
+
+    template <class Tp>
+    std::string listElement( const Tp & val_r ) const  //< use TFormater::asXmlListElement
+    { return _formater.xmlListElement( val_r ); }
+
+    XmlFormaterAdaptor( const TFormater & formater_r )
+    : _formater( formater_r )
+    {}
+  private:
+    const TFormater & _formater;
   };
 
 } // namespace out
@@ -115,65 +182,125 @@ namespace out
 ///////////////////////////////////////////////////////////////////
 namespace out
 {
-  namespace detail
+  ///////////////////////////////////////////////////////////////////
+  /// \class ListLayout::Writer
+  /// \brief Write out a List according to the layout
+  // TODO: wrap singlelines; support for attributed text;
+  ///////////////////////////////////////////////////////////////////
+  template <class TFormater>
+  struct ListLayout::Writer
   {
-    // TODO: wrap singlelines; support for atttibuted text;
-    struct BasicList
-    {
-      NON_COPYABLE( BasicList );
+    NON_COPYABLE( Writer );
+
+    Writer( std::ostream & str_r, ListLayout layout_r, const TFormater & formater_r )
+    : _str( str_r )
+    , _layout( layout_r )
+    , _formater( formater_r )
+    , _linewidth( defaultTermwidth() )
+    , _indent( _layout._indent, ' ' )
+    {}
 
-      BasicList( ListLayout layout_r, unsigned linewidth_r )
-      : _layout( std::move(layout_r) )
-      , _linewidth( linewidth_r )
-      , _indent( _layout._indent, ' ' )
-      , _cpos( 0U )
-      {}
+    ~Writer()
+    { if ( !_layout._singleline && _cpos ) _str << std::endl; }
 
-      ~BasicList()
-      { if ( !_layout._singleline && _cpos ) std::cout << std::endl; }
+    template <class Tp>
+    void operator<<( Tp && val_r ) const
+    {
+      const std::string & element( _formater.listElement( std::forward<Tp>(val_r) ) );
 
-      void print( const std::string & val_r )
+      if ( _layout._singleline )
+      {
+       if ( _layout._gaped )
+         _str << std::endl;
+       _str << _indent << element << std::endl;
+      }
+      else
       {
-       if ( _layout._singleline )
+       if ( _cpos != 0 && ! fitsOnLine( 1/*' '*/ + element.size() ) )
+         endLine();
+
+       if ( _cpos == 0 )
        {
-         if ( _layout._gaped )
-           std::cout << std::endl;
-         std::cout << _indent << val_r << std::endl;
+         if ( !_indent.empty() )
+           printAndCount( _indent );
        }
        else
-       {
-         if ( _cpos != 0 && ! fitsOnLine( 1/*' '*/ + val_r.size() ) )
-           endLine();
-
-         if ( _cpos == 0 )
-         {
-           if ( !_indent.empty() )
-             printAndCount( _indent );
-         }
-         else
-           printAndCount( " " );
-
-         printAndCount( val_r );
-       }
+         printAndCount( " " );
+
+       printAndCount( element );
       }
+    }
 
-    private:
-      bool fitsOnLine( unsigned val_r )
-      { return( !_layout._wrapline || _linewidth == out::termwidthUnlimited || _cpos + val_r <= _linewidth ); }
+  private:
+    bool fitsOnLine( unsigned size_r ) const
+    { return( !_layout._wrapline || _linewidth == out::termwidthUnlimited || _cpos + size_r <= _linewidth ); }
 
-      void printAndCount( const std::string & val_r )
-      { _cpos += val_r.size(); std::cout << val_r; }
+    void printAndCount( const std::string & element_r ) const
+    { _cpos += element_r.size(); _str << element_r; }
 
-      void endLine()
-      { std::cout << std::endl; _cpos = 0U; }
+    void endLine() const
+    { _str << std::endl; _cpos = 0U; }
 
-    private:
-      const ListLayout _layout;
-      unsigned         _linewidth;     ///< desired line width
-      const std::string        _indent;
-      unsigned         _cpos;
-    };
+  private:
+    std::ostream &     _str;
+    const ListLayout & _layout;
+    const TFormater &  _formater;
+    const unsigned     _linewidth;     ///< desired line width
+    const std::string  _indent;
+    mutable unsigned   _cpos = 0U;
+  };
+
+  ///////////////////////////////////////////////////////////////////
+  /// \class TableLayout::Writer
+  /// \brief Write out a Table according to the layout
+  ///////////////////////////////////////////////////////////////////
+  template <class TFormater>
+  struct TableLayout::Writer
+  {
+    NON_COPYABLE( Writer );
+
+    Writer( std::ostream & str_r, const TableLayout & layout_r, const TFormater & formater_r )
+    : _str( str_r )
+    , _layout( layout_r )
+    , _formater( formater_r )
+    {}
+
+    ~Writer()
+    {
+      if ( !_t.empty() )
+      {
+       _t.setHeader( _formater.header() );
+       _str << _t;
+      }
+    }
+
+    template <class Tp>
+    void operator<<( Tp && val_r ) const
+    { _t.add( _formater.row( std::forward<Tp>(val_r) ) ); }
+
+  private:
+    std::ostream &     _str;
+    const TableLayout &        _layout;
+    const TFormater &  _formater;
+    mutable Table      _t;
+  };
+
+
+  /** Write formated container to stream */
+  template <class TContainer, class TFormater, class TLayout = typename TFormater::NormalLayout>
+  void writeContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r, const TLayout & layout_r = TLayout() )
+  {
+    typedef typename TLayout::template Writer<TFormater> Writer;
+    Writer writer( str_r, layout_r, formater_r );
+    for ( auto && el : container_r )
+      writer << el;
   }
+
+  /** Write XML formated container to stream */
+  template <class TContainer, class TFormater>
+  void xmlWriteContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r )
+  { writeContainer( str_r, container_r, out::XmlFormaterAdaptor<TFormater>(formater_r) ); }
+
 } // namespace out
 ///////////////////////////////////////////////////////////////////
 
@@ -360,74 +487,40 @@ public:
     { if ( out().typeNORMAL() && ! title_r.empty() ) std::cout << title_r << std::endl; }
   };
 
-  ///////////////////////////////////////////////////////////////////
-  /// \class List<ListFormater>
-  /// \brief Printing a list
-  ///////////////////////////////////////////////////////////////////
-  template <class _ListFormater = out::ListFormater>
-  struct List : protected ParentOut
-  {
-    List( Out & out_r, _ListFormater formater_r, out::ListLayout layout_r = typename _ListFormater::ListLayout() )
-    : ParentOut( out_r ), _formater( std::move(formater_r) ), _base( std::move(layout_r), out_r.termwidth() )
-    {}
-
-    template <class _Tp>
-    List & operator<<( _Tp && val_r )
-    { _base.print( _formater( std::forward<_Tp>(val_r) ) ); return *this; }
-
-  private:
-    _ListFormater _formater;
-    out::detail::BasicList _base;
-  };
-  ///////////////////////////////////////////////////////////////////
-
-public:
-  /** Write list from iterator pair */
-  template <class _Iterator, class _ListFormater = out::ListFormater>
-  void list( _Iterator begin_r, _Iterator end_r, _ListFormater && formater_r = _ListFormater() )
+private:
+  /** Write container creating a TitleNode with \c size="nnn" attribue and
+   * replacing optional \c %1% in \a title_r with size. */
+  template <class TContainer, class TFormater>
+  void container( const std::string & nodeName_r, const std::string & title_r,
+                 const TContainer & container_r, const TFormater & formater_r )
   {
+    TitleNode guard( XmlNode( *this, nodeName_r, XmlNode::Attr( "size", str::numstring( container_r.size() ) ) ),
+                    str::FormatNAC( title_r ) % container_r.size() );
     switch ( type() )
     {
       case TYPE_NORMAL:
-      {
-       List<_ListFormater> mlist( *this, std::forward<_ListFormater>(formater_r) );
-       for_( it, begin_r, end_r ) mlist << ( *it );
-      }
-      break;
+       writeContainer( std::cout, container_r, formater_r );
+       break;
       case TYPE_XML:
-      {
-       typedef typename _ListFormater::XmlFormater XmlFormater;
-       List<XmlFormater> mlist( *this, XmlFormater(), out::XmlListLayout() );
-       for_( it, begin_r, end_r ) mlist << ( *it );
-      }
-      break;
+       xmlWriteContainer( std::cout, container_r, formater_r );
+       break;
     }
   }
 
-  /** Write list from constainer */
-  template <class _Container, class _ListFormater = out::ListFormater>
-  void list( const _Container & container_r, _ListFormater && formater_r = _ListFormater() )
-  { list( container_r.begin(), container_r.end(), std::forward<_ListFormater>(formater_r) ); }
-
-  /** Write list from iterator pair enclosed by a \ref Node */
-  template <class _Iterator, class _ListFormater = out::ListFormater>
-  void list( XmlNode && node_r, _Iterator begin_r, _Iterator end_r, _ListFormater && formater_r = _ListFormater() )
-  { XmlNode guard( std::move(node_r) ); list( begin_r, end_r, std::forward<_ListFormater>(formater_r) ); }
-
-  /** Write list from constainer enclosed by a \ref Node */
-  template <class _Container, class _ListFormater = out::ListFormater>
-  void list( XmlNode && node_r, const _Container & container_r, _ListFormater && formater_r = _ListFormater() )
-  { XmlNode guard( std::move(node_r) ); list( container_r.begin(), container_r.end(), std::forward<_ListFormater>(formater_r) ); }
-
+public:
   /** Write list from container creating a TitleNode with \c size="nnn" attribue and
    * replacing optional \c %1% in \a title_r with size. */
-  template <class _Container, class _ListFormater = out::ListFormater>
-  void list( const std::string & nodeName_r, const std::string & title_r, const _Container & container_r, _ListFormater && formater_r = _ListFormater() )
-  {
-    TitleNode guard( XmlNode( *this, nodeName_r, XmlNode::Attr( "size", str::numstring( container_r.size() ) ) ),
-                    (boost::formatNAC( title_r ) % container_r.size()).str() );
-    list( container_r, std::forward<_ListFormater>(formater_r) );
-  }
+  template <class TContainer, class TFormater = out::ListFormater>
+  void list( const std::string & nodeName_r, const std::string & title_r,
+            const TContainer & container_r, const TFormater & formater_r = TFormater() )
+  { container( nodeName_r, title_r, container_r, formater_r ); }
+
+  /** Write table from container creating a TitleNode with \c size="nnn" attribue and
+   * replacing optional \c %1% in \a title_r with size. */
+  template <class TContainer, class TFormater = out::TableFormater>
+  void table( const std::string & nodeName_r, const std::string & title_r,
+             const TContainer & container_r, const TFormater & formater_r = TFormater() )
+  { container( nodeName_r, title_r, container_r, formater_r ); }
 
 public:
   /** NORMAL: An empty line */
@@ -481,8 +574,8 @@ public:
     ~Info()
     { out().info( _str->str() ); }
 
-    template<class _Tp>
-    std::ostream & operator<<( const _Tp & val )
+    template<class Tp>
+    std::ostream & operator<<( const Tp & val )
     { return (*_str) << val; /*return *this;*/ }
 
    private:
@@ -707,10 +800,11 @@ public:
     return ret;
   }
 
-protected:
   /** Width for formated output [0==unlimited]. */
   virtual unsigned termwidth() const { return out::termwidthUnlimited; }
 
+protected:
+
   /**
    * Determine whether the output is intended for the particular type.
    */
@@ -1027,23 +1121,58 @@ struct Out::Error
   Error( int exitcode_r )
   : _exitcode( exitcode_r ) {}
 
-  Error( int exitcode_r, const std::string & msg_r, const std::string & hint_r = std::string() )
-  : _exitcode( exitcode_r ) , _msg( msg_r ) , _hint( hint_r ) {}
-  Error( int exitcode_r, const boost::format & msg_r, const std::string & hint_r = std::string() )
-  : _exitcode( exitcode_r ) , _msg( boost::str( msg_r ) ) , _hint( hint_r ) {}
-  Error( int exitcode_r, const std::string & msg_r, const boost::format & hint_r )
-  : _exitcode( exitcode_r ) , _msg( msg_r ) , _hint(  boost::str( hint_r ) ) {}
+  // basic: code msg hint
+  Error( int exitcode_r, std::string msg_r, std::string hint_r = std::string() )
+  : _exitcode( exitcode_r ), _msg( std::move(msg_r) ), _hint( std::move(hint_r) ) {}
+  Error( int exitcode_r, const boost::format & msg_r, std::string hint_r = std::string() )
+  : _exitcode( exitcode_r ), _msg( boost::str( msg_r ) ), _hint( std::move(hint_r) ) {}
+  Error( int exitcode_r, std::string msg_r, const boost::format & hint_r )
+  : _exitcode( exitcode_r ), _msg( std::move(msg_r) ), _hint( boost::str( hint_r ) ) {}
   Error( int exitcode_r, const boost::format & msg_r, const boost::format & hint_r )
-  : _exitcode( exitcode_r ) , _msg( boost::str( msg_r ) ) , _hint( boost::str( hint_r ) ) {}
-
-  Error( const std::string & msg_r, const std::string & hint_r = std::string() )
-  : _exitcode( ZYPPER_EXIT_OK ) , _msg( msg_r ) , _hint( hint_r ) {}
-  Error( const boost::format & msg_r, const std::string & hint_r = std::string() )
-  : _exitcode( ZYPPER_EXIT_OK ) , _msg( boost::str( msg_r ) ) , _hint( hint_r ) {}
-  Error( const std::string & msg_r, const boost::format & hint_r )
-  : _exitcode( ZYPPER_EXIT_OK ) , _msg( msg_r ) , _hint(  boost::str( hint_r ) ) {}
+  : _exitcode( exitcode_r ), _msg( boost::str( msg_r ) ), _hint( boost::str( hint_r ) ) {}
+
+  // code exception hint
+  Error( int exitcode_r, const zypp::Exception & ex_r, std::string hint_r = std::string() )
+  : _exitcode( exitcode_r ), _msg( combine( ex_r ) ), _hint( std::move(hint_r) ) {}
+  Error( int exitcode_r, const zypp::Exception & ex_r, const boost::format & hint_r )
+  : _exitcode( exitcode_r ), _msg( combine( ex_r ) ), _hint( boost::str( hint_r ) ) {}
+
+  // code (msg exception) hint
+  Error( int exitcode_r, std::string msg_r, const zypp::Exception & ex_r, std::string hint_r = std::string() )
+  : _exitcode( exitcode_r ), _msg( combine( std::move(msg_r), ex_r ) ), _hint( std::move(hint_r) ) {}
+  Error( int exitcode_r, const boost::format & msg_r, const zypp::Exception & ex_r, std::string hint_r = std::string() )
+  : _exitcode( exitcode_r ), _msg( combine( boost::str( msg_r ), ex_r ) ), _hint( std::move(hint_r) ) {}
+  Error( int exitcode_r, std::string msg_r, const zypp::Exception & ex_r, const boost::format & hint_r )
+  : _exitcode( exitcode_r ), _msg( combine( std::move(msg_r), ex_r ) ), _hint( boost::str( hint_r ) ) {}
+  Error( int exitcode_r, const boost::format & msg_r, const zypp::Exception & ex_r, const boost::format & hint_r )
+  : _exitcode( exitcode_r ), _msg( combine( boost::str( msg_r ), ex_r ) ), _hint( boost::str( hint_r ) ) {}
+
+
+  // as above but without code ZYPPER_EXIT_OK
+  Error( std::string msg_r, std::string hint_r = std::string() )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( std::move(msg_r) ), _hint( std::move(hint_r) ) {}
+  Error( const boost::format & msg_r, std::string hint_r = std::string() )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( boost::str( msg_r ) ), _hint( std::move(hint_r) ) {}
+  Error( std::string msg_r, const boost::format & hint_r )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( std::move(msg_r) ), _hint( boost::str( hint_r ) ) {}
   Error( const boost::format & msg_r, const boost::format & hint_r )
-  : _exitcode( ZYPPER_EXIT_OK ) , _msg( boost::str( msg_r ) ) , _hint( boost::str( hint_r ) ) {}
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( boost::str( msg_r ) ), _hint( boost::str( hint_r ) ) {}
+
+  Error( const zypp::Exception & ex_r, std::string hint_r = std::string() )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( combine( ex_r ) ), _hint( std::move(hint_r) ) {}
+  Error( const zypp::Exception & ex_r, const boost::format & hint_r )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( combine( ex_r ) ), _hint( boost::str( hint_r ) ) {}
+
+  Error( std::string msg_r, const zypp::Exception & ex_r, std::string hint_r = std::string() )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( combine( std::move(msg_r), ex_r ) ), _hint( std::move(hint_r) ) {}
+  Error( const boost::format & msg_r, const zypp::Exception & ex_r, std::string hint_r = std::string() )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( combine( boost::str( msg_r ), ex_r ) ), _hint( std::move(hint_r) ) {}
+  Error( std::string msg_r, const zypp::Exception & ex_r, const boost::format & hint_r )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( combine( std::move(msg_r), ex_r ) ), _hint( boost::str( hint_r ) ) {}
+  Error( const boost::format & msg_r, const zypp::Exception & ex_r, const boost::format & hint_r )
+  : _exitcode( ZYPPER_EXIT_OK ), _msg( combine( boost::str( msg_r ), ex_r ) ), _hint( boost::str( hint_r ) ) {}
+
+
 
   /** Default way of processing a caught \ref Error exception.
    * \li Write error message and optional hint to screen.
@@ -1055,6 +1184,10 @@ struct Out::Error
   int _exitcode;       //< ZYPPER_EXIT_OK indicates exitcode is already set.
   std::string _msg;
   std::string _hint;
+
+private:
+  static std::string combine( std::string && msg_r, const zypp::Exception & ex_r );
+  static std::string combine( const zypp::Exception & ex_r );
 };
 ///////////////////////////////////////////////////////////////////
 
index 9a95045..469c759 100644 (file)
@@ -17,6 +17,7 @@ stream-element =
       selectable-list-element? |
       search-result-element? |   # for zypper search
       selectable-info-element? | # for zypper info
+      locks-list-element? |     # for zypper locks
 
       # random text can appear between tags - this text should be ignored
       text
@@ -207,6 +208,29 @@ selectable-info-element =
     )
   }
 
+locks-list-element =
+  element locks {
+    attribute size { xsd:integer },
+    element lock {
+      attribute number { xsd:integer },
+      element name { xsd:string }*,
+      element type { xsd:string }*,
+      element repo { xsd:string }*,
+      element matches {
+        attribute size { xsd:integer },
+        element match {
+          attribute arch { xsd:string },
+          attribute edition { xsd:string },
+          attribute installed { xsd:boolean },
+          attribute name { xsd:string },
+          attribute repo { xsd:string },
+          attribute kind { xsd:string }
+        }*
+      }?
+    }*
+  }
+
+
 # TODO
 common-selectable-info =
   attribute installed { xsd:boolean },
@@ -222,3 +246,5 @@ patch-selectable-info =
     "installed" | "not-installed" | "not-applicable" | "no-longer-applicable" |
     "applied" | "not-needed" | "broken" | "needed"
   }
+
+
index 6eb4bdc..f5b68cc 100644 (file)
@@ -1764,12 +1764,11 @@ void add_repo(Zypper & zypper, RepoInfo & repo)
 
   if ( !repo.gpgCheck() )
   {
-    zypper.out().warning( boost::formatNAC(
+    zypper.out().warning(
       // translators: BOOST STYLE POSITIONAL DIRECTIVES ( %N% )
       // translators: %1% - a repository name
-      _("GPG checking is disabled in configuration of repository '%1%'. Integrity and origin of packages cannot be verified."))
-      % repo.asUserString()
-    );
+      str::FormatNAC(_("GPG checking is disabled in configuration of repository '%1%'. Integrity and origin of packages cannot be verified."))
+      % repo.asUserString() );
   }
 
   ostringstream s;
index 399983f..467b4b0 100644 (file)
@@ -22,7 +22,7 @@ BuildRequires:  boost-devel >= 1.33.1
 BuildRequires:  cmake >= 2.4.6
 BuildRequires:  gcc-c++ >= 4.7
 BuildRequires:  gettext-devel >= 0.15
-BuildRequires:  libzypp-devel >= 14.42.0
+BuildRequires:  libzypp-devel >= 14.45.0
 BuildRequires:  readline-devel >= 5.1
 Requires:       procps
 %if 0%{?suse_version}