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