#
SET(LIBZYPP_MAJOR "15")
SET(LIBZYPP_COMPATMINOR "11")
-SET(LIBZYPP_MINOR "11")
+SET(LIBZYPP_MINOR "12")
SET(LIBZYPP_PATCH "0")
#
-# LAST RELEASED: 15.11.0 (11)
+# LAST RELEASED: 15.12.0 (11)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
-------------------------------------------------------------------
+Tue Aug 11 18:48:57 CEST 2015 - ma@suse.de
+
+- History: Add 'command' tag showing who triggered the commit.
+ The corresponding HistoryLogData class for parsing is
+ HistoryLogDataStampCommand. Available data are the commandline
+ executed, user@hostname and userdata/transactionID. (FATE#312298)
+- Add convenience comparison PoolItem<>ResObject::constPtr
+- Fixes for SWIG 2.x
+- version 15.12.0 (11)
+
+-------------------------------------------------------------------
Mon Aug 10 16:22:06 CEST 2015 - ma@suse.de
- Make multiversion an individual solvables property (FATE#318778)
history.clear();
parser.readAll();
- BOOST_CHECK_EQUAL( history.size(), 7 );
+ BOOST_CHECK_EQUAL( history.size(), 8 );
BOOST_CHECK( dynamic_pointer_cast<HistoryLogDataRepoAdd> ( history[0] ) );
BOOST_CHECK( dynamic_pointer_cast<HistoryLogDataInstall> ( history[1] ) );
BOOST_CHECK( dynamic_pointer_cast<HistoryLogDataInstall> ( history[2] ) );
BOOST_CHECK( dynamic_pointer_cast<HistoryLogDataRepoRemove> ( history[4] ) );
BOOST_CHECK( dynamic_pointer_cast<HistoryLogDataRemove> ( history[5] ) );
BOOST_CHECK( dynamic_pointer_cast<HistoryLogData> ( history[6] ) );
+ BOOST_CHECK( dynamic_pointer_cast<HistoryLogDataStampCommand> ( history[7] ) );
BOOST_CHECK_EQUAL( (*history[1])[HistoryLogDataInstall::USERDATA_INDEX], "trans|ID" ); // properly (un)escaped?
HistoryLogDataInstall::Ptr p = dynamic_pointer_cast<HistoryLogDataInstall>( history[1] );
2010-06-01 16:11:17|bad |unknown action field
discard\|one field
discard|to fields but bad date
+2015-08-11 18:42:49|command|root@fibonacci|'/Local/ma/zypp/BUILD/zypper/src/zypper' 'in' '-f' 'xteddy'|
#include "zypp/ZConfig.h"
#include "zypp/base/String.h"
#include "zypp/base/Logger.h"
+#include "zypp/base/IOStream.h"
#include "zypp/PathInfo.h"
#include "zypp/Date.h"
using std::endl;
using std::string;
-namespace
+namespace zypp
{
- inline string timestamp()
- { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); }
-
- inline string userAtHostname()
+ namespace
{
- static char buf[256];
- string result;
- char * tmp = ::cuserid(buf);
- if (tmp)
+ inline string timestamp()
+ { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); }
+
+ inline string userAtHostname()
{
- result = string(tmp);
- if (!::gethostname(buf, 255))
- result += "@" + string(buf);
+ static char buf[256];
+ string result;
+ char * tmp = ::cuserid(buf);
+ if (tmp)
+ {
+ result = string(tmp);
+ if (!::gethostname(buf, 255))
+ result += "@" + string(buf);
+ }
+ return result;
}
- return result;
- }
- static std::string pidAndAppname()
- {
- static std::string _val;
- if ( _val.empty() )
+ static std::string pidAndAppname()
{
- pid_t mypid = getpid();
- zypp::Pathname p( "/proc/"+zypp::str::numstring(mypid)+"/exe" );
- zypp::Pathname myname( zypp::filesystem::readlink( p ) );
+ static std::string _val;
+ if ( _val.empty() )
+ {
+ pid_t mypid = getpid();
+ zypp::Pathname p( "/proc/"+zypp::str::numstring(mypid)+"/exe" );
+ zypp::Pathname myname( zypp::filesystem::readlink( p ) );
- _val += zypp::str::numstring(mypid);
- _val += ":";
- _val += myname.basename();
+ _val += zypp::str::numstring(mypid);
+ _val += ":";
+ _val += myname.basename();
+ }
+ return _val;
}
- return _val;
- }
-}
-namespace zypp
-{
+ static std::string cmdline()
+ {
+ static std::string _val;
+ if ( _val.empty() )
+ {
+ pid_t mypid = getpid();
+ {
+ std::ifstream cmdlineStr( Pathname("/proc/"+zypp::str::numstring(mypid)+"/cmdline").c_str() );
+ char ch;
+ const char * sep = "'";
+ while ( cmdlineStr && cmdlineStr.get( ch ) )
+ {
+ if ( sep )
+ {
+ _val += sep;
+ sep = nullptr;
+ }
+ switch ( ch )
+ {
+ case '\0': _val += '\''; sep = " '"; break;
+ case '\n': _val += ' '; break;
+ case '\\': _val += '\\'; _val += '\\'; break;
+ case '|': _val += '\\'; _val += '|'; break;
+ default: _val += ch; break;
+ }
+ }
+ }
+ }
+ return _val;
+ }
+ } // namespace
+
namespace
{
const char _sep = '|';
if ( !_refcnt )
closeLog();
}
- }
+ } // namespace
///////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////
- void HistoryLog::comment( const string & comment, bool timestamp )
+ void HistoryLog::comment( const string & comment, bool timestamp_r )
{
if (comment.empty())
return;
_log << "# ";
- if ( timestamp )
- _log << ::timestamp() << " ";
+ if ( timestamp_r )
+ _log << timestamp() << " ";
const char * s = comment.c_str();
const char * c = s;
/////////////////////////////////////////////////////////////////////////
+ void HistoryLog::stampCommand()
+ {
+ _log
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::STAMP_COMMAND.asString(true) // 2 action
+ << _sep << userAtHostname() // 3 requested by
+ << _sep << cmdline() // 4 command
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 6 userdata
+ << endl;
+
+ }
+
void HistoryLog::install( const PoolItem & pi )
{
const Package::constPtr p = asKind<Package>(pi.resolvable());
// ApplLow is what the solver selected on behalf of the user.
if (pi.status().isByUser() || pi.status().isByApplLow() )
- _log << _sep << userAtHostname(); // 6 reqested by
+ _log << _sep << userAtHostname(); // 6 requested by
else if (pi.status().isByApplHigh())
_log << _sep << pidAndAppname();
else
// ApplLow is what the solver selected on behalf of the user.
if ( pi.status().isByUser() || pi.status().isByApplLow() )
- _log << _sep << userAtHostname(); // 6 reqested by
+ _log << _sep << userAtHostname(); // 6 requested by
else if (pi.status().isByApplHigh())
_log << _sep << pidAndAppname();
else
*/
void comment( const std::string & comment, bool timestamp = false );
+ /** Log info about the current process. */
+ void stampCommand();
+
/**
* Log installation (or update) of a package.
*/
const HistoryActionID HistoryActionID::REPO_REMOVE (HistoryActionID::REPO_REMOVE_e);
const HistoryActionID HistoryActionID::REPO_CHANGE_ALIAS (HistoryActionID::REPO_CHANGE_ALIAS_e);
const HistoryActionID HistoryActionID::REPO_CHANGE_URL (HistoryActionID::REPO_CHANGE_URL_e);
+ const HistoryActionID HistoryActionID::STAMP_COMMAND (HistoryActionID::STAMP_COMMAND_e);
HistoryActionID::HistoryActionID(const std::string & strval_r)
: _id(parse(strval_r))
_table["rremove"] = REPO_REMOVE_e;
_table["ralias"] = REPO_CHANGE_ALIAS_e;
_table["rurl"] = REPO_CHANGE_URL_e;
+ _table["command"] = STAMP_COMMAND_e;
_table["NONE"] = _table["none"] = NONE_e;
}
_table[REPO_REMOVE_e] = PairType( "rremove" , "rremove" );
_table[REPO_CHANGE_ALIAS_e] = PairType( "ralias" , "ralias " );
_table[REPO_CHANGE_URL_e] = PairType( "rurl" , "rurl " );
+ _table[STAMP_COMMAND_e] = PairType( "command" , "command" );
_table[NONE_e] = PairType( "NONE" , "NONE " );
}
OUTS( REPO_REMOVE_e, HistoryLogDataRepoRemove );
OUTS( REPO_CHANGE_ALIAS_e, HistoryLogDataRepoAliasChange );
OUTS( REPO_CHANGE_URL_e, HistoryLogDataRepoUrlChange );
+ OUTS( STAMP_COMMAND_e, HistoryLogDataStampCommand );
#undef OUTS
// intentionally no default:
case HistoryActionID::NONE_e:
Url HistoryLogDataRepoUrlChange::newUrl() const { return optionalAt( NEWURL_INDEX ); }
std::string HistoryLogDataRepoUrlChange::userdata() const { return optionalAt( USERDATA_INDEX ); }
+ ///////////////////////////////////////////////////////////////////
+ // class HistoryLogDataStampCommand
+ ///////////////////////////////////////////////////////////////////
+ HistoryLogDataStampCommand::HistoryLogDataStampCommand( FieldVector & fields_r )
+ : HistoryLogData( fields_r )
+ {}
+ std::string HistoryLogDataStampCommand::executedBy() const { return optionalAt( USER_INDEX ); }
+ std::string HistoryLogDataStampCommand::command() const { return optionalAt( COMMAND_INDEX ); }
+ std::string HistoryLogDataStampCommand::userdata() const { return optionalAt( USERDATA_INDEX ); }
+
} // namespace zypp
///////////////////////////////////////////////////////////////////
static const HistoryActionID REPO_REMOVE;
static const HistoryActionID REPO_CHANGE_ALIAS;
static const HistoryActionID REPO_CHANGE_URL;
+ static const HistoryActionID STAMP_COMMAND;
enum ID
{
REPO_ADD_e,
REPO_REMOVE_e,
REPO_CHANGE_ALIAS_e,
- REPO_CHANGE_URL_e
+ REPO_CHANGE_URL_e,
+ STAMP_COMMAND_e
};
HistoryActionID() : _id(NONE_e) {}
std::string userdata() const; ///< userdata/transactionID
};
+ ///////////////////////////////////////////////////////////////////
+ /// \class HistoryLogDataStampCommand
+ /// \brief A zypp history log line identifying the program that
+ /// triggered the following commit.
+ /// \ingroup g_ZyppHistory
+ ///////////////////////////////////////////////////////////////////
+ class HistoryLogDataStampCommand : public HistoryLogData
+ {
+ public:
+ typedef shared_ptr<HistoryLogDataStampCommand> Ptr;
+ typedef shared_ptr<const HistoryLogDataStampCommand> constPtr;
+ /** Ctor \b moving \a FieldVector (via swap).
+ * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields.
+ */
+ HistoryLogDataStampCommand( FieldVector & fields_r );
+
+ public:
+ enum Index ///< indices of known fields
+ {
+ DATE_INDEX = HistoryLogData::DATE_INDEX,
+ ACTION_INDEX = HistoryLogData::ACTION_INDEX,
+ USER_INDEX, ///< executed by user@hostname
+ COMMAND_INDEX, ///< the commandline executed
+ USERDATA_INDEX, ///< userdata/transactionID
+ };
+
+ public:
+ std::string executedBy() const; ///< executed by user@hostname
+ std::string command() const; ///< the commandline executed
+ std::string userdata() const; ///< userdata/transactionID
+ };
+
} // namespace zypp
///////////////////////////////////////////////////////////////////
#endif /* ZYPP_HISTORYLOGDATA_H_ */
/** \relates PoolItem Stream output */
std::ostream & operator<<( std::ostream & str, const PoolItem & obj );
+
+ /** \relates PoolItem Required to disambiguate vs. (PoolItem,ResObject::constPtr) due to implicit PoolItem::operator ResObject::constPtr */
+ inline bool operator==( const PoolItem & lhs, const PoolItem & rhs )
+ { return lhs.resolvable() == rhs.resolvable(); }
+
+ /** \relates PoolItem Convenience compare */
+ inline bool operator==( const PoolItem & lhs, const ResObject::constPtr & rhs )
+ { return lhs.resolvable() == rhs; }
+
+ /** \relates PoolItem Convenience compare */
+ inline bool operator==( const ResObject::constPtr & lhs, const PoolItem & rhs )
+ { return lhs == rhs.resolvable(); }
+
+
+ /** \relates PoolItem Required to disambiguate vs. (PoolItem,ResObject::constPtr) due to implicit PoolItem::operator ResObject::constPtr */
+ inline bool operator!=( const PoolItem & lhs, const PoolItem & rhs )
+ { return ! (lhs==rhs); }
+
+ /** \relates PoolItem Convenience compare */
+ inline bool operator!=( const PoolItem & lhs, const ResObject::constPtr & rhs )
+ { return ! (lhs==rhs); }
+
+ /** \relates PoolItem Convenience compare */
+ inline bool operator!=( const ResObject::constPtr & lhs, const PoolItem & rhs )
+ { return ! (lhs==rhs); }
+
/** Solvable to PoolItem transform functor.
* \relates PoolItem
* \relates sat::SolvIterMixin
{ return make_filter_end( filter_r, *this ); }
template<class _Filter>
- Iterable<filter_iterator<_Filter,const_iterator>> filter( const _Filter & filter_r ) const
+ Iterable<filter_iterator<_Filter,const_iterator> > filter( const _Filter & filter_r ) const
{ return makeIterable( filterBegin( filter_r ), filterEnd( filter_r ) ); }
//@}
filter_iterator<filter::ByStatus,const_iterator> byStatusEnd( const filter::ByStatus & filter_r ) const
{ return make_filter_end( filter_r, *this ); }
- Iterable<filter_iterator<filter::ByStatus,const_iterator>> byStatus( const filter::ByStatus & filter_r ) const
+ Iterable<filter_iterator<filter::ByStatus,const_iterator> > byStatus( const filter::ByStatus & filter_r ) const
{ return makeIterable( byStatusBegin( filter_r ), byStatusEnd( filter_r ) ); }
//@}
public:
/** \name Save and restore state. */
//@{
- void SaveState( const ResObject::Kind & kind_r );
+ void SaveState( const ResKind & kind_r );
- void RestoreState( const ResObject::Kind & kind_r );
+ void RestoreState( const ResKind & kind_r );
//@}
///////////////////////////////////////////////////////////////////
protected:
SolvableType() {}
- SolvableType( SolvableType && ) {}
SolvableType( const SolvableType & ) {}
- void operator=( SolvableType && ) {}
void operator=( const SolvableType & ) {}
+#ifndef SWIG
+ SolvableType( SolvableType && ) {}
+ void operator=( SolvableType && ) {}
+#endif
~SolvableType() {}
};
ZYppCommitResult::TransactionStepList & steps( result_r.rTransactionStepList() );
MIL << "TargetImpl::commit(<list>" << policy_r << ")" << steps.size() << endl;
+ HistoryLog().stampCommand();
+
bool abort = false;
RpmPostTransCollector postTransCollector( _root );
std::vector<sat::Solvable> successfullyInstalledPackages;
/** */
struct ByKind : public SelectableFilterFunctor
{
- ByKind( const ResObject::Kind & kind_r )
+ ByKind( const ResKind & kind_r )
: _kind( kind_r )
{}
return obj && obj->kind() == _kind;
}
- ResObject::Kind _kind;
+ ResKind _kind;
};
/** */
IdString Selectable::ident() const
{ return _pimpl->ident(); }
- ResObject::Kind Selectable::kind() const
+ ResKind Selectable::kind() const
{ return _pimpl->kind(); }
const std::string & Selectable::name() const
IdString ident() const;
/** The ResObjects kind. */
- ResObject::Kind kind() const;
+ ResKind kind() const;
/** The ResObjects name. */
const std::string & name() const;
public:
template <class _Iterator>
- Impl( const ResObject::Kind & kind_r,
+ Impl( const ResKind & kind_r,
const std::string & name_r,
_Iterator begin_r,
_Iterator end_r )
{ return _ident; }
/** */
- ResObject::Kind kind() const
+ ResKind kind() const
{ return _kind; }
/** */
private:
const IdString _ident;
- const ResObject::Kind _kind;
+ const ResKind _kind;
const std::string _name;
InstalledItemSet _installedItems;
AvailableItemSet _availableItems;