8b1270118bdd2f89b4c426be03a8383beb39e94b
[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     std::string Solvable::lookupStrAttribute( const SolvAttr &attr ) const
75     {
76       const char *s = repo_lookup_str(this->get(), attr.idStr().id());
77       return s ? s : std::string();
78     }
79
80     int Solvable::lookupNumAttribute( const SolvAttr &attr ) const
81     {
82       return repo_lookup_num(this->get(), attr.idStr().id());
83     }
84
85     ResKind Solvable::kind() const
86     {
87       NO_SOLVABLE_RETURN( ResKind() );
88       // detect srcpackages by 'arch'
89       switch ( _solvable->arch )
90       {
91         case ARCH_SRC:
92         case ARCH_NOSRC:
93           return ResKind::srcpackage;
94           break;
95       }
96
97       const char * ident = IdString( _solvable->name ).c_str();
98       const char * sep = ::strchr( ident, ':' );
99
100       // no ':' in package names (hopefully)
101       if ( ! sep )
102         return ResKind::package;
103
104       // quick check for well known kinds
105       if ( sep-ident >= 4 )
106       {
107         switch ( ident[3] )
108         {
109 #define OUTS(K,S) if ( ::strncmp( ident, ResKind::K.c_str(), S ) ) return ResKind::K
110           //             ----v
111           case 'c': OUTS( patch, 5 );       break;
112           case 'd': OUTS( product, 7 );     break;
113           case 'i': OUTS( script, 6 );      break;
114           case 'k': OUTS( package, 7 );     break;
115           case 'm': OUTS( atom, 4 );        break;
116           case 'p': OUTS( srcpackage, 10 ); break;
117           case 's': OUTS( message, 7 );     break;
118           case 't': OUTS( pattern, 7 );     break;
119 #undef OUTS
120         }
121       }
122
123       // an unknown kind
124       return ResKind( std::string( ident, sep-ident ) );
125     }
126
127     bool Solvable::isKind( const ResKind & kind_r ) const
128     {
129       NO_SOLVABLE_RETURN( false );
130
131       // detect srcpackages by 'arch'
132       if ( kind_r == ResKind::srcpackage )
133       {
134         return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
135       }
136
137       // no ':' in package names (hopefully)
138       const char * ident = IdString( _solvable->name ).c_str();
139       if ( kind_r == ResKind::package )
140       {
141         return( ::strchr( ident, ':' ) == 0 );
142       }
143
144       // look for a 'kind:' prefix
145       const char * kind = kind_r.c_str();
146       unsigned     ksize = ::strlen( kind );
147       return( ::strncmp( ident, kind, ksize ) == 0
148               && ident[ksize] == ':' );
149     }
150
151     std::string Solvable::name() const
152     {
153       NO_SOLVABLE_RETURN( std::string() );
154       const char * ident = IdString( _solvable->name ).c_str();
155       const char * sep = ::strchr( ident, ':' );
156       return( sep ? sep+1 : ident );
157     }
158
159     Edition Solvable::edition() const
160     {
161       NO_SOLVABLE_RETURN( Edition() );
162       return Edition( _solvable->evr );
163     }
164
165     Arch Solvable::arch() const
166     {
167       NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() );
168       switch ( _solvable->arch )
169       {
170         case ARCH_SRC:
171         case ARCH_NOSRC:
172           return Arch_noarch; //ArchId( ARCH_NOARCH );
173           break;
174       }
175       return Arch( IdString(_solvable->arch).asString() );
176       //return ArchId( _solvable->arch );
177     }
178
179     IdString Solvable::vendor() const
180     {
181       NO_SOLVABLE_RETURN( IdString() );
182       return IdString( _solvable->vendor );
183     }
184
185     Capabilities Solvable::operator[]( Dep which_r ) const
186     {
187       NO_SOLVABLE_RETURN( Capabilities() );
188       ::Offset offs = 0;
189       switch( which_r.inSwitch() )
190       {
191         case Dep::PROVIDES_e:    offs = _solvable->provides;    break;
192         case Dep::REQUIRES_e:    offs = _solvable->requires;    break;
193         case Dep::CONFLICTS_e:   offs = _solvable->conflicts;   break;
194         case Dep::OBSOLETES_e:   offs = _solvable->obsoletes;   break;
195         case Dep::RECOMMENDS_e:  offs = _solvable->recommends;  break;
196         case Dep::SUGGESTS_e:    offs = _solvable->suggests;    break;
197         case Dep::FRESHENS_e:    offs = _solvable->freshens;    break;
198         case Dep::ENHANCES_e:    offs = _solvable->enhances;    break;
199         case Dep::SUPPLEMENTS_e: offs = _solvable->supplements; break;
200
201         case Dep::PREREQUIRES_e:
202           // prerequires are a subset of requires
203           if ( (offs = _solvable->requires) )
204             return Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker );
205           else
206             return Capabilities();
207           break;
208       }
209
210       return offs ? Capabilities( _solvable->repo->idarraydata + offs )
211                   : Capabilities();
212     }
213
214     /******************************************************************
215     **
216     **  FUNCTION NAME : operator<<
217     **  FUNCTION TYPE : std::ostream &
218     */
219     std::ostream & operator<<( std::ostream & str, const Solvable & obj )
220     {
221       if ( ! obj )
222         return str << "sat::solvable()";
223
224       return str << "sat::solvable(" << obj.id() << "|"
225           << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
226           << '-' << obj.edition() << '.' << obj.arch() << "){"
227           << obj.repo().name() << "}";
228     }
229
230     /******************************************************************
231     **
232     **  FUNCTION NAME : dumpOn
233     **  FUNCTION TYPE : std::ostream &
234     */
235     std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
236     {
237       str << obj;
238       if ( obj )
239       {
240 #define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X]
241         OUTS(PROVIDES);
242         OUTS(PREREQUIRES);
243         OUTS(REQUIRES);
244         OUTS(CONFLICTS);
245         OUTS(OBSOLETES);
246         OUTS(RECOMMENDS);
247         OUTS(SUGGESTS);
248         OUTS(FRESHENS);
249         OUTS(ENHANCES);
250         OUTS(SUPPLEMENTS);
251 #undef OUTS
252       }
253       return str;
254     }
255
256     /////////////////////////////////////////////////////////////////
257   } // namespace sat
258   ///////////////////////////////////////////////////////////////////
259   /////////////////////////////////////////////////////////////////
260 } // namespace zypp
261 ///////////////////////////////////////////////////////////////////