backup
[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     sat::detail::IdType relFromStr( ::_Pool * pool_r,
37                                     const Arch & arch_r,
38                                     const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & kind_r )
39     {
40       sat::detail::IdType nid( sat::detail::noId );
41       return nid;
42     }
43
44     sat::detail::IdType relFromStr( ::_Pool * pool_r,
45                                     const std::string & name_r, Rel op_r, const Edition & ed_r,
46                                     const ResKind & kind_r )
47     {
48       sat::detail::IdType nid( sat::detail::noId );
49       if ( ! kind_r || kind_r == ResKind::package )
50       {
51         nid = IdString( name_r ).id();
52       }
53       else
54       {
55         // non-packages prefixed by kind
56         nid = IdString( str::form( "%s:%s",
57                         kind_r.c_str(),
58                                      name_r.c_str() ) ).id();
59       }
60
61       if ( op_r != Rel::ANY && ed_r != Edition::noedition )
62       {
63         nid = ::rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true );
64       }
65
66       return nid;
67     }
68
69     sat::detail::IdType relFromStr( ::_Pool * pool_r,
70                                       const std::string & str_r, const ResKind & kind_r,
71                                       Capability::CtorFlag flag_r )
72     {
73       // strval_r has at least two words which could make 'op edition'?
74       // improve regex!
75       static const str::regex  rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
76       static str::smatch what;
77
78       std::string name( str_r );
79       Rel         op;
80       Edition     ed;
81       if ( flag_r == Capability::UNPARSED
82            && str_r.find(' ') != std::string::npos
83            && str::regex_match( str_r, what, rx ) )
84       {
85         try
86         {
87           Rel     cop( what[3] );
88           Edition ced( what[5] );
89           name = what[1];
90           op = cop;
91           ed = ced;
92         }
93         catch ( Exception & excpt )
94         {
95           // So they don't make valid 'op edition'
96           ZYPP_CAUGHT( excpt );
97           DBG << "Trying named relation for: " << str_r << endl;
98         }
99       }
100       //else
101       // not a versioned relation
102
103       return relFromStr( pool_r, name, op, ed, kind_r );
104     }
105
106     /////////////////////////////////////////////////////////////////
107   } // namespace
108   ///////////////////////////////////////////////////////////////////
109
110   const Capability Capability::Null( STRID_NULL );
111
112   /////////////////////////////////////////////////////////////////
113
114   Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r )
115   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
116   {}
117
118   Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r )
119   : _id( relFromStr( myPool().getPool(), str_r.c_str(), prefix_r, flag_r ) )
120   {}
121
122   Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r )
123   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
124   {}
125
126   Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r )
127   : _id( relFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) )
128   {}
129
130
131   Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r )
132   : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) )
133   {}
134
135   Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r )
136   : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) )
137   {}
138
139   Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r )
140   : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) )
141   {}
142
143 #if 0
144   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 = ResKind() );
145   Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
146   Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
147   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 = ResKind() );
148   Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
149   Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
150 #endif
151
152   const char * Capability::c_str() const
153   { return( _id ? ::dep2str( myPool().getPool(), _id ) : "" ); }
154
155   CapMatch Capability::_doMatch( sat::detail::IdType lhs,  sat::detail::IdType rhs )
156   {
157 #warning MIGRATE TO SAT
158 #warning TESTCASE
159     if ( lhs == rhs )
160       return CapMatch::yes;
161
162     CapDetail l( lhs );
163     CapDetail r( rhs );
164
165     switch ( l.kind() )
166     {
167       case CapDetail::NOCAP:
168         return( r.kind() == CapDetail::NOCAP ); // NOCAP matches NOCAP only
169         break;
170       case CapDetail::EXPRESSION:
171         return CapMatch::irrelevant;
172         break;
173       case CapDetail::NAMED:
174       case CapDetail::VERSIONED:
175         break;
176     }
177
178     switch ( r.kind() )
179     {
180       case CapDetail::NOCAP:
181         return CapMatch::no; // match case handled above
182         break;
183       case CapDetail::EXPRESSION:
184         return CapMatch::irrelevant;
185         break;
186       case CapDetail::NAMED:
187       case CapDetail::VERSIONED:
188         break;
189     }
190     // comparing two simple caps:
191     if ( l.name() != r.name() )
192       return CapMatch::no;
193
194     // isNamed matches ANY edition:
195     if ( l.isNamed() || r.isNamed() )
196       return CapMatch::yes;
197
198     // both are versioned:
199     return overlaps( Edition::MatchRange( l.op(), l.ed() ),
200                      Edition::MatchRange( r.op(), r.ed() ) );
201   }
202
203   bool Capability::isInterestingFileSpec( const char * name_r )
204   {
205     static       str::smatch what;
206     static const str::regex  filenameRegex(
207                  "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/",
208                  str::regex::optimize|str::regex::nosubs );
209
210     return str::regex_match( name_r, what, filenameRegex );
211   }
212
213   /******************************************************************
214   **
215   **    FUNCTION NAME : operator<<
216   **    FUNCTION TYPE : std::ostream &
217   */
218   std::ostream & operator<<( std::ostream & str, const Capability & obj )
219   {
220     return str << obj.detail();
221   }
222
223   std::ostream & dumpOn( std::ostream & str, const Capability & obj )
224   {
225     return str << obj.detail();
226   }
227
228   ///////////////////////////////////////////////////////////////////
229   //
230   //    CLASS NAME : CapDetail
231   //
232   ///////////////////////////////////////////////////////////////////
233
234   void CapDetail::_init()
235   {
236     // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 )
237
238     if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId )
239       return; // NOCAP
240
241     if ( ! ISRELDEP(_lhs) )
242     {
243       _kind = NAMED;
244       return;
245     }
246
247     ::Reldep * rd = GETRELDEP( myPool().getPool(), _lhs );
248     _lhs  = rd->name;
249     _rhs  = rd->evr;
250     _flag = rd->flags;
251
252     _kind = Rel::isRel( _flag ) ? VERSIONED : EXPRESSION;
253   }
254
255   /******************************************************************
256   **
257   **    FUNCTION NAME : operator<<
258   **    FUNCTION TYPE : std::ostream &
259   */
260   std::ostream & operator<<( std::ostream & str, const CapDetail & obj )
261   {
262     switch ( obj.kind() )
263     {
264       case CapDetail::NOCAP:
265         return str << "<NoCap>";
266         break;
267       case CapDetail::NAMED:
268         return str << obj.name();
269         break;
270       case CapDetail::VERSIONED:
271         return str << obj.name() << " " << obj.op() << " " << obj.ed();
272         break;
273       case CapDetail::EXPRESSION:
274         switch ( obj.capRel() )
275         {
276           case CapDetail::REL_NONE:
277           case CapDetail::CAP_AND:
278           case CapDetail::CAP_OR:
279           case CapDetail::CAP_WITH:
280             return str << obj.lhs().detail() << " " << obj.capRel() << " " << obj.rhs().detail();
281             break;
282           case CapDetail::CAP_NAMESPACE:
283             return str << obj.lhs().detail() << "(" << obj.rhs().detail() << ")";
284         }
285         break;
286     }
287     return str <<  "<UnknownCap>";
288   }
289
290   std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj )
291   {
292     switch ( obj )
293     {
294       case CapDetail::NOCAP:      return str << "NoCap"; break;
295       case CapDetail::NAMED:      return str << "NamedCap"; break;
296       case CapDetail::VERSIONED:  return str << "VersionedCap"; break;
297       case CapDetail::EXPRESSION: return str << "CapExpression"; break;
298     }
299     return str << "UnknownCap";
300   }
301
302   std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj )
303   {
304     switch ( obj )
305     {
306       case CapDetail::REL_NONE:      return str << "NoCapRel"; break;
307       case CapDetail::CAP_AND:       return str << "AND"; break;
308       case CapDetail::CAP_OR:        return str << "OR"; break;
309       case CapDetail::CAP_WITH:      return str << "WITH"; break;
310       case CapDetail::CAP_NAMESPACE: return str << "NAMESPACE"; break;
311    }
312     return str << "UnknownCapRel";
313   }
314
315   /////////////////////////////////////////////////////////////////
316 } // namespace zypp
317 ///////////////////////////////////////////////////////////////////