Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / Patch.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Patch.cc
10  *
11 */
12 #include <iostream>
13
14 #include "zypp/base/LogTools.h"
15 #include "zypp/base/String.h"
16 #include "zypp/Patch.h"
17 #include "zypp/sat/WhatProvides.h"
18
19 using std::endl;
20
21 ///////////////////////////////////////////////////////////////////
22 namespace zypp
23 { /////////////////////////////////////////////////////////////////
24
25   IMPL_PTR_TYPE( Patch );
26
27   ///////////////////////////////////////////////////////////////////
28   //
29   //    METHOD NAME : Patch::Patch
30   //    METHOD TYPE : Ctor
31   //
32   Patch::Patch( const sat::Solvable & solvable_r )
33   : ResObject( solvable_r )
34   {}
35
36   ///////////////////////////////////////////////////////////////////
37   //
38   //    METHOD NAME : Patch::~Patch
39   //    METHOD TYPE : Dtor
40   //
41   Patch::~Patch()
42   {}
43
44   ///////////////////////////////////////////////////////////////////
45
46   std::string Patch::category() const
47   { return str::toLower(lookupStrAttribute( sat::SolvAttr::patchcategory )); }
48
49   Patch::Category Patch::categoryEnum() const
50   { return categoryEnum( category() ); }
51
52   bool Patch::isCategory( const std::string & category_r ) const
53   { return( str::compareCI( category_r, category() ) == 0 ); }
54
55   bool Patch::isCategory( Categories category_r ) const
56   { return category_r.testFlag( categoryEnum() ); }
57
58   Patch::Category Patch::categoryEnum( const std::string & category_r )
59   {
60     switch ( category_r[0] )
61     {
62       //        CAT_YAST
63       case 'y':
64       case 'Y':
65         if ( str::compareCI( category_r, "yast" ) == 0 )
66           return CAT_YAST;
67         break;
68
69       //        CAT_SECURITY
70       case 's':
71       case 'S':
72         if ( str::compareCI( category_r, "security" ) == 0 )
73           return CAT_SECURITY;
74         break;
75
76       //        CAT_RECOMMENDED
77       case 'r':
78       case 'R':
79         if ( str::compareCI( category_r, "recommended" ) == 0 )
80           return CAT_RECOMMENDED;
81         break;
82       case 'b':
83       case 'B':
84         if ( str::compareCI( category_r, "bugfix" ) == 0 )      // rhn
85           return CAT_RECOMMENDED;
86         break;
87
88       //        CAT_OPTIONAL
89       case 'o':
90       case 'O':
91         if ( str::compareCI( category_r, "optional" ) == 0 )
92           return CAT_OPTIONAL;
93         break;
94       case 'f':
95       case 'F':
96         if ( str::compareCI( category_r, "feature" ) == 0 )
97           return CAT_OPTIONAL;
98         break;
99       case 'e':
100       case 'E':
101         if ( str::compareCI( category_r, "enhancement" ) == 0 ) // rhn
102           return CAT_OPTIONAL;
103         break;
104
105       //        CAT_DOCUMENT
106       case 'd':
107       case 'D':
108         if ( str::compareCI( category_r, "document" ) == 0 )
109           return CAT_DOCUMENT;
110         break;
111     }
112     // default:
113     INT << "Unrecognized Patch::Category string '" << category_r << "'" << endl;
114     return CAT_OTHER;
115   }
116
117   std::string asString( const Patch::Category & obj )
118   {
119     switch ( obj )
120     {
121       case Patch::CAT_OTHER:            return std::string( "other" );          break;
122       case Patch::CAT_YAST:             return std::string( "yast" );           break;
123       case Patch::CAT_SECURITY:         return std::string( "security" );       break;
124       case Patch::CAT_RECOMMENDED:      return std::string( "recommended" );    break;
125       case Patch::CAT_OPTIONAL:         return std::string( "optional" );       break;
126       case Patch::CAT_DOCUMENT:         return std::string( "document" );       break;
127     }
128     // make gcc happy:
129     return std::string( "other" );
130   }
131
132   ///////////////////////////////////////////////////////////////////
133
134   std::string Patch::severity() const
135   { return str::toLower(lookupStrAttribute( sat::SolvAttr::severity )); }
136
137   Patch::SeverityFlag Patch::severityFlag() const
138   { return severityFlag( severity() ); }
139
140   bool Patch::isSeverity( const std::string & severity_r ) const
141   { return( str::compareCI( severity_r, severity() ) == 0 ); }
142
143   bool Patch::isSeverity( SeverityFlags severity_r ) const
144   { return severity_r.testFlag( severityFlag() ); }
145
146   Patch::SeverityFlag Patch::severityFlag( const std::string & severity_r )
147   {
148     switch ( severity_r[0] )
149     {
150       case 'l':
151       case 'L':
152         if ( str::compareCI( severity_r, "low" ) == 0 )
153           return SEV_LOW;
154         break;
155
156       case 'm':
157       case 'M':
158         if ( str::compareCI( severity_r, "moderate" ) == 0 )
159           return SEV_MODERATE;
160         break;
161
162       case 'i':
163       case 'I':
164         if ( str::compareCI( severity_r, "important" ) == 0 )
165           return SEV_IMPORTANT;
166         break;
167
168       case 'c':
169       case 'C':
170         if ( str::compareCI( severity_r, "critical" ) == 0 )
171           return SEV_CRITICAL;
172         break;
173
174       case 'u':
175       case 'U':
176         if ( str::compareCI( severity_r, "unspecified" ) == 0 )
177           return SEV_NONE;
178         break;
179
180       case '\0':
181         return SEV_NONE;
182         break;
183     }
184     // default:
185     INT << "Unrecognized Patch::Severity string '" << severity_r << "'" << endl;
186     return SEV_OTHER;
187   }
188
189   std::string asString( const Patch::SeverityFlag & obj )
190   {
191     switch ( obj )
192     {
193       case Patch::SEV_OTHER:    return std::string( "unknown" );        break;
194       case Patch::SEV_NONE:     return std::string( "unspecified" );    break;
195       case Patch::SEV_LOW:      return std::string( "low" );            break;
196       case Patch::SEV_MODERATE: return std::string( "moderate" );       break;
197       case Patch::SEV_IMPORTANT:return std::string( "important" );      break;
198       case Patch::SEV_CRITICAL: return std::string( "critical" );       break;
199     }
200     // make gcc happy:
201     return std::string( "unknown" );
202   }
203
204   ///////////////////////////////////////////////////////////////////
205   //
206 std::string Patch::message( const Locale & lang_r ) const
207   { return lookupStrAttribute( sat::SolvAttr::message, lang_r ); }
208
209   bool Patch::rebootSuggested() const
210   { return lookupBoolAttribute( sat::SolvAttr::rebootSuggested ); }
211
212   bool Patch::restartSuggested() const
213   { return lookupBoolAttribute( sat::SolvAttr::restartSuggested ); }
214
215   bool Patch::reloginSuggested() const
216   { return lookupBoolAttribute( sat::SolvAttr::reloginSuggested ); }
217
218   Patch::InteractiveFlags Patch::interactiveFlags() const
219   {
220     InteractiveFlags patchFlags (NoFlags);
221     if ( rebootSuggested() )
222       patchFlags |= Reboot;
223
224     if ( ! message().empty() )
225       patchFlags |= Message;
226
227     if ( ! licenseToConfirm().empty() )
228       patchFlags |= License;
229
230     Patch::Contents c( contents() );
231     for_( it, c.begin(), c.end() )
232     {
233       if ( ! makeResObject(*it)->licenseToConfirm().empty() )
234       {
235         patchFlags |= License;
236         break;
237       }
238     }
239     return patchFlags;
240   }
241
242   bool Patch::interactiveWhenIgnoring( InteractiveFlags flags_r ) const
243   {
244     if ( interactiveFlags() & ( ~flags_r ) )
245     {
246       return true;
247     }
248     else
249     {
250       return false;
251     }
252   }
253
254   bool Patch::interactive() const
255   {
256     return interactiveWhenIgnoring();
257   }
258
259   std::string asString( const Patch::InteractiveFlag & obj )
260   {
261     switch ( obj )
262     {
263       case Patch::NoFlags:      return "";              break;
264       case Patch::Reboot:       return "reboot";        break;
265       case Patch::Message:      return "message";       break;
266       case Patch::License:      return "license";       break;
267     }
268     return str::hexstring(obj);
269   }
270
271   Patch::Contents Patch::contents() const
272   {
273     Contents result;
274     // DBG << *this << endl;
275     sat::LookupAttr updateCollection( sat::SolvAttr::updateCollection, satSolvable() );
276     for_( entry, updateCollection.begin(), updateCollection.end() )
277     {
278       IdString name    ( entry.subFind( sat::SolvAttr::updateCollectionName ).idStr() );
279       Edition  edition ( entry.subFind( sat::SolvAttr::updateCollectionEvr ).idStr() );
280       Arch     arch    ( entry.subFind( sat::SolvAttr::updateCollectionArch ).idStr() );
281       if ( name.empty() )
282       {
283         WAR << "Ignore malformed updateCollection entry: " << name << "-" << edition << "." << arch << endl;
284         continue;
285       }
286
287       // The entry is relevant if there is an installed
288       // package with the same name and arch.
289       bool relevant = false;
290       sat::WhatProvides providers( (Capability( name.id() )) );
291       for_( it, providers.begin(), providers.end() )
292       {
293         if ( it->isSystem() && it->ident() == name && it->arch() == arch )
294         {
295           relevant = true;
296           break;
297         }
298       }
299       if ( ! relevant )
300       {
301         // DBG << "Not relevant: " << name << "-" << edition << "." << arch << endl;
302         continue;
303       }
304
305       /* find exact providers first (this matches the _real_ 'collection content' of the patch */
306       providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::EQ, edition, ResKind::package ) );
307       if ( providers.empty() )
308       {
309         /* no exact providers: find 'best' providers: those with a larger evr */
310         providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::GT, edition, ResKind::package ) );
311         if ( providers.empty() )
312         {
313           // Hmm, this patch is not installable, no one is providing the package in the collection
314           // FIXME: raise execption ? fake a solvable ?
315           WAR << "Missing provider: " << name << "-" << edition << "." << arch << endl;
316           continue;
317         }
318       }
319
320       // FIXME ?! loop over providers and try to find installed ones ?
321       // DBG << "Found " << name << "-" << edition << "." << arch << ": " << *(providers.begin()) << endl;
322       result.get().insert( *(providers.begin()) );
323     }
324
325     return result;
326   }
327
328   ///////////////////////////////////////////////////////////////////
329   //
330   //    CLASS NAME : Patch::ReferenceIterator
331   //
332   ///////////////////////////////////////////////////////////////////
333
334   Patch::ReferenceIterator::ReferenceIterator( const sat::Solvable & val_r )
335   { base_reference() = sat::LookupAttr( sat::SolvAttr::updateReference, val_r ).begin(); }
336
337   std::string Patch::ReferenceIterator::id() const
338   { return base_reference().subFind( sat::SolvAttr::updateReferenceId ).asString(); }
339   std::string Patch::ReferenceIterator::href() const
340   { return base_reference().subFind( sat::SolvAttr::updateReferenceHref ).asString(); }
341   std::string Patch::ReferenceIterator::title() const
342   { return base_reference().subFind( sat::SolvAttr::updateReferenceTitle ).asString(); }
343   std::string Patch::ReferenceIterator::type() const
344   { return base_reference().subFind( sat::SolvAttr::updateReferenceType ).asString(); }
345
346   /////////////////////////////////////////////////////////////////
347 } // namespace zypp
348 ///////////////////////////////////////////////////////////////////