Removed obsolete files and classes.
[platform/upstream/libzypp.git] / zypp / solver / detail / Testcase.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/solver/detail/Testcase.cc
10  *
11 */
12 #include <iostream>
13 #include <fstream>
14 #include <sstream>
15 #include <streambuf>
16
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"
28
29
30 /////////////////////////////////////////////////////////////////////////
31 namespace zypp
32 { ///////////////////////////////////////////////////////////////////////
33   ///////////////////////////////////////////////////////////////////////
34   namespace solver
35   { /////////////////////////////////////////////////////////////////////
36     /////////////////////////////////////////////////////////////////////
37     namespace detail
38     { ///////////////////////////////////////////////////////////////////
39         
40 #define TAB "\t"
41 #define TAB2 "\t\t"
42         
43 using namespace std;
44 using namespace zypp::capability;
45 using namespace zypp::str;
46
47 IMPL_PTR_TYPE(HelixResolvable); 
48
49 static std::string xml_escape( const std::string &text )
50 {
51   iobind::parser::xml_escape_parser parser;
52   return parser.escape(text);
53 }
54
55 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
56 {
57   string result;
58   result += "<" + tag + ">";
59
60   if ( escape)
61    result += xml_escape(text);
62   else
63    result += text;
64
65   result += "</" + tag + ">";
66   return result;
67 }
68
69         
70 template<class T>
71 std::string helixXML( const T &obj ); //undefined
72
73 template<> 
74 std::string helixXML( const Edition &edition )
75 {
76     stringstream str;
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");    
82     return str.str();
83 }
84
85 template<> 
86 std::string helixXML( const Arch &arch )
87 {
88     stringstream str;
89     str << xml_tag_enclose(arch.asString(), "arch");        
90     return str.str();    
91 }
92
93 template<> 
94 std::string helixXML( const Capability &cap )
95 {
96     stringstream str;
97     VersionedCap::constPtr vercap = asKind<VersionedCap>(cap);
98     if (vercap
99         && vercap->op() != Rel::NONE
100         && vercap->op() != Rel::ANY
101         && !vercap->edition().version().empty() )
102     {
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()) << "'";
110     }
111     else
112     {
113       str << "<dep name='" << xml_escape(cap.asString()) << "'";
114     }
115     
116     str << " kind=\"" << toLower (cap.refers().asString()) << "\""
117         << " />" << endl;
118         
119     return str.str();    
120 }
121
122 template<> 
123 std::string helixXML( const Capabilities &caps )
124 {
125     stringstream str;
126     Capabilities::iterator it = caps.begin();
127     str << endl;
128     for ( ; it != caps.end(); ++it)
129     {
130         str << TAB2 << helixXML((*it));
131     }
132     str << TAB;
133     return str.str();
134 }
135
136 template<> 
137 std::string helixXML( const Dependencies &dep )
138 {
139     stringstream str;
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;
158     return str.str();    
159 }
160
161 std::string helixXML( const PoolItem_Ref &item )
162 {
163   const Resolvable::constPtr resolvable = item.resolvable();
164   stringstream str;
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
169       return str.str();
170   }
171   
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;
180   } else {
181       str << TAB << helixXML (resolvable->arch()) << endl;      
182       str << TAB << helixXML (resolvable->edition()) << endl;            
183   }
184   str << helixXML (resolvable->deps());              
185
186   str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;  
187   return str.str();
188 }
189
190 //---------------------------------------------------------------------------
191
192 Testcase::Testcase()
193     :dumpPath("/var/log/YaST2/solverTestcase")    
194 {
195 }
196
197 Testcase::Testcase(const std::string & path)
198     :dumpPath(path)
199 {
200 }
201         
202
203 Testcase::~Testcase()
204 {
205 }
206
207 bool Testcase::createTestcase(Resolver & resolver)
208 {
209     PathInfo path (dumpPath);
210
211     if ( !path.isExist() ) {
212         if (zypp::filesystem::mkdir (dumpPath)!=0) {
213             ERR << "Cannot create directory " << dumpPath << endl;
214             return false;
215         }
216     } else {
217         if (!path.isDir()) {
218             ERR << dumpPath << " is not a directory." << endl;
219             return false;
220         }
221         // remove old stuff
222         zypp::filesystem::clean_dir (dumpPath);
223     }
224     
225     zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
226     zypp::base::LogControl::TmpExcessive excessive;
227
228     resolver.reset(true); // true = resetting all valid solverresults
229     resolver.resolvePool();
230
231     zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );    
232
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");    
241
242     for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
243     {
244         Resolvable::constPtr res = it->resolvable();
245
246         if (isKind<Language>(res)) {
247             if ( it->status().isInstalled()
248                  || it->status().isToBeInstalled()) {
249                 language.push_back (*it);               
250             }
251         } else {
252             if ( it->status().isInstalled() ) {
253                 // system channel
254                 system.addResolvable (*it);
255             } else {
256                 // repo channels
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())
262                                                           + "-package.xml");
263                 }
264                 repoTable[repo]->addResolvable (*it);
265             }
266         
267             if ( it->status().isToBeInstalled()
268                  && !(it->status().isBySolver())) {
269                 items_to_install.push_back (*it);
270             }
271             if ( it->status().isKept()
272                  && !(it->status().isBySolver())) {
273                 items_keep.push_back (*it);
274             }       
275             if ( it->status().isToBeUninstalled()
276                  && !(it->status().isBySolver())) {
277                 items_to_remove.push_back (*it);
278             }
279             if ( it->status().isLocked()
280                  && !(it->status().isBySolver())
281                  && !isKind<SystemResObject>(res)) {
282                 items_locked.push_back (*it);
283             }
284             
285         }
286     }
287
288     // writing control file "*-test.xml"
289
290     HelixControl control (dumpPath + "/solver-test.xml",
291                           repoTable,
292                           resolver.architecture(),
293                           language);
294
295     for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
296         control.installResolvable (iter->resolvable()); 
297     }
298
299     for (PoolItemList::const_iterator iter = items_locked.begin(); iter != items_locked.end(); iter++) {
300         control.lockResolvable (iter->resolvable());    
301     }
302     
303     for (PoolItemList::const_iterator iter = items_keep.begin(); iter != items_keep.end(); iter++) {
304         control.keepResolvable (iter->resolvable());    
305     }
306
307     for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
308         control.deleteResolvable (iter->resolvable());  
309     }
310
311     control.addDependencies (resolver.extraCapability(), resolver.extraConflicts());
312
313     return true;
314 }
315
316 //---------------------------------------------------------------------------
317
318 HelixResolvable::HelixResolvable(const std::string & path)
319     :dumpFile (path)    
320 {
321     file = new ofstream(path.c_str());
322     if (!file) {
323         ZYPP_THROW (Exception( "Can't open " + path ) );
324     }
325
326     *file << "<channel><subchannel>" << endl;
327 }
328
329 HelixResolvable::~HelixResolvable()
330 {
331     *file << "</subchannel></channel>" << endl;
332 }
333     
334
335 void HelixResolvable::addResolvable(const PoolItem_Ref item)
336 {
337     *file << helixXML (item);
338 }
339
340 //---------------------------------------------------------------------------
341
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) 
348 {
349     file = new ofstream(controlPath.c_str());
350     if (!file) {
351         ZYPP_THROW (Exception( "Can't open " + controlPath ) );
352     }
353
354     *file << "<?xml version=\"1.0\"?>" << endl
355           << "<!-- testcase generated by YaST -->" << endl
356           << "<test>" << 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();
366               ++itUrl )
367         {
368             *file << TAB << "- url         : " << *itUrl << endl;
369         }       
370         *file << TAB << "- path        : " << repo.info().path() << endl;
371         *file << TAB << "- type        : " << repo.info().type() << endl;       
372         *file << TAB << " -->" << endl;
373         
374         *file << TAB << "<channel file=\"" << numstring(repo.numericId())
375               << "-package.xml\" name=\"" << numstring(repo.numericId())
376               << "\" />" << endl << endl;
377     }
378     for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
379         *file << TAB << "<locale name=\"" <<  iter->resolvable()->name()
380               << "\" />" << endl;
381     }    
382     *file << "</setup>" << endl
383           << "<trial>" << endl
384           << "<showpool all=\"yes\"/>" << endl
385           << "<establish/>" << endl
386           << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
387 }
388
389 HelixControl::HelixControl()
390     :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
391 {
392     HelixControl (dumpFile);
393 }
394
395 HelixControl::~HelixControl()
396 {
397     *file << "</trial>" << endl
398           << "</test>" << endl;
399 }
400
401 void HelixControl::installResolvable(const ResObject::constPtr &resObject)
402 {
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() << "\"" 
407           << "/>" << endl;
408 }
409
410 void HelixControl::lockResolvable(const ResObject::constPtr &resObject)
411 {
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() << "\"" 
416           << "/>" << endl;
417 }
418
419 void HelixControl::keepResolvable(const ResObject::constPtr &resObject)
420 {
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() << "\"" 
425           << "/>" << endl;
426 }
427     
428 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject)
429 {
430     Repository repo  = resObject->repository();    
431     *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
432           << " name=\"" << resObject->name() << "\"" << "/>" << endl;    
433 }
434
435 void HelixControl::addDependencies (const Capabilities & capRequire, const Capabilities & capConflict)
436 {
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;    
440     }
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;    
444     }    
445 }
446
447
448       ///////////////////////////////////////////////////////////////////
449     };// namespace detail
450     /////////////////////////////////////////////////////////////////////
451     /////////////////////////////////////////////////////////////////////
452   };// namespace solver
453   ///////////////////////////////////////////////////////////////////////
454   ///////////////////////////////////////////////////////////////////////
455 };// namespace zypp
456 /////////////////////////////////////////////////////////////////////////