1ee504f1da4a77994fc55e7e5f8ab4ea06115921
[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 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   ///////////////////////////////////////////////////////////////////
118
119   std::string Patch::severity() const
120   { return lookupStrAttribute( sat::SolvAttr::severity ); }
121
122   Patch::SeverityFlag Patch::severityFlag() const
123   { return severityFlag( severity() ); }
124
125   bool Patch::isSeverity( const std::string & severity_r ) const
126   { return( str::compareCI( severity_r, severity() ) == 0 ); }
127
128   bool Patch::isSeverity( SeverityFlags severity_r ) const
129   { return severity_r.testFlag( severityFlag() ); }
130
131   Patch::SeverityFlag Patch::severityFlag( const std::string & severity_r )
132   {
133     switch ( severity_r[0] )
134     {
135       case 'l':
136       case 'L':
137         if ( str::compareCI( severity_r, "low" ) == 0 )
138           return SEV_LOW;
139         break;
140
141       case 'm':
142       case 'M':
143         if ( str::compareCI( severity_r, "moderate" ) == 0 )
144           return SEV_MODERATE;
145         break;
146
147       case 'i':
148       case 'I':
149         if ( str::compareCI( severity_r, "important" ) == 0 )
150           return SEV_IMPORTANT;
151         break;
152
153       case 'c':
154       case 'C':
155         if ( str::compareCI( severity_r, "critical" ) == 0 )
156           return SEV_CRITICAL;
157         break;
158
159       case 'u':
160       case 'U':
161         if ( str::compareCI( severity_r, "unspecified" ) == 0 )
162           return SEV_NONE;
163         break;
164
165       case '\0':
166         return SEV_NONE;
167         break;
168     }
169     // default:
170     INT << "Unrecognized Patch::Severity string '" << severity_r << "'" << endl;
171     return SEV_OTHER;
172   }
173
174   std::string asString( const Patch::SeverityFlag & obj )
175   {
176     switch ( obj )
177     {
178       case Patch::SEV_OTHER:    return std::string( "unknown" );        break;
179       case Patch::SEV_NONE:     return std::string( "unspecified" );    break;
180       case Patch::SEV_LOW:      return std::string( "low" );            break;
181       case Patch::SEV_MODERATE: return std::string( "moderate" );       break;
182       case Patch::SEV_IMPORTANT:return std::string( "important" );      break;
183       case Patch::SEV_CRITICAL: return std::string( "critical" );       break;
184     }
185     // make gcc happy:
186     return std::string( "unknown" );
187   }
188
189   ///////////////////////////////////////////////////////////////////
190
191   std::string Patch::message( const Locale & lang_r ) const
192   { return lookupStrAttribute( sat::SolvAttr::message, lang_r ); }
193
194   bool Patch::rebootSuggested() const
195   { return lookupBoolAttribute( sat::SolvAttr::rebootSuggested ); }
196
197   bool Patch::restartSuggested() const
198   { return lookupBoolAttribute( sat::SolvAttr::restartSuggested ); }
199
200   bool Patch::reloginSuggested() const
201   { return lookupBoolAttribute( sat::SolvAttr::reloginSuggested ); }
202
203   Patch::InteractiveFlags Patch::interactiveFlags() const
204   {
205     InteractiveFlags patchFlags (NoFlags);
206     if ( rebootSuggested() )
207       patchFlags |= Reboot;
208
209     if ( ! message().empty() )
210       patchFlags |= Message;
211
212     if ( ! licenseToConfirm().empty() )
213       patchFlags |= License;
214
215     Patch::Contents c( contents() );
216     for_( it, c.begin(), c.end() )
217     {
218       if ( ! makeResObject(*it)->licenseToConfirm().empty() )
219       {
220         patchFlags |= License;
221         break;
222       }
223     }
224     return patchFlags;
225   }
226
227   bool Patch::interactiveWhenIgnoring( InteractiveFlags flags_r ) const
228   {
229     if ( interactiveFlags() & ( ~flags_r ) )
230     {
231       return true;
232     }
233     else
234     {
235       return false;
236     }
237   }
238
239   bool Patch::interactive() const
240   {
241     return interactiveWhenIgnoring();
242   }
243
244   Patch::Contents Patch::contents() const
245   {
246     Contents result;
247     // DBG << *this << endl;
248     sat::LookupAttr updateCollection( sat::SolvAttr::updateCollection, satSolvable() );
249     for_( entry, updateCollection.begin(), updateCollection.end() )
250     {
251       IdString name    ( entry.subFind( sat::SolvAttr::updateCollectionName ).idStr() );
252       Edition  edition ( entry.subFind( sat::SolvAttr::updateCollectionEvr ).idStr() );
253       Arch     arch    ( entry.subFind( sat::SolvAttr::updateCollectionArch ).idStr() );
254       if ( name.empty() )
255       {
256         WAR << "Ignore malformed updateCollection entry: " << name << "-" << edition << "." << arch << endl;
257         continue;
258       }
259
260       // The entry is relevant if there is an installed
261       // package with the same name and arch.
262       bool relevant = false;
263       sat::WhatProvides providers( (Capability( name.id() )) );
264       for_( it, providers.begin(), providers.end() )
265       {
266         if ( it->isSystem() && it->ident() == name && it->arch() == arch )
267         {
268           relevant = true;
269           break;
270         }
271       }
272       if ( ! relevant )
273       {
274         // DBG << "Not relevant: " << name << "-" << edition << "." << arch << endl;
275         continue;
276       }
277
278       /* find exact providers first (this matches the _real_ 'collection content' of the patch */
279       providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::EQ, edition, ResKind::package ) );
280       if ( providers.empty() )
281       {
282         /* no exact providers: find 'best' providers: those with a larger evr */
283         providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::GT, edition, ResKind::package ) );
284         if ( providers.empty() )
285         {
286           // Hmm, this patch is not installable, no one is providing the package in the collection
287           // FIXME: raise execption ? fake a solvable ?
288           WAR << "Missing provider: " << name << "-" << edition << "." << arch << endl;
289           continue;
290         }
291       }
292
293       // FIXME ?! loop over providers and try to find installed ones ?
294       // DBG << "Found " << name << "-" << edition << "." << arch << ": " << *(providers.begin()) << endl;
295       result.get().insert( *(providers.begin()) );
296     }
297
298     return result;
299   }
300
301   ///////////////////////////////////////////////////////////////////
302   //
303   //    CLASS NAME : Patch::ReferenceIterator
304   //
305   ///////////////////////////////////////////////////////////////////
306
307   Patch::ReferenceIterator::ReferenceIterator( const sat::Solvable & val_r )
308   { base_reference() = sat::LookupAttr( sat::SolvAttr::updateReference, val_r ).begin(); }
309
310   std::string Patch::ReferenceIterator::id() const
311   { return base_reference().subFind( sat::SolvAttr::updateReferenceId ).asString(); }
312   std::string Patch::ReferenceIterator::href() const
313   { return base_reference().subFind( sat::SolvAttr::updateReferenceHref ).asString(); }
314   std::string Patch::ReferenceIterator::title() const
315   { return base_reference().subFind( sat::SolvAttr::updateReferenceTitle ).asString(); }
316   std::string Patch::ReferenceIterator::type() const
317   { return base_reference().subFind( sat::SolvAttr::updateReferenceType ).asString(); }
318
319   /////////////////////////////////////////////////////////////////
320 } // namespace zypp
321 ///////////////////////////////////////////////////////////////////