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/PathInfo.h"
21 #include "zypp/Product.h"
22 #include "zypp/Package.h"
23 #include "zypp/Edition.h"
24 #include "zypp/target/store/xml_escape_parser.hpp"
25 #include "zypp/capability/VersionedCap.h"
26 #include "zypp/base/String.h"
27 #include "zypp/base/PtrTypes.h"
30 /////////////////////////////////////////////////////////////////////////
32 { ///////////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////////
36 /////////////////////////////////////////////////////////////////////
38 { ///////////////////////////////////////////////////////////////////
44 using namespace zypp::capability;
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 VersionedCap::constPtr vercap = asKind<VersionedCap>(cap);
99 && vercap->op() != Rel::NONE
100 && vercap->op() != Rel::ANY
101 && !vercap->edition().version().empty() )
103 // version capability
104 str << "<dep name='" << xml_escape(vercap->index()) << "' op='" << xml_escape(vercap->op().asString()) <<
105 "' version='" << vercap->edition().version() << "'";
106 if (!vercap->edition().release().empty())
107 str << " release='" << vercap->edition().release() << "'";
108 if (vercap->edition().epoch() != Edition::noepoch)
109 str << " epoch='" << numstring(vercap->edition().epoch()) << "'";
113 str << "<dep name='" << xml_escape(cap.asString()) << "'";
116 str << " kind=\"" << toLower (cap.refers().asString()) << "\""
123 std::string helixXML( const Capabilities &caps )
126 Capabilities::iterator it = caps.begin();
128 for ( ; it != caps.end(); ++it)
130 str << TAB2 << helixXML((*it));
137 std::string helixXML( const Dependencies &dep )
140 if ( dep[Dep::PROVIDES].size() > 0 )
141 str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
142 if ( dep[Dep::CONFLICTS].size() > 0 )
143 str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
144 if ( dep[Dep::OBSOLETES].size() > 0 )
145 str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
146 if ( dep[Dep::FRESHENS].size() > 0 )
147 str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
148 if ( dep[Dep::REQUIRES].size() > 0 )
149 str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;
150 if ( dep[Dep::RECOMMENDS].size() > 0 )
151 str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
152 if ( dep[Dep::ENHANCES].size() > 0 )
153 str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
154 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
155 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
156 if ( dep[Dep::SUGGESTS].size() > 0 )
157 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
161 std::string helixXML( const PoolItem_Ref &item )
163 const Resolvable::constPtr resolvable = item.resolvable();
165 if ( isKind<SystemResObject>(resolvable)
166 || isKind<Language>(resolvable) ) {
167 // system resolvable will be generated by the resolver
168 // language dependencies will be written i another part
172 str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
173 str << TAB << xml_tag_enclose (resolvable->name(), "name", true) << endl;
174 str << TAB << xml_tag_enclose (item->vendor(), "vendor", true) << endl;
175 if ( isKind<Package>(resolvable) ) {
176 str << TAB << "<history>" << endl << TAB << "<update>" << endl;
177 str << TAB2 << helixXML (resolvable->arch()) << endl;
178 str << TAB2 << helixXML (resolvable->edition()) << endl;
179 str << TAB << "</update>" << endl << TAB << "</history>" << endl;
181 str << TAB << helixXML (resolvable->arch()) << endl;
182 str << TAB << helixXML (resolvable->edition()) << endl;
184 str << helixXML (resolvable->deps());
186 str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;
190 //---------------------------------------------------------------------------
193 :dumpPath("/var/log/YaST2/solverTestcase")
197 Testcase::Testcase(const std::string & path)
203 Testcase::~Testcase()
207 bool Testcase::createTestcase(Resolver & resolver)
209 PathInfo path (dumpPath);
211 if ( !path.isExist() ) {
212 if (zypp::filesystem::mkdir (dumpPath)!=0) {
213 ERR << "Cannot create directory " << dumpPath << endl;
218 ERR << dumpPath << " is not a directory." << endl;
222 zypp::filesystem::clean_dir (dumpPath);
225 zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
226 zypp::base::LogControl::TmpExcessive excessive;
228 resolver.reset(true); // true = resetting all valid solverresults
229 resolver.resolvePool();
231 zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );
233 ResPool pool = resolver.pool();
234 RepositoryTable repoTable;
235 PoolItemList items_to_install;
236 PoolItemList items_to_remove;
237 PoolItemList items_locked;
238 PoolItemList items_keep;
239 PoolItemList language;
240 HelixResolvable system (dumpPath + "/solver-system.xml");
242 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
244 Resolvable::constPtr res = it->resolvable();
246 if (isKind<Language>(res)) {
247 if ( it->status().isInstalled()
248 || it->status().isToBeInstalled()) {
249 language.push_back (*it);
252 if ( it->status().isInstalled() ) {
254 system.addResolvable (*it);
257 ResObject::constPtr repoItem = it->resolvable();
258 Repository repo = repoItem->repository();
259 if (repoTable.find (repo) == repoTable.end()) {
260 repoTable[repo] = new HelixResolvable(dumpPath + "/"
261 + numstring(repo.numericId())
264 repoTable[repo]->addResolvable (*it);
267 if ( it->status().isToBeInstalled()
268 && !(it->status().isBySolver())) {
269 items_to_install.push_back (*it);
271 if ( it->status().isKept()
272 && !(it->status().isBySolver())) {
273 items_keep.push_back (*it);
275 if ( it->status().isToBeUninstalled()
276 && !(it->status().isBySolver())) {
277 items_to_remove.push_back (*it);
279 if ( it->status().isLocked()
280 && !(it->status().isBySolver())
281 && !isKind<SystemResObject>(res)) {
282 items_locked.push_back (*it);
288 // writing control file "*-test.xml"
290 HelixControl control (dumpPath + "/solver-test.xml",
292 resolver.architecture(),
295 for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
296 control.installResolvable (iter->resolvable());
299 for (PoolItemList::const_iterator iter = items_locked.begin(); iter != items_locked.end(); iter++) {
300 control.lockResolvable (iter->resolvable());
303 for (PoolItemList::const_iterator iter = items_keep.begin(); iter != items_keep.end(); iter++) {
304 control.keepResolvable (iter->resolvable());
307 for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
308 control.deleteResolvable (iter->resolvable());
311 control.addDependencies (resolver.extraCapability(), resolver.extraConflicts());
316 //---------------------------------------------------------------------------
318 HelixResolvable::HelixResolvable(const std::string & path)
321 file = new ofstream(path.c_str());
323 ZYPP_THROW (Exception( "Can't open " + path ) );
326 *file << "<channel><subchannel>" << endl;
329 HelixResolvable::~HelixResolvable()
331 *file << "</subchannel></channel>" << endl;
335 void HelixResolvable::addResolvable(const PoolItem_Ref item)
337 *file << helixXML (item);
340 //---------------------------------------------------------------------------
342 HelixControl::HelixControl(const std::string & controlPath,
343 const RepositoryTable & repoTable,
344 const Arch & systemArchitecture,
345 const PoolItemList &languages,
346 const std::string & systemPath)
347 :dumpFile (controlPath)
349 file = new ofstream(controlPath.c_str());
351 ZYPP_THROW (Exception( "Can't open " + controlPath ) );
354 *file << "<?xml version=\"1.0\"?>" << endl
355 << "<!-- testcase generated by YaST -->" << endl
357 << "<setup arch=\"" << systemArchitecture << "\">" << endl
358 << TAB << "<system file=\"" << systemPath << "\"/>" << endl << endl;
359 for ( RepositoryTable::const_iterator it = repoTable.begin();
360 it != repoTable.end(); ++it ) {
361 Repository repo = it->first;
362 *file << TAB << "<!-- " << endl
363 << TAB << "- alias : " << repo.info().alias() << endl;
364 for ( RepoInfo::urls_const_iterator itUrl = repo.info().baseUrlsBegin();
365 itUrl != repo.info().baseUrlsEnd();
368 *file << TAB << "- url : " << *itUrl << endl;
370 *file << TAB << "- path : " << repo.info().path() << endl;
371 *file << TAB << "- type : " << repo.info().type() << endl;
372 *file << TAB << " -->" << endl;
374 *file << TAB << "<channel file=\"" << numstring(repo.numericId())
375 << "-package.xml\" name=\"" << numstring(repo.numericId())
376 << "\" />" << endl << endl;
378 for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
379 *file << TAB << "<locale name=\"" << iter->resolvable()->name()
382 *file << "</setup>" << endl
384 << "<showpool all=\"yes\"/>" << endl
385 << "<establish/>" << endl
386 << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
389 HelixControl::HelixControl()
390 :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
392 HelixControl (dumpFile);
395 HelixControl::~HelixControl()
397 *file << "</trial>" << endl
398 << "</test>" << endl;
401 void HelixControl::installResolvable(const ResObject::constPtr &resObject)
403 Repository repo = resObject->repository();
404 *file << "<install channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
405 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
406 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
410 void HelixControl::lockResolvable(const ResObject::constPtr &resObject)
412 Repository repo = resObject->repository();
413 *file << "<lock channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
414 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
415 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
419 void HelixControl::keepResolvable(const ResObject::constPtr &resObject)
421 Repository repo = resObject->repository();
422 *file << "<keep channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
423 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
424 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
428 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject)
430 Repository repo = resObject->repository();
431 *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
432 << " name=\"" << resObject->name() << "\"" << "/>" << endl;
435 void HelixControl::addDependencies (const Capabilities & capRequire, const Capabilities & capConflict)
437 for (Capabilities::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) {
438 *file << "<addRequire " << " kind=\"" << toLower (iter->kind().asString()) << "\""
439 << " name=\"" << iter->asString() << "\"" << "/>" << endl;
441 for (Capabilities::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) {
442 *file << "<addConflict " << " kind=\"" << toLower (iter->kind().asString()) << "\""
443 << " name=\"" << iter->asString() << "\"" << "/>" << endl;
448 ///////////////////////////////////////////////////////////////////
449 };// namespace detail
450 /////////////////////////////////////////////////////////////////////
451 /////////////////////////////////////////////////////////////////////
452 };// namespace solver
453 ///////////////////////////////////////////////////////////////////////
454 ///////////////////////////////////////////////////////////////////////
456 /////////////////////////////////////////////////////////////////////////