From ea104481de5b5f35d69dea52907f6a3394f589dc Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A1n=20Kupec?= Date: Mon, 26 Jan 2009 13:28:49 +0100 Subject: [PATCH] HistoryLog reader: - dumpTo() and operator<< for HistoryItem* - hid implementation - allow to ignore invalid log entries with setIngoreInvalidItems(true) --- zypp/HistoryLog.cc | 2 +- zypp/HistoryLogData.cc | 92 ++++++++++++++++++++++--- zypp/HistoryLogData.h | 17 ++++- zypp/parser/HistoryLogReader.cc | 144 ++++++++++++++++++++++++++++------------ zypp/parser/HistoryLogReader.h | 66 ++++++++++++++++-- 5 files changed, 263 insertions(+), 58 deletions(-) diff --git a/zypp/HistoryLog.cc b/zypp/HistoryLog.cc index 7839d6f..1c8218f 100644 --- a/zypp/HistoryLog.cc +++ b/zypp/HistoryLog.cc @@ -33,7 +33,7 @@ using std::string; namespace { inline string timestamp() - { return zypp::Date::now().form( "%Y-%m-%d %H:%M:%S" ); } + { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); } inline string userAtHostname() { diff --git a/zypp/HistoryLogData.cc b/zypp/HistoryLogData.cc index eb92ae6..362500d 100644 --- a/zypp/HistoryLogData.cc +++ b/zypp/HistoryLogData.cc @@ -113,6 +113,18 @@ namespace zypp action = HistoryActionID(str::trim(fields[1])); } + void HistoryItem::dumpTo(ostream & str) const + { + str << date.form(HISTORY_LOG_DATE_FORMAT) << "|" << action.asString(); + } + + ostream & operator<<(ostream & str, const HistoryItem & obj) + { + obj.dumpTo(str); + return str; + } + + ///////////////////////////////////////////////////////////////////// // // CLASS NAME: HistoryItemInstall @@ -135,24 +147,22 @@ namespace zypp checksum = CheckSum::sha(fields[7]); } - const std::string HistoryItemInstall::asString() const + void HistoryItemInstall::dumpTo(ostream & str) const { - ostringstream str; - str - << date.form(HISTORY_LOG_DATE_FORMAT) << "|" - << action.asString() << "|" + HistoryItem::dumpTo(str); + str << "|" << name << "|" << edition << "|" << arch << "|" << reqby << "|" << repoalias << "|" << checksum; - return str.str(); } - std::ostream & operator<<(std::ostream & str, const HistoryItemInstall & obj) + ostream & operator<<(ostream & str, const HistoryItemInstall & obj) { - return str << obj.asString(); + obj.dumpTo(str); + return str; } @@ -176,6 +186,22 @@ namespace zypp reqby = fields[5]; } + void HistoryItemRemove::dumpTo(ostream & str) const + { + HistoryItem::dumpTo(str); + str << "|" + << name << "|" + << edition << "|" + << arch << "|" + << reqby; + } + + ostream & operator<<(ostream & str, const HistoryItemRemove & obj) + { + obj.dumpTo(str); + return str; + } + ///////////////////////////////////////////////////////////////////// // @@ -195,6 +221,20 @@ namespace zypp url = Url(fields[3]); } + void HistoryItemRepoAdd::dumpTo(ostream & str) const + { + HistoryItem::dumpTo(str); + str << "|" + << alias << "|" + << url; + } + + ostream & operator<<(ostream & str, const HistoryItemRepoAdd & obj) + { + obj.dumpTo(str); + return str; + } + ///////////////////////////////////////////////////////////////////// // @@ -213,6 +253,18 @@ namespace zypp alias = fields[2]; } + void HistoryItemRepoRemove::dumpTo(ostream & str) const + { + HistoryItem::dumpTo(str); + str << "|" << alias; + } + + ostream & operator<<(ostream & str, const HistoryItemRepoRemove & obj) + { + obj.dumpTo(str); + return str; + } + ///////////////////////////////////////////////////////////////////// // @@ -232,6 +284,18 @@ namespace zypp newalias = fields[3]; } + void HistoryItemRepoAliasChange::dumpTo(ostream & str) const + { + HistoryItem::dumpTo(str); + str << "|" << oldalias << "|" << newalias; + } + + ostream & operator<<(ostream & str, const HistoryItemRepoAliasChange & obj) + { + obj.dumpTo(str); + return str; + } + ///////////////////////////////////////////////////////////////////// // @@ -251,5 +315,17 @@ namespace zypp newurl = Url(fields[3]); } + void HistoryItemRepoUrlChange::dumpTo(ostream & str) const + { + HistoryItem::dumpTo(str); + str << "|" << alias << "|" << newurl; + } + + ostream & operator<<(ostream & str, const HistoryItemRepoUrlChange & obj) + { + obj.dumpTo(str); + return str; + } + } diff --git a/zypp/HistoryLogData.h b/zypp/HistoryLogData.h index 41178db..c542ef4 100644 --- a/zypp/HistoryLogData.h +++ b/zypp/HistoryLogData.h @@ -13,6 +13,8 @@ #ifndef ZYPP_HISTORYLOGDATA_H_ #define ZYPP_HISTORYLOGDATA_H_ +#include + #include "zypp/Date.h" #include "zypp/Edition.h" #include "zypp/Arch.h" @@ -93,6 +95,8 @@ namespace zypp virtual ~HistoryItem() {} + virtual void dumpTo(std::ostream & str) const; + public: Date date; HistoryActionID action; @@ -113,7 +117,7 @@ namespace zypp virtual ~HistoryItemInstall() {} - virtual const std::string asString() const; + virtual void dumpTo(std::ostream & str) const; public: std::string name; @@ -139,6 +143,8 @@ namespace zypp virtual ~HistoryItemRemove() {} + virtual void dumpTo(std::ostream & str) const; + public: std::string name; Edition edition; @@ -161,6 +167,8 @@ namespace zypp virtual ~HistoryItemRepoAdd() {} + virtual void dumpTo(std::ostream & str) const; + public: std::string alias; Url url; @@ -181,6 +189,8 @@ namespace zypp virtual ~HistoryItemRepoRemove() {} + virtual void dumpTo(std::ostream & str) const; + public: std::string alias; }; @@ -200,6 +210,8 @@ namespace zypp virtual ~HistoryItemRepoAliasChange() {} + virtual void dumpTo(std::ostream & str) const; + public: std::string oldalias; std::string newalias; @@ -220,12 +232,15 @@ namespace zypp virtual ~HistoryItemRepoUrlChange() {} + virtual void dumpTo(std::ostream & str) const; + public: std::string alias; Url newurl; }; ///////////////////////////////////////////////////////////////////// + std::ostream & operator<<(std::ostream & str, const HistoryItem & obj); } diff --git a/zypp/parser/HistoryLogReader.cc b/zypp/parser/HistoryLogReader.cc index 8309b54..e339a76 100644 --- a/zypp/parser/HistoryLogReader.cc +++ b/zypp/parser/HistoryLogReader.cc @@ -31,16 +31,68 @@ namespace zypp ///////////////////////////////////////////////////////////////////// // - // CLASS NAME: HistoryLogReader + // CLASS NAME: HistoryLogReader::Impl // ///////////////////////////////////////////////////////////////////// - HistoryLogReader::HistoryLogReader( const Pathname & historyFile, - const ProcessItem & callback ) - : _filename(historyFile), _callback(callback) + struct HistoryLogReader::Impl + { + Impl( const Pathname & historyFile, const ProcessItem & callback ); + ~Impl() + {} + + HistoryItem::Ptr createHistoryItem(HistoryItem::FieldVector & fields); + + void readAll(const ProgressData::ReceiverFnc & progress); + + Pathname _filename; + ProcessItem _callback; + bool _ignoreInvalid; + }; + + HistoryLogReader::Impl::Impl( const Pathname & historyFile, + const ProcessItem & callback ) + : _filename(historyFile), _callback(callback), _ignoreInvalid(false) {} - void HistoryLogReader::readAll(const ProgressData::ReceiverFnc & progress) + HistoryItem::Ptr + HistoryLogReader::Impl::createHistoryItem(HistoryItem::FieldVector & fields) + { + HistoryActionID aid(str::trim(fields[1])); + switch (aid.toEnum()) + { + case HistoryActionID::INSTALL_e: + return HistoryItemInstall::Ptr(new HistoryItemInstall(fields)); + break; + + case HistoryActionID::REMOVE_e: + return HistoryItemRemove::Ptr(new HistoryItemRemove(fields)); + break; + + case HistoryActionID::REPO_ADD_e: + return HistoryItemRepoAdd::Ptr(new HistoryItemRepoAdd(fields)); + break; + + case HistoryActionID::REPO_REMOVE_e: + return HistoryItemRepoRemove::Ptr(new HistoryItemRepoRemove(fields)); + break; + + case HistoryActionID::REPO_CHANGE_ALIAS_e: + return HistoryItemRepoAliasChange::Ptr(new HistoryItemRepoAliasChange(fields)); + break; + + case HistoryActionID::REPO_CHANGE_URL_e: + return HistoryItemRepoUrlChange::Ptr(new HistoryItemRepoUrlChange(fields)); + break; + + default: + WAR << "Unknown history log action type: " << fields[1] << endl; + } + + return HistoryItem::Ptr(); + } + + void HistoryLogReader::Impl::readAll(const ProgressData::ReceiverFnc & progress) { InputStream is(_filename); iostr::EachLine line(is); @@ -49,14 +101,15 @@ namespace zypp pd.sendTo( progress ); pd.toMin(); - for (; line; line.next(), pd.tick()) + HistoryItem::FieldVector fields; + HistoryItem::Ptr item_ptr; + for (; line; line.next(), pd.tick(), fields.clear(), item_ptr.reset()) { const string & s = *line; if (s[0] == '#') // ignore comments continue; - // determine action - HistoryItem::FieldVector fields; + // parse fields str::splitEscaped(s, back_inserter(fields), "|", true); if (fields.size() <= 2) @@ -64,46 +117,33 @@ namespace zypp str::form("Bad number of fields. Got %ld, expected more than %d.", fields.size(), 2))); - // parse into the data structures - HistoryActionID aid(str::trim(fields[1])); try { - switch (aid.toEnum()) - { - case HistoryActionID::INSTALL_e: - _callback(HistoryItemInstall::Ptr(new HistoryItemInstall(fields))); - break; - - case HistoryActionID::REMOVE_e: - _callback(HistoryItemRemove::Ptr(new HistoryItemRemove(fields))); - break; - - case HistoryActionID::REPO_ADD_e: - _callback(HistoryItemRepoAdd::Ptr(new HistoryItemRepoAdd(fields))); - break; - - case HistoryActionID::REPO_REMOVE_e: - _callback(HistoryItemRepoRemove::Ptr(new HistoryItemRepoRemove(fields))); - break; - - case HistoryActionID::REPO_CHANGE_ALIAS_e: - _callback(HistoryItemRepoAliasChange::Ptr(new HistoryItemRepoAliasChange(fields))); - break; - - case HistoryActionID::REPO_CHANGE_URL_e: - _callback(HistoryItemRepoUrlChange::Ptr(new HistoryItemRepoUrlChange(fields))); - break; + item_ptr = createHistoryItem(fields); + } + catch (const Exception & e) + { + ZYPP_CAUGHT(e); + ERR << "Invalid history log entry on line #" << line.lineNo() << ":" << endl + << s << endl; - default: - WAR << "Unknown history log action type: " << fields[1] << endl; + if (!_ignoreInvalid) + { + ParseException newe( + str::form("Error in history log on line #%u.", line.lineNo() ) ); + newe.remember(e); + ZYPP_THROW(newe); } } - catch (const Exception & e) + + if (item_ptr) + _callback(item_ptr); + else if (!_ignoreInvalid) { - ParseException newe( - str::form("Error in history log on line #%u.", line.lineNo())); - newe.remember(e); - ZYPP_THROW(newe); + ParseException + e(str::form("Error in history log on line #%u.", line.lineNo())); + e.addHistory("Unknown entry type."); + ZYPP_THROW(e); } } @@ -111,9 +151,29 @@ namespace zypp } + ///////////////////////////////////////////////////////////////////// + // + // CLASS NAME: HistoryLogReader + // + ///////////////////////////////////////////////////////////////////// + + HistoryLogReader::HistoryLogReader( const Pathname & historyFile, + const ProcessItem & callback ) + : _pimpl(new HistoryLogReader::Impl(historyFile, callback)) + {} + HistoryLogReader::~HistoryLogReader() {} + void HistoryLogReader::setIgnoreInvalidItems(bool ignoreInvalid) + { _pimpl->_ignoreInvalid = ignoreInvalid; } + + bool HistoryLogReader::ignoreInvalidItems() const + { return _pimpl->_ignoreInvalid; } + + void HistoryLogReader::readAll(const ProgressData::ReceiverFnc & progress) + { _pimpl->readAll(progress); } + ///////////////////////////////////////////////////////////////// } // namespace parser diff --git a/zypp/parser/HistoryLogReader.h b/zypp/parser/HistoryLogReader.h index 43dda7a..7cc4b29 100644 --- a/zypp/parser/HistoryLogReader.h +++ b/zypp/parser/HistoryLogReader.h @@ -35,7 +35,40 @@ namespace zypp // CLASS NAME: HistoryLogReader // /** + * Reads a zypp history log file and calls the ProcessItem function passed + * in the constructor for each item found. * + * Example: + * + * + * struct HistoryItemCollector + * { + * vector items; + * + * bool processEntry( 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; + * } + * + * + * + * \see http://en.opensuse.org/Libzypp/Package_History */ class HistoryLogReader { @@ -51,17 +84,38 @@ namespace zypp * Read the whole log file. */ void readAll( - const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc()); + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() ); + + /** + * Read log from specified \a date. + */ + void readFrom( const Date & date, + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() ); - /* - * readFrom(Date); - * readFromTo(Date, Date); + /** + * Read log between \a fromDate and \a toDate. + */ + void readFromTo( const Date & fromDate, const Date & toDate, + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() ); + + /** + * Set the reader to ignore invalid log entries and continue with the rest. + * + * \param ignoreInvalid true will cause the reader to ignore invalid entries */ + void setIgnoreInvalidItems( bool ignoreInvalid = false ); + + /** + * Whether the reader is set to ignore invalid log entries. + */ + bool ignoreInvalidItems() const; private: - Pathname _filename; - ProcessItem _callback; + /** Implementation */ + class Impl; + RW_pointer > _pimpl; }; + /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// -- 2.7.4