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