libzypp  12.16.5
HistoryLogReader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
13 #include <iostream>
14 
15 #include "zypp/base/InputStream.h"
16 #include "zypp/base/IOStream.h"
17 #include "zypp/base/Logger.h"
19 
21 
22 using std::endl;
23 
25 namespace zypp
26 {
28  namespace parser
29  {
30 
32  //
33  // class HistoryLogReader::Impl
34  //
37  {
38  Impl( const Pathname & historyFile_r, const Options & options_r, const ProcessData & callback_r )
39  : _filename( historyFile_r )
40  , _options( options_r )
41  , _callback( callback_r )
42  {}
43 
44  bool parseLine( const std::string & line_r, unsigned int lineNr_r );
45 
46  void readAll( const ProgressData::ReceiverFnc & progress_r );
47  void readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r );
48  void readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r );
49 
50  Pathname _filename;
51  Options _options;
53 
54 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
55  ProcessItem _oldAPICallback;
56  private:
57  HistoryItem::Ptr _oldAPIcreateHistoryItem( HistoryItem::FieldVector & fields );
58  void _oldAPIparseLine(const std::string & line, unsigned int lineNr);
59 #endif // WITH_DEPRECATED_HISTORYITEM_API
60  };
61 
62  bool HistoryLogReader::Impl::parseLine( const std::string & line_r, unsigned lineNr_r )
63  {
64 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
65  if ( _oldAPICallback )
66  {
67  _oldAPIparseLine( line_r, lineNr_r );
68  return true; // old api did not eavluate callback return value :(
69  }
70 #endif // WITH_DEPRECATED_HISTORYITEM_API
71 
72  // parse into fields
74  str::splitEscaped( line_r, std::back_inserter(fields), "|", true );
75  if ( fields.size() >= 2 )
76  str::trim( fields[1] ); // for whatever reason writer is padding the action field
77 
78  // move into data class
80  try
81  {
82  data = HistoryLogData::create( fields );
83  }
84  catch ( const Exception & excpt )
85  {
86  ZYPP_CAUGHT( excpt );
87  if ( _options.testFlag( IGNORE_INVALID_ITEMS ) )
88  {
89  WAR << "Ignore invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
90  return true;
91  }
92  else
93  {
94  ERR << "Invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl;
95  ParseException newexcpt( str::Str() << "Error in history log on line #" << lineNr_r );
96  newexcpt.remember( excpt );
97  ZYPP_THROW( newexcpt );
98  }
99  }
100 
101  // consume data
102  if ( _callback && !_callback( data ) )
103  {
104  WAR << "Stop parsing requested by consumer callback on line #" << lineNr_r << endl;
105  return false;
106  }
107  return true;
108  }
109 
111  {
112  InputStream is( _filename );
113  iostr::EachLine line( is );
114 
115  ProgressData pd;
116  pd.sendTo( progress_r );
117  pd.toMin();
118 
119  for ( ; line; line.next(), pd.tick() )
120  {
121  // ignore comments
122  if ( (*line)[0] == '#' )
123  continue;
124 
125  if ( ! parseLine( *line, line.lineNo() ) )
126  break; // requested by consumer callback
127  }
128 
129  pd.toMax();
130  }
131 
132  void HistoryLogReader::Impl::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r )
133  {
134  InputStream is( _filename );
135  iostr::EachLine line( is );
136 
137  ProgressData pd;
138  pd.sendTo( progress_r );
139  pd.toMin();
140 
141  bool pastDate = false;
142  for ( ; line; line.next(), pd.tick() )
143  {
144  const std::string & s = *line;
145 
146  // ignore comments
147  if ( s[0] == '#' )
148  continue;
149 
150  if ( pastDate )
151  {
152  if ( ! parseLine( s, line.lineNo() ) )
153  break; // requested by consumer callback
154  }
155  else
156  {
157  Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT );
158  if ( logDate > date_r )
159  {
160  pastDate = true;
161  if ( ! parseLine( s, line.lineNo() ) )
162  break; // requested by consumer callback
163  }
164  }
165  }
166 
167  pd.toMax();
168  }
169 
170  void HistoryLogReader::Impl::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r )
171  {
172  InputStream is( _filename );
173  iostr::EachLine line( is );
174 
175  ProgressData pd;
176  pd.sendTo( progress_r );
177  pd.toMin();
178 
179  bool pastFromDate = false;
180  for ( ; line; line.next(), pd.tick() )
181  {
182  const std::string & s = *line;
183 
184  // ignore comments
185  if ( s[0] == '#' )
186  continue;
187 
188  Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT );
189 
190  // past toDate - stop reading
191  if ( logDate >= toDate_r )
192  break;
193 
194  // past fromDate - start reading
195  if ( !pastFromDate && logDate > fromDate_r )
196  pastFromDate = true;
197 
198  if ( pastFromDate )
199  {
200  if ( ! parseLine( s, line.lineNo() ) )
201  break; // requested by consumer callback
202  }
203  }
204 
205  pd.toMax();
206  }
207 
208 
209 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
210  HistoryItem::Ptr HistoryLogReader::Impl::_oldAPIcreateHistoryItem( HistoryItem::FieldVector & fields )
211  {
212  HistoryActionID aid( str::trim( fields[1] ) );
213  switch ( aid.toEnum() )
214  {
216  return HistoryItemInstall::Ptr( new HistoryItemInstall( fields ) );
217  break;
218 
220  return HistoryItemRemove::Ptr( new HistoryItemRemove( fields ) );
221  break;
222 
224  return HistoryItemRepoAdd::Ptr( new HistoryItemRepoAdd( fields ) );
225  break;
226 
228  return HistoryItemRepoRemove::Ptr( new HistoryItemRepoRemove( fields ) );
229  break;
230 
232  return HistoryItemRepoAliasChange::Ptr( new HistoryItemRepoAliasChange( fields ) );
233  break;
234 
236  return HistoryItemRepoUrlChange::Ptr( new HistoryItemRepoUrlChange( fields ) );
237  break;
238 
240  break;
241  }
242  return HistoryItem::Ptr();
243  }
244  void HistoryLogReader::Impl::_oldAPIparseLine( const std::string & line, unsigned int lineNr )
245  {
246  // parse into fields
247  HistoryItem::FieldVector fields;
248  str::splitEscaped( line, back_inserter(fields), "|", true );
249 
250  if ( fields.size() <= 2 )
251  {
252  if ( ! _options.testFlag( IGNORE_INVALID_ITEMS ) )
253  {
254  ParseException e( str::form( "Error in history log on line #%u.", lineNr ) );
255  e.addHistory( str::form( "Bad number of fields. Got %zd, expected more than %d.", fields.size(), 2 ) );
256  ZYPP_THROW( e );
257  }
258  else
259  {
260  WAR << "Ignoring suspicious non-comment entry on line #" << lineNr << endl;
261  return;
262  }
263  }
264 
265  HistoryItem::Ptr item_ptr;
266  try
267  {
268  item_ptr = _oldAPIcreateHistoryItem( fields );
269  }
270  catch ( const Exception & e )
271  {
272  ZYPP_CAUGHT(e);
273  ERR << "Invalid history log entry on line #" << lineNr << " '"<< line << "'" << endl;
274 
275  if ( ! _options.testFlag( IGNORE_INVALID_ITEMS ) )
276  {
277  ParseException newe( str::form( "Error in history log on line #%u.", lineNr ) );
278  newe.remember( e );
279  ZYPP_THROW( newe );
280  }
281  }
282 
283  if ( item_ptr )
284  {
285  _oldAPICallback( item_ptr );
286  }
287  else if ( ! _options.testFlag( IGNORE_INVALID_ITEMS ) )
288  {
289  ParseException e( str::form( "Error in history log on line #%u.", lineNr ) );
290  e.addHistory( "Unknown entry type." );
291  ZYPP_THROW( e );
292  }
293  else
294  {
295  WAR << "Unknown history log action type: " << fields[1] << " on line #" << lineNr << endl;
296  }
297  }
298 #endif // WITH_DEPRECATED_HISTORYITEM_API
299 
301  //
302  // class HistoryLogReader
303  //
305 
306 #if defined(WITH_DEPRECATED_HISTORYITEM_API)
307  HistoryLogReader::HistoryLogReader( const Pathname & historyFile,
308  const ProcessItem & callback )
309  : _pimpl(new HistoryLogReader::Impl( historyFile, Options(), ProcessData() ) )
310  { _pimpl->_oldAPICallback = callback; }
311 #endif // WITH_DEPRECATED_HISTORYITEM_API
312 
313  HistoryLogReader::HistoryLogReader( const Pathname & historyFile_r, const Options & options_r, const ProcessData & callback_r )
314  : _pimpl( new HistoryLogReader::Impl( historyFile_r, options_r, callback_r ) )
315  {}
316 
318  {}
319 
320  void HistoryLogReader::setIgnoreInvalidItems( bool ignoreInvalid_r )
321  { _pimpl->_options.setFlag( IGNORE_INVALID_ITEMS, ignoreInvalid_r ); }
322 
324  { return _pimpl->_options.testFlag( IGNORE_INVALID_ITEMS ); }
325 
327  { _pimpl->readAll( progress_r ); }
328 
329  void HistoryLogReader::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r )
330  { _pimpl->readFrom( date_r, progress_r ); }
331 
332  void HistoryLogReader::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r )
333  { _pimpl->readFromTo( fromDate_r, toDate_r, progress_r ); }
334 
335  } // namespace parser
337 } // namespace zypp