1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/solver/detail/Testcase.cc
17 #include "zypp/solver/detail/Testcase.h"
18 #include "zypp/base/Logger.h"
19 #include "zypp/base/LogControl.h"
20 #include "zypp/ZConfig.h"
21 #include "zypp/PathInfo.h"
22 #include "zypp/Product.h"
23 #include "zypp/Package.h"
24 #include "zypp/Edition.h"
25 #include "zypp/parser/xml_escape_parser.hpp"
26 #include "zypp/base/String.h"
27 #include "zypp/base/PtrTypes.h"
28 #include "zypp/Capabilities.h"
31 /////////////////////////////////////////////////////////////////////////
33 { ///////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////////
37 /////////////////////////////////////////////////////////////////////
39 { ///////////////////////////////////////////////////////////////////
45 using namespace zypp::str;
47 IMPL_PTR_TYPE(HelixResolvable);
49 static std::string xml_escape( const std::string &text )
51 iobind::parser::xml_escape_parser parser;
52 return parser.escape(text);
55 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
58 result += "<" + tag + ">";
61 result += xml_escape(text);
65 result += "</" + tag + ">";
71 std::string helixXML( const T &obj ); //undefined
74 std::string helixXML( const Edition &edition )
77 str << xml_tag_enclose(edition.version(), "version");
78 if (!edition.release().empty())
79 str << xml_tag_enclose(edition.release(), "release");
80 if (edition.epoch() != Edition::noepoch)
81 str << xml_tag_enclose(numstring(edition.epoch()), "epoch");
86 std::string helixXML( const Arch &arch )
89 str << xml_tag_enclose(arch.asString(), "arch");
94 std::string helixXML( const Capability &cap )
97 str << "<dep name='" << xml_escape(cap.asString()) << "' />" << endl;
103 std::string helixXML( const Capabilities &caps )
106 Capabilities::const_iterator it = caps.begin();
108 for ( ; it != caps.end(); ++it)
110 str << TAB2 << helixXML((*it));
117 std::string helixXML( const CapabilitySet &caps )
120 CapabilitySet::const_iterator it = caps.begin();
122 for ( ; it != caps.end(); ++it)
124 str << TAB2 << helixXML((*it));
132 std::string helixXML( const Dependencies &dep )
135 if ( dep[Dep::PROVIDES].size() > 0 )
136 str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
137 if ( dep[Dep::CONFLICTS].size() > 0 )
138 str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
139 if ( dep[Dep::OBSOLETES].size() > 0 )
140 str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
141 if ( dep[Dep::FRESHENS].size() > 0 )
142 str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
143 if ( dep[Dep::REQUIRES].size() > 0 )
144 str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;
145 if ( dep[Dep::RECOMMENDS].size() > 0 )
146 str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
147 if ( dep[Dep::ENHANCES].size() > 0 )
148 str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
149 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
150 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
151 if ( dep[Dep::SUGGESTS].size() > 0 )
152 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
156 inline string helixXML( const Resolvable::constPtr &obj, Dep deptag_r )
159 Capabilities caps( obj->dep(deptag_r) );
160 if ( ! caps.empty() )
161 out << " " << xml_tag_enclose(helixXML(caps), deptag_r.asString()) << endl;
165 std::string helixXML( const PoolItem &item )
167 const Resolvable::constPtr resolvable = item.resolvable();
169 str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
170 str << TAB << xml_tag_enclose (resolvable->name(), "name", true) << endl;
171 str << TAB << xml_tag_enclose (item->vendor(), "vendor", true) << endl;
172 if ( isKind<Package>(resolvable) ) {
173 str << TAB << "<history>" << endl << TAB << "<update>" << endl;
174 str << TAB2 << helixXML (resolvable->arch()) << endl;
175 str << TAB2 << helixXML (resolvable->edition()) << endl;
176 str << TAB << "</update>" << endl << TAB << "</history>" << endl;
178 str << TAB << helixXML (resolvable->arch()) << endl;
179 str << TAB << helixXML (resolvable->edition()) << endl;
181 str << helixXML( resolvable, Dep::PROVIDES);
182 str << helixXML( resolvable, Dep::PREREQUIRES);
183 str << helixXML( resolvable, Dep::CONFLICTS);
184 str << helixXML( resolvable, Dep::OBSOLETES);
185 str << helixXML( resolvable, Dep::FRESHENS);
186 str << helixXML( resolvable, Dep::REQUIRES);
187 str << helixXML( resolvable, Dep::RECOMMENDS);
188 str << helixXML( resolvable, Dep::ENHANCES);
189 str << helixXML( resolvable, Dep::SUPPLEMENTS);
190 str << helixXML( resolvable, Dep::SUGGESTS);
192 str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;
196 //---------------------------------------------------------------------------
199 :dumpPath("/var/log/YaST2/solverTestcase")
203 Testcase::Testcase(const std::string & path)
209 Testcase::~Testcase()
214 bool Testcase::createTestcasePool(const ResPool &pool)
216 PathInfo path (dumpPath);
218 if ( !path.isExist() ) {
219 if (zypp::filesystem::mkdir (dumpPath)!=0) {
220 ERR << "Cannot create directory " << dumpPath << endl;
225 ERR << dumpPath << " is not a directory." << endl;
229 zypp::filesystem::clean_dir (dumpPath);
232 RepositoryTable repoTable;
233 HelixResolvable system (dumpPath + "/solver-system.xml.gz");
235 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
237 Resolvable::constPtr res = it->resolvable();
239 if ( it->status().isInstalled() ) {
241 system.addResolvable (*it);
244 ResObject::constPtr repoItem = it->resolvable();
245 Repository repo = repoItem->repository();
246 if (repoTable.find (repo) == repoTable.end()) {
247 repoTable[repo] = new HelixResolvable(dumpPath + "/"
248 + numstring(repo.numericId())
249 + "-package.xml.gz");
251 repoTable[repo]->addResolvable (*it);
257 bool Testcase::createTestcase(Resolver & resolver, bool dumpPool, bool runSolver)
259 PathInfo path (dumpPath);
261 if ( !path.isExist() ) {
262 if (zypp::filesystem::mkdir (dumpPath)!=0) {
263 ERR << "Cannot create directory " << dumpPath << endl;
268 ERR << dumpPath << " is not a directory." << endl;
271 // remove old stuff if pool will be dump
273 zypp::filesystem::clean_dir (dumpPath);
277 zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
278 zypp::base::LogControl::TmpExcessive excessive;
280 resolver.reset(true); // true = resetting all valid solverresults
281 resolver.resolvePool();
283 zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );
286 ResPool pool = resolver.pool();
287 RepositoryTable repoTable;
288 PoolItemList items_to_install;
289 PoolItemList items_to_remove;
290 PoolItemList items_locked;
291 PoolItemList items_keep;
292 PoolItemList language;
293 HelixResolvable_Ptr system = NULL;
296 system = new HelixResolvable(dumpPath + "/solver-system.xml.gz");
298 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
300 Resolvable::constPtr res = it->resolvable();
302 #warning NO MORE LANGUAGE RESOLVABLE
303 // - use pools list of requested locales and pass it as 'LocaleList language'
304 // - restore the list via Pool::setRequestedLocales.
306 if (isKind<Language>(res)) {
307 if ( it->status().isInstalled()
308 || it->status().isToBeInstalled()) {
309 language.push_back (*it);
313 if ( system && it->status().isInstalled() ) {
315 system->addResolvable (*it);
318 ResObject::constPtr repoItem = it->resolvable();
319 Repository repo = repoItem->repository();
321 if (repoTable.find (repo) == repoTable.end()) {
322 repoTable[repo] = new HelixResolvable(dumpPath + "/"
323 + numstring(repo.numericId())
324 + "-package.xml.gz");
326 repoTable[repo]->addResolvable (*it);
330 if ( it->status().isToBeInstalled()
331 && !(it->status().isBySolver())) {
332 items_to_install.push_back (*it);
334 if ( it->status().isKept()
335 && !(it->status().isBySolver())) {
336 items_keep.push_back (*it);
338 if ( it->status().isToBeUninstalled()
339 && !(it->status().isBySolver())) {
340 items_to_remove.push_back (*it);
342 if ( it->status().isLocked()
343 && !(it->status().isBySolver())) {
344 items_locked.push_back (*it);
348 // writing control file "*-test.xml"
350 HelixControl control (dumpPath + "/solver-test.xml",
352 ZConfig::instance().systemArchitecture(),
355 for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
356 control.installResolvable (iter->resolvable(), iter->status());
359 for (PoolItemList::const_iterator iter = items_locked.begin(); iter != items_locked.end(); iter++) {
360 control.lockResolvable (iter->resolvable(), iter->status());
363 for (PoolItemList::const_iterator iter = items_keep.begin(); iter != items_keep.end(); iter++) {
364 control.keepResolvable (iter->resolvable(), iter->status());
367 for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
368 control.deleteResolvable (iter->resolvable(), iter->status());
371 control.addDependencies (resolver.extraRequires(), resolver.extraConflicts());
376 //---------------------------------------------------------------------------
378 HelixResolvable::HelixResolvable(const std::string & path)
381 file = new ofgzstream(path.c_str());
383 ZYPP_THROW (Exception( "Can't open " + path ) );
386 *file << "<channel><subchannel>" << endl;
389 HelixResolvable::~HelixResolvable()
391 *file << "</subchannel></channel>" << endl;
396 void HelixResolvable::addResolvable(const PoolItem item)
398 *file << helixXML (item);
401 //---------------------------------------------------------------------------
403 HelixControl::HelixControl(const std::string & controlPath,
404 const RepositoryTable & repoTable,
405 const Arch & systemArchitecture,
406 const PoolItemList &languages,
407 const std::string & systemPath)
408 :dumpFile (controlPath)
410 file = new ofstream(controlPath.c_str());
412 ZYPP_THROW (Exception( "Can't open " + controlPath ) );
415 *file << "<?xml version=\"1.0\"?>" << endl
416 << "<!-- testcase generated by YaST -->" << endl
418 << "<setup arch=\"" << systemArchitecture << "\">" << endl
419 << TAB << "<system file=\"" << systemPath << "\"/>" << endl << endl;
420 for ( RepositoryTable::const_iterator it = repoTable.begin();
421 it != repoTable.end(); ++it ) {
422 Repository repo = it->first;
423 *file << TAB << "<!-- " << endl
424 << TAB << "- alias : " << repo.info().alias() << endl;
425 for ( RepoInfo::urls_const_iterator itUrl = repo.info().baseUrlsBegin();
426 itUrl != repo.info().baseUrlsEnd();
429 *file << TAB << "- url : " << *itUrl << endl;
431 *file << TAB << "- path : " << repo.info().path() << endl;
432 *file << TAB << "- type : " << repo.info().type() << endl;
433 *file << TAB << " -->" << endl;
435 *file << TAB << "<channel file=\"" << numstring(repo.numericId())
436 << "-package.xml.gz\" name=\"" << numstring(repo.numericId())
437 << "\" />" << endl << endl;
439 for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
440 *file << TAB << "<locale name=\"" << iter->resolvable()->name()
443 *file << "</setup>" << endl
445 << "<showpool all=\"yes\"/>" << endl
446 << "<establish/>" << endl
447 << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
450 HelixControl::HelixControl()
451 :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
453 HelixControl (dumpFile);
456 HelixControl::~HelixControl()
458 *file << "</trial>" << endl
459 << "</test>" << endl;
462 void HelixControl::installResolvable(const ResObject::constPtr &resObject,
463 const ResStatus &status)
465 Repository repo = resObject->repository();
466 *file << "<install channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
467 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
468 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
469 << " status=\"" << status << "\""
473 void HelixControl::lockResolvable(const ResObject::constPtr &resObject,
474 const ResStatus &status)
476 Repository repo = resObject->repository();
477 *file << "<lock channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
478 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
479 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
480 << " status=\"" << status << "\""
484 void HelixControl::keepResolvable(const ResObject::constPtr &resObject,
485 const ResStatus &status)
487 Repository repo = resObject->repository();
488 *file << "<keep channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
489 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
490 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
491 << " status=\"" << status << "\""
495 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject,
496 const ResStatus &status)
498 Repository repo = resObject->repository();
499 *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
500 << " name=\"" << resObject->name() << "\""
501 << " status=\"" << status << "\""
505 void HelixControl::addDependencies (const CapabilitySet & capRequire, const CapabilitySet & capConflict)
507 for (CapabilitySet::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) {
508 *file << "<addRequire " << " name=\"" << iter->asString() << "\"" << "/>" << endl;
510 for (CapabilitySet::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) {
511 *file << "<addConflict " << " name=\"" << iter->asString() << "\"" << "/>" << endl;
516 ///////////////////////////////////////////////////////////////////
517 };// namespace detail
518 /////////////////////////////////////////////////////////////////////
519 /////////////////////////////////////////////////////////////////////
520 };// namespace solver
521 ///////////////////////////////////////////////////////////////////////
522 ///////////////////////////////////////////////////////////////////////
524 /////////////////////////////////////////////////////////////////////////