16 #include <boost/function_output_iterator.hpp> 18 #define ZYPP_USE_RESOLVER_INTERNALS 40 #include <yaml-cpp/yaml.h> 43 #include <solv/testcase.h> 61 :dumpPath(
"/var/log/YaST2/solverTestcase")
64 Testcase::Testcase(
const std::string & path)
71 bool Testcase::createTestcase(Resolver & resolver,
bool dumpPool,
bool runSolver)
73 PathInfo path (dumpPath);
75 if ( !path.isExist() ) {
77 ERR <<
"Cannot create directory " << dumpPath << endl;
82 ERR << dumpPath <<
" is not a directory." << endl;
95 resolver.resolvePool();
98 ResPool pool = resolver.pool();
99 PoolItemList items_to_install;
100 PoolItemList items_to_remove;
101 PoolItemList items_locked;
102 PoolItemList items_keep;
105 const std::string slvTestcaseName =
"testcase.t";
106 const std::string slvResult =
"solver.result";
109 [ nrepos = resolver.get()->pool->nrepos ](
auto **x ){
111 for (
int i = 1; i < nrepos; i++ )
112 solv_free((
void *)x[i]);
113 solv_free((
void *)x);
116 if ( ::testcase_write( resolver.get(), dumpPath.c_str(), TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS, slvTestcaseName.c_str(), slvResult.c_str() ) == 0 ) {
117 ERR <<
"Failed to write solv data, aborting." << endl;
122 const sat::Pool & satpool( sat::Pool::instance() );
126 const auto addTag = [&](
const std::string & tag_r,
bool yesno_r = true ){
127 yOut << YAML::Key << tag_r << YAML::Value << yesno_r;
130 yOut << YAML::BeginMap << YAML::Key <<
"version" << YAML::Value <<
"1.0";
132 yOut << YAML::Key <<
"setup" << YAML::Value << YAML::BeginMap;
134 yOut << YAML::Key <<
"channels";
135 yOut << YAML::Value << YAML::BeginSeq;
137 std::set<Repository::IdType>
repos;
138 for (
const PoolItem & pi : pool ) {
139 if ( pi.status().isToBeInstalled()
140 && !(pi.status().isBySolver())) {
141 items_to_install.push_back( pi );
143 if ( pi.status().isKept()
144 && !(pi.status().isBySolver())) {
145 items_keep.push_back( pi );
147 if ( pi.status().isToBeUninstalled()
148 && !(pi.status().isBySolver())) {
149 items_to_remove.push_back( pi );
151 if ( pi.status().isLocked()
152 && !(pi.status().isBySolver())) {
153 items_locked.push_back( pi );
156 const auto &myRepo = pi.repository();
157 const auto &myRepoInfo = myRepo.info();
158 if (
repos.find( myRepo.id()) ==
repos.end() ) {
159 repos.insert( myRepo.id() );
160 yOut << YAML::Value << YAML::BeginMap;
161 yOut << YAML::Key <<
"alias" << YAML::Value << myRepo.alias();
162 yOut << YAML::Key <<
"url" << YAML::BeginSeq;
163 for (
auto itUrl = myRepoInfo.baseUrlsBegin(); itUrl != myRepoInfo.baseUrlsEnd(); ++itUrl ) {
164 yOut << YAML::Value << itUrl->asString();
166 yOut << YAML::EndSeq;
167 yOut << YAML::Key <<
"path" << YAML::Value << myRepoInfo.path().asString();
168 yOut << YAML::Key <<
"type" << YAML::Value << myRepoInfo.type().asString();
169 yOut << YAML::Key <<
"generated" << YAML::Value << myRepo.generatedTimestamp().form(
"%Y-%m-%d %H:%M:%S" );
170 yOut << YAML::Key <<
"outdated" << YAML::Value << myRepo.suggestedExpirationTimestamp().form(
"%Y-%m-%d %H:%M:%S" );
171 yOut << YAML::Key <<
"priority" << YAML::Value << myRepoInfo.priority();
172 yOut << YAML::Key <<
"file" << YAML::Value << str::Format(
"%1%.repo.gz") % repoFileNames[myRepo.id()->repoid];
174 yOut << YAML::EndMap;
179 yOut << YAML::EndSeq;
181 yOut << YAML::Key <<
"arch" << YAML::Value << ZConfig::instance().systemArchitecture().asString() ;
182 yOut << YAML::Key <<
"solverTestcase" << YAML::Value << slvTestcaseName ;
183 yOut << YAML::Key <<
"solverResult" << YAML::Value << slvResult ;
186 const LocaleSet & addedLocales( satpool.getAddedRequestedLocales() );
187 const LocaleSet & removedLocales( satpool.getRemovedRequestedLocales() );
188 const LocaleSet & requestedLocales( satpool.getRequestedLocales() );
190 yOut << YAML::Key <<
"locales" << YAML::Value << YAML::BeginSeq ;
191 for ( Locale l : requestedLocales ) {
192 yOut << YAML::Value << YAML::BeginMap;
193 yOut << YAML::Key <<
"fate" << YAML::Value << ( addedLocales.count(l) ?
"added" :
"" ) ;
194 yOut << YAML::Key <<
"name" << YAML::Value << l.asString() ;
195 yOut << YAML::EndMap;
198 for ( Locale l : removedLocales ) {
199 yOut << YAML::Value << YAML::BeginMap;
200 yOut << YAML::Key <<
"fate" << YAML::Value <<
"removed" ;
201 yOut << YAML::Key <<
"name" << YAML::Value << l.asString() ;
202 yOut << YAML::EndMap;
204 yOut << YAML::EndSeq;
207 const auto &writeListOrFile = [&](
const std::string &name,
const auto &list,
const auto &callback ) {
208 if ( list.size() > 10 ) {
209 const std::string fName = str::Format(
"zypp-%1%.yaml") % name;
210 yOut << YAML::Key << name << YAML::Value << fName;
212 YAML::Emitter yOutFile;
213 callback( yOutFile, list );
215 std::ofstream fout( dumpPath+
"/"+fName );
216 fout << yOutFile.c_str();
218 yOut << YAML::Key << name << YAML::Value ;
219 callback( yOut, list );
224 const auto &writeAutoInst = [] ( YAML::Emitter &out,
const auto &autoInstalledList ) {
225 out << YAML::BeginSeq;
227 out << YAML::Value << IdString(n).asString() ;
231 writeListOrFile(
"autoinst", satpool.autoInstalled(), writeAutoInst );
234 const auto &writeModalias = []( YAML::Emitter &out,
const auto &modAliasList ){
235 out << YAML::BeginSeq;
236 for (
const auto &modAlias : modAliasList ) {
237 out << YAML::Value << modAlias ;
241 writeListOrFile(
"modalias", target::Modalias::instance().modaliasList(), writeModalias );
244 const auto &writeMultiVersion = [] ( YAML::Emitter &out,
const auto &multiversionList ) {
245 out << YAML::BeginSeq;
246 for (
const auto &multiver : multiversionList ) {
247 out << YAML::Value << multiver ;
251 writeListOrFile(
"multiversion", ZConfig::instance().multiversionSpec(), writeMultiVersion );
254 yOut << YAML::Key <<
"resolverFlags" << YAML::Value << YAML::BeginMap;
255 yOut << YAML::Key <<
"focus" << YAML::Value <<
asString( resolver.focus() );
257 addTag(
"ignorealreadyrecommended", resolver.ignoreAlreadyRecommended() );
258 addTag(
"onlyRequires", resolver.onlyRequires() );
259 addTag(
"forceResolve", resolver.forceResolve() );
261 addTag(
"cleandepsOnRemove", resolver.cleandepsOnRemove() );
263 addTag(
"allowDowngrade", resolver.allowDowngrade() );
264 addTag(
"allowNameChange", resolver.allowNameChange() );
265 addTag(
"allowArchChange", resolver.allowArchChange() );
266 addTag(
"allowVendorChange", resolver.allowVendorChange() );
268 addTag(
"dupAllowDowngrade", resolver.dupAllowDowngrade() );
269 addTag(
"dupAllowNameChange", resolver.dupAllowNameChange() );
270 addTag(
"dupAllowArchChange", resolver.dupAllowArchChange() );
271 addTag(
"dupAllowVendorChange", resolver.dupAllowVendorChange() );
274 yOut << YAML::EndMap;
275 yOut << YAML::EndMap;
277 yOut << YAML::Key <<
"trials" << YAML::Value << YAML::BeginSeq;
279 yOut << YAML::Value << YAML::BeginMap << YAML::Key <<
"trial" << YAML::Value;
281 yOut << YAML::BeginSeq;
283 const auto &writeJobsToFile = [&](
const std::string &fName,
const auto &data,
const auto &cb ){
284 yOut << YAML::Value << YAML::BeginMap;
285 yOut << YAML::Key <<
"include" << YAML::Value << fName;
286 yOut << YAML::EndMap;
288 YAML::Emitter yOutFile;
289 yOutFile << YAML::BeginSeq;
290 cb( yOutFile, data );
291 yOutFile << YAML::EndSeq;
293 std::ofstream fout( dumpPath+
"/"+fName );
294 fout << yOutFile.c_str();
298 const auto &writePoolItemJobs = [](
const std::string &jobName ){
299 return [ &jobName ] ( YAML::Emitter &yOut,
const PoolItemList &poolItems,
bool shortInfo = false ) {
300 for (
const PoolItem & pi : poolItems ) {
301 yOut << YAML::Value << YAML::BeginMap;
303 std::stringstream status;
304 status << pi.status();
306 yOut << YAML::Key <<
"job" << YAML::Value << jobName
307 << YAML::Key <<
"kind" << YAML::Value << pi.kind().asString()
308 << YAML::Key <<
"name" << YAML::Value << pi.name()
309 << YAML::Key <<
"status" << YAML::Value << status.str();
311 yOut << YAML::Key <<
"channel" << YAML::Value << pi.repoInfo().alias()
312 << YAML::Key <<
"arch" << YAML::Value << pi.arch().asString()
313 << YAML::Key <<
"version" << YAML::Value << pi.edition().version()
314 << YAML::Key <<
"release" << YAML::Value << pi.edition().release();
316 yOut << YAML::EndMap;
321 const auto &writeMapJob = []( YAML::Emitter &yOut,
const std::string &name,
const std::map<std::string, std::string> &values = std::map<std::string, std::string>() ){
322 yOut << YAML::Value << YAML::BeginMap;
323 yOut << YAML::Key <<
"job" << YAML::Value << name;
324 for (
const auto &v : values )
325 yOut << YAML::Key << v.first << YAML::Value << v.second;
326 yOut << YAML::EndMap;
329 writePoolItemJobs(
"install")( yOut, items_to_install );
330 writePoolItemJobs(
"keep")( yOut, items_keep );
331 writePoolItemJobs(
"uninstall")( yOut, items_to_remove, true );
333 if ( items_locked.size() )
334 writeJobsToFile(
"zypp-locks.yaml", items_locked, writePoolItemJobs(
"lock") );
336 for (
const auto &v : resolver.extraRequires() )
337 writeMapJob( yOut,
"addRequire", { {
"name", v.asString() } } );
338 for (
const auto &v : SystemCheck::instance().requiredSystemCap() )
339 writeMapJob( yOut,
"addRequire", { {
"name", v.asString() } } );
341 for (
const auto &v : resolver.extraConflicts() )
342 writeMapJob( yOut,
"addConflict", { {
"name", v.asString() } } );
343 for (
const auto &v : SystemCheck::instance().conflictSystemCap() )
344 writeMapJob( yOut,
"addConflict", { {
"name", v.asString() } } );
346 for (
const auto &v : resolver.upgradeRepos() )
347 writeMapJob( yOut,
"upgradeRepo", { {
"name", v.alias() } } );
349 if ( resolver.isUpgradeMode() )
350 writeMapJob( yOut,
"distupgrade" );
352 if ( resolver.isUpdateMode() )
353 writeMapJob( yOut,
"update" );
355 if ( resolver.isVerifyingMode() )
356 writeMapJob( yOut,
"verify" );
358 yOut << YAML::EndSeq;
359 yOut << YAML::EndMap;
360 yOut << YAML::EndSeq;
361 yOut << YAML::EndMap;
362 yOut << YAML::EndMap;
364 std::ofstream fout( dumpPath+
"/zypp-control.yaml" );
365 fout << yOut.c_str();
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int IdType
Generic Id type.
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
int clean_dir(const Pathname &path)
Like 'rm -r DIR/ *'.
Exchange LineWriter for the lifetime of this object.
void logfile(const Pathname &logfile_r)
Set path for the logfile.
static LogControl instance()
Singleton access.
Turn on excessive logging for the lifetime of this object.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet