60c658c6a5c844f152c30d7a849a057fe8b17215
[platform/upstream/libzypp.git] / zypp / ui / UserWantedPackages.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /**
10  * \file        zypp/ui/UserWantedPackages.cc
11  *
12  *  \author     Stefan Hundhammer <sh@suse.de>
13  *
14  */
15 #include <iostream>
16 #include "zypp/base/Logger.h"
17
18 #include "zypp/ui/UserWantedPackages.h"
19
20 #include "zypp/base/PtrTypes.h"
21 #include "zypp/ui/Selectable.h"
22 #include "zypp/ResObject.h"
23 #include "zypp/Package.h"
24 #include "zypp/Selection.h"
25 #include "zypp/Pattern.h"
26 #include "zypp/Language.h"
27 #include "zypp/Patch.h"
28 #include "zypp/ZYppFactory.h"
29 #include "zypp/ResPoolProxy.h"
30
31
32 using std::string;
33 using std::set;
34 using std::endl;
35
36
37 namespace zypp
38 {
39     namespace ui
40     {
41         typedef ResPoolProxy::const_iterator    PoolProxyIterator;
42
43         static inline ResPoolProxy              poolProxy()     { return getZYpp()->poolProxy();        }
44
45         template<class T> PoolProxyIterator poolProxyBegin()    { return poolProxy().byKindBegin<T>();  }
46         template<class T> PoolProxyIterator poolProxyEnd()      { return poolProxy().byKindEnd<T>();    }
47
48         static inline PoolProxyIterator pkgBegin()              { return poolProxyBegin<Package>();     }
49         static inline PoolProxyIterator pkgEnd()                { return poolProxyEnd<Package>();       }
50
51         static inline PoolProxyIterator langBegin()             { return poolProxyBegin<Language>();    }
52         static inline PoolProxyIterator langEnd()               { return poolProxyEnd<Language>();      }
53
54         static inline PoolProxyIterator patchesBegin()          { return poolProxyBegin<Patch>();       }
55         static inline PoolProxyIterator patchesEnd()            { return poolProxyEnd<Patch>();         }
56
57         template<typename T> bool contains( const std::set<T> & container, T search )
58         {
59             return container.find( search ) != container.end();
60         }
61
62
63
64         static void addDirectlySelectedPackages ( set<string> & pkgNames );
65         template<class PkgSet_T> void addPkgSetPackages( set<string> & pkgNames );
66
67         static void addSelectionPackages        ( set<string> & pkgNames );
68         static void addPatternPackages          ( set<string> & pkgNames );
69         static void addLanguagePackages         ( set<string> & pkgNames );
70         static void addPatchPackages            ( set<string> & pkgNames );
71
72
73
74         set<string> userWantedPackageNames()
75         {
76             set<string> pkgNames;
77
78             DBG << "Collecting packages the user explicitly asked for" << endl;
79
80             addDirectlySelectedPackages ( pkgNames );
81             addSelectionPackages        ( pkgNames );
82             addPatternPackages          ( pkgNames );
83             addLanguagePackages         ( pkgNames );
84             addPatchPackages            ( pkgNames );
85
86             return pkgNames;
87         }
88
89
90
91         static void addDirectlySelectedPackages( set<string> & pkgNames )
92         {
93             for ( PoolProxyIterator it = pkgBegin();
94                   it != pkgEnd();
95                   ++it )
96             {
97                 // Add all packages the user wanted to transact directly,
98                 // no matter what the transaction is (install, update, delete)
99
100                 if ( (*it)->toModify() && (*it)->modifiedBy() == ResStatus::USER )
101                 {
102                     DBG << "Explicit user transaction on pkg \"" << (*it)->name() << "\"" << endl;
103
104                     pkgNames.insert( (*it)->name() );
105                 }
106             }
107         }
108
109
110
111         static void addSelectionPackages( set<string> & pkgNames )
112         {
113             addPkgSetPackages<Selection>( pkgNames );
114         }
115
116
117         static void addPatternPackages( set<string> & pkgNames )
118         {
119             addPkgSetPackages<Pattern>( pkgNames );
120         }
121
122
123         /**
124          * Template to handle Selections and Patterns
125          **/
126         template<class PkgSet_T> void addPkgSetPackages( set<string> & pkgNames )
127         {
128             for ( PoolProxyIterator it = poolProxyBegin<PkgSet_T>();
129                   it != poolProxyEnd<PkgSet_T>();
130                   ++it )
131             {
132                 // Take all pkg sets (selections or patterns) into account that
133                 // will be transacted, no matter if the user explicitly asked
134                 // for that pkg set or if the selection is required by another
135                 // pkg set of the same class
136
137                 typename PkgSet_T::constPtr pkgSet = dynamic_pointer_cast<const PkgSet_T>( (*it)->theObj() );
138
139                 if ( pkgSet && (*it)->toModify() )
140                 {
141                     DBG << (*it)->theObj()->kind().asString()
142                         << " will be transacted: \"" << pkgSet->name() << "\"" << endl;
143
144                     set<string> setPkgs = pkgSet->install_packages();
145                     pkgNames.insert( setPkgs.begin(), setPkgs.end() );
146                 }
147             }
148         }
149
150
151
152         static void addLanguagePackages( set<string> & pkgNames )
153         {
154             // Build a set of all languages that are to be transacted
155
156             set<string> wantedLanguages;
157
158             for ( PoolProxyIterator lang_it = langBegin();
159                   lang_it != langEnd();
160                   ++lang_it )
161             {
162                 if ( (*lang_it)->toModify() )
163                 {
164                     DBG << "Language will be transacted: \"" << (*lang_it)->name() << "\"" << endl;
165
166                     wantedLanguages.insert( (*lang_it)->name() );
167                 }
168             }
169
170
171             // Check all packages if they support any of the wanted languages
172
173             for ( PoolProxyIterator pkg_it = pkgBegin();
174                   pkg_it != pkgEnd();
175                   ++pkg_it )
176             {
177                 ResObject::constPtr obj = (*pkg_it)->theObj();
178
179                 if ( obj )
180                 {
181                     CapSet freshens = obj->dep( Dep::FRESHENS );
182
183                     for ( CapSet::const_iterator cap_it = freshens.begin();
184                           cap_it != freshens.end();
185                           ++cap_it )
186                     {
187                         if ( contains( wantedLanguages, (*cap_it).index() ) )
188                             pkgNames.insert( obj->name() );
189                     }
190                 }
191             }
192         }
193
194
195
196         static void addPatchPackages( set<string> & pkgNames )
197         {
198             for ( PoolProxyIterator patch_it = patchesBegin();
199                   patch_it != patchesEnd();
200                   ++patch_it )
201             {
202                 Patch::constPtr patch = dynamic_pointer_cast<const Patch>( (*patch_it)->theObj() );
203
204                 if ( patch && (*patch_it)->toModify() )
205                 {
206                     DBG << "Patch will be transacted: \"" << patch->name()
207                         << "\" - \"" << patch->summary() << "\"" << endl;
208
209                     Patch::AtomList atomList = patch->atoms();
210
211                     for ( Patch::AtomList::iterator atom_it = atomList.begin();
212                           atom_it != atomList.end();
213                           ++atom_it )
214                     {
215                         pkgNames.insert( (*atom_it)->name() );
216                     }
217                 }
218             }
219         }
220
221     } // namespace ui
222 } // namespace zypp