adapt capability strings to changed satsolver dep2str
[platform/upstream/libzypp.git] / zypp / Capability.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/Capability.cc
10  *
11 */
12 #include <iostream>
13 #include "zypp/base/Logger.h"
14
15 #include "zypp/base/String.h"
16 #include "zypp/base/Regex.h"
17 #include "zypp/base/Gettext.h"
18 #include "zypp/base/Exception.h"
19
20 #include "zypp/Arch.h"
21 #include "zypp/Rel.h"
22 #include "zypp/Edition.h"
23 #include "zypp/Capability.h"
24
25 #include "zypp/sat/detail/PoolImpl.h"
26 #include "zypp/sat/Pool.h"
27
28 using std::endl;
29
30 ///////////////////////////////////////////////////////////////////
31 namespace zypp
32 { /////////////////////////////////////////////////////////////////
33   ///////////////////////////////////////////////////////////////////
34   namespace
35   { /////////////////////////////////////////////////////////////////
36     /** Build \ref Capability from data. No parsing required.
37     */
38     sat::detail::IdType relFromStr( ::_Pool * pool_r,
39                                     const Arch & arch_r,
40                                     const std::string & name_r,
41                                     Rel op_r,
42                                     const Edition & ed_r,
43                                     const ResKind & kind_r )
44     {
45       // First build the name, non-packages prefixed by kind
46       sat::detail::IdType nid( sat::detail::noId );
47       if ( ! kind_r || kind_r == ResKind::package )
48       {
49         nid = IdString( name_r ).id();
50       }
51       else
52       {
53         nid = IdString( str::form( "%s:%s",
54                         kind_r.c_str(),
55                         name_r.c_str() ) ).id();
56       }
57
58
59       // Extend name by architecture, if provided
60       if ( ! arch_r.empty() )
61       {
62         nid = ::rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true );
63       }
64
65       // Extend 'op edition', if provided
66       if ( op_r != Rel::ANY && ed_r != Edition::noedition )
67       {
68         nid = ::rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true );
69       }
70
71       return nid;
72     }
73
74     /** Build \ref Capability from data, just parsing name for '[.arch]'.
75     */
76     sat::detail::IdType relFromStr( ::_Pool * pool_r,
77                                     const std::string & name_r, Rel op_r, const Edition & ed_r,
78                                     const ResKind & kind_r )
79     {
80       Arch arch( Arch_empty );
81       std::string name( name_r );
82
83       std::string::size_type asep( name_r.rfind( "." ) );
84       if ( asep != std::string::npos )
85       {
86         Arch ext( name_r.substr( asep+1 ) );
87         if ( ext.isBuiltIn() )
88         {
89           arch = ext;
90           name.erase( asep );
91         }
92       }
93
94       return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r );
95     }
96
97     /** Full parse from string, unless Capability::PARSED.
98     */
99     sat::detail::IdType relFromStr( ::_Pool * pool_r,
100                                     const std::string & str_r, const ResKind & kind_r,
101                                     Capability::CtorFlag flag_r )
102     {
103       // strval_r has at least two words which could make 'op edition'?
104       // improve regex!
105       static const str::regex  rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
106       static str::smatch what;
107
108       std::string name( str_r );
109       Rel         op;
110       Edition     ed;
111       if ( flag_r == Capability::UNPARSED
112            && str_r.find(' ') != std::string::npos
113            && str::regex_match( str_r, what, rx ) )
114       {
115         try
116         {
117           Rel     cop( what[3] );
118           Edition ced( what[5] );
119           name = what[1];
120           op = cop;
121           ed = ced;
122         }
123         catch ( Exception & excpt )
124         {
125           // So they don't make valid 'op edition'
126           ZYPP_CAUGHT( excpt );
127           DBG << "Trying named relation for: " << str_r << endl;
128         }
129       }
130       //else
131       // not a versioned relation
132
133       return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch]
134     }
135
136     /////////////////////////////////////////////////////////////////
137   } // namespace
138   ///////////////////////////////////////////////////////////////////
139
140   const Capability Capability::Null( STRID_NULL );
141
142   /////////////////////////////////////////////////////////////////
143
144   Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
145   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
146   {}
147
148   Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
149   : _id( relFromStr( myPool().getPool(), str_r.c_str(), prefix_r, flag_r ) )
150   {}
151
152   Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
153   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
154   {}
155
156   Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
157   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
158   {}
159
160   ///////////////////////////////////////////////////////////////////
161   // Ctor from <name[.arch] op edition>.
162   ///////////////////////////////////////////////////////////////////
163
164   Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
165   : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
166   {}
167   Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
168   : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) )
169   {}
170   Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
171   : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) )
172   {}
173
174   ///////////////////////////////////////////////////////////////////
175   // Ctor from <arch name op edition>.
176   ///////////////////////////////////////////////////////////////////
177
178   Capability::Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
179   : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
180   {}
181   Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
182   : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) )
183   {}
184   Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
185   : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) )
186   {}
187   Capability::Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
188   : _id( relFromStr( myPool().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
189   {}
190   Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
191   : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) )
192   {}
193   Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
194   : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) )
195   {}
196
197   const char * Capability::c_str() const
198   { return( _id ? ::dep2str( myPool().getPool(), _id ) : "" ); }
199
200   CapMatch Capability::_doMatch( sat::detail::IdType lhs,  sat::detail::IdType rhs )
201   {
202 #warning MIGRATE TO SAT
203 #warning TESTCASE
204     if ( lhs == rhs )
205       return CapMatch::yes;
206
207     CapDetail l( lhs );
208     CapDetail r( rhs );
209
210     switch ( l.kind() )
211     {
212       case CapDetail::NOCAP:
213         return( r.kind() == CapDetail::NOCAP ); // NOCAP matches NOCAP only
214         break;
215       case CapDetail::EXPRESSION:
216         return CapMatch::irrelevant;
217         break;
218       case CapDetail::NAMED:
219       case CapDetail::VERSIONED:
220         break;
221     }
222
223     switch ( r.kind() )
224     {
225       case CapDetail::NOCAP:
226         return CapMatch::no; // match case handled above
227         break;
228       case CapDetail::EXPRESSION:
229         return CapMatch::irrelevant;
230         break;
231       case CapDetail::NAMED:
232       case CapDetail::VERSIONED:
233         break;
234     }
235     // comparing two simple caps:
236     if ( l.name() != r.name() )
237       return CapMatch::no;
238
239     // if both are arch restricted they must match
240     if ( l.arch() != r.arch()
241          && ! ( l.arch().empty() || r.arch().empty() ) )
242       return CapMatch::no;
243
244     // isNamed matches ANY edition:
245     if ( l.isNamed() || r.isNamed() )
246       return CapMatch::yes;
247
248     // both are versioned:
249     return overlaps( Edition::MatchRange( l.op(), l.ed() ),
250                      Edition::MatchRange( r.op(), r.ed() ) );
251   }
252
253   bool Capability::isInterestingFileSpec( const char * name_r )
254   {
255     static       str::smatch what;
256     static const str::regex  filenameRegex(
257                  "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/",
258                  str::regex::optimize|str::regex::nosubs );
259
260     return str::regex_match( name_r, what, filenameRegex );
261   }
262
263   /******************************************************************
264   **
265   **    FUNCTION NAME : operator<<
266   **    FUNCTION TYPE : std::ostream &
267   */
268   std::ostream & operator<<( std::ostream & str, const Capability & obj )
269   {
270     return str << obj.detail();
271   }
272
273   std::ostream & dumpOn( std::ostream & str, const Capability & obj )
274   {
275     return str << obj.detail();
276   }
277
278   ///////////////////////////////////////////////////////////////////
279   //
280   //    CLASS NAME : CapDetail
281   //
282   ///////////////////////////////////////////////////////////////////
283
284   void CapDetail::_init()
285   {
286     // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
287
288     if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId )
289       return; // NOCAP
290
291     if ( ! ISRELDEP(_lhs) )
292     {
293       // this is name without arch!
294       _kind = NAMED;
295       return;
296     }
297
298     ::Reldep * rd = GETRELDEP( myPool().getPool(), _lhs );
299     _lhs  = rd->name;
300     _rhs  = rd->evr;
301     _flag = rd->flags;
302
303     if ( Rel::isRel( _flag ) )
304     {
305       _kind = VERSIONED;
306       // Check for name.arch...
307       if ( ! ISRELDEP(_lhs) )
308         return; // this is name without arch!
309       rd = GETRELDEP( myPool().getPool(), _lhs );
310       if ( rd->flags != CAP_ARCH )
311         return; // this is not name.arch
312       // This is name.arch:
313       _lhs = rd->name;
314       _archIfSimple = rd->evr;
315     }
316     else if ( rd->flags == CAP_ARCH )
317     {
318       _kind = NAMED;
319       // This is name.arch:
320       _lhs = rd->name;
321       _archIfSimple = rd->evr;
322     }
323     else
324     {
325       _kind = EXPRESSION;
326       return;
327     }
328   }
329
330   /******************************************************************
331   **
332   **    FUNCTION NAME : operator<<
333   **    FUNCTION TYPE : std::ostream &
334   */
335   std::ostream & operator<<( std::ostream & str, const CapDetail & obj )
336   {
337     switch ( obj.kind() )
338     {
339       case CapDetail::NOCAP:
340         return str << "<NoCap>";
341         break;
342       case CapDetail::NAMED:
343         str << obj.name();
344         if ( obj.hasArch() )
345           str << '.' << obj.arch();
346         return str;
347         break;
348       case CapDetail::VERSIONED:
349         str << obj.name();
350         if ( obj.hasArch() )
351           str << '.' << obj.arch();
352         return str << " " << obj.op() << " " << obj.ed();
353         break;
354       case CapDetail::EXPRESSION:
355         switch ( obj.capRel() )
356         {
357           case CapDetail::REL_NONE:
358           case CapDetail::CAP_AND:
359           case CapDetail::CAP_OR:
360           case CapDetail::CAP_WITH:
361           case CapDetail::CAP_ARCH:
362             return str << obj.lhs().detail() << " " << obj.capRel() << " " << obj.rhs().detail();
363             break;
364           case CapDetail::CAP_NAMESPACE:
365             return str << obj.lhs().detail() << "(" << obj.rhs().detail() << ")";
366         }
367         break;
368     }
369     return str <<  "<UnknownCap>";
370   }
371
372   std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj )
373   {
374     switch ( obj )
375     {
376       case CapDetail::NOCAP:      return str << "NoCap"; break;
377       case CapDetail::NAMED:      return str << "NamedCap"; break;
378       case CapDetail::VERSIONED:  return str << "VersionedCap"; break;
379       case CapDetail::EXPRESSION: return str << "CapExpression"; break;
380     }
381     return str << "UnknownCap";
382   }
383
384   std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj )
385   {
386     switch ( obj )
387     {
388       case CapDetail::REL_NONE:      return str << "NoCapRel"; break;
389       case CapDetail::CAP_AND:       return str << "&"; break; // AND
390       case CapDetail::CAP_OR:        return str << "|"; break; // OR
391       case CapDetail::CAP_WITH:      return str << "+"; break; // WITH
392       case CapDetail::CAP_NAMESPACE: return str << "NAMESPACE"; break;
393       case CapDetail::CAP_ARCH:      return str << "ARCH"; break;
394    }
395     return str << "UnknownCapRel";
396   }
397
398   /////////////////////////////////////////////////////////////////
399 } // namespace zypp
400 ///////////////////////////////////////////////////////////////////