Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / solver / detail / Helper.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* Helper.cc
3  *
4  * Static helpers
5  *
6  * Copyright (C) 2000-2002 Ximian, Inc.
7  * Copyright (C) 2005 SUSE Linux Products GmbH
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License,
11  * version 2, as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307, USA.
22  */
23 #include <sstream>
24
25 #include "zypp/solver/detail/Helper.h"
26 #include "zypp/Capabilities.h"
27 #include "zypp/base/Logger.h"
28 #include "zypp/base/String.h"
29 #include "zypp/base/Gettext.h"
30 #include "zypp/VendorAttr.h"
31 #include "zypp/base/Algorithm.h"
32 #include "zypp/ResPool.h"
33 #include "zypp/ResFilters.h"
34 #include "zypp/RepoInfo.h"
35
36 using namespace std;
37
38 /////////////////////////////////////////////////////////////////////////
39 namespace zypp
40 { ///////////////////////////////////////////////////////////////////////
41   ///////////////////////////////////////////////////////////////////////
42   namespace solver
43   { /////////////////////////////////////////////////////////////////////
44     /////////////////////////////////////////////////////////////////////
45     namespace detail
46     { ///////////////////////////////////////////////////////////////////
47
48 ostream &
49 operator<< (ostream & os, const PoolItemList & itemlist)
50 {
51     for (PoolItemList::const_iterator iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
52         if (iter != itemlist.begin())
53             os << ", ";
54         os << *iter;
55     }
56     return os;
57 }
58
59
60 class LookFor : public resfilter::PoolItemFilterFunctor
61 {
62   public:
63     PoolItem item;
64
65     bool operator()( PoolItem provider )
66     {
67         item = provider;
68         return false;                           // stop here, we found it
69     }
70 };
71
72
73 // just find installed item with same kind/name as item
74
75 template<class _Iter>
76 static PoolItem findInstalledByNameAndKind ( _Iter begin, _Iter end, const string & name, const Resolvable::Kind & kind)
77 {
78     LookFor info;
79
80     invokeOnEach(begin, end,
81                   resfilter::ByInstalled (),                                    // ByInstalled
82                   functor::functorRef<bool,PoolItem> (info) );
83
84     _XDEBUG("Helper::findInstalledByNameAndKind (" << name << ", " << kind << ") => " << info.item);
85     return info.item;
86
87 }
88
89 PoolItem Helper::findInstalledByNameAndKind (const ResPool & pool, const string & name, const Resolvable::Kind & kind)
90 { return detail::findInstalledByNameAndKind( pool.byIdentBegin( kind, name ), pool.byIdentEnd( kind, name ), name, kind ); }
91
92 PoolItem Helper::findInstalledItem (const ResPool & pool, PoolItem item)
93 { return findInstalledByNameAndKind(pool, item->name(), item->kind() ); }
94
95 PoolItem Helper::findInstalledItem( const std::vector<PoolItem> & pool, PoolItem item )
96 { return detail::findInstalledByNameAndKind( pool.begin(), pool.end(), item->name(), item->kind() ); }
97
98
99 // just find uninstalled item with same kind/name as item
100
101 PoolItem
102 Helper::findUninstalledByNameAndKind (const ResPool & pool, const string & name, const Resolvable::Kind & kind)
103 {
104     LookFor info;
105
106     invokeOnEach( pool.byIdentBegin( kind, name ),
107                   pool.byIdentEnd( kind, name ),
108                   resfilter::ByUninstalled(),                                   // ByUninstalled
109                   functor::functorRef<bool,PoolItem> (info) );
110
111     _XDEBUG("Helper::findUninstalledByNameAndKind (" << name << ", " << kind << ") => " << info.item);
112     return info.item;
113 }
114
115
116 //----------------------------------------------------------------------------
117
118 class LookForUpdate : public resfilter::PoolItemFilterFunctor
119 {
120   public:
121     PoolItem uninstalled;
122     PoolItem installed;
123
124     bool operator()( PoolItem provider )
125     {
126         // is valid
127         if ( ! provider.resolvable() )
128         {
129           WAR << "Warning: '" << provider << "' not valid" << endl;
130           return true;
131         }
132
133         if ( installed.resolvable() )
134         {
135           if ( !VendorAttr::instance().equivalent( installed, provider ) )
136           {
137             MIL << "Discarding '" << provider << "' from vendor '"
138                 << provider->vendor() << "' different to uninstalled '"
139                 << installed->vendor() << "' vendor." << endl;
140             return true;
141           }
142         }
143
144         if ((!uninstalled                                                       // none yet
145             || (uninstalled->edition().compare( provider->edition() ) < 0)      // or a better edition
146             || (uninstalled->arch().compare( provider->arch() ) < 0) ) // or a better architecture
147             && !provider.status().isLocked() )                                  // is not locked
148         {
149             uninstalled = provider;                                             // store
150         }
151         return true;
152     }
153 };
154
155
156 // just find best (according to edition) uninstalled item with same kind/name as item
157 // *DOES* check edition
158
159 template<class _Iter>
160 static PoolItem findUpdateItem( _Iter begin, _Iter end, PoolItem item )
161 {
162     LookForUpdate info;
163     info.installed = item;
164
165     invokeOnEach( begin, end,
166                   functor::chain (resfilter::ByUninstalled (),                                          // ByUninstalled
167                                   resfilter::byEdition<CompareByGT<Edition> >( item->edition() )),      // only look at better editions
168                   functor::functorRef<bool,PoolItem> (info) );
169
170     _XDEBUG("Helper::findUpdateItem(" << item << ") => " << info.uninstalled);
171     return info.uninstalled;
172 }
173
174 PoolItem Helper::findUpdateItem (const ResPool & pool, PoolItem item)
175 { return detail::findUpdateItem( pool.byIdentBegin( item ), pool.byIdentEnd( item ), item ); }
176
177 PoolItem Helper::findUpdateItem (const std::vector<PoolItem> & pool, PoolItem item)
178 { return detail::findUpdateItem( pool.begin(), pool.end(), item ); }
179
180
181 //----------------------------------------------------------------------------
182
183 class LookForReinstall : public resfilter::PoolItemFilterFunctor
184 {
185   public:
186     PoolItem uninstalled;
187
188     bool operator()( PoolItem provider )
189     {
190         if (provider.status().isLocked()) {
191             return true; // search next
192         } else {
193             uninstalled = provider;
194             return false;                               // stop here, we found it
195         }
196     }
197 };
198
199
200 PoolItem
201 Helper::findReinstallItem (const ResPool & pool, PoolItem item)
202 {
203     LookForReinstall info;
204
205     invokeOnEach( pool.byIdentBegin( item ),
206                   pool.byIdentEnd( item ),
207                   functor::chain (resfilter::ByUninstalled (),                                          // ByUninstalled
208                                   resfilter::byEdition<CompareByEQ<Edition> >( item->edition() )),
209                   functor::functorRef<bool,PoolItem> (info) );
210
211     _XDEBUG("Helper::findReinstallItem(" << item << ") => " << info.uninstalled);
212     return info.uninstalled;
213 }
214
215 //----------------------------------------------------------------------------
216
217 class CheckIfBest : public resfilter::PoolItemFilterFunctor
218 {
219   public:
220     PoolItem _item;
221     bool is_best;
222
223     CheckIfBest( PoolItem item )
224         : _item( item )
225         , is_best( true )               // assume we already have the best
226     {}
227
228     // check if provider is better. If yes, end the search.
229
230     bool operator()( PoolItem provider )
231     {
232         int archcmp = _item->arch().compare( provider->arch() );
233         if (((archcmp < 0)                                                      // provider has a better architecture
234              || ((archcmp == 0)
235                  && (_item->edition().compare( provider->edition() ) < 0)))     // or a better edition
236             && !provider.status().isLocked())                                   // and is not locked
237         {
238             is_best = false;
239             return false;
240         }
241         return true;
242     }
243 };
244
245
246 // check if the given item is the best one of the pool
247
248 bool
249 Helper::isBestUninstalledItem (const ResPool & pool, PoolItem item)
250 {
251     CheckIfBest info( item );
252
253     invokeOnEach( pool.byIdentBegin( item ),
254                   pool.byIdentEnd( item ),
255                   resfilter::ByUninstalled(),                   // ByUninstalled
256                   functor::functorRef<bool,PoolItem>( info ) );
257
258     _XDEBUG("Helper::isBestUninstalledItem(" << item << ") => " << info.is_best);
259     return info.is_best;
260 }
261
262 std::string
263 Helper::itemToString (PoolItem item, bool shortVersion)
264 {
265     ostringstream os;
266     if (!item) return "";
267
268     if (item->kind() != ResKind::package)
269         os << item->kind() << ':';
270     os  << item->name();
271     if (!shortVersion) {
272         os << '-' << item->edition();
273         if (item->arch() != "") {
274             os << '.' << item->arch();
275         }
276
277         string alias = item->repoInfo().alias();
278         if (!alias.empty()
279             && alias != "@System")
280         {
281             os << '[' << alias << ']';
282         }
283     }
284     return os.str();
285 }
286
287 std::string
288 Helper::capToString (const Capability & capability)
289 {
290     ostringstream os;
291     os << capability.asString();
292     return os.str();
293 }
294
295
296 ///////////////////////////////////////////////////////////////////
297     };// namespace detail
298     /////////////////////////////////////////////////////////////////////
299     /////////////////////////////////////////////////////////////////////
300   };// namespace solver
301   ///////////////////////////////////////////////////////////////////////
302   ///////////////////////////////////////////////////////////////////////
303 };// namespace zypp
304 /////////////////////////////////////////////////////////////////////////
305