libzypp  10.5.0
HistoryLogReader.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00009 
00013 #include <iostream>
00014 
00015 #include "zypp/base/InputStream.h"
00016 #include "zypp/base/IOStream.h"
00017 #include "zypp/base/Logger.h"
00018 #include "zypp/parser/ParseException.h"
00019 
00020 #include "zypp/parser/HistoryLogReader.h"
00021 
00022 using namespace std;
00023 
00025 namespace zypp
00026 { 
00027 
00028   namespace parser
00029   { 
00030 
00031 
00033   //
00034   // CLASS NAME: HistoryLogReader::Impl
00035   //
00037 
00038   struct HistoryLogReader::Impl
00039   {
00040     Impl( const Pathname & historyFile, const ProcessItem & callback );
00041     ~Impl()
00042     {}
00043 
00044     HistoryItem::Ptr createHistoryItem(HistoryItem::FieldVector & fields);
00045     void parseLine(const string & line, unsigned int lineNr);
00046 
00047     void readAll(const ProgressData::ReceiverFnc & progress);
00048     void readFrom(const Date & date,
00049         const ProgressData::ReceiverFnc & progress);
00050     void readFromTo(
00051         const Date & fromDate, const Date & toDate,
00052         const ProgressData::ReceiverFnc & progress);
00053 
00054     Pathname _filename;
00055     ProcessItem _callback;
00056     bool _ignoreInvalid;
00057   };
00058 
00059   HistoryLogReader::Impl::Impl( const Pathname & historyFile,
00060                                 const ProcessItem & callback )
00061     : _filename(historyFile), _callback(callback), _ignoreInvalid(false)
00062   {}
00063 
00064   HistoryItem::Ptr
00065   HistoryLogReader::Impl::createHistoryItem(HistoryItem::FieldVector & fields)
00066   {
00067     HistoryActionID aid(str::trim(fields[1]));
00068     switch (aid.toEnum())
00069     {
00070     case HistoryActionID::INSTALL_e:
00071         return HistoryItemInstall::Ptr(new HistoryItemInstall(fields));
00072       break;
00073 
00074     case HistoryActionID::REMOVE_e:
00075       return HistoryItemRemove::Ptr(new HistoryItemRemove(fields));
00076       break;
00077 
00078     case HistoryActionID::REPO_ADD_e:
00079       return HistoryItemRepoAdd::Ptr(new HistoryItemRepoAdd(fields));
00080       break;
00081 
00082     case HistoryActionID::REPO_REMOVE_e:
00083       return HistoryItemRepoRemove::Ptr(new HistoryItemRepoRemove(fields));
00084       break;
00085 
00086     case HistoryActionID::REPO_CHANGE_ALIAS_e:
00087       return HistoryItemRepoAliasChange::Ptr(new HistoryItemRepoAliasChange(fields));
00088       break;
00089 
00090     case HistoryActionID::REPO_CHANGE_URL_e:
00091       return HistoryItemRepoUrlChange::Ptr(new HistoryItemRepoUrlChange(fields));
00092       break;
00093 
00094     default:
00095       WAR << "Unknown history log action type: " << fields[1] << endl;
00096     }
00097 
00098     return HistoryItem::Ptr();
00099   }
00100 
00101   void HistoryLogReader::Impl::parseLine(const string & line, unsigned int lineNr)
00102   {
00103     HistoryItem::FieldVector fields;
00104     HistoryItem::Ptr item_ptr;
00105 
00106     // parse into fields
00107     str::splitEscaped(line, back_inserter(fields), "|", true);
00108 
00109     if (fields.size() <= 2)
00110     {
00111       ParseException
00112         e(str::form("Error in history log on line #%u.", lineNr));
00113       e.addHistory(
00114           str::form("Bad number of fields. Got %zd, expected more than %d.",
00115               fields.size(), 2));
00116       ZYPP_THROW(e);
00117     }
00118 
00119     try
00120     {
00121       item_ptr = createHistoryItem(fields);
00122     }
00123     catch (const Exception & e)
00124     {
00125       ZYPP_CAUGHT(e);
00126       ERR << "Invalid history log entry on line #" << lineNr << ":" << endl
00127           << line << endl;
00128 
00129       if (!_ignoreInvalid)
00130       {
00131         ParseException newe(
00132             str::form("Error in history log on line #%u.", lineNr ) );
00133         newe.remember(e);
00134         ZYPP_THROW(newe);
00135       }
00136     }
00137 
00138     if (item_ptr)
00139       _callback(item_ptr);
00140     else if (!_ignoreInvalid)
00141     {
00142       ParseException
00143         e(str::form("Error in history log on line #%u.", lineNr));
00144       e.addHistory("Unknown entry type.");
00145       ZYPP_THROW(e);
00146     }
00147   }
00148 
00149   void HistoryLogReader::Impl::readAll(const ProgressData::ReceiverFnc & progress)
00150   {
00151     InputStream is(_filename);
00152     iostr::EachLine line(is);
00153 
00154     ProgressData pd;
00155     pd.sendTo( progress );
00156     pd.toMin();
00157 
00158     for (; line; line.next(), pd.tick() )
00159     {
00160       // ignore comments
00161       if ((*line)[0] == '#')
00162         continue;
00163 
00164       parseLine(*line, line.lineNo());
00165     }
00166 
00167     pd.toMax();
00168   }
00169 
00170   void HistoryLogReader::Impl::readFrom(const Date & date,
00171       const ProgressData::ReceiverFnc & progress)
00172   {
00173     InputStream is(_filename);
00174     iostr::EachLine line(is);
00175 
00176     ProgressData pd;
00177     pd.sendTo( progress );
00178     pd.toMin();
00179 
00180     bool pastDate = false;
00181     for (; line; line.next(), pd.tick())
00182     {
00183       const string & s = *line;
00184 
00185       // ignore comments
00186       if (s[0] == '#')
00187         continue;
00188 
00189       if (pastDate)
00190         parseLine(s, line.lineNo());
00191       else
00192       {
00193         Date logDate(s.substr(0, s.find('|')), HISTORY_LOG_DATE_FORMAT);
00194         if (logDate > date)
00195         {
00196           pastDate = true;
00197           parseLine(s, line.lineNo());
00198         }
00199       }
00200     }
00201 
00202     pd.toMax();
00203   }
00204 
00205   void HistoryLogReader::Impl::readFromTo(
00206       const Date & fromDate, const Date & toDate,
00207       const ProgressData::ReceiverFnc & progress)
00208   {
00209     InputStream is(_filename);
00210     iostr::EachLine line(is);
00211 
00212     ProgressData pd;
00213     pd.sendTo(progress);
00214     pd.toMin();
00215 
00216     bool pastFromDate = false;
00217     for (; line; line.next(), pd.tick())
00218     {
00219       const string & s = *line;
00220 
00221       // ignore comments
00222       if (s[0] == '#')
00223         continue;
00224 
00225       Date logDate(s.substr(0, s.find('|')), HISTORY_LOG_DATE_FORMAT);
00226 
00227       // past toDate - stop reading
00228       if (logDate >= toDate)
00229         break;
00230 
00231       // past fromDate - start reading
00232       if (!pastFromDate && logDate > fromDate)
00233         pastFromDate = true;
00234 
00235       if (pastFromDate)
00236         parseLine(s, line.lineNo());
00237     }
00238 
00239     pd.toMax();
00240   }
00241 
00243   //
00244   // CLASS NAME: HistoryLogReader
00245   //
00247 
00248   HistoryLogReader::HistoryLogReader( const Pathname & historyFile,
00249                                       const ProcessItem & callback )
00250     : _pimpl(new HistoryLogReader::Impl(historyFile, callback))
00251   {}
00252 
00253   HistoryLogReader::~HistoryLogReader()
00254   {}
00255 
00256   void HistoryLogReader::setIgnoreInvalidItems(bool ignoreInvalid)
00257   { _pimpl->_ignoreInvalid = ignoreInvalid; }
00258 
00259   bool HistoryLogReader::ignoreInvalidItems() const
00260   { return _pimpl->_ignoreInvalid; }
00261 
00262   void HistoryLogReader::readAll(const ProgressData::ReceiverFnc & progress)
00263   { _pimpl->readAll(progress); }
00264 
00265   void HistoryLogReader::readFrom(const Date & date,
00266       const ProgressData::ReceiverFnc & progress)
00267   { _pimpl->readFrom(date, progress); }
00268 
00269   void HistoryLogReader::readFromTo(
00270       const Date & fromDate, const Date & toDate,
00271       const ProgressData::ReceiverFnc & progress)
00272   { _pimpl->readFromTo(fromDate, toDate, progress); }
00273 
00274 
00276   } // namespace parser
00279 } // namespace zypp