\li The user data string will also be passed to commit plugins, so they can make use of it. The btrfs e.g would be able to tag created snapshots with this string. \see \ref plugin-commit
+\li The user data string will appear on each histoy line logging package or repository related events (install, delete, add, modify). \see \ref zypp::HistoryLog and zypp::parser::HistoryLogReader
+
*/
--- /dev/null
+/** \defgroup g_ZyppHistory Libzypp History File
+
+Log important events like installation/deletion of packages and repositories.
+
+
+\section g_ZyppHistory_Location Location
+
+The default location is \c /var/log/zypp/history. This can be changed via \c history.logfile key in \c /etc/zypp/zypp.conf.
+
+
+\section g_ZyppHistory_Format Format
+
+\li CSV file with pipe character (|) as the value separator
+\li one event per line
+\li different actions have different set of values (columns), see the tables below
+\li lines starting with # are treated as comments
+
+\see \ref zypp-userdata
+
+\subsection g_ZyppHistory_Format_Colummn Action Columns
+
+\subsubsection g_ZyppHistory_Format_Colummn_Install Install
+A package has been installed.
+\li \b 1 timestamp
+\li \b 2 action ID (\c "install")
+\li \b 3 package name
+\li \b 4 package epoch:version-release
+\li \b 5 package architecture
+\li \b 6 requested by (user@hostname, pid:appname, or empty (solver))
+\li \b 7 repository alias
+\li \b 8 package checksum
+\li \b 9 userdata/transactionId
+
+\subsubsection g_ZyppHistory_Format_Colummn_Remove Remove
+A package has been removed.
+\li \b 1 timestamp
+\li \b 2 action ID (\c "remove")
+\li \b 3 package name
+\li \b 4 package epoch:version-release
+\li \b 5 package architecture
+\li \b 6 requested by (user@hostname, pid:appname, or empty (solver))
+\li \b 7 userdata/transactionId
+
+\subsubsection g_ZyppHistory_Format_Colummn_Radd Radd
+A repository has been added.
+\li \b 1 timestamp
+\li \b 2 action ID (\c "radd")
+\li \b 3 repository alias
+\li \b 4 primary URL
+\li \b 5 userdata/transactionId
+
+\subsubsection g_ZyppHistory_Format_Colummn_Rremove Rremove
+A repository has been removed.
+\li \b 1 timestamp
+\li \b 2 action ID (\c "rremove")
+\li \b 3 repository alias
+\li \b 4 userdata/transactionId
+
+\subsubsection g_ZyppHistory_Format_Colummn_Ralias Ralias
+A repository alias has changed.
+\li \b 1 timestamp
+\li \b 2 action ID (\c "ralias")
+\li \b 3 old alias
+\li \b 4 new alias
+\li \b 5 userdata/transactionId
+
+\subsubsection g_ZyppHistory_Format_Colummn_Rurl Rurl
+The primary URL of a repository has changed.
+\li \b 1 timestamp
+\li \b 2 action ID (\c "rurl")
+\li \b 3 repository alias
+\li \b 4 new URL
+\li \b 5 userdata/transactionId
+
+
+\section g_ZyppHistory_Example Example
+
+\code
+2008-09-24 11:48:58|rremove|packman
+2008-09-24 11:50:02|radd |packman|http://packman.iu-bremen.de/suse/11.0
+2008-09-24 11:53:10|install|amarok-yauap|1.4.10-25|x86_64||factory|4421dfa718ab73c805c1c695c97b1b67f39bf2f3
+2008-09-24 11:53:25|install|amarok-lang|1.4.10-25|x86_64||factory|691030edafcc4fbc22aa225350f9de32974e4bc2
+# Additional rpm output:
+# warning: /var/cache/zypp/packages/packman/x86_64/amarok-1.4.10-100.pm.1.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID 9a795806
+#
+2008-09-24 11:53:45|install|amarok|1.4.10-100.pm.1|x86_64|root@kompost|packman|ee0fffa1e4eeaaeb8799bd05c6882ef74100d681
+\endcode
+
+*/
/*! \defgroup g_Algorithm Algorithms
*/
////////////////////////////////////////////////////////////////////////////////
+/*! \defgroup g_Parser Parser
+*/
+////////////////////////////////////////////////////////////////////////////////
return;
_log
- << timestamp() // 1 timestamp
- << _sep << HistoryActionID::INSTALL.asString(true) // 2 action
- << _sep << p->name() // 3 name
- << _sep << p->edition() // 4 evr
- << _sep << p->arch(); // 5 arch
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::INSTALL.asString(true) // 2 action
+ << _sep << p->name() // 3 name
+ << _sep << p->edition() // 4 evr
+ << _sep << p->arch(); // 5 arch
// 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 reqested by
else if (pi.status().isByApplHigh())
_log << _sep << pidAndAppname();
else
_log << _sep;
_log
- << _sep << p->repoInfo().alias() // 7 repo alias
- << _sep << p->checksum().checksum(); // 8 checksum
-
- _log << endl;
-
- //_log << pi << endl;
+ << _sep << p->repoInfo().alias() // 7 repo alias
+ << _sep << p->checksum().checksum() // 8 checksum
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 9 userdata
+ << endl;
}
return;
_log
- << timestamp() // 1 timestamp
- << _sep << HistoryActionID::REMOVE.asString(true) // 2 action
- << _sep << p->name() // 3 name
- << _sep << p->edition() // 4 evr
- << _sep << p->arch(); // 5 arch
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::REMOVE.asString(true) // 2 action
+ << _sep << p->name() // 3 name
+ << _sep << p->edition() // 4 evr
+ << _sep << p->arch(); // 5 arch
// 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 reqested by
else if (pi.status().isByApplHigh())
_log << _sep << pidAndAppname();
else
_log << _sep;
- // we don't have checksum in rpm db
- // << _sep << p->checksum().checksum(); // x checksum
-
- _log << endl;
-
- //_log << pi << endl;
+ _log
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 7 userdata
+ << endl;
}
/////////////////////////////////////////////////////////////////////////
void HistoryLog::addRepository(const RepoInfo & repo)
{
_log
- << timestamp() // 1 timestamp
- << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action
- << _sep << str::escape(repo.alias(), _sep) // 3 alias
- // what about the rest of the URLs??
- << _sep << *repo.baseUrlsBegin() // 4 primary URL
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action
+ << _sep << str::escape(repo.alias(), _sep) // 3 alias
+ << _sep << *repo.baseUrlsBegin() // 4 primary URL
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
<< endl;
}
void HistoryLog::removeRepository(const RepoInfo & repo)
{
_log
- << timestamp() // 1 timestamp
- << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action
- << _sep << str::escape(repo.alias(), _sep) // 3 alias
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action
+ << _sep << str::escape(repo.alias(), _sep) // 3 alias
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 4 userdata
<< endl;
}
if (oldrepo.alias() != newrepo.alias())
{
_log
- << timestamp() // 1 timestamp
- << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action
- << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias
- << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action
+ << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias
+ << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
<< endl;
}
-
if (*oldrepo.baseUrlsBegin() != *newrepo.baseUrlsBegin())
{
_log
- << timestamp() //1 timestamp
- << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action
- << _sep << str::escape(oldrepo.alias(), _sep) // 3 old url
- << _sep << *newrepo.baseUrlsBegin() // 4 new url
+ << timestamp() // 1 timestamp
+ << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action
+ << _sep << str::escape(oldrepo.alias(), _sep) // 3 old url
+ << _sep << *newrepo.baseUrlsBegin() // 4 new url
+ << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
<< endl;
}
}
class RepoInfo;
///////////////////////////////////////////////////////////////////
- //
- // CLASS NAME : HistoryLog
- /**
- * Simple wrapper for progress log. Refcnt, filename and corresponding
- * ofstream are static members. Logfile constructor raises, destructor
- * lowers refcounter. On refcounter changing from 0->1, file is opened.
- * Changing from 1->0 the file is closed. Thus Logfile objects should be
- * local to those functions, writing the log, and must not be stored
- * permanently.
- *
- * Usage:
- * <code>
- * some method ()
- * {
- * PoolItem pi;
- * ...
- * HistoryLog().install(pi);
- * ...
- * HistoryLog().comment(someMessage);
- * }
- * </code>
- *
- * \note Take care to set proper target root dir if needed. Either pass
- * it via the constructor, or set it via setRoot(Pathname) method.
- * The default location of the file is determined by
- * \ref ZConfig::historyLogPath() which defaults to
- * /var/log/zypp/history.
- *
- * \see http://en.opensuse.org/Libzypp/Package_History
- *
- * \todo The implementation as pseudo signleton is questionable.
- * Use shared_ptr instead of handcrafted ref/unref. Manage multiple
- * logs at different locations.
- */
+ /// \class HistoryLog
+ /// \brief Writing the zypp history file
+ /// \ingroup g_ZyppHistory
+ ///
+ /// Reference counted signleton for writhing the zypp history file.
+ /// The history file is opened on demand and closed when the last
+ /// HistoryLog object drops its reference. Thus HistoryLog objects
+ /// should be local to those functions, writing the log, and must
+ /// not be stored permanently.
+ ///
+ /// \code
+ /// some method ()
+ /// {
+ /// PoolItem pi;
+ /// ...
+ /// HistoryLog().install(pi);
+ /// ...
+ /// HistoryLog().comment(someMessage);
+ /// }
+ /// \endcode
+ ///
+ /// \note Take care to set proper target root dir if needed. Either pass
+ /// it via the constructor, or set it via setRoot(Pathname) method.
+ /// The default location of the file is determined by
+ /// \ref zypp::ZConfig::historyLogPath (default: \c /var/log/zypp/history).
+ ///
+ /// \todo The implementation as pseudo signleton is questionable.
+ /// Use shared_ptr instead of handcrafted ref/unref. Manage multiple
+ /// logs at different locations.
+ ///////////////////////////////////////////////////////////////////
class HistoryLog
{
HistoryLog( const HistoryLog & );
namespace zypp
{
-
-
///////////////////////////////////////////////////////////////////
- //
- // CLASS NAME : HistoryActionID
- //
- /**
- * Enumeration of known history actions.
- *
- * \ingroup g_EnumerationClass
- */
+ /// \class HistoryActionID
+ /// \brief Enumeration of known history actions.
+ /// \ingroup g_EnumerationClass
+ /// \ingroup g_ZyppHistory
+ ///////////////////////////////////////////////////////////////////
struct HistoryActionID
{
static const HistoryActionID NONE;
case HistoryActionID::REPO_CHANGE_URL_e:
return HistoryItemRepoUrlChange::Ptr( new HistoryItemRepoUrlChange( fields ) );
break;
+
+ case HistoryActionID::NONE_e:
+ break;
}
return HistoryItem::Ptr();
}
namespace parser
{ /////////////////////////////////////////////////////////////////
-
+ ///////////////////////////////////////////////////////////////////
+ /// \class HistoryLogReader
+ /// \brief Zypp history file parser
+ /// \ingroup g_ZyppHistory
+ /// \ingroup g_ZyppParser
+ ///
+ /// Reads a zypp history log file and calls the ProcessItem function
+ /// passed in the constructor for each item read.
+ ///
+ /// \code
+ /// struct HistoryItemCollector
+ /// {
+ /// vector<HistoryItem::Ptr> items;
+ ///
+ /// bool operator()( const HistoryItem::Ptr & item_ptr )
+ /// {
+ /// items.push_back(item_ptr);
+ /// return true;
+ /// }
+ /// }
+ /// ...
+ /// HistoryItemCollector ic;
+ /// HistoryLogReader reader("/var/log/zypp/history", boost::ref(ic));
+ ///
+ /// try
+ /// {
+ /// reader.readAll();
+ /// }
+ /// catch (const Exception & e)
+ /// {
+ /// cout << e.asUserHistory() << endl;
+ /// }
+ /// \endcode
/////////////////////////////////////////////////////////////////////
- //
- // CLASS NAME: HistoryLogReader
- //
- /**
- * Reads a zypp history log file and calls the ProcessItem function passed
- * in the constructor for each item read.
- *
- * Example:
- * <code>
- *
- * struct HistoryItemCollector
- * {
- * vector<HistoryItem::Ptr> items;
- *
- * bool operator()( const HistoryItem::Ptr & item_ptr )
- * {
- * items.push_back(item_ptr);
- * return true;
- * }
- * }
- *
- * ...
- *
- * HistoryItemCollector ic;
- * HistoryLogReader reader("/var/log/zypp/history", boost::ref(ic));
- *
- * try
- * {
- * reader.readAll();
- * }
- * catch (const Exception & e)
- * {
- * cout << e.asUserHistory() << endl;
- * }
- *
- * </code>
- *
- * \see http://en.opensuse.org/Libzypp/Package_History
- */
class HistoryLogReader
{
public: