00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00015 #include <iostream> 00016 #include "zypp/base/Logger.h" 00017 00018 #include "zypp/ui/UserWantedPackages.h" 00019 00020 #include "zypp/base/PtrTypes.h" 00021 #include "zypp/ui/Selectable.h" 00022 #include "zypp/ResObject.h" 00023 #include "zypp/Package.h" 00024 #include "zypp/Selection.h" 00025 #include "zypp/Pattern.h" 00026 #include "zypp/Language.h" 00027 #include "zypp/Patch.h" 00028 #include "zypp/ZYppFactory.h" 00029 #include "zypp/ResPoolProxy.h" 00030 00031 00032 using std::string; 00033 using std::set; 00034 using std::endl; 00035 00036 00037 namespace zypp 00038 { 00039 namespace ui 00040 { 00041 typedef ResPoolProxy::const_iterator PoolProxyIterator; 00042 00043 static inline ResPoolProxy poolProxy() { return getZYpp()->poolProxy(); } 00044 00045 template<class T> PoolProxyIterator poolProxyBegin() { return poolProxy().byKindBegin<T>(); } 00046 template<class T> PoolProxyIterator poolProxyEnd() { return poolProxy().byKindEnd<T>(); } 00047 00048 static inline PoolProxyIterator pkgBegin() { return poolProxyBegin<Package>(); } 00049 static inline PoolProxyIterator pkgEnd() { return poolProxyEnd<Package>(); } 00050 00051 static inline PoolProxyIterator langBegin() { return poolProxyBegin<Language>(); } 00052 static inline PoolProxyIterator langEnd() { return poolProxyEnd<Language>(); } 00053 00054 static inline PoolProxyIterator patchesBegin() { return poolProxyBegin<Patch>(); } 00055 static inline PoolProxyIterator patchesEnd() { return poolProxyEnd<Patch>(); } 00056 00057 template<typename T> bool contains( const std::set<T> & container, T search ) 00058 { 00059 return container.find( search ) != container.end(); 00060 } 00061 00062 00063 00064 static void addDirectlySelectedPackages ( set<string> & pkgNames ); 00065 template<class PkgSet_T> void addPkgSetPackages( set<string> & pkgNames ); 00066 00067 static void addSelectionPackages ( set<string> & pkgNames ); 00068 static void addPatternPackages ( set<string> & pkgNames ); 00069 static void addLanguagePackages ( set<string> & pkgNames ); 00070 static void addPatchPackages ( set<string> & pkgNames ); 00071 00072 00073 00074 set<string> userWantedPackageNames() 00075 { 00076 set<string> pkgNames; 00077 00078 DBG << "Collecting packages the user explicitly asked for" << endl; 00079 00080 addDirectlySelectedPackages ( pkgNames ); 00081 addSelectionPackages ( pkgNames ); 00082 addPatternPackages ( pkgNames ); 00083 addLanguagePackages ( pkgNames ); 00084 addPatchPackages ( pkgNames ); 00085 00086 return pkgNames; 00087 } 00088 00089 00090 00091 static void addDirectlySelectedPackages( set<string> & pkgNames ) 00092 { 00093 for ( PoolProxyIterator it = pkgBegin(); 00094 it != pkgEnd(); 00095 ++it ) 00096 { 00097 // Add all packages the user wanted to transact directly, 00098 // no matter what the transaction is (install, update, delete) 00099 00100 if ( (*it)->toModify() && (*it)->modifiedBy() == ResStatus::USER ) 00101 { 00102 DBG << "Explicit user transaction on pkg \"" << (*it)->name() << "\"" << endl; 00103 00104 pkgNames.insert( (*it)->name() ); 00105 } 00106 } 00107 } 00108 00109 00110 00111 static void addSelectionPackages( set<string> & pkgNames ) 00112 { 00113 addPkgSetPackages<Selection>( pkgNames ); 00114 } 00115 00116 00117 static void addPatternPackages( set<string> & pkgNames ) 00118 { 00119 addPkgSetPackages<Pattern>( pkgNames ); 00120 } 00121 00122 00126 template<class PkgSet_T> void addPkgSetPackages( set<string> & pkgNames ) 00127 { 00128 for ( PoolProxyIterator it = poolProxyBegin<PkgSet_T>(); 00129 it != poolProxyEnd<PkgSet_T>(); 00130 ++it ) 00131 { 00132 // Take all pkg sets (selections or patterns) into account that 00133 // will be transacted, no matter if the user explicitly asked 00134 // for that pkg set or if the selection is required by another 00135 // pkg set of the same class 00136 00137 typename PkgSet_T::constPtr pkgSet = dynamic_pointer_cast<const PkgSet_T>( (*it)->theObj() ); 00138 00139 if ( pkgSet && (*it)->toModify() ) 00140 { 00141 DBG << (*it)->theObj()->kind().asString() 00142 << " will be transacted: \"" << pkgSet->name() << "\"" << endl; 00143 00144 set<string> setPkgs = pkgSet->install_packages(); 00145 pkgNames.insert( setPkgs.begin(), setPkgs.end() ); 00146 } 00147 } 00148 } 00149 00150 00151 00152 static void addLanguagePackages( set<string> & pkgNames ) 00153 { 00154 // Build a set of all languages that are to be transacted 00155 00156 set<string> wantedLanguages; 00157 00158 for ( PoolProxyIterator lang_it = langBegin(); 00159 lang_it != langEnd(); 00160 ++lang_it ) 00161 { 00162 if ( (*lang_it)->toModify() ) 00163 { 00164 DBG << "Language will be transacted: \"" << (*lang_it)->name() << "\"" << endl; 00165 00166 wantedLanguages.insert( (*lang_it)->name() ); 00167 } 00168 } 00169 00170 00171 // Check all packages if they support any of the wanted languages 00172 00173 for ( PoolProxyIterator pkg_it = pkgBegin(); 00174 pkg_it != pkgEnd(); 00175 ++pkg_it ) 00176 { 00177 ResObject::constPtr obj = (*pkg_it)->theObj(); 00178 00179 if ( obj ) 00180 { 00181 CapSet freshens = obj->dep( Dep::FRESHENS ); 00182 00183 for ( CapSet::const_iterator cap_it = freshens.begin(); 00184 cap_it != freshens.end(); 00185 ++cap_it ) 00186 { 00187 if ( contains( wantedLanguages, (*cap_it).index() ) ) 00188 pkgNames.insert( obj->name() ); 00189 } 00190 } 00191 } 00192 } 00193 00194 00195 00196 static void addPatchPackages( set<string> & pkgNames ) 00197 { 00198 for ( PoolProxyIterator patch_it = patchesBegin(); 00199 patch_it != patchesEnd(); 00200 ++patch_it ) 00201 { 00202 Patch::constPtr patch = dynamic_pointer_cast<const Patch>( (*patch_it)->theObj() ); 00203 00204 if ( patch && (*patch_it)->toModify() ) 00205 { 00206 DBG << "Patch will be transacted: \"" << patch->name() 00207 << "\" - \"" << patch->summary() << "\"" << endl; 00208 00209 Patch::AtomList atomList = patch->atoms(); 00210 00211 for ( Patch::AtomList::iterator atom_it = atomList.begin(); 00212 atom_it != atomList.end(); 00213 ++atom_it ) 00214 { 00215 pkgNames.insert( (*atom_it)->name() ); 00216 } 00217 } 00218 } 00219 } 00220 00221 } // namespace ui 00222 } // namespace zypp