libzypp 9.41.1

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 std::endl;
00023 
00025 namespace zypp
00026 {
00028   namespace parser
00029   {
00030 
00032   //
00033   //    class HistoryLogReader::Impl
00034   //
00036   struct HistoryLogReader::Impl
00037   {
00038     Impl( const Pathname & historyFile_r, const Options & options_r, const ProcessData & callback_r )
00039     :  _filename( historyFile_r )
00040     , _options( options_r )
00041     , _callback( callback_r )
00042     {}
00043 
00044     bool parseLine( const std::string & line_r, unsigned int lineNr_r );
00045 
00046     void readAll( const ProgressData::ReceiverFnc & progress_r );
00047     void readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r );
00048     void readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r );
00049 
00050     Pathname _filename;
00051     Options  _options;
00052     ProcessData _callback;
00053 
00054 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
00055     ProcessItem _oldAPICallback;
00056   private:
00057     HistoryItem::Ptr _oldAPIcreateHistoryItem( HistoryItem::FieldVector & fields );
00058     void _oldAPIparseLine(const std::string & line, unsigned int lineNr);
00059 #endif // WITH_DEPRECATED_HISTORYITEM_API
00060   };
00061 
00062   bool HistoryLogReader::Impl::parseLine( const std::string & line_r, unsigned lineNr_r )
00063   {
00064 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
00065     if ( _oldAPICallback )
00066     {
00067       _oldAPIparseLine( line_r, lineNr_r );
00068       return true;      // old api did not eavluate callback return value :(
00069     }
00070 #endif // WITH_DEPRECATED_HISTORYITEM_API
00071 
00072     // parse into fields
00073     HistoryLogData::FieldVector fields;
00074     str::splitEscaped( line_r, std::back_inserter(fields), "|", true );
00075     if ( fields.size() >= 2 )
00076       str::trim( fields[1] );   // for whatever reason writer is padding the action field
00077 
00078     // move into data class
00079     HistoryLogData::Ptr data;
00080     try
00081     {
00082       data = HistoryLogData::create( fields );
00083     }
00084     catch ( const Exception & excpt )
00085     {
00086       ZYPP_CAUGHT( excpt );
00087       if ( _options.testFlag( IGNORE_INVALID_ITEMS ) )
00088       {
00089         WAR << "Ignore invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
00090         return true;
00091       }
00092       else
00093       {
00094         ERR << "Invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
00095         ParseException newexcpt( str::Str() << "Error in history log on line #" << lineNr_r );
00096         newexcpt.remember( excpt );
00097         ZYPP_THROW( newexcpt );
00098       }
00099     }
00100 
00101     // consume data
00102     if ( _callback && !_callback( data ) )
00103     {
00104       WAR << "Stop parsing requested by consumer callback on line #" << lineNr_r << endl;
00105       return false;
00106     }
00107     return true;
00108   }
00109 
00110   void HistoryLogReader::Impl::readAll( const ProgressData::ReceiverFnc & progress_r )
00111   {
00112     InputStream is( _filename );
00113     iostr::EachLine line( is );
00114 
00115     ProgressData pd;
00116     pd.sendTo( progress_r );
00117     pd.toMin();
00118 
00119     for ( ; line; line.next(), pd.tick() )
00120     {
00121       // ignore comments
00122       if ( (*line)[0] == '#' )
00123         continue;
00124 
00125       if ( ! parseLine( *line, line.lineNo() ) )
00126         break;  // requested by consumer callback
00127     }
00128 
00129     pd.toMax();
00130   }
00131 
00132   void HistoryLogReader::Impl::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r )
00133   {
00134     InputStream is( _filename );
00135     iostr::EachLine line( is );
00136 
00137     ProgressData pd;
00138     pd.sendTo( progress_r );
00139     pd.toMin();
00140 
00141     bool pastDate = false;
00142     for ( ; line; line.next(), pd.tick() )
00143     {
00144       const std::string & s = *line;
00145 
00146       // ignore comments
00147       if ( s[0] == '#' )
00148         continue;
00149 
00150       if ( pastDate )
00151       {
00152         if ( ! parseLine( s, line.lineNo() ) )
00153           break;        // requested by consumer callback
00154       }
00155       else
00156       {
00157         Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT );
00158         if ( logDate > date_r )
00159         {
00160           pastDate = true;
00161           if ( ! parseLine( s, line.lineNo() ) )
00162             break;      // requested by consumer callback
00163         }
00164       }
00165     }
00166 
00167     pd.toMax();
00168   }
00169 
00170   void HistoryLogReader::Impl::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r )
00171   {
00172     InputStream is( _filename );
00173     iostr::EachLine line( is );
00174 
00175     ProgressData pd;
00176     pd.sendTo( progress_r );
00177     pd.toMin();
00178 
00179     bool pastFromDate = false;
00180     for ( ; line; line.next(), pd.tick() )
00181     {
00182       const std::string & s = *line;
00183 
00184       // ignore comments
00185       if ( s[0] == '#' )
00186         continue;
00187 
00188       Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT );
00189 
00190       // past toDate - stop reading
00191       if ( logDate >= toDate_r )
00192         break;
00193 
00194       // past fromDate - start reading
00195       if ( !pastFromDate && logDate > fromDate_r )
00196         pastFromDate = true;
00197 
00198       if ( pastFromDate )
00199       {
00200         if ( ! parseLine( s, line.lineNo() ) )
00201           break;        // requested by consumer callback
00202       }
00203     }
00204 
00205     pd.toMax();
00206   }
00207 
00208 
00209 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
00210   HistoryItem::Ptr HistoryLogReader::Impl::_oldAPIcreateHistoryItem( HistoryItem::FieldVector & fields )
00211   {
00212     HistoryActionID aid( str::trim( fields[1] ) );
00213     switch ( aid.toEnum() )
00214     {
00215     case HistoryActionID::INSTALL_e:
00216       return HistoryItemInstall::Ptr( new HistoryItemInstall( fields ) );
00217       break;
00218 
00219     case HistoryActionID::REMOVE_e:
00220       return HistoryItemRemove::Ptr( new HistoryItemRemove( fields ) );
00221       break;
00222 
00223     case HistoryActionID::REPO_ADD_e:
00224       return HistoryItemRepoAdd::Ptr( new HistoryItemRepoAdd( fields ) );
00225       break;
00226 
00227     case HistoryActionID::REPO_REMOVE_e:
00228       return HistoryItemRepoRemove::Ptr( new HistoryItemRepoRemove( fields ) );
00229       break;
00230 
00231     case HistoryActionID::REPO_CHANGE_ALIAS_e:
00232       return HistoryItemRepoAliasChange::Ptr( new HistoryItemRepoAliasChange( fields ) );
00233       break;
00234 
00235     case HistoryActionID::REPO_CHANGE_URL_e:
00236       return HistoryItemRepoUrlChange::Ptr( new HistoryItemRepoUrlChange( fields ) );
00237       break;
00238 
00239     case HistoryActionID::NONE_e:
00240       break;
00241     }
00242     return HistoryItem::Ptr();
00243   }
00244   void HistoryLogReader::Impl::_oldAPIparseLine( const std::string & line, unsigned int lineNr )
00245   {
00246     // parse into fields
00247     HistoryItem::FieldVector fields;
00248     str::splitEscaped( line, back_inserter(fields), "|", true );
00249 
00250     if ( fields.size() <= 2 )
00251     {
00252       if ( ! _options.testFlag( IGNORE_INVALID_ITEMS ) )
00253       {
00254         ParseException e( str::form( "Error in history log on line #%u.", lineNr ) );
00255         e.addHistory( str::form( "Bad number of fields. Got %zd, expected more than %d.", fields.size(), 2 ) );
00256         ZYPP_THROW( e );
00257       }
00258       else
00259       {
00260         WAR << "Ignoring suspicious non-comment entry on line #" << lineNr << endl;
00261         return;
00262       }
00263     }
00264 
00265     HistoryItem::Ptr item_ptr;
00266     try
00267     {
00268       item_ptr = _oldAPIcreateHistoryItem( fields );
00269     }
00270     catch ( const Exception & e )
00271     {
00272       ZYPP_CAUGHT(e);
00273       ERR << "Invalid history log entry on line #" << lineNr << " '"<< line << "'" << endl;
00274 
00275       if ( ! _options.testFlag( IGNORE_INVALID_ITEMS ) )
00276       {
00277         ParseException newe( str::form( "Error in history log on line #%u.", lineNr ) );
00278         newe.remember( e );
00279         ZYPP_THROW( newe );
00280       }
00281     }
00282 
00283     if ( item_ptr )
00284     {
00285       _oldAPICallback( item_ptr );
00286     }
00287     else if ( ! _options.testFlag( IGNORE_INVALID_ITEMS ) )
00288     {
00289       ParseException e( str::form( "Error in history log on line #%u.", lineNr ) );
00290       e.addHistory( "Unknown entry type." );
00291       ZYPP_THROW( e );
00292     }
00293     else
00294     {
00295       WAR << "Unknown history log action type: " << fields[1] << " on line #" << lineNr << endl;
00296     }
00297   }
00298 #endif // WITH_DEPRECATED_HISTORYITEM_API
00299 
00301   //
00302   //    class HistoryLogReader
00303   //
00305 
00306 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
00307   HistoryLogReader::HistoryLogReader( const Pathname & historyFile,
00308                                       const ProcessItem & callback )
00309   : _pimpl(new HistoryLogReader::Impl( historyFile, Options(), ProcessData() ) )
00310   { _pimpl->_oldAPICallback = callback; }
00311 #endif // WITH_DEPRECATED_HISTORYITEM_API
00312 
00313   HistoryLogReader::HistoryLogReader( const Pathname & historyFile_r, const Options & options_r, const ProcessData & callback_r )
00314   : _pimpl( new HistoryLogReader::Impl( historyFile_r, options_r, callback_r ) )
00315   {}
00316 
00317   HistoryLogReader::~HistoryLogReader()
00318   {}
00319 
00320   void HistoryLogReader::setIgnoreInvalidItems( bool ignoreInvalid_r )
00321   { _pimpl->_options.setFlag( IGNORE_INVALID_ITEMS, ignoreInvalid_r ); }
00322 
00323   bool HistoryLogReader::ignoreInvalidItems() const
00324   { return _pimpl->_options.testFlag( IGNORE_INVALID_ITEMS ); }
00325 
00326   void HistoryLogReader::readAll( const ProgressData::ReceiverFnc & progress_r )
00327   { _pimpl->readAll( progress_r ); }
00328 
00329   void HistoryLogReader::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r )
00330   { _pimpl->readFrom( date_r, progress_r ); }
00331 
00332   void HistoryLogReader::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r )
00333   { _pimpl->readFromTo( fromDate_r, toDate_r, progress_r ); }
00334 
00335   } // namespace parser
00337 } // namespace zypp