libzypp 9.41.1
|
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