libzypp 17.37.17
CommitMessages.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include "CommitMessages.h"
10
11#include <zypp-core/TriBool.h>
12#include <zypp-core/ng/core/String>
14#include <string>
15#include <string_view>
16
18{
19 namespace {
20 // Serializes a field of type T into the ByteArray buffer, appending a \0 to terminate the field
21 template <typename T>
22 void serializeStepField ( ByteArray &data, const T&field ) {
23 if constexpr ( std::is_same_v<bool, T> ) {
24 if ( field ) {
25 data.push_back ('1');
26 data.push_back ('\0');
27 } else {
28 data.push_back ('0');
29 data.push_back ('\0');
30 }
31 } else if constexpr ( std::is_same_v<std::string, T> ) {
32 data.insert(data.end(), field.begin(), field.end() );
33 data.push_back ('\0');
34 } else {
35 // numbers, convert to string and recursively call again
36 serializeStepField (data, str::numstring (field) );
37 }
38 }
39
40 // fetches a terminated string from the iterator, requires the terminator to come up before hitting the \a end
41 std::string fetchTerminatedField ( ByteArray::const_iterator &i, ByteArray::const_iterator end, const char term = '\0' ){
42 std::string fData;
43 fData.reserve(512);
44 while ( true ) {
45 if ( i == end )
46 ZYPP_THROW( zypp::PluginFrameException("Unexpected end of field in transaction step") );
47 if ( *i == term ) {
48 i++; // consume the terminator
49 break;
50 }
51 fData.push_back( *i );
52 i++;
53 }
54
55 fData.shrink_to_fit();
56 return fData;
57 };
58
59 template <typename T>
60 using has_stepid = decltype(std::declval<T>().stepId);
61
62 template <typename T>
63 zyppng::expected<PluginFrame> makeTrivialMessage( const std::string &command, const T& msg ) {
64
65 PluginFrame f(command);
67 f.addHeader ("stepId", asString (msg.stepId) );
68 return zyppng::expected<PluginFrame>::success ( std::move(f) );
69 }
70
71 template <typename T>
72 zyppng::expected<T> parseTrivialMessage( const PluginFrame &msg ) {
73 try {
74 T c;
75 if ( msg.command() != T::typeName )
76 return zyppng::expected<T>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException( str::Str()<<"Message is not a " << T::typeName ) ) );
77
78 if constexpr ( std::is_detected_v<has_stepid, T> ) {
79 zyppng::rpc::parseHeaderIntoField ( msg, "stepId", c.stepId );
80 }
81
83
84 } catch( const zypp::Exception &e ) {
85 ZYPP_CAUGHT (e);
87 }
88 }
89 }
90
91#define IMPL_TRIVIAL_MESSAGE( Type ) \
92 zyppng::expected<PluginFrame> Type::toStompMessage() const \
93 { \
94 return makeTrivialMessage( #Type, *this ); \
95 } \
96 \
97 zyppng::expected<Type> Type::fromStompMessage(const PluginFrame &msg) \
98 { \
99 return parseTrivialMessage<Type>( msg ); \
100 }
101
103 {
105 f.addHeader ("flags", asString (flags) );
106 f.addHeader ("arch", arch );
107 f.addHeader ("root", root );
108 f.addHeader ("dbPath", dbPath );
109 f.addHeader ("lockFilePath", lockFilePath );
110 f.addHeader ("ignoreArch", ignoreArch ? "1" : "0" );
111
112 ByteArray &body = f.bodyRef();
113 for ( const auto &step : transactionSteps ) {
114 if ( std::holds_alternative<InstallStep>(step) ) {
115 const InstallStep &value = std::get<InstallStep>(step);
116 body.push_back( InstallStepType );
117 serializeStepField( body, value.stepId );
118 serializeStepField( body, value.pathname );
119 serializeStepField( body, value.multiversion );
120
121 } else if ( std::holds_alternative<RemoveStep>(step) ) {
122 const RemoveStep &value = std::get<RemoveStep>(step);
123 body.push_back( RemoveStepType );
124 serializeStepField( body, value.stepId );
125 serializeStepField( body, value.name );
126 serializeStepField( body, value.version );
127 serializeStepField( body, value.release );
128 serializeStepField( body, value.arch );
129 } else {
130 return zyppng::expected<PluginFrame>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Unknown Step type in message") ) );
131 }
132 }
133 body.shrink_to_fit();
134 return zyppng::expected<PluginFrame>::success ( std::move(f) );
135 }
136
138 {
139 try {
140 Commit c;
141
142 if ( msg.command() != Commit::typeName )
143 return zyppng::expected<Commit>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a Commit") ) );
144
145 zyppng::rpc::parseHeaderIntoField ( msg, "flags", c.flags );
146 zyppng::rpc::parseHeaderIntoField ( msg, "arch", c.arch );
147 zyppng::rpc::parseHeaderIntoField ( msg, "root", c.root );
148 zyppng::rpc::parseHeaderIntoField ( msg, "dbPath", c.dbPath );
149 zyppng::rpc::parseHeaderIntoField ( msg, "lockFilePath", c.lockFilePath );
150 zyppng::rpc::parseHeaderIntoField ( msg, "ignoreArch", c.ignoreArch );
151
152 // we got the fields, lets parse the steps
153 // steps are serialized into a very simple form, starting with one byte that tells us what step type we look at
154 // <stepType><step fields seperated by \0>
155 enum ParseState {
156 ReadingStepType,
157 Reading
158 };
159
160 const auto &data = msg.body ();
161 for ( auto i = data.begin(); i != data.end(); ) {
162 uint8_t stepType = *i;
163 i++;
164
165 if ( i == data.end() )
166 return zyppng::expected<Commit>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Invalid data in commit message") ) );
167
168 switch ( stepType ) {
169 case InstallStepType: {
170 InstallStep s;
171 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.stepId );
172 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.pathname );
173 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.multiversion );
174 c.transactionSteps.push_back(s);
175 break;
176 }
177 case RemoveStepType: {
178 RemoveStep s;
179 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.stepId );
180 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.name );
181 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.version );
182 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.release );
183 zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.arch );
184 c.transactionSteps.push_back(s);
185 break;
186 }
187 default:
188 return zyppng::expected<Commit>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Invalid step type in commit message") ) );
189 }
190 }
191
192 return zyppng::expected<Commit>::success ( std::move(c) );
193
194 } catch( const zypp::Exception &e ) {
195 ZYPP_CAUGHT (e);
197 }
198 }
199
201 {
203 ByteArray &body = f.bodyRef();
204 for ( const auto &err : problems ) {
205 serializeStepField ( body, err );
206 }
207 return zyppng::expected<PluginFrame>::success ( std::move(f) );
208 }
209
211 {
212 try {
214 if ( msg.command() != TransactionError::typeName )
215 return zyppng::expected<TransactionError>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a TransactionError") ) );
216
217 const auto &data = msg.body ();
218 for ( auto i = data.begin(); i != data.end(); ) {
219 c.problems.push_back( fetchTerminatedField( i, data.end() ) );
220 }
221
222 return zyppng::expected<TransactionError>::success( std::move(c) );
223
224 } catch ( const zypp::Exception &e ) {
225 ZYPP_CAUGHT (e);
227 }
228 }
229
237
239 {
240 try {
241 RpmLog c;
242 if ( msg.command() != RpmLog::typeName )
243 return zyppng::expected<RpmLog>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a RpmLog") ) );
244
245 zyppng::rpc::parseHeaderIntoField ( msg, "level", c.level );
246 c.line = msg.body().asString();
247
248 return zyppng::expected<RpmLog>::success( std::move(c) );
249
250 } catch ( const zypp::Exception &e ) {
251 ZYPP_CAUGHT (e);
253 }
254 }
255
259
261 {
263 f.addHeader ("stepId", asString (stepId) );
264 f.addHeader ("amount", asString (amount) );
265 return zyppng::expected<PluginFrame>::success ( std::move(f) );
266 }
267
269 {
270 try {
272 if ( msg.command() != PackageProgress::typeName )
273 return zyppng::expected<PackageProgress>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a PackageProgress") ) );
274
275 zyppng::rpc::parseHeaderIntoField ( msg, "stepId", c.stepId );
276 zyppng::rpc::parseHeaderIntoField ( msg, "amount", c.amount );
277
278 return zyppng::expected<PackageProgress>::success( std::move(c) );
279
280 } catch ( const zypp::Exception &e ) {
281 ZYPP_CAUGHT (e);
283 }
284 }
285
292
294 {
295 try {
296 CleanupBegin c;
297 if ( msg.command() != CleanupBegin::typeName )
298 return zyppng::expected<CleanupBegin>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a CleanupBegin") ) );
299
300 zyppng::rpc::parseHeaderIntoField ( msg, "nvra", c.nvra );
301 return zyppng::expected<CleanupBegin>::success( std::move(c) );
302
303 } catch ( const zypp::Exception &e ) {
304 ZYPP_CAUGHT (e);
306 }
307 }
308
315
317 {
318 try {
320 if ( msg.command() != CleanupFinished::typeName )
321 return zyppng::expected<CleanupFinished>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a CleanupFinished") ) );
322
323 zyppng::rpc::parseHeaderIntoField ( msg, "nvra", c.nvra );
324 return zyppng::expected<CleanupFinished>::success( std::move(c) );
325
326 } catch ( const zypp::Exception &e ) {
327 ZYPP_CAUGHT (e);
329 }
330 }
331
339
341 {
342 try {
344 if ( msg.command() != CleanupProgress::typeName )
345 return zyppng::expected<CleanupProgress>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a CleanupProgress") ) );
346
347 zyppng::rpc::parseHeaderIntoField ( msg, "nvra", c.nvra );
348 zyppng::rpc::parseHeaderIntoField ( msg, "amount", c.amount );
349 return zyppng::expected<CleanupProgress>::success( std::move(c) );
350
351 } catch ( const zypp::Exception &e ) {
352 ZYPP_CAUGHT (e);
354 }
355 }
356
358 {
360 f.addHeader ("stepId" , asString (stepId) );
361 f.addHeader ("scriptType" , asString (scriptType) );
362 f.addHeader ("scriptPackage", asString (scriptPackage) );
363 return zyppng::expected<PluginFrame>::success ( std::move(f) );
364 }
365
367 {
368 try {
369 ScriptBegin c;
370 if ( msg.command() != ScriptBegin::typeName )
371 return zyppng::expected<ScriptBegin>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a ScriptBegin") ) );
372
373 zyppng::rpc::parseHeaderIntoField ( msg, "stepId" , c.stepId );
374 zyppng::rpc::parseHeaderIntoField ( msg, "scriptType" , c.scriptType );
375 zyppng::rpc::parseHeaderIntoField ( msg, "scriptPackage" , c.scriptPackage );
376
377 return zyppng::expected<ScriptBegin>::success( std::move(c) );
378
379 } catch ( const zypp::Exception &e ) {
380 ZYPP_CAUGHT (e);
382 }
383 }
384
386
388 {
390 f.addHeader ("stepId" , asString (stepId) );
391 f.addHeader ("fatal" , asString (fatal) );
392 return zyppng::expected<PluginFrame>::success ( std::move(f) );
393 }
394
396 {
397 try {
398 ScriptError c;
399 if ( msg.command() != ScriptError::typeName )
400 return zyppng::expected<ScriptError>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a ScriptError") ) );
401
402 zyppng::rpc::parseHeaderIntoField ( msg, "stepId" , c.stepId );
403 zyppng::rpc::parseHeaderIntoField ( msg, "fatal" , c.fatal );
404
405 return zyppng::expected<ScriptError>::success( std::move(c) );
406
407 } catch ( const zypp::Exception &e ) {
408 ZYPP_CAUGHT (e);
410 }
411 }
412
419
421 {
422 try {
423 TransBegin c;
424 if ( msg.command() != TransBegin::typeName )
425 return zyppng::expected<TransBegin>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a TransBegin") ) );
426
427 zyppng::rpc::parseHeaderIntoField ( msg, "name" , c.name );
428
429 return zyppng::expected<TransBegin>::success( std::move(c) );
430
431 } catch ( const zypp::Exception &e ) {
432 ZYPP_CAUGHT (e);
434 }
435 }
436
438
445
447 {
448 try {
450 if ( msg.command() != TransProgress::typeName )
451 return zyppng::expected<TransProgress>::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a TransProgress") ) );
452
453 zyppng::rpc::parseHeaderIntoField ( msg, "amount", c.amount );
454
455 return zyppng::expected<TransProgress>::success( std::move(c) );
456
457 } catch ( const zypp::Exception &e ) {
458 ZYPP_CAUGHT (e);
460 }
461 }
462
463}
#define IMPL_TRIVIAL_MESSAGE(Type)
std::string asString() const
Definition ByteArray.h:24
Base class for Exception.
Definition Exception.h:153
Base class for PluginFrame Exception.
Command frame for communication with PluginScript.
Definition PluginFrame.h:42
ByteArray & bodyRef()
Return a reference to the frame body.
void setBody(const std::string &body_r)
Set the frame body.
const ByteArray & body() const
Return the frame body.
const std::string & command() const
Return the frame command.
void addHeader(const std::string &key_r, const std::string &value_r=std::string())
Add header for key_r leaving already existing headers for key_r unchanged.
static expected success(ConsParams &&...params)
Definition expected.h:115
constexpr bool is_detected_v
Definition type_traits.h:57
std::string numstring(char n, int w=0)
Definition String.h:290
std::string asString(const Patch::Category &obj)
Definition Patch.cc:122
void parseHeaderIntoField(const zypp::PluginFrame &msg, const std::string &name, T &target)
void parseDataIntoField(const std::string &headerVal, T &target)
zypp::PluginFrame prepareFrame()
static zyppng::expected< CleanupBegin > fromStompMessage(const zypp::PluginFrame &msg)
static constexpr std::string_view typeName
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static constexpr std::string_view typeName
static zyppng::expected< CleanupFinished > fromStompMessage(const zypp::PluginFrame &msg)
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static constexpr std::string_view typeName
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static zyppng::expected< CleanupProgress > fromStompMessage(const zypp::PluginFrame &msg)
std::vector< TransactionStep > transactionSteps
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static constexpr std::string_view typeName
static zyppng::expected< Commit > fromStompMessage(const zypp::PluginFrame &msg)
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static zyppng::expected< PackageProgress > fromStompMessage(const zypp::PluginFrame &msg)
static constexpr std::string_view typeName
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static constexpr std::string_view typeName
static zyppng::expected< RpmLog > fromStompMessage(const zypp::PluginFrame &msg)
static constexpr std::string_view typeName
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static zyppng::expected< ScriptBegin > fromStompMessage(const zypp::PluginFrame &msg)
static zyppng::expected< ScriptError > fromStompMessage(const zypp::PluginFrame &msg)
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static constexpr std::string_view typeName
static constexpr std::string_view typeName
static zyppng::expected< TransBegin > fromStompMessage(const zypp::PluginFrame &msg)
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static zyppng::expected< TransProgress > fromStompMessage(const zypp::PluginFrame &msg)
static constexpr std::string_view typeName
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static constexpr std::string_view typeName
zyppng::expected< zypp::PluginFrame > toStompMessage() const
static zyppng::expected< TransactionError > fromStompMessage(const zypp::PluginFrame &msg)
std::vector< std::string > problems
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:213
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:463
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459