aarch64 support
[tools/libzypp.git] / zypp / parser / HistoryLogReader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9
10 /** \file HistoryLogReader.cc
11  *
12  */
13 #include <iostream>
14
15 #include "zypp/base/InputStream.h"
16 #include "zypp/base/IOStream.h"
17 #include "zypp/base/Logger.h"
18 #include "zypp/parser/ParseException.h"
19
20 #include "zypp/parser/HistoryLogReader.h"
21
22 using namespace std;
23
24 ///////////////////////////////////////////////////////////////////
25 namespace zypp
26 { /////////////////////////////////////////////////////////////////
27   ///////////////////////////////////////////////////////////////////
28   namespace parser
29   { /////////////////////////////////////////////////////////////////
30
31
32   /////////////////////////////////////////////////////////////////////
33   //
34   // CLASS NAME: HistoryLogReader::Impl
35   //
36   /////////////////////////////////////////////////////////////////////
37
38   struct HistoryLogReader::Impl
39   {
40     Impl( const Pathname & historyFile, const ProcessItem & callback );
41     ~Impl()
42     {}
43
44     HistoryItem::Ptr createHistoryItem(HistoryItem::FieldVector & fields);
45     void parseLine(const string & line, unsigned int lineNr);
46
47     void readAll(const ProgressData::ReceiverFnc & progress);
48     void readFrom(const Date & date,
49         const ProgressData::ReceiverFnc & progress);
50     void readFromTo(
51         const Date & fromDate, const Date & toDate,
52         const ProgressData::ReceiverFnc & progress);
53
54     Pathname _filename;
55     ProcessItem _callback;
56     bool _ignoreInvalid;
57   };
58
59   HistoryLogReader::Impl::Impl( const Pathname & historyFile,
60                                 const ProcessItem & callback )
61     : _filename(historyFile), _callback(callback), _ignoreInvalid(false)
62   {}
63
64   HistoryItem::Ptr
65   HistoryLogReader::Impl::createHistoryItem(HistoryItem::FieldVector & fields)
66   {
67     HistoryActionID aid(str::trim(fields[1]));
68     switch (aid.toEnum())
69     {
70     case HistoryActionID::INSTALL_e:
71         return HistoryItemInstall::Ptr(new HistoryItemInstall(fields));
72       break;
73
74     case HistoryActionID::REMOVE_e:
75       return HistoryItemRemove::Ptr(new HistoryItemRemove(fields));
76       break;
77
78     case HistoryActionID::REPO_ADD_e:
79       return HistoryItemRepoAdd::Ptr(new HistoryItemRepoAdd(fields));
80       break;
81
82     case HistoryActionID::REPO_REMOVE_e:
83       return HistoryItemRepoRemove::Ptr(new HistoryItemRepoRemove(fields));
84       break;
85
86     case HistoryActionID::REPO_CHANGE_ALIAS_e:
87       return HistoryItemRepoAliasChange::Ptr(new HistoryItemRepoAliasChange(fields));
88       break;
89
90     case HistoryActionID::REPO_CHANGE_URL_e:
91       return HistoryItemRepoUrlChange::Ptr(new HistoryItemRepoUrlChange(fields));
92       break;
93
94     default:
95       WAR << "Unknown history log action type: " << fields[1] << endl;
96     }
97
98     return HistoryItem::Ptr();
99   }
100
101   void HistoryLogReader::Impl::parseLine(const string & line, unsigned int lineNr)
102   {
103     HistoryItem::FieldVector fields;
104     HistoryItem::Ptr item_ptr;
105
106     // parse into fields
107     str::splitEscaped(line, back_inserter(fields), "|", true);
108
109     if (fields.size() <= 2)
110     {
111       ParseException
112         e(str::form("Error in history log on line #%u.", lineNr));
113       e.addHistory(
114           str::form("Bad number of fields. Got %zd, expected more than %d.",
115               fields.size(), 2));
116       ZYPP_THROW(e);
117     }
118
119     try
120     {
121       item_ptr = createHistoryItem(fields);
122     }
123     catch (const Exception & e)
124     {
125       ZYPP_CAUGHT(e);
126       ERR << "Invalid history log entry on line #" << lineNr << ":" << endl
127           << line << endl;
128
129       if (!_ignoreInvalid)
130       {
131         ParseException newe(
132             str::form("Error in history log on line #%u.", lineNr ) );
133         newe.remember(e);
134         ZYPP_THROW(newe);
135       }
136     }
137
138     if (item_ptr)
139       _callback(item_ptr);
140     else if (!_ignoreInvalid)
141     {
142       ParseException
143         e(str::form("Error in history log on line #%u.", lineNr));
144       e.addHistory("Unknown entry type.");
145       ZYPP_THROW(e);
146     }
147   }
148
149   void HistoryLogReader::Impl::readAll(const ProgressData::ReceiverFnc & progress)
150   {
151     InputStream is(_filename);
152     iostr::EachLine line(is);
153
154     ProgressData pd;
155     pd.sendTo( progress );
156     pd.toMin();
157
158     for (; line; line.next(), pd.tick() )
159     {
160       // ignore comments
161       if ((*line)[0] == '#')
162         continue;
163
164       parseLine(*line, line.lineNo());
165     }
166
167     pd.toMax();
168   }
169
170   void HistoryLogReader::Impl::readFrom(const Date & date,
171       const ProgressData::ReceiverFnc & progress)
172   {
173     InputStream is(_filename);
174     iostr::EachLine line(is);
175
176     ProgressData pd;
177     pd.sendTo( progress );
178     pd.toMin();
179
180     bool pastDate = false;
181     for (; line; line.next(), pd.tick())
182     {
183       const string & s = *line;
184
185       // ignore comments
186       if (s[0] == '#')
187         continue;
188
189       if (pastDate)
190         parseLine(s, line.lineNo());
191       else
192       {
193         Date logDate(s.substr(0, s.find('|')), HISTORY_LOG_DATE_FORMAT);
194         if (logDate > date)
195         {
196           pastDate = true;
197           parseLine(s, line.lineNo());
198         }
199       }
200     }
201
202     pd.toMax();
203   }
204
205   void HistoryLogReader::Impl::readFromTo(
206       const Date & fromDate, const Date & toDate,
207       const ProgressData::ReceiverFnc & progress)
208   {
209     InputStream is(_filename);
210     iostr::EachLine line(is);
211
212     ProgressData pd;
213     pd.sendTo(progress);
214     pd.toMin();
215
216     bool pastFromDate = false;
217     for (; line; line.next(), pd.tick())
218     {
219       const string & s = *line;
220
221       // ignore comments
222       if (s[0] == '#')
223         continue;
224
225       Date logDate(s.substr(0, s.find('|')), HISTORY_LOG_DATE_FORMAT);
226
227       // past toDate - stop reading
228       if (logDate >= toDate)
229         break;
230
231       // past fromDate - start reading
232       if (!pastFromDate && logDate > fromDate)
233         pastFromDate = true;
234
235       if (pastFromDate)
236         parseLine(s, line.lineNo());
237     }
238
239     pd.toMax();
240   }
241
242   /////////////////////////////////////////////////////////////////////
243   //
244   // CLASS NAME: HistoryLogReader
245   //
246   /////////////////////////////////////////////////////////////////////
247
248   HistoryLogReader::HistoryLogReader( const Pathname & historyFile,
249                                       const ProcessItem & callback )
250     : _pimpl(new HistoryLogReader::Impl(historyFile, callback))
251   {}
252
253   HistoryLogReader::~HistoryLogReader()
254   {}
255
256   void HistoryLogReader::setIgnoreInvalidItems(bool ignoreInvalid)
257   { _pimpl->_ignoreInvalid = ignoreInvalid; }
258
259   bool HistoryLogReader::ignoreInvalidItems() const
260   { return _pimpl->_ignoreInvalid; }
261
262   void HistoryLogReader::readAll(const ProgressData::ReceiverFnc & progress)
263   { _pimpl->readAll(progress); }
264
265   void HistoryLogReader::readFrom(const Date & date,
266       const ProgressData::ReceiverFnc & progress)
267   { _pimpl->readFrom(date, progress); }
268
269   void HistoryLogReader::readFromTo(
270       const Date & fromDate, const Date & toDate,
271       const ProgressData::ReceiverFnc & progress)
272   { _pimpl->readFromTo(fromDate, toDate, progress); }
273
274
275     /////////////////////////////////////////////////////////////////
276   } // namespace parser
277   ///////////////////////////////////////////////////////////////////
278 /////////////////////////////////////////////////////////////////
279 } // namespace zypp
280 ///////////////////////////////////////////////////////////////////