From 54b19c36c9c0944a1e404c51d436e47491f022a5 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Tue, 10 Jan 2017 14:29:33 +0900 Subject: [PATCH] Imported Upstream version 1.11.60 Change-Id: I96d0c4e734e8ade7053b35602f81ab594fc76dba Signed-off-by: DongHun Kwak --- VERSION.cmake | 4 +- package/zypper.changes | 7 + src/Table.cc | 9 +- src/Table.h | 9 +- src/Zypper.cc | 10 +- src/callbacks/keyring.h | 10 +- src/callbacks/rpm.h | 88 +++++----- src/locks.cc | 302 ++++++++++++++++++--------------- src/output/Out.cc | 24 +++ src/output/Out.h | 435 +++++++++++++++++++++++++++++++----------------- src/output/xmlout.rnc | 26 +++ src/repos.cc | 7 +- zypper.spec.cmake | 2 +- 13 files changed, 580 insertions(+), 353 deletions(-) diff --git a/VERSION.cmake b/VERSION.cmake index b3d2e77..096a9ed 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -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 #======= diff --git a/package/zypper.changes b/package/zypper.changes index 8ee31da..8eefbb0 100644 --- a/package/zypper.changes +++ b/package/zypper.changes @@ -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 diff --git a/src/Table.cc b/src/Table.cc index f2d8644..6f58cb6 100644 --- a/src/Table.cc +++ b/src/Table.cc @@ -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; } diff --git a/src/Table.h b/src/Table.h index 1ae3f29..c2fefd8 100644 --- a/src/Table.h +++ b/src/Table.h @@ -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; diff --git a/src/Zypper.cc b/src/Zypper.cc index 7913763..2759e08 100644 --- a/src/Zypper.cc +++ b/src/Zypper.cc @@ -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 ) diff --git a/src/callbacks/keyring.h b/src/callbacks/keyring.h index d03a8bd..7e72980 100644 --- a/src/callbacks/keyring.h +++ b/src/callbacks/keyring.h @@ -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" ) ) diff --git a/src/callbacks/rpm.h b/src/callbacks/rpm.h index b7cdf66..5be5d18 100644 --- a/src/callbacks/rpm.h +++ b/src/callbacks/rpm.h @@ -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 - 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 - std::string operator()( const _Tp & val_r ) const - { return operator()( makeResObject( asSolvable( val_r ) ) ); } + template + 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 << "kind() << "\""; + ret << " name=\"" << val_r->name() << "\""; + ret << " edition=\"" << val_r->edition() << "\""; + ret << " arch=\"" << val_r->arch() << "\""; { - str::Str ret; - ret << "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" << "" << xml::escape( text ) << "" << ""; - 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" << "" << xml::escape( text ) << "" << ""; + else + ret << "/>"; } - }; + return ret; + } - template - std::string operator()( const _Tp & val_r ) const - { return operator()( makeResObject( asSolvable( val_r ) ) ); } + template + 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 + 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 & 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) VR(>) + int res = sat::compareByN( lhs, rhs ); // ascending l i; - std::set a; - for ( const auto & solv : q ) - { (solv.isSystem()?i:a).insert( solv ); } - - std::vector 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 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; + // + { + ++_i; + xmlout::Node lock( str.stream(), "lock", { { "number", _i } } ); -void list_locks(Zypper & zypper) -{ - shared_ptr listLocksOptions = zypper.commandOptionsOrDefaultAs(); + // (solvable_name) + for ( const std::string & val : q_r.attribute( sat::SolvAttr::name ) ) + { *xmlout::Node( *lock, "name" ) << val; } + // (query_string) + for ( const std::string & val : q_r.strings() ) + { *xmlout::Node( *lock, "name" ) << val; } - bool withSolvables = listLocksOptions->_withSolvables; - bool withMatches = withSolvables||listLocksOptions->_withMatches; + // + 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() ) ); + // + for ( const std::string & repo : q_r.repos() ) + { *xmlout::Node( *lock, "repo" ) << repo; } - Table t; + if ( _withMatches ) + { + // + 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 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 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_r ) + : _withSolvables( listLocksOptions_r->_withSolvables ) + , _withMatches( _withSolvables || listLocksOptions_r->_withMatches ) + {} - t << tr; + private: + static std::string get_string_for_table( const std::set & 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() ) ); + out.gap(); } template diff --git a/src/output/Out.cc b/src/output/Out.cc index 3a5f3f7..72fb530 100644 --- a/src/output/Out.cc +++ b/src/output/Out.cc @@ -11,6 +11,14 @@ #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 ); } diff --git a/src/output/Out.h b/src/output/Out.h index 0126571..9b83dee 100644 --- a/src/output/Out.h +++ b/src/output/Out.h @@ -24,34 +24,25 @@ #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 - std::string asListElement( const _Tp & val_r ); - - /** \relates ListFormater XML representation of types in lists [no default] */ - template - std::string asXmlListElement( const _Tp & val_r ); - /////////////////////////////////////////////////////////////////// /// \class ListLayout /// \brief Basic list layout @@ -59,6 +50,8 @@ namespace out /////////////////////////////////////////////////////////////////// struct ListLayout { + template 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 struct ListLayoutInit : public ListLayout { ListLayoutInit() : ListLayout( _Singleline, _Wrapline, _Gaped, _Indent ) {} }; } + typedef detail::ListLayoutInit XmlListLayout; typedef detail::ListLayoutInit DefaultListLayout; ///< one element per line, no indent typedef detail::ListLayoutInit DefaultGapedListLayout; ///< one element per line, no indent, gaped @@ -84,29 +78,102 @@ namespace out typedef detail::ListLayoutInit 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 struct Writer; + }; - struct XmlFormater //< XML representation of element - { - template - 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 //< NORMAL representation of element - std::string operator()( const _Tp & val_r ) const + /** \relates XmlFormater XML representation of types [no default] */ + template + 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 + 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 + TableHeader asTableHeader(); + + template <> + inline TableHeader asTableHeader() + { return TableHeader(); } + + /** \relates TableFormater NORMAL representation of types as TableRow [no default] */ + template + TableRow asTableRow( const Tp & val_r ); + + /////////////////////////////////////////////////////////////////// + /// \class XmlFormater + /// \brief XML representation of types in container [asXmlListElement] + /////////////////////////////////////////////////////////////////// + struct XmlFormater + { + template + 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 + 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 //< 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 + struct XmlFormaterAdaptor + { + typedef XmlListLayout NormalLayout; //< Layout as XML list + + template + 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 + 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 + void operator<<( Tp && val_r ) const + { + const std::string & element( _formater.listElement( std::forward(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 + 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 + void operator<<( Tp && val_r ) const + { _t.add( _formater.row( std::forward(val_r) ) ); } + + private: + std::ostream & _str; + const TableLayout & _layout; + const TFormater & _formater; + mutable Table _t; + }; + + + /** Write formated container to stream */ + template + void writeContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r, const TLayout & layout_r = TLayout() ) + { + typedef typename TLayout::template Writer Writer; + Writer writer( str_r, layout_r, formater_r ); + for ( auto && el : container_r ) + writer << el; } + + /** Write XML formated container to stream */ + template + void xmlWriteContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r ) + { writeContainer( str_r, container_r, out::XmlFormaterAdaptor(formater_r) ); } + } // namespace out /////////////////////////////////////////////////////////////////// @@ -360,74 +487,40 @@ public: { if ( out().typeNORMAL() && ! title_r.empty() ) std::cout << title_r << std::endl; } }; - /////////////////////////////////////////////////////////////////// - /// \class List - /// \brief Printing a list - /////////////////////////////////////////////////////////////////// - template - 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 - 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 - 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 + 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 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 - 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 - 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 - 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 - 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 + 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 + 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 - std::ostream & operator<<( const _Tp & val ) + template + 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 ); }; /////////////////////////////////////////////////////////////////// diff --git a/src/output/xmlout.rnc b/src/output/xmlout.rnc index 9a95045..469c759 100644 --- a/src/output/xmlout.rnc +++ b/src/output/xmlout.rnc @@ -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" } + + diff --git a/src/repos.cc b/src/repos.cc index 6eb4bdc..f5b68cc 100644 --- a/src/repos.cc +++ b/src/repos.cc @@ -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; diff --git a/zypper.spec.cmake b/zypper.spec.cmake index 399983f..467b4b0 100644 --- a/zypper.spec.cmake +++ b/zypper.spec.cmake @@ -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} -- 2.7.4