HistoryLog reader:
authorJán Kupec <jkupec@suse.cz>
Mon, 26 Jan 2009 12:28:49 +0000 (13:28 +0100)
committerJán Kupec <jkupec@suse.cz>
Mon, 26 Jan 2009 12:28:49 +0000 (13:28 +0100)
- dumpTo() and operator<< for HistoryItem*
- hid implementation
- allow to ignore invalid log entries with setIngoreInvalidItems(true)

zypp/HistoryLog.cc
zypp/HistoryLogData.cc
zypp/HistoryLogData.h
zypp/parser/HistoryLogReader.cc
zypp/parser/HistoryLogReader.h

index 7839d6f..1c8218f 100644 (file)
@@ -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()
   {
index eb92ae6..362500d 100644 (file)
@@ -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;
+  }
+
 
 }
index 41178db..c542ef4 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef ZYPP_HISTORYLOGDATA_H_
 #define ZYPP_HISTORYLOGDATA_H_
 
+#include <iosfwd>
+
 #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);
 
 }
 
index 8309b54..e339a76 100644 (file)
@@ -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
index 43dda7a..7cc4b29 100644 (file)
@@ -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:
+   * <code>
+   *
+   * struct HistoryItemCollector
+   * {
+   *   vector<HistoryItem::Ptr> 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;
+   * }
+   *
+   * </code>
+   *
+   * \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 <tt>true</tt> 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<Impl,rw_pointer::Scoped<Impl> > _pimpl;
   };
+  ///////////////////////////////////////////////////////////////////
 
 
   /////////////////////////////////////////////////////////////////