HistoryLog reader:
[platform/upstream/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
46     void readAll(const ProgressData::ReceiverFnc & progress);
47
48     Pathname _filename;
49     ProcessItem _callback;
50     bool _ignoreInvalid;
51   };
52
53   HistoryLogReader::Impl::Impl( const Pathname & historyFile,
54                                 const ProcessItem & callback )
55     : _filename(historyFile), _callback(callback), _ignoreInvalid(false)
56   {}
57
58   HistoryItem::Ptr
59   HistoryLogReader::Impl::createHistoryItem(HistoryItem::FieldVector & fields)
60   {
61     HistoryActionID aid(str::trim(fields[1]));
62     switch (aid.toEnum())
63     {
64     case HistoryActionID::INSTALL_e:
65         return HistoryItemInstall::Ptr(new HistoryItemInstall(fields));
66       break;
67
68     case HistoryActionID::REMOVE_e:
69       return HistoryItemRemove::Ptr(new HistoryItemRemove(fields));
70       break;
71
72     case HistoryActionID::REPO_ADD_e:
73       return HistoryItemRepoAdd::Ptr(new HistoryItemRepoAdd(fields));
74       break;
75
76     case HistoryActionID::REPO_REMOVE_e:
77       return HistoryItemRepoRemove::Ptr(new HistoryItemRepoRemove(fields));
78       break;
79
80     case HistoryActionID::REPO_CHANGE_ALIAS_e:
81       return HistoryItemRepoAliasChange::Ptr(new HistoryItemRepoAliasChange(fields));
82       break;
83
84     case HistoryActionID::REPO_CHANGE_URL_e:
85       return HistoryItemRepoUrlChange::Ptr(new HistoryItemRepoUrlChange(fields));
86       break;
87
88     default:
89       WAR << "Unknown history log action type: " << fields[1] << endl;
90     }
91
92     return HistoryItem::Ptr();
93   }
94
95   void HistoryLogReader::Impl::readAll(const ProgressData::ReceiverFnc & progress)
96   {
97     InputStream is(_filename);
98     iostr::EachLine line(is);
99
100     ProgressData pd;
101     pd.sendTo( progress );
102     pd.toMin();
103
104     HistoryItem::FieldVector fields;
105     HistoryItem::Ptr item_ptr;
106     for (; line; line.next(), pd.tick(), fields.clear(), item_ptr.reset())
107     {
108       const string & s = *line;
109       if (s[0] == '#') // ignore comments
110         continue;
111
112       // parse fields
113       str::splitEscaped(s, back_inserter(fields), "|", true);
114
115       if (fields.size() <= 2)
116         ZYPP_THROW(ParseException(
117           str::form("Bad number of fields. Got %ld, expected more than %d.",
118             fields.size(), 2)));
119
120       try
121       {
122         item_ptr = createHistoryItem(fields);
123       }
124       catch (const Exception & e)
125       {
126         ZYPP_CAUGHT(e);
127         ERR << "Invalid history log entry on line #" << line.lineNo() << ":" << endl
128             << s << endl;
129
130         if (!_ignoreInvalid)
131         {
132           ParseException newe(
133               str::form("Error in history log on line #%u.", line.lineNo() ) );
134           newe.remember(e);
135           ZYPP_THROW(newe);
136         }
137       }
138
139       if (item_ptr)
140         _callback(item_ptr);
141       else if (!_ignoreInvalid)
142       {
143         ParseException
144           e(str::form("Error in history log on line #%u.", line.lineNo()));
145         e.addHistory("Unknown entry type.");
146         ZYPP_THROW(e);
147       }
148     }
149
150     pd.toMax();
151   }
152
153
154   /////////////////////////////////////////////////////////////////////
155   //
156   // CLASS NAME: HistoryLogReader
157   //
158   /////////////////////////////////////////////////////////////////////
159
160   HistoryLogReader::HistoryLogReader( const Pathname & historyFile,
161                                       const ProcessItem & callback )
162     : _pimpl(new HistoryLogReader::Impl(historyFile, callback))
163   {}
164
165   HistoryLogReader::~HistoryLogReader()
166   {}
167
168   void HistoryLogReader::setIgnoreInvalidItems(bool ignoreInvalid)
169   { _pimpl->_ignoreInvalid = ignoreInvalid; }
170
171   bool HistoryLogReader::ignoreInvalidItems() const
172   { return _pimpl->_ignoreInvalid; }
173
174   void HistoryLogReader::readAll(const ProgressData::ReceiverFnc & progress)
175   { _pimpl->readAll(progress); }
176
177
178     /////////////////////////////////////////////////////////////////
179   } // namespace parser
180   ///////////////////////////////////////////////////////////////////
181 /////////////////////////////////////////////////////////////////
182 } // namespace zypp
183 ///////////////////////////////////////////////////////////////////