Workaround ZConfig access causing ZYppLock creation.
[platform/upstream/libzypp.git] / zypp / sat / Solvable.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/Solvable.cc
10  *
11 */
12 #include <iostream>
13
14 #include "zypp/base/Logger.h"
15 #include "zypp/base/Gettext.h"
16 #include "zypp/base/Exception.h"
17
18 #include "zypp/sat/detail/PoolImpl.h"
19 #include "zypp/sat/Solvable.h"
20 #include "zypp/sat/Repo.h"
21
22 using std::endl;
23
24 ///////////////////////////////////////////////////////////////////
25 namespace zypp
26 { /////////////////////////////////////////////////////////////////
27   ///////////////////////////////////////////////////////////////////
28   namespace sat
29   { /////////////////////////////////////////////////////////////////
30
31     const Solvable Solvable::nosolvable;
32
33     /////////////////////////////////////////////////////////////////
34
35     ::_Solvable * Solvable::get() const
36     { return myPool().getSolvable( _id ); }
37
38 #define NO_SOLVABLE_RETURN( VAL ) \
39     ::_Solvable * _solvable( get() ); \
40     if ( ! _solvable ) return VAL
41
42     Solvable Solvable::nextInPool() const
43     { return Solvable( myPool().getNextId( _id ) ); }
44
45     Solvable Solvable::nextInRepo() const
46     {
47       NO_SOLVABLE_RETURN( nosolvable );
48       for ( detail::SolvableIdType next = _id+1; next < unsigned(_solvable->repo->end); ++next )
49       {
50         ::_Solvable * nextS( myPool().getSolvable( next ) );
51         if ( nextS && nextS->repo == _solvable->repo )
52         {
53           return Solvable( next );
54         }
55       }
56       return nosolvable;
57     }
58
59     Repo Solvable::repo() const
60     {
61       NO_SOLVABLE_RETURN( Repo::norepo );
62       return Repo( _solvable->repo );
63     }
64
65     bool Solvable::isSystem() const
66     { return repo().isSystemRepo(); }
67
68     IdString Solvable::ident() const
69     {
70       NO_SOLVABLE_RETURN( IdString() );
71       return IdString( _solvable->name );
72     }
73
74     ResKind Solvable::kind() const
75     {
76       NO_SOLVABLE_RETURN( ResKind() );
77       // detect srcpackages by 'arch'
78       switch ( _solvable->arch )
79       {
80         case ARCH_SRC:
81         case ARCH_NOSRC:
82           return ResKind::srcpackage;
83           break;
84       }
85
86       const char * ident = IdString( _solvable->name ).c_str();
87       const char * sep = ::strchr( ident, ':' );
88
89       // no ':' in package names (hopefully)
90       if ( ! sep )
91         return ResKind::package;
92
93       // quick check for well known kinds
94       if ( sep-ident >= 4 )
95       {
96         switch ( ident[3] )
97         {
98 #define OUTS(K,S) if ( ::strncmp( ident, ResKind::K.c_str(), S ) ) return ResKind::K
99           //             ----v
100           case 'c': OUTS( patch, 5 );       break;
101           case 'd': OUTS( product, 7 );     break;
102           case 'e': OUTS( selection, 9 );   break;
103           case 'g': OUTS( language, 8 );    break;
104           case 'i': OUTS( script, 6 );      break;
105           case 'k': OUTS( package, 7 );     break;
106           case 'm': OUTS( atom, 4 );        break;
107           case 'p': OUTS( srcpackage, 10 ); break;
108           case 's': OUTS( message, 7 );     break;
109           case 't': OUTS( pattern, 7 );     break;
110 #undef OUTS
111         }
112       }
113
114       // an unknown kind
115       return ResKind( std::string( ident, sep-ident ) );
116     }
117
118     bool Solvable::isKind( const ResKind & kind_r ) const
119     {
120       NO_SOLVABLE_RETURN( false );
121
122       // detect srcpackages by 'arch'
123       if ( kind_r == ResKind::srcpackage )
124       {
125         return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
126       }
127
128       // no ':' in package names (hopefully)
129       const char * ident = IdString( _solvable->name ).c_str();
130       if ( kind_r == ResKind::package )
131       {
132         return( ::strchr( ident, ':' ) == 0 );
133       }
134
135       // look for a 'kind:' prefix
136       const char * kind = kind_r.c_str();
137       unsigned     ksize = ::strlen( kind );
138       return( ::strncmp( ident, kind, ksize ) == 0
139               && ident[ksize] == ':' );
140     }
141
142     std::string Solvable::name() const
143     {
144       NO_SOLVABLE_RETURN( std::string() );
145       const char * ident = IdString( _solvable->name ).c_str();
146       const char * sep = ::strchr( ident, ':' );
147       return( sep ? sep+1 : ident );
148     }
149
150     Edition Solvable::edition() const
151     {
152       NO_SOLVABLE_RETURN( Edition() );
153       return Edition( _solvable->evr );
154     }
155
156     Arch Solvable::arch() const
157     {
158       NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() );
159       switch ( _solvable->arch )
160       {
161         case ARCH_SRC:
162         case ARCH_NOSRC:
163           return Arch_noarch; //ArchId( ARCH_NOARCH );
164           break;
165       }
166       return Arch( IdString(_solvable->arch).asString() );
167       //return ArchId( _solvable->arch );
168     }
169
170     IdString Solvable::vendor() const
171     {
172       NO_SOLVABLE_RETURN( IdString() );
173       return IdString( _solvable->vendor );
174     }
175
176     Capabilities Solvable::operator[]( Dep which_r ) const
177     {
178       NO_SOLVABLE_RETURN( Capabilities() );
179       ::Offset offs = 0;
180       switch( which_r.inSwitch() )
181       {
182         case Dep::PROVIDES_e:    offs = _solvable->provides;    break;
183         case Dep::REQUIRES_e:    offs = _solvable->requires;    break;
184         case Dep::CONFLICTS_e:   offs = _solvable->conflicts;   break;
185         case Dep::OBSOLETES_e:   offs = _solvable->obsoletes;   break;
186         case Dep::RECOMMENDS_e:  offs = _solvable->recommends;  break;
187         case Dep::SUGGESTS_e:    offs = _solvable->suggests;    break;
188         case Dep::FRESHENS_e:    offs = _solvable->freshens;    break;
189         case Dep::ENHANCES_e:    offs = _solvable->enhances;    break;
190         case Dep::SUPPLEMENTS_e: offs = _solvable->supplements; break;
191
192         case Dep::PREREQUIRES_e:
193           // prerequires are a subset of requires
194           if ( (offs = _solvable->requires) )
195             return Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker );
196           else
197             return Capabilities();
198           break;
199       }
200
201       return offs ? Capabilities( _solvable->repo->idarraydata + offs )
202                   : Capabilities();
203     }
204
205     /******************************************************************
206     **
207     **  FUNCTION NAME : operator<<
208     **  FUNCTION TYPE : std::ostream &
209     */
210     std::ostream & operator<<( std::ostream & str, const Solvable & obj )
211     {
212       if ( ! obj )
213         return str << "sat::solvable()";
214
215       return str << "sat::solvable(" << obj.id() << "|"
216           << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
217           << '-' << obj.edition() << '.' << obj.arch() << "){"
218           << obj.repo().name() << "}";
219     }
220
221     /******************************************************************
222     **
223     **  FUNCTION NAME : dumpOn
224     **  FUNCTION TYPE : std::ostream &
225     */
226     std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
227     {
228       str << obj;
229       if ( obj )
230       {
231 #define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X]
232         OUTS(PROVIDES);
233         OUTS(PREREQUIRES);
234         OUTS(REQUIRES);
235         OUTS(CONFLICTS);
236         OUTS(OBSOLETES);
237         OUTS(RECOMMENDS);
238         OUTS(SUGGESTS);
239         OUTS(FRESHENS);
240         OUTS(ENHANCES);
241         OUTS(SUPPLEMENTS);
242 #undef OUTS
243       }
244       return str;
245     }
246
247     /////////////////////////////////////////////////////////////////
248   } // namespace sat
249   ///////////////////////////////////////////////////////////////////
250   /////////////////////////////////////////////////////////////////
251 } // namespace zypp
252 ///////////////////////////////////////////////////////////////////