libzypp 17.25.7
TargetImpl.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <iostream>
13#include <fstream>
14#include <sstream>
15#include <string>
16#include <list>
17#include <set>
18
19#include <sys/types.h>
20#include <dirent.h>
21
22#include <zypp/base/LogTools.h>
23#include <zypp/base/Exception.h>
24#include <zypp/base/Iterator.h>
25#include <zypp/base/Gettext.h>
26#include <zypp/base/IOStream.h>
29#include <zypp/base/Json.h>
30
31#include <zypp/ZConfig.h>
32#include <zypp/ZYppFactory.h>
33#include <zypp/PathInfo.h>
34
35#include <zypp/PoolItem.h>
36#include <zypp/ResObjects.h>
37#include <zypp/Url.h>
38#include <zypp/TmpPath.h>
39#include <zypp/RepoStatus.h>
41#include <zypp/Repository.h>
42#include <zypp/ShutdownLock_p.h>
43
44#include <zypp/ResFilters.h>
45#include <zypp/HistoryLog.h>
51
54
55#include <zypp/sat/Pool.h>
59
60#include <zypp/PluginExecutor.h>
61
62using std::endl;
63
65extern "C"
66{
67#include <solv/repo_rpmdb.h>
68}
69namespace zypp
70{
71 namespace target
72 {
73 inline std::string rpmDbStateHash( const Pathname & root_r )
74 {
75 std::string ret;
76 AutoDispose<void*> state { ::rpm_state_create( sat::Pool::instance().get(), root_r.c_str() ), ::rpm_state_free };
77 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) -> void {
78 ::solv_chksum_free( chk, nullptr );
79 } };
80 if ( ::rpm_hash_database_state( state, chk ) == 0 )
81 {
82 int md5l;
83 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
84 ret = ::pool_bin2hex( sat::Pool::instance().get(), md5, md5l );
85 }
86 else
87 WAR << "rpm_hash_database_state failed" << endl;
88 return ret;
89 }
90
91 inline RepoStatus rpmDbRepoStatus( const Pathname & root_r )
92 { return RepoStatus( rpmDbStateHash( root_r ), Date() ); }
93
94 } // namespace target
95} // namespace
97
99namespace zypp
100{
102 namespace
103 {
104 // HACK for bnc#906096: let pool re-evaluate multiversion spec
105 // if target root changes. ZConfig returns data sensitive to
106 // current target root.
107 inline void sigMultiversionSpecChanged()
108 {
110 }
111 } //namespace
113
115 namespace json
116 {
117 // Lazy via template specialisation / should switch to overloading
118
119 template<>
120 inline std::string toJSON( const ZYppCommitResult::TransactionStepList & steps_r )
121 {
122 using sat::Transaction;
123 json::Array ret;
124
125 for ( const Transaction::Step & step : steps_r )
126 // ignore implicit deletes due to obsoletes and non-package actions
127 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
128 ret.add( step );
129
130 return ret.asJSON();
131 }
132
134 template<>
135 inline std::string toJSON( const sat::Transaction::Step & step_r )
136 {
137 static const std::string strType( "type" );
138 static const std::string strStage( "stage" );
139 static const std::string strSolvable( "solvable" );
140
141 static const std::string strTypeDel( "-" );
142 static const std::string strTypeIns( "+" );
143 static const std::string strTypeMul( "M" );
144
145 static const std::string strStageDone( "ok" );
146 static const std::string strStageFailed( "err" );
147
148 static const std::string strSolvableN( "n" );
149 static const std::string strSolvableE( "e" );
150 static const std::string strSolvableV( "v" );
151 static const std::string strSolvableR( "r" );
152 static const std::string strSolvableA( "a" );
153
154 using sat::Transaction;
155 json::Object ret;
156
157 switch ( step_r.stepType() )
158 {
159 case Transaction::TRANSACTION_IGNORE: /*empty*/ break;
160 case Transaction::TRANSACTION_ERASE: ret.add( strType, strTypeDel ); break;
161 case Transaction::TRANSACTION_INSTALL: ret.add( strType, strTypeIns ); break;
162 case Transaction::TRANSACTION_MULTIINSTALL: ret.add( strType, strTypeMul ); break;
163 }
164
165 switch ( step_r.stepStage() )
166 {
167 case Transaction::STEP_TODO: /*empty*/ break;
168 case Transaction::STEP_DONE: ret.add( strStage, strStageDone ); break;
169 case Transaction::STEP_ERROR: ret.add( strStage, strStageFailed ); break;
170 }
171
172 {
173 IdString ident;
174 Edition ed;
175 Arch arch;
176 if ( sat::Solvable solv = step_r.satSolvable() )
177 {
178 ident = solv.ident();
179 ed = solv.edition();
180 arch = solv.arch();
181 }
182 else
183 {
184 // deleted package; post mortem data stored in Transaction::Step
185 ident = step_r.ident();
186 ed = step_r.edition();
187 arch = step_r.arch();
188 }
189
190 json::Object s {
191 { strSolvableN, ident.asString() },
192 { strSolvableV, ed.version() },
193 { strSolvableR, ed.release() },
194 { strSolvableA, arch.asString() }
195 };
196 if ( Edition::epoch_t epoch = ed.epoch() )
197 s.add( strSolvableE, epoch );
198
199 ret.add( strSolvable, s );
200 }
201
202 return ret.asJSON();
203 }
204 } // namespace json
206
208 namespace target
209 {
211 namespace
212 {
213 SolvIdentFile::Data getUserInstalledFromHistory( const Pathname & historyFile_r )
214 {
215 SolvIdentFile::Data onSystemByUserList;
216 // go and parse it: 'who' must constain an '@', then it was installed by user request.
217 // 2009-09-29 07:25:19|install|lirc-remotes|0.8.5-3.2|x86_64|root@opensuse|InstallationImage|a204211eb0...
218 std::ifstream infile( historyFile_r.c_str() );
219 for( iostr::EachLine in( infile ); in; in.next() )
220 {
221 const char * ch( (*in).c_str() );
222 // start with year
223 if ( *ch < '1' || '9' < *ch )
224 continue;
225 const char * sep1 = ::strchr( ch, '|' ); // | after date
226 if ( !sep1 )
227 continue;
228 ++sep1;
229 // if logs an install or delete
230 bool installs = true;
231 if ( ::strncmp( sep1, "install|", 8 ) )
232 {
233 if ( ::strncmp( sep1, "remove |", 8 ) )
234 continue; // no install and no remove
235 else
236 installs = false; // remove
237 }
238 sep1 += 8; // | after what
239 // get the package name
240 const char * sep2 = ::strchr( sep1, '|' ); // | after name
241 if ( !sep2 || sep1 == sep2 )
242 continue;
243 (*in)[sep2-ch] = '\0';
244 IdString pkg( sep1 );
245 // we're done, if a delete
246 if ( !installs )
247 {
248 onSystemByUserList.erase( pkg );
249 continue;
250 }
251 // now guess whether user installed or not (3rd next field contains 'user@host')
252 if ( (sep1 = ::strchr( sep2+1, '|' )) // | after version
253 && (sep1 = ::strchr( sep1+1, '|' )) // | after arch
254 && (sep2 = ::strchr( sep1+1, '|' )) ) // | after who
255 {
256 (*in)[sep2-ch] = '\0';
257 if ( ::strchr( sep1+1, '@' ) )
258 {
259 // by user
260 onSystemByUserList.insert( pkg );
261 continue;
262 }
263 }
264 }
265 MIL << "onSystemByUserList found: " << onSystemByUserList.size() << endl;
266 return onSystemByUserList;
267 }
268 } // namespace
270
272 namespace
273 {
274 inline PluginFrame transactionPluginFrame( const std::string & command_r, ZYppCommitResult::TransactionStepList & steps_r )
275 {
276 return PluginFrame( command_r, json::Object {
277 { "TransactionStepList", steps_r }
278 }.asJSON() );
279 }
280 } // namespace
282
285 {
286 unsigned toKeep( ZConfig::instance().solver_upgradeTestcasesToKeep() );
287 MIL << "Testcases to keep: " << toKeep << endl;
288 if ( !toKeep )
289 return;
290 Target_Ptr target( getZYpp()->getTarget() );
291 if ( ! target )
292 {
293 WAR << "No Target no Testcase!" << endl;
294 return;
295 }
296
297 std::string stem( "updateTestcase" );
298 Pathname dir( target->assertRootPrefix("/var/log/") );
299 Pathname next( dir / Date::now().form( stem+"-%Y-%m-%d-%H-%M-%S" ) );
300
301 {
302 std::list<std::string> content;
303 filesystem::readdir( content, dir, /*dots*/false );
304 std::set<std::string> cases;
305 for_( c, content.begin(), content.end() )
306 {
307 if ( str::startsWith( *c, stem ) )
308 cases.insert( *c );
309 }
310 if ( cases.size() >= toKeep )
311 {
312 unsigned toDel = cases.size() - toKeep + 1; // +1 for the new one
313 for_( c, cases.begin(), cases.end() )
314 {
315 filesystem::recursive_rmdir( dir/(*c) );
316 if ( ! --toDel )
317 break;
318 }
319 }
320 }
321
322 MIL << "Write new testcase " << next << endl;
323 getZYpp()->resolver()->createSolverTestcase( next.asString(), false/*no solving*/ );
324 }
325
327 namespace
328 {
329
340 std::pair<bool,PatchScriptReport::Action> doExecuteScript( const Pathname & root_r,
341 const Pathname & script_r,
343 {
344 MIL << "Execute script " << PathInfo(Pathname::assertprefix( root_r,script_r)) << endl;
345
346 HistoryLog historylog;
347 historylog.comment(script_r.asString() + _(" executed"), /*timestamp*/true);
348 ExternalProgram prog( script_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
349
350 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
351 {
352 historylog.comment(output);
353 if ( ! report_r->progress( PatchScriptReport::OUTPUT, output ) )
354 {
355 WAR << "User request to abort script " << script_r << endl;
356 prog.kill();
357 // the rest is handled by exit code evaluation
358 // in case the script has meanwhile finished.
359 }
360 }
361
362 std::pair<bool,PatchScriptReport::Action> ret( std::make_pair( false, PatchScriptReport::ABORT ) );
363
364 if ( prog.close() != 0 )
365 {
366 ret.second = report_r->problem( prog.execError() );
367 WAR << "ACTION" << ret.second << "(" << prog.execError() << ")" << endl;
368 std::ostringstream sstr;
369 sstr << script_r << _(" execution failed") << " (" << prog.execError() << ")" << endl;
370 historylog.comment(sstr.str(), /*timestamp*/true);
371 return ret;
372 }
373
374 report_r->finish();
375 ret.first = true;
376 return ret;
377 }
378
382 bool executeScript( const Pathname & root_r,
383 const Pathname & script_r,
384 callback::SendReport<PatchScriptReport> & report_r )
385 {
386 std::pair<bool,PatchScriptReport::Action> action( std::make_pair( false, PatchScriptReport::ABORT ) );
387
388 do {
389 action = doExecuteScript( root_r, script_r, report_r );
390 if ( action.first )
391 return true; // success
392
393 switch ( action.second )
394 {
396 WAR << "User request to abort at script " << script_r << endl;
397 return false; // requested abort.
398 break;
399
401 WAR << "User request to skip script " << script_r << endl;
402 return true; // requested skip.
403 break;
404
406 break; // again
407 }
408 } while ( action.second == PatchScriptReport::RETRY );
409
410 // THIS is not intended to be reached:
411 INT << "Abort on unknown ACTION request " << action.second << " returned" << endl;
412 return false; // abort.
413 }
414
420 bool RunUpdateScripts( const Pathname & root_r,
421 const Pathname & scriptsPath_r,
422 const std::vector<sat::Solvable> & checkPackages_r,
423 bool aborting_r )
424 {
425 if ( checkPackages_r.empty() )
426 return true; // no installed packages to check
427
428 MIL << "Looking for new update scripts in (" << root_r << ")" << scriptsPath_r << endl;
429 Pathname scriptsDir( Pathname::assertprefix( root_r, scriptsPath_r ) );
430 if ( ! PathInfo( scriptsDir ).isDir() )
431 return true; // no script dir
432
433 std::list<std::string> scripts;
434 filesystem::readdir( scripts, scriptsDir, /*dots*/false );
435 if ( scripts.empty() )
436 return true; // no scripts in script dir
437
438 // Now collect and execute all matching scripts.
439 // On ABORT: at least log all outstanding scripts.
440 // - "name-version-release"
441 // - "name-version-release-*"
442 bool abort = false;
443 std::map<std::string, Pathname> unify; // scripts <md5,path>
444 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
445 {
446 std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) );
447 for_( sit, scripts.begin(), scripts.end() )
448 {
449 if ( ! str::hasPrefix( *sit, prefix ) )
450 continue;
451
452 if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' )
453 continue; // if not exact match it had to continue with '-'
454
455 PathInfo script( scriptsDir / *sit );
456 Pathname localPath( scriptsPath_r/(*sit) ); // without root prefix
457 std::string unifytag; // must not stay empty
458
459 if ( script.isFile() )
460 {
461 // Assert it's set executable, unify by md5sum.
462 filesystem::addmod( script.path(), 0500 );
463 unifytag = filesystem::md5sum( script.path() );
464 }
465 else if ( ! script.isExist() )
466 {
467 // Might be a dangling symlink, might be ok if we are in
468 // instsys (absolute symlink within the system below /mnt).
469 // readlink will tell....
470 unifytag = filesystem::readlink( script.path() ).asString();
471 }
472
473 if ( unifytag.empty() )
474 continue;
475
476 // Unify scripts
477 if ( unify[unifytag].empty() )
478 {
479 unify[unifytag] = localPath;
480 }
481 else
482 {
483 // translators: We may find the same script content in files with different names.
484 // Only the first occurence is executed, subsequent ones are skipped. It's a one-line
485 // message for a log file. Preferably start translation with "%s"
486 std::string msg( str::form(_("%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
487 MIL << "Skip update script: " << msg << endl;
488 HistoryLog().comment( msg, /*timestamp*/true );
489 continue;
490 }
491
492 if ( abort || aborting_r )
493 {
494 WAR << "Aborting: Skip update script " << *sit << endl;
495 HistoryLog().comment(
496 localPath.asString() + _(" execution skipped while aborting"),
497 /*timestamp*/true);
498 }
499 else
500 {
501 MIL << "Found update script " << *sit << endl;
502 callback::SendReport<PatchScriptReport> report;
503 report->start( make<Package>( *it ), script.path() );
504
505 if ( ! executeScript( root_r, localPath, report ) ) // script path without root prefix!
506 abort = true; // requested abort.
507 }
508 }
509 }
510 return !abort;
511 }
512
514 //
516
517 inline void copyTo( std::ostream & out_r, const Pathname & file_r )
518 {
519 std::ifstream infile( file_r.c_str() );
520 for( iostr::EachLine in( infile ); in; in.next() )
521 {
522 out_r << *in << endl;
523 }
524 }
525
526 inline std::string notificationCmdSubst( const std::string & cmd_r, const UpdateNotificationFile & notification_r )
527 {
528 std::string ret( cmd_r );
529#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
530 SUBST_IF( "%p", notification_r.solvable().asString() );
531 SUBST_IF( "%P", notification_r.file().asString() );
532#undef SUBST_IF
533 return ret;
534 }
535
536 void sendNotification( const Pathname & root_r,
537 const UpdateNotifications & notifications_r )
538 {
539 if ( notifications_r.empty() )
540 return;
541
542 std::string cmdspec( ZConfig::instance().updateMessagesNotify() );
543 MIL << "Notification command is '" << cmdspec << "'" << endl;
544 if ( cmdspec.empty() )
545 return;
546
547 std::string::size_type pos( cmdspec.find( '|' ) );
548 if ( pos == std::string::npos )
549 {
550 ERR << "Can't send Notification: Missing 'format |' in command spec." << endl;
551 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
552 return;
553 }
554
555 std::string formatStr( str::toLower( str::trim( cmdspec.substr( 0, pos ) ) ) );
556 std::string commandStr( str::trim( cmdspec.substr( pos + 1 ) ) );
557
558 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
559 Format format = UNKNOWN;
560 if ( formatStr == "none" )
561 format = NONE;
562 else if ( formatStr == "single" )
563 format = SINGLE;
564 else if ( formatStr == "digest" )
565 format = DIGEST;
566 else if ( formatStr == "bulk" )
567 format = BULK;
568 else
569 {
570 ERR << "Can't send Notification: Unknown format '" << formatStr << " |' in command spec." << endl;
571 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
572 return;
573 }
574
575 // Take care: commands are ececuted chroot(root_r). The message file
576 // pathnames in notifications_r are local to root_r. For physical access
577 // to the file they need to be prefixed.
578
579 if ( format == NONE || format == SINGLE )
580 {
581 for_( it, notifications_r.begin(), notifications_r.end() )
582 {
583 std::vector<std::string> command;
584 if ( format == SINGLE )
585 command.push_back( "<"+Pathname::assertprefix( root_r, it->file() ).asString() );
586 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
587
588 ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
589 if ( true ) // Wait for feedback
590 {
591 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
592 {
593 DBG << line;
594 }
595 int ret = prog.close();
596 if ( ret != 0 )
597 {
598 ERR << "Notification command returned with error (" << ret << ")." << endl;
599 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
600 return;
601 }
602 }
603 }
604 }
605 else if ( format == DIGEST || format == BULK )
606 {
607 filesystem::TmpFile tmpfile;
608 std::ofstream out( tmpfile.path().c_str() );
609 for_( it, notifications_r.begin(), notifications_r.end() )
610 {
611 if ( format == DIGEST )
612 {
613 out << it->file() << endl;
614 }
615 else if ( format == BULK )
616 {
617 copyTo( out << '\f', Pathname::assertprefix( root_r, it->file() ) );
618 }
619 }
620
621 std::vector<std::string> command;
622 command.push_back( "<"+tmpfile.path().asString() ); // redirect input
623 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
624
625 ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
626 if ( true ) // Wait for feedback otherwise the TmpFile goes out of scope.
627 {
628 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
629 {
630 DBG << line;
631 }
632 int ret = prog.close();
633 if ( ret != 0 )
634 {
635 ERR << "Notification command returned with error (" << ret << ")." << endl;
636 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
637 return;
638 }
639 }
640 }
641 else
642 {
643 INT << "Can't send Notification: Missing handler for 'format |' in command spec." << endl;
644 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
645 return;
646 }
647 }
648
649
655 void RunUpdateMessages( const Pathname & root_r,
656 const Pathname & messagesPath_r,
657 const std::vector<sat::Solvable> & checkPackages_r,
658 ZYppCommitResult & result_r )
659 {
660 if ( checkPackages_r.empty() )
661 return; // no installed packages to check
662
663 MIL << "Looking for new update messages in (" << root_r << ")" << messagesPath_r << endl;
664 Pathname messagesDir( Pathname::assertprefix( root_r, messagesPath_r ) );
665 if ( ! PathInfo( messagesDir ).isDir() )
666 return; // no messages dir
667
668 std::list<std::string> messages;
669 filesystem::readdir( messages, messagesDir, /*dots*/false );
670 if ( messages.empty() )
671 return; // no messages in message dir
672
673 // Now collect all matching messages in result and send them
674 // - "name-version-release"
675 // - "name-version-release-*"
676 HistoryLog historylog;
677 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
678 {
679 std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) );
680 for_( sit, messages.begin(), messages.end() )
681 {
682 if ( ! str::hasPrefix( *sit, prefix ) )
683 continue;
684
685 if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' )
686 continue; // if not exact match it had to continue with '-'
687
688 PathInfo message( messagesDir / *sit );
689 if ( ! message.isFile() || message.size() == 0 )
690 continue;
691
692 MIL << "Found update message " << *sit << endl;
693 Pathname localPath( messagesPath_r/(*sit) ); // without root prefix
694 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
695 historylog.comment( str::Str() << _("New update message") << " " << localPath, /*timestamp*/true );
696 }
697 }
698 sendNotification( root_r, result_r.updateMessages() );
699 }
700
704 void logPatchStatusChanges( const sat::Transaction & transaction_r, TargetImpl & target_r )
705 {
707 if ( changedPseudoInstalled.empty() )
708 return;
709
710 if ( ! transaction_r.actionEmpty( ~sat::Transaction::STEP_DONE ) )
711 {
712 // Need to recompute the patch list if commit is incomplete!
713 // We remember the initially established status, then reload the
714 // Target to get the current patch status. Then compare.
715 WAR << "Need to recompute the patch status changes as commit is incomplete!" << endl;
716 ResPool::EstablishedStates establishedStates{ ResPool::instance().establishedStates() };
717 target_r.load();
718 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
719 }
720
721 HistoryLog historylog;
722 for ( const auto & el : changedPseudoInstalled )
723 historylog.patchStateChange( el.first, el.second );
724 }
725
727 } // namespace
729
730 void XRunUpdateMessages( const Pathname & root_r,
731 const Pathname & messagesPath_r,
732 const std::vector<sat::Solvable> & checkPackages_r,
733 ZYppCommitResult & result_r )
734 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
735
737
739
741 //
742 // METHOD NAME : TargetImpl::TargetImpl
743 // METHOD TYPE : Ctor
744 //
745 TargetImpl::TargetImpl( const Pathname & root_r, bool doRebuild_r )
746 : _root( root_r )
747 , _requestedLocalesFile( home() / "RequestedLocales" )
748 , _autoInstalledFile( home() / "AutoInstalled" )
749 , _hardLocksFile( Pathname::assertprefix( _root, ZConfig::instance().locksFile() ) )
750 , _vendorAttr( Pathname::assertprefix( _root, ZConfig::instance().vendorPath() ) )
751 {
752 _rpm.initDatabase( root_r, doRebuild_r );
753
755
757 sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged
758 MIL << "Initialized target on " << _root << endl;
759 }
760
764 static std::string generateRandomId()
765 {
766 std::ifstream uuidprovider( "/proc/sys/kernel/random/uuid" );
767 return iostr::getline( uuidprovider );
768 }
769
775 void updateFileContent( const Pathname &filename,
776 boost::function<bool ()> condition,
777 boost::function<std::string ()> value )
778 {
779 std::string val = value();
780 // if the value is empty, then just dont
781 // do anything, regardless of the condition
782 if ( val.empty() )
783 return;
784
785 if ( condition() )
786 {
787 MIL << "updating '" << filename << "' content." << endl;
788
789 // if the file does not exist we need to generate the uuid file
790
791 std::ofstream filestr;
792 // make sure the path exists
793 filesystem::assert_dir( filename.dirname() );
794 filestr.open( filename.c_str() );
795
796 if ( filestr.good() )
797 {
798 filestr << val;
799 filestr.close();
800 }
801 else
802 {
803 // FIXME, should we ignore the error?
804 ZYPP_THROW(Exception("Can't openfile '" + filename.asString() + "' for writing"));
805 }
806 }
807 }
808
810 static bool fileMissing( const Pathname &pathname )
811 {
812 return ! PathInfo(pathname).isExist();
813 }
814
816 {
817 // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine)
818 if ( root() != "/" )
819 return;
820
821 // Create the anonymous unique id, used for download statistics
822 Pathname idpath( home() / "AnonymousUniqueId");
823
824 try
825 {
826 updateFileContent( idpath,
827 boost::bind(fileMissing, idpath),
829 }
830 catch ( const Exception &e )
831 {
832 WAR << "Can't create anonymous id file" << endl;
833 }
834
835 }
836
838 {
839 // create the anonymous unique id
840 // this value is used for statistics
841 Pathname flavorpath( home() / "LastDistributionFlavor");
842
843 // is there a product
845 if ( ! p )
846 {
847 WAR << "No base product, I won't create flavor cache" << endl;
848 return;
849 }
850
851 std::string flavor = p->flavor();
852
853 try
854 {
855
856 updateFileContent( flavorpath,
857 // only if flavor is not empty
858 functor::Constant<bool>( ! flavor.empty() ),
860 }
861 catch ( const Exception &e )
862 {
863 WAR << "Can't create flavor cache" << endl;
864 return;
865 }
866 }
867
869 //
870 // METHOD NAME : TargetImpl::~TargetImpl
871 // METHOD TYPE : Dtor
872 //
874 {
876 sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged
877 MIL << "Targets closed" << endl;
878 }
879
881 //
882 // solv file handling
883 //
885
887 {
888 return Pathname::assertprefix( _root, ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
889 }
890
892 {
893 Pathname base = solvfilesPath();
895 }
896
898 {
899 Pathname base = solvfilesPath();
900 Pathname rpmsolv = base/"solv";
901 Pathname rpmsolvcookie = base/"cookie";
902
903 bool build_rpm_solv = true;
904 // lets see if the rpm solv cache exists
905
906 RepoStatus rpmstatus( rpmDbRepoStatus(_root) && RepoStatus(_root/"etc/products.d") );
907
908 bool solvexisted = PathInfo(rpmsolv).isExist();
909 if ( solvexisted )
910 {
911 // see the status of the cache
912 PathInfo cookie( rpmsolvcookie );
913 MIL << "Read cookie: " << cookie << endl;
914 if ( cookie.isExist() )
915 {
916 RepoStatus status = RepoStatus::fromCookieFile(rpmsolvcookie);
917 // now compare it with the rpm database
918 if ( status == rpmstatus )
919 build_rpm_solv = false;
920 MIL << "Read cookie: " << rpmsolvcookie << " says: "
921 << (build_rpm_solv ? "outdated" : "uptodate") << endl;
922 }
923 }
924
925 if ( build_rpm_solv )
926 {
927 // if the solvfile dir does not exist yet, we better create it
929
930 Pathname oldSolvFile( solvexisted ? rpmsolv : Pathname() ); // to speedup rpmdb2solv
931
933 if ( !tmpsolv )
934 {
935 // Can't create temporary solv file, usually due to insufficient permission
936 // (user query while @System solv needs refresh). If so, try switching
937 // to a location within zypps temp. space (will be cleaned at application end).
938
939 bool switchingToTmpSolvfile = false;
940 Exception ex("Failed to cache rpm database.");
941 ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
942
943 if ( ! solvfilesPathIsTemp() )
944 {
945 base = getZYpp()->tmpPath() / sat::Pool::instance().systemRepoAlias();
946 rpmsolv = base/"solv";
947 rpmsolvcookie = base/"cookie";
948
950 tmpsolv = filesystem::TmpFile::makeSibling( rpmsolv );
951
952 if ( tmpsolv )
953 {
954 WAR << "Using a temporary solv file at " << base << endl;
955 switchingToTmpSolvfile = true;
956 _tmpSolvfilesPath = base;
957 }
958 else
959 {
960 ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
961 }
962 }
963
964 if ( ! switchingToTmpSolvfile )
965 {
966 ZYPP_THROW(ex);
967 }
968 }
969
970 // Take care we unlink the solvfile on exception
972
974 cmd.push_back( "rpmdb2solv" );
975 if ( ! _root.empty() ) {
976 cmd.push_back( "-r" );
977 cmd.push_back( _root.asString() );
978 }
979 cmd.push_back( "-D" );
980 cmd.push_back( rpm().dbPath().asString() );
981 cmd.push_back( "-X" ); // autogenerate pattern/product/... from -package
982 // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages
983 cmd.push_back( "-p" );
984 cmd.push_back( Pathname::assertprefix( _root, "/etc/products.d" ).asString() );
985
986 if ( ! oldSolvFile.empty() )
987 cmd.push_back( oldSolvFile.asString() );
988
989 cmd.push_back( "-o" );
990 cmd.push_back( tmpsolv.path().asString() );
991
993 std::string errdetail;
994
995 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
996 WAR << " " << output;
997 if ( errdetail.empty() ) {
998 errdetail = prog.command();
999 errdetail += '\n';
1000 }
1001 errdetail += output;
1002 }
1003
1004 int ret = prog.close();
1005 if ( ret != 0 )
1006 {
1007 Exception ex(str::form("Failed to cache rpm database (%d).", ret));
1008 ex.remember( errdetail );
1009 ZYPP_THROW(ex);
1010 }
1011
1012 ret = filesystem::rename( tmpsolv, rpmsolv );
1013 if ( ret != 0 )
1014 ZYPP_THROW(Exception("Failed to move cache to final destination"));
1015 // if this fails, don't bother throwing exceptions
1016 filesystem::chmod( rpmsolv, 0644 );
1017
1018 rpmstatus.saveToCookieFile(rpmsolvcookie);
1019
1020 // We keep it.
1021 guard.resetDispose();
1022 sat::updateSolvFileIndex( rpmsolv ); // content digest for zypper bash completion
1023
1024 // system-hook: Finally send notification to plugins
1025 if ( root() == "/" )
1026 {
1027 PluginExecutor plugins;
1028 plugins.load( ZConfig::instance().pluginsPath()/"system" );
1029 if ( plugins )
1030 plugins.send( PluginFrame( "PACKAGESETCHANGED" ) );
1031 }
1032 }
1033 else
1034 {
1035 // On the fly add missing solv.idx files for bash completion.
1036 if ( ! PathInfo(base/"solv.idx").isExist() )
1037 sat::updateSolvFileIndex( rpmsolv );
1038 }
1039 return build_rpm_solv;
1040 }
1041
1043 {
1044 load( false );
1045 }
1046
1048 {
1049 Repository system( sat::Pool::instance().findSystemRepo() );
1050 if ( system )
1051 system.eraseFromPool();
1052 }
1053
1054 void TargetImpl::load( bool force )
1055 {
1056 bool newCache = buildCache();
1057 MIL << "New cache built: " << (newCache?"true":"false") <<
1058 ", force loading: " << (force?"true":"false") << endl;
1059
1060 // now add the repos to the pool
1061 sat::Pool satpool( sat::Pool::instance() );
1062 Pathname rpmsolv( solvfilesPath() / "solv" );
1063 MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoAlias() << ")" << endl;
1064
1065 // Providing an empty system repo, unload any old content
1066 Repository system( sat::Pool::instance().findSystemRepo() );
1067
1068 if ( system && ! system.solvablesEmpty() )
1069 {
1070 if ( newCache || force )
1071 {
1072 system.eraseFromPool(); // invalidates system
1073 }
1074 else
1075 {
1076 return; // nothing to do
1077 }
1078 }
1079
1080 if ( ! system )
1081 {
1082 system = satpool.systemRepo();
1083 }
1084
1085 try
1086 {
1087 MIL << "adding " << rpmsolv << " to system" << endl;
1088 system.addSolv( rpmsolv );
1089 }
1090 catch ( const Exception & exp )
1091 {
1092 ZYPP_CAUGHT( exp );
1093 MIL << "Try to handle exception by rebuilding the solv-file" << endl;
1094 clearCache();
1095 buildCache();
1096
1097 system.addSolv( rpmsolv );
1098 }
1099 satpool.rootDir( _root );
1100
1101 // (Re)Load the requested locales et al.
1102 // If the requested locales are empty, we leave the pool untouched
1103 // to avoid undoing changes the application applied. We expect this
1104 // to happen on a bare metal installation only. An already existing
1105 // target should be loaded before its settings are changed.
1106 {
1108 if ( ! requestedLocales.empty() )
1109 {
1111 }
1112 }
1113 {
1114 if ( ! PathInfo( _autoInstalledFile.file() ).isExist() )
1115 {
1116 // Initialize from history, if it does not exist
1117 Pathname historyFile( Pathname::assertprefix( _root, ZConfig::instance().historyLogFile() ) );
1118 if ( PathInfo( historyFile ).isExist() )
1119 {
1120 SolvIdentFile::Data onSystemByUser( getUserInstalledFromHistory( historyFile ) );
1121 SolvIdentFile::Data onSystemByAuto;
1122 for_( it, system.solvablesBegin(), system.solvablesEnd() )
1123 {
1124 IdString ident( (*it).ident() );
1125 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1126 onSystemByAuto.insert( ident );
1127 }
1128 _autoInstalledFile.setData( onSystemByAuto );
1129 }
1130 // on the fly removed any obsolete SoftLocks file
1131 filesystem::unlink( home() / "SoftLocks" );
1132 }
1133 // read from AutoInstalled file
1135 for ( const auto & idstr : _autoInstalledFile.data() )
1136 q.push( idstr.id() );
1137 satpool.setAutoInstalled( q );
1138 }
1139
1140 // Load the needreboot package specs
1141 {
1142 sat::SolvableSpec needrebootSpec;
1143 needrebootSpec.addProvides( Capability("installhint(reboot-needed)") );
1144
1145 Pathname needrebootFile { Pathname::assertprefix( root(), ZConfig::instance().needrebootFile() ) };
1146 if ( PathInfo( needrebootFile ).isFile() )
1147 needrebootSpec.parseFrom( needrebootFile );
1148
1149 Pathname needrebootDir { Pathname::assertprefix( root(), ZConfig::instance().needrebootPath() ) };
1150 if ( PathInfo( needrebootDir ).isDir() )
1151 {
1152 static const StrMatcher isRpmConfigBackup( "\\.rpm(new|save|orig)$", Match::REGEX );
1153
1155 [&]( const Pathname & dir_r, const char *const str_r )->bool
1156 {
1157 if ( ! isRpmConfigBackup( str_r ) )
1158 {
1159 Pathname needrebootFile { needrebootDir / str_r };
1160 if ( PathInfo( needrebootFile ).isFile() )
1161 needrebootSpec.parseFrom( needrebootFile );
1162 }
1163 return true;
1164 });
1165 }
1166 satpool.setNeedrebootSpec( std::move(needrebootSpec) );
1167 }
1168
1169 if ( ZConfig::instance().apply_locks_file() )
1170 {
1171 const HardLocksFile::Data & hardLocks( _hardLocksFile.data() );
1172 if ( ! hardLocks.empty() )
1173 {
1175 }
1176 }
1177
1178 // now that the target is loaded, we can cache the flavor
1180
1181 MIL << "Target loaded: " << system.solvablesSize() << " resolvables" << endl;
1182 }
1183
1185 //
1186 // COMMIT
1187 //
1190 {
1191 // ----------------------------------------------------------------- //
1192 ZYppCommitPolicy policy_r( policy_rX );
1193 bool explicitDryRun = policy_r.dryRun(); // explicit dry run will trigger a fileconflict check, implicit (download-only) not.
1194
1195 ShutdownLock lck("Zypp commit running.");
1196
1197 // Fake outstanding YCP fix: Honour restriction to media 1
1198 // at installation, but install all remaining packages if post-boot.
1199 if ( policy_r.restrictToMedia() > 1 )
1200 policy_r.allMedia();
1201
1202 if ( policy_r.downloadMode() == DownloadDefault ) {
1203 if ( root() == "/" )
1204 policy_r.downloadMode(DownloadInHeaps);
1205 else
1207 }
1208 // DownloadOnly implies dry-run.
1209 else if ( policy_r.downloadMode() == DownloadOnly )
1210 policy_r.dryRun( true );
1211 // ----------------------------------------------------------------- //
1212
1213 MIL << "TargetImpl::commit(<pool>, " << policy_r << ")" << endl;
1214
1216 // Compute transaction:
1218 ZYppCommitResult result( root() );
1219 result.rTransaction() = pool_r.resolver().getTransaction();
1220 result.rTransaction().order();
1221 // steps: this is our todo-list
1223 if ( policy_r.restrictToMedia() )
1224 {
1225 // Collect until the 1st package from an unwanted media occurs.
1226 // Further collection could violate install order.
1227 MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
1228 for_( it, result.transaction().begin(), result.transaction().end() )
1229 {
1230 if ( makeResObject( *it )->mediaNr() > 1 )
1231 break;
1232 steps.push_back( *it );
1233 }
1234 }
1235 else
1236 {
1237 result.rTransactionStepList().insert( steps.end(), result.transaction().begin(), result.transaction().end() );
1238 }
1239 MIL << "Todo: " << result << endl;
1240
1242 // Prepare execution of commit plugins:
1244 PluginExecutor commitPlugins;
1245 if ( root() == "/" && ! policy_r.dryRun() )
1246 {
1247 commitPlugins.load( ZConfig::instance().pluginsPath()/"commit" );
1248 }
1249 if ( commitPlugins )
1250 commitPlugins.send( transactionPluginFrame( "COMMITBEGIN", steps ) );
1251
1253 // Write out a testcase if we're in dist upgrade mode.
1255 if ( pool_r.resolver().upgradeMode() || pool_r.resolver().upgradingRepos() )
1256 {
1257 if ( ! policy_r.dryRun() )
1258 {
1260 }
1261 else
1262 {
1263 DBG << "dryRun: Not writing upgrade testcase." << endl;
1264 }
1265 }
1266
1268 // Store non-package data:
1270 if ( ! policy_r.dryRun() )
1271 {
1273 // requested locales
1275 // autoinstalled
1276 {
1277 SolvIdentFile::Data newdata;
1278 for ( sat::Queue::value_type id : result.rTransaction().autoInstalled() )
1279 newdata.insert( IdString(id) );
1280 _autoInstalledFile.setData( newdata );
1281 }
1282 // hard locks
1283 if ( ZConfig::instance().apply_locks_file() )
1284 {
1285 HardLocksFile::Data newdata;
1286 pool_r.getHardLockQueries( newdata );
1287 _hardLocksFile.setData( newdata );
1288 }
1289 }
1290 else
1291 {
1292 DBG << "dryRun: Not storing non-package data." << endl;
1293 }
1294
1296 // First collect and display all messages
1297 // associated with patches to be installed.
1299 if ( ! policy_r.dryRun() )
1300 {
1301 for_( it, steps.begin(), steps.end() )
1302 {
1303 if ( ! it->satSolvable().isKind<Patch>() )
1304 continue;
1305
1306 PoolItem pi( *it );
1307 if ( ! pi.status().isToBeInstalled() )
1308 continue;
1309
1310 Patch::constPtr patch( asKind<Patch>(pi.resolvable()) );
1311 if ( ! patch ||patch->message().empty() )
1312 continue;
1313
1314 MIL << "Show message for " << patch << endl;
1316 if ( ! report->show( patch ) )
1317 {
1318 WAR << "commit aborted by the user" << endl;
1320 }
1321 }
1322 }
1323 else
1324 {
1325 DBG << "dryRun: Not checking patch messages." << endl;
1326 }
1327
1329 // Remove/install packages.
1331 DBG << "commit log file is set to: " << HistoryLog::fname() << endl;
1332 if ( ! policy_r.dryRun() || policy_r.downloadMode() == DownloadOnly )
1333 {
1334 // Prepare the package cache. Pass all items requiring download.
1335 CommitPackageCache packageCache;
1336 packageCache.setCommitList( steps.begin(), steps.end() );
1337
1338 bool miss = false;
1339 if ( policy_r.downloadMode() != DownloadAsNeeded )
1340 {
1341 // Preload the cache. Until now this means pre-loading all packages.
1342 // Once DownloadInHeaps is fully implemented, this will change and
1343 // we may actually have more than one heap.
1344 for_( it, steps.begin(), steps.end() )
1345 {
1346 switch ( it->stepType() )
1347 {
1350 // proceed: only install actionas may require download.
1351 break;
1352
1353 default:
1354 // next: no download for or non-packages and delete actions.
1355 continue;
1356 break;
1357 }
1358
1359 PoolItem pi( *it );
1360 if ( pi->isKind<Package>() || pi->isKind<SrcPackage>() )
1361 {
1362 ManagedFile localfile;
1363 try
1364 {
1365 localfile = packageCache.get( pi );
1366 localfile.resetDispose(); // keep the package file in the cache
1367 }
1368 catch ( const AbortRequestException & exp )
1369 {
1370 it->stepStage( sat::Transaction::STEP_ERROR );
1371 miss = true;
1372 WAR << "commit cache preload aborted by the user" << endl;
1374 break;
1375 }
1376 catch ( const SkipRequestException & exp )
1377 {
1378 ZYPP_CAUGHT( exp );
1379 it->stepStage( sat::Transaction::STEP_ERROR );
1380 miss = true;
1381 WAR << "Skipping cache preload package " << pi->asKind<Package>() << " in commit" << endl;
1382 continue;
1383 }
1384 catch ( const Exception & exp )
1385 {
1386 // bnc #395704: missing catch causes abort.
1387 // TODO see if packageCache fails to handle errors correctly.
1388 ZYPP_CAUGHT( exp );
1389 it->stepStage( sat::Transaction::STEP_ERROR );
1390 miss = true;
1391 INT << "Unexpected Error: Skipping cache preload package " << pi->asKind<Package>() << " in commit" << endl;
1392 continue;
1393 }
1394 }
1395 }
1396 packageCache.preloaded( true ); // try to avoid duplicate infoInCache CBs in commit
1397 }
1398
1399 if ( miss )
1400 {
1401 ERR << "Some packages could not be provided. Aborting commit."<< endl;
1402 }
1403 else
1404 {
1405 if ( ! policy_r.dryRun() )
1406 {
1407 // if cache is preloaded, check for file conflicts
1408 commitFindFileConflicts( policy_r, result );
1409 commit( policy_r, packageCache, result );
1410 }
1411 else
1412 {
1413 DBG << "dryRun/downloadOnly: Not installing/deleting anything." << endl;
1414 if ( explicitDryRun ) {
1415 // if cache is preloaded, check for file conflicts
1416 commitFindFileConflicts( policy_r, result );
1417 }
1418 }
1419 }
1420 }
1421 else
1422 {
1423 DBG << "dryRun: Not downloading/installing/deleting anything." << endl;
1424 if ( explicitDryRun ) {
1425 // if cache is preloaded, check for file conflicts
1426 commitFindFileConflicts( policy_r, result );
1427 }
1428 }
1429
1430 {
1431 // NOTE: Removing rpm in a transaction, rpm removes the /var/lib/rpm compat symlink.
1432 // We re-create it, in case it was lost to prevent legacy tools from accidentally
1433 // assuming no database is present.
1434 if ( ! PathInfo(_root/"/var/lib/rpm",PathInfo::LSTAT).isExist()
1435 && PathInfo(_root/"/usr/lib/sysimage/rpm").isDir() ) {
1436 WAR << "(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1437 filesystem::assert_dir( _root/"/var/lib" );
1438 filesystem::symlink( "../../usr/lib/sysimage/rpm", _root/"/var/lib/rpm" );
1439 }
1440 }
1441
1443 // Send result to commit plugins:
1445 if ( commitPlugins )
1446 commitPlugins.send( transactionPluginFrame( "COMMITEND", steps ) );
1447
1449 // Try to rebuild solv file while rpm database is still in cache
1451 if ( ! policy_r.dryRun() )
1452 {
1453 buildCache();
1454 }
1455
1456 MIL << "TargetImpl::commit(<pool>, " << policy_r << ") returns: " << result << endl;
1457 return result;
1458 }
1459
1461 //
1462 // COMMIT internal
1463 //
1465 namespace
1466 {
1467 struct NotifyAttemptToModify
1468 {
1469 NotifyAttemptToModify( ZYppCommitResult & result_r ) : _result( result_r ) {}
1470
1471 void operator()()
1472 { if ( _guard ) { _result.attemptToModify( true ); _guard = false; } }
1473
1474 TrueBool _guard;
1475 ZYppCommitResult & _result;
1476 };
1477 } // namespace
1478
1479 void TargetImpl::commit( const ZYppCommitPolicy & policy_r,
1480 CommitPackageCache & packageCache_r,
1481 ZYppCommitResult & result_r )
1482 {
1483 // steps: this is our todo-list
1485 MIL << "TargetImpl::commit(<list>" << policy_r << ")" << steps.size() << endl;
1486
1488
1489 // Send notification once upon 1st call to rpm
1490 NotifyAttemptToModify attemptToModify( result_r );
1491
1492 bool abort = false;
1493
1494 RpmPostTransCollector postTransCollector( _root );
1495 std::vector<sat::Solvable> successfullyInstalledPackages;
1496 TargetImpl::PoolItemList remaining;
1497
1498 for_( step, steps.begin(), steps.end() )
1499 {
1500 PoolItem citem( *step );
1501 if ( step->stepType() == sat::Transaction::TRANSACTION_IGNORE )
1502 {
1503 if ( citem->isKind<Package>() )
1504 {
1505 // for packages this means being obsoleted (by rpm)
1506 // thius no additional action is needed.
1507 step->stepStage( sat::Transaction::STEP_DONE );
1508 continue;
1509 }
1510 }
1511
1512 if ( citem->isKind<Package>() )
1513 {
1514 Package::constPtr p = citem->asKind<Package>();
1515 if ( citem.status().isToBeInstalled() )
1516 {
1517 ManagedFile localfile;
1518 try
1519 {
1520 localfile = packageCache_r.get( citem );
1521 }
1522 catch ( const AbortRequestException &e )
1523 {
1524 WAR << "commit aborted by the user" << endl;
1525 abort = true;
1526 step->stepStage( sat::Transaction::STEP_ERROR );
1527 break;
1528 }
1529 catch ( const SkipRequestException &e )
1530 {
1531 ZYPP_CAUGHT( e );
1532 WAR << "Skipping package " << p << " in commit" << endl;
1533 step->stepStage( sat::Transaction::STEP_ERROR );
1534 continue;
1535 }
1536 catch ( const Exception &e )
1537 {
1538 // bnc #395704: missing catch causes abort.
1539 // TODO see if packageCache fails to handle errors correctly.
1540 ZYPP_CAUGHT( e );
1541 INT << "Unexpected Error: Skipping package " << p << " in commit" << endl;
1542 step->stepStage( sat::Transaction::STEP_ERROR );
1543 continue;
1544 }
1545
1546 // create a installation progress report proxy
1547 RpmInstallPackageReceiver progress( citem.resolvable() );
1548 progress.connect(); // disconnected on destruction.
1549
1550 bool success = false;
1551 rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB );
1552 // Why force and nodeps?
1553 //
1554 // Because zypp builds the transaction and the resolver asserts that
1555 // everything is fine.
1556 // We use rpm just to unpack and register the package in the database.
1557 // We do this step by step, so rpm is not aware of the bigger context.
1558 // So we turn off rpms internal checks, because we do it inside zypp.
1559 flags |= rpm::RPMINST_NODEPS;
1560 flags |= rpm::RPMINST_FORCE;
1561 //
1562 if (p->multiversionInstall()) flags |= rpm::RPMINST_NOUPGRADE;
1563 if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST;
1564 if (policy_r.rpmExcludeDocs()) flags |= rpm::RPMINST_EXCLUDEDOCS;
1565 if (policy_r.rpmNoSignature()) flags |= rpm::RPMINST_NOSIGNATURE;
1566
1567 attemptToModify();
1568 try
1569 {
1571 if ( postTransCollector.collectScriptFromPackage( localfile ) )
1572 flags |= rpm::RPMINST_NOPOSTTRANS;
1573 rpm().installPackage( localfile, flags );
1574 HistoryLog().install(citem);
1575
1576 if ( progress.aborted() )
1577 {
1578 WAR << "commit aborted by the user" << endl;
1579 localfile.resetDispose(); // keep the package file in the cache
1580 abort = true;
1581 step->stepStage( sat::Transaction::STEP_ERROR );
1582 break;
1583 }
1584 else
1585 {
1586 if ( citem.isNeedreboot() ) {
1587 auto rebootNeededFile = root() / "/run/reboot-needed";
1588 if ( filesystem::assert_file( rebootNeededFile ) == EEXIST)
1589 filesystem::touch( rebootNeededFile );
1590 }
1591
1592 success = true;
1593 step->stepStage( sat::Transaction::STEP_DONE );
1594 }
1595 }
1596 catch ( Exception & excpt_r )
1597 {
1598 ZYPP_CAUGHT(excpt_r);
1599 localfile.resetDispose(); // keep the package file in the cache
1600
1601 if ( policy_r.dryRun() )
1602 {
1603 WAR << "dry run failed" << endl;
1604 step->stepStage( sat::Transaction::STEP_ERROR );
1605 break;
1606 }
1607 // else
1608 if ( progress.aborted() )
1609 {
1610 WAR << "commit aborted by the user" << endl;
1611 abort = true;
1612 }
1613 else
1614 {
1615 WAR << "Install failed" << endl;
1616 }
1617 step->stepStage( sat::Transaction::STEP_ERROR );
1618 break; // stop
1619 }
1620
1621 if ( success && !policy_r.dryRun() )
1622 {
1624 successfullyInstalledPackages.push_back( citem.satSolvable() );
1625 step->stepStage( sat::Transaction::STEP_DONE );
1626 }
1627 }
1628 else
1629 {
1630 RpmRemovePackageReceiver progress( citem.resolvable() );
1631 progress.connect(); // disconnected on destruction.
1632
1633 bool success = false;
1634 rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB );
1635 flags |= rpm::RPMINST_NODEPS;
1636 if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST;
1637
1638 attemptToModify();
1639 try
1640 {
1641 rpm().removePackage( p, flags );
1642 HistoryLog().remove(citem);
1643
1644 if ( progress.aborted() )
1645 {
1646 WAR << "commit aborted by the user" << endl;
1647 abort = true;
1648 step->stepStage( sat::Transaction::STEP_ERROR );
1649 break;
1650 }
1651 else
1652 {
1653 success = true;
1654 step->stepStage( sat::Transaction::STEP_DONE );
1655 }
1656 }
1657 catch (Exception & excpt_r)
1658 {
1659 ZYPP_CAUGHT( excpt_r );
1660 if ( progress.aborted() )
1661 {
1662 WAR << "commit aborted by the user" << endl;
1663 abort = true;
1664 step->stepStage( sat::Transaction::STEP_ERROR );
1665 break;
1666 }
1667 // else
1668 WAR << "removal of " << p << " failed";
1669 step->stepStage( sat::Transaction::STEP_ERROR );
1670 }
1671 if ( success && !policy_r.dryRun() )
1672 {
1674 step->stepStage( sat::Transaction::STEP_DONE );
1675 }
1676 }
1677 }
1678 else if ( ! policy_r.dryRun() ) // other resolvables (non-Package)
1679 {
1680 // Status is changed as the buddy package buddy
1681 // gets installed/deleted. Handle non-buddies only.
1682 if ( ! citem.buddy() )
1683 {
1684 if ( citem->isKind<Product>() )
1685 {
1686 Product::constPtr p = citem->asKind<Product>();
1687 if ( citem.status().isToBeInstalled() )
1688 {
1689 ERR << "Can't install orphan product without release-package! " << citem << endl;
1690 }
1691 else
1692 {
1693 // Deleting the corresponding product entry is all we con do.
1694 // So the product will no longer be visible as installed.
1695 std::string referenceFilename( p->referenceFilename() );
1696 if ( referenceFilename.empty() )
1697 {
1698 ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1699 }
1700 else
1701 {
1702 Pathname referencePath { Pathname("/etc/products.d") / referenceFilename }; // no root prefix for rpmdb lookup!
1703 if ( ! rpm().hasFile( referencePath.asString() ) )
1704 {
1705 // If it's not owned by a package, we can delete it.
1706 referencePath = Pathname::assertprefix( _root, referencePath ); // now add a root prefix
1707 if ( filesystem::unlink( referencePath ) != 0 )
1708 ERR << "Delete orphan product failed: " << referencePath << endl;
1709 }
1710 else
1711 {
1712 WAR << "Won't remove orphan product: '/etc/products.d/" << referenceFilename << "' is owned by a package." << endl;
1713 }
1714 }
1715 }
1716 }
1717 else if ( citem->isKind<SrcPackage>() && citem.status().isToBeInstalled() )
1718 {
1719 // SrcPackage is install-only
1720 SrcPackage::constPtr p = citem->asKind<SrcPackage>();
1721 installSrcPackage( p );
1722 }
1723
1725 step->stepStage( sat::Transaction::STEP_DONE );
1726 }
1727
1728 } // other resolvables
1729
1730 } // for
1731
1732 // process all remembered posttrans scripts. If aborting,
1733 // at least log omitted scripts.
1734 if ( abort || (abort = !postTransCollector.executeScripts()) )
1735 postTransCollector.discardScripts();
1736
1737 // Check presence of update scripts/messages. If aborting,
1738 // at least log omitted scripts.
1739 if ( ! successfullyInstalledPackages.empty() )
1740 {
1741 if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(),
1742 successfullyInstalledPackages, abort ) )
1743 {
1744 WAR << "Commit aborted by the user" << endl;
1745 abort = true;
1746 }
1747 // send messages after scripts in case some script generates output,
1748 // that should be kept in t %ghost message file.
1749 RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(),
1750 successfullyInstalledPackages,
1751 result_r );
1752 }
1753
1754 // jsc#SLE-5116: Log patch status changes to history
1755 // NOTE: Should be the last action as it may need to reload
1756 // the Target in case of an incomplete transaction.
1757 logPatchStatusChanges( result_r.transaction(), *this );
1758
1759 if ( abort )
1760 {
1761 HistoryLog().comment( "Commit was aborted." );
1763 }
1764 }
1765
1767
1769 {
1770 return _rpm;
1771 }
1772
1773 bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
1774 {
1775 return _rpm.hasFile(path_str, name_str);
1776 }
1777
1779 namespace
1780 {
1781 parser::ProductFileData baseproductdata( const Pathname & root_r )
1782 {
1784 PathInfo baseproduct( Pathname::assertprefix( root_r, "/etc/products.d/baseproduct" ) );
1785
1786 if ( baseproduct.isFile() )
1787 {
1788 try
1789 {
1790 ret = parser::ProductFileReader::scanFile( baseproduct.path() );
1791 }
1792 catch ( const Exception & excpt )
1793 {
1794 ZYPP_CAUGHT( excpt );
1795 }
1796 }
1797 else if ( PathInfo( Pathname::assertprefix( root_r, "/etc/products.d" ) ).isDir() )
1798 {
1799 ERR << "baseproduct symlink is dangling or missing: " << baseproduct << endl;
1800 }
1801 return ret;
1802 }
1803
1804 inline Pathname staticGuessRoot( const Pathname & root_r )
1805 {
1806 if ( root_r.empty() )
1807 {
1808 // empty root: use existing Target or assume "/"
1809 Pathname ret ( ZConfig::instance().systemRoot() );
1810 if ( ret.empty() )
1811 return Pathname("/");
1812 return ret;
1813 }
1814 return root_r;
1815 }
1816
1817 inline std::string firstNonEmptyLineIn( const Pathname & file_r )
1818 {
1819 std::ifstream idfile( file_r.c_str() );
1820 for( iostr::EachLine in( idfile ); in; in.next() )
1821 {
1822 std::string line( str::trim( *in ) );
1823 if ( ! line.empty() )
1824 return line;
1825 }
1826 return std::string();
1827 }
1828 } // namespace
1830
1832 {
1833 ResPool pool(ResPool::instance());
1834 for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() )
1835 {
1836 Product::constPtr p = (*it)->asKind<Product>();
1837 if ( p->isTargetDistribution() )
1838 return p;
1839 }
1840 return nullptr;
1841 }
1842
1844 {
1845 const Pathname needroot( staticGuessRoot(root_r) );
1846 const Target_constPtr target( getZYpp()->getTarget() );
1847 if ( target && target->root() == needroot )
1848 return target->requestedLocales();
1849 return RequestedLocalesFile( home(needroot) / "RequestedLocales" ).locales();
1850 }
1851
1853 {
1854 MIL << "updateAutoInstalled if changed..." << endl;
1855 SolvIdentFile::Data newdata;
1856 for ( auto id : sat::Pool::instance().autoInstalled() )
1857 newdata.insert( IdString(id) ); // explicit ctor!
1858 _autoInstalledFile.setData( std::move(newdata) );
1859 }
1860
1862 { return baseproductdata( _root ).registerTarget(); }
1863 // static version:
1864 std::string TargetImpl::targetDistribution( const Pathname & root_r )
1865 { return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
1866
1868 { return baseproductdata( _root ).registerRelease(); }
1869 // static version:
1871 { return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
1872
1874 { return baseproductdata( _root ).registerFlavor(); }
1875 // static version:
1877 { return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
1878
1880 {
1882 parser::ProductFileData pdata( baseproductdata( _root ) );
1883 ret.shortName = pdata.shortName();
1884 ret.summary = pdata.summary();
1885 return ret;
1886 }
1887 // static version:
1889 {
1891 parser::ProductFileData pdata( baseproductdata( staticGuessRoot(root_r) ) );
1892 ret.shortName = pdata.shortName();
1893 ret.summary = pdata.summary();
1894 return ret;
1895 }
1896
1898 {
1899 if ( _distributionVersion.empty() )
1900 {
1902 if ( !_distributionVersion.empty() )
1903 MIL << "Remember distributionVersion = '" << _distributionVersion << "'" << endl;
1904 }
1905 return _distributionVersion;
1906 }
1907 // static version
1908 std::string TargetImpl::distributionVersion( const Pathname & root_r )
1909 {
1910 std::string distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
1911 if ( distributionVersion.empty() )
1912 {
1913 // ...But the baseproduct method is not expected to work on RedHat derivatives.
1914 // On RHEL, Fedora and others the "product version" is determined by the first package
1915 // providing 'system-release'. This value is not hardcoded in YUM and can be configured
1916 // with the $distroverpkg variable.
1917 scoped_ptr<rpm::RpmDb> tmprpmdb;
1918 if ( ZConfig::instance().systemRoot() == Pathname() )
1919 {
1920 try
1921 {
1922 tmprpmdb.reset( new rpm::RpmDb );
1923 tmprpmdb->initDatabase( /*default ctor uses / but no additional keyring exports */ );
1924 }
1925 catch( ... )
1926 {
1927 return "";
1928 }
1929 }
1932 distributionVersion = it->tag_version();
1933 }
1934 return distributionVersion;
1935 }
1936
1937
1939 {
1940 return firstNonEmptyLineIn( home() / "LastDistributionFlavor" );
1941 }
1942 // static version:
1943 std::string TargetImpl::distributionFlavor( const Pathname & root_r )
1944 {
1945 return firstNonEmptyLineIn( staticGuessRoot(root_r) / "/var/lib/zypp/LastDistributionFlavor" );
1946 }
1947
1949 namespace
1950 {
1951 std::string guessAnonymousUniqueId( const Pathname & root_r )
1952 {
1953 // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine)
1954 std::string ret( firstNonEmptyLineIn( root_r / "/var/lib/zypp/AnonymousUniqueId" ) );
1955 if ( ret.empty() && root_r != "/" )
1956 {
1957 // if it has nonoe, use the outer systems one
1958 ret = firstNonEmptyLineIn( "/var/lib/zypp/AnonymousUniqueId" );
1959 }
1960 return ret;
1961 }
1962 }
1963
1965 {
1966 return guessAnonymousUniqueId( root() );
1967 }
1968 // static version:
1969 std::string TargetImpl::anonymousUniqueId( const Pathname & root_r )
1970 {
1971 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
1972 }
1973
1975
1977 {
1978 MIL << "New VendorAttr: " << vendorAttr_r << endl;
1979 _vendorAttr = std::move(vendorAttr_r);
1980 }
1982
1983 void TargetImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r )
1984 {
1985 // provide on local disk
1986 ManagedFile localfile = provideSrcPackage(srcPackage_r);
1987 // create a installation progress report proxy
1988 RpmInstallPackageReceiver progress( srcPackage_r );
1989 progress.connect(); // disconnected on destruction.
1990 // install it
1991 rpm().installPackage ( localfile );
1992 }
1993
1994 ManagedFile TargetImpl::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r )
1995 {
1996 // provide on local disk
1997 repo::RepoMediaAccess access_r;
1998 repo::SrcPackageProvider prov( access_r );
1999 return prov.provideSrcPackage( srcPackage_r );
2000 }
2002 } // namespace target
2005} // namespace zypp
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:396
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Interface to gettext.
#define _(MSG)
Definition: Gettext.h:37
#define DBG
Definition: Logger.h:78
#define MIL
Definition: Logger.h:79
#define ERR
Definition: Logger.h:81
#define WAR
Definition: Logger.h:80
#define INT
Definition: Logger.h:83
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:70
#define idstr(V)
const Pathname & _root
Definition: RepoManager.cc:143
#define SUBST_IF(PAT, VAL)
ZYppCommitResult & _result
Definition: TargetImpl.cc:1475
TrueBool _guard
Definition: TargetImpl.cc:1474
Architecture.
Definition: Arch.h:37
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Arch.cc:485
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:162
A sat capability.
Definition: Capability.h:60
Store and operate on date (time_t).
Definition: Date.h:33
static Date now()
Return the current time.
Definition: Date.h:78
Edition represents [epoch:]version[-release]
Definition: Edition.h:61
unsigned epoch_t
Type of an epoch.
Definition: Edition.h:64
std::string version() const
Version.
Definition: Edition.cc:94
std::string release() const
Release.
Definition: Edition.cc:110
epoch_t epoch() const
Epoch.
Definition: Edition.cc:82
Base class for Exception.
Definition: Exception.h:146
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:105
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
const std::string & command() const
The command we're executing.
std::vector< std::string > Arguments
int close()
Wait for the progamm to complete.
Writing the zypp history file.
Definition: HistoryLog.h:57
void stampCommand()
Log info about the current process.
Definition: HistoryLog.cc:220
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
Definition: HistoryLog.cc:163
void remove(const PoolItem &pi)
Log removal of a package.
Definition: HistoryLog.cc:260
static const Pathname & fname()
Get the current log file path.
Definition: HistoryLog.cc:179
void install(const PoolItem &pi)
Log installation (or update) of a package.
Definition: HistoryLog.cc:232
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Definition: HistoryLog.cc:188
Access to the sat-pools string space.
Definition: IdString.h:43
std::string asString() const
Conversion to std::string
Definition: IdString.h:98
@ REGEX
Regular Expression.
Definition: StrMatcher.h:48
Package interface.
Definition: Package.h:33
TraitsType::constPtrType constPtr
Definition: Package.h:38
Class representing a patch.
Definition: Patch.h:38
TraitsType::constPtrType constPtr
Definition: Patch.h:43
Parallel execution of stateful PluginScripts.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Command frame for communication with PluginScript.
Definition: PluginFrame.h:41
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:51
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
Definition: PoolItem.cc:218
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:204
sat::Solvable buddy() const
Return the buddy we share our status object with.
Definition: PoolItem.cc:206
Product interface.
Definition: Product.h:33
TraitsType::constPtrType constPtr
Definition: Product.h:38
Track changing files or directories.
Definition: RepoStatus.h:41
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
Definition: RepoStatus.cc:194
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
Definition: RepoStatus.cc:212
bool solvablesEmpty() const
Whether Repository contains solvables.
Definition: Repository.cc:219
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
Definition: Repository.cc:241
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
Definition: Repository.cc:231
size_type solvablesSize() const
Number of solvables in Repository.
Definition: Repository.cc:225
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
Definition: Repository.cc:320
void eraseFromPool()
Remove this Repository from it's Pool.
Definition: Repository.cc:297
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from the established one.
Definition: PoolImpl.cc:26
Global ResObject pool.
Definition: ResPool.h:61
static ResPool instance()
Singleton ctor.
Definition: ResPool.cc:37
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
Definition: ResPool.h:341
void setHardLockQueries(const HardLockQueries &newLocks_r)
Set a new set of queries.
Definition: ResPool.cc:103
Resolver & resolver() const
The Resolver.
Definition: ResPool.cc:61
const LocaleSet & getRequestedLocales() const
Return the requested locales.
Definition: ResPool.cc:130
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from their initial one.
Definition: ResPool.h:349
byKind_iterator byKindEnd(const ResKind &kind_r) const
Definition: ResPool.h:268
EstablishedStates establishedStates() const
Factory for EstablishedStates.
Definition: ResPool.cc:76
byKind_iterator byKindBegin(const ResKind &kind_r) const
Definition: ResPool.h:261
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
Definition: ResPool.cc:106
bool isToBeInstalled() const
Definition: ResStatus.h:253
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
Definition: ResStatus.h:485
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
Definition: Resolver.cc:74
bool upgradeMode() const
Definition: Resolver.cc:97
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
Definition: Resolver.cc:136
Attempts to create a lock to prevent the system from going into hibernate/shutdown.
SrcPackage interface.
Definition: SrcPackage.h:30
TraitsType::constPtrType constPtr
Definition: SrcPackage.h:36
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition: StrMatcher.h:298
Definition of vendor equivalence.
Definition: VendorAttr.h:61
Interim helper class to collect global options and settings.
Definition: ZConfig.h:60
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
std::string distroverpkg() const
Package telling the "product version" on systems not using /etc/product.d/baseproduct.
Definition: ZConfig.cc:1176
Options and policies for ZYpp::commit.
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
ZYppCommitPolicy & rpmExcludeDocs(bool yesNo_r)
Use rpm option –excludedocs (default: false)
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
ZYppCommitPolicy & allMedia()
Process all media (default)
ZYppCommitPolicy & rpmNoSignature(bool yesNo_r)
Use rpm option –nosignature (default: false)
Result returned from ZYpp::commit.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
std::vector< sat::Transaction::Step > TransactionStepList
const sat::Transaction & transaction() const
The full transaction list.
sat::Transaction & rTransaction()
Manipulate transaction.
std::string receiveLine()
Read one line from the input stream.
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
const char * c_str() const
String representation.
Definition: Pathname.h:110
const std::string & asString() const
String representation.
Definition: Pathname.h:91
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition: Pathname.cc:235
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:128
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:218
Pathname path() const
Definition: TmpPath.cc:146
Data returned by ProductFileReader.
bool empty() const
Whether this is an empty object without valid data.
static ProductFileData scanFile(const Pathname &file_r)
Parse one file (or symlink) and return the ProductFileData parsed.
Provides files from different repos.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r) const
Provide SrcPackage in a local file.
Global sat-pool.
Definition: Pool.h:47
void setAutoInstalled(const Queue &autoInstalled_r)
Set ident list of all autoinstalled solvables.
Definition: Pool.cc:265
Pathname rootDir() const
Get rootdir (for file conflicts check)
Definition: Pool.cc:64
static Pool instance()
Singleton ctor.
Definition: Pool.h:55
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition: Pool.cc:46
void setNeedrebootSpec(sat::SolvableSpec needrebootSpec_r)
Solvables which should trigger the reboot-needed hint if installed/updated.
Definition: Pool.cc:267
Repository systemRepo()
Return the system repository, create it if missing.
Definition: Pool.cc:178
void initRequestedLocales(const LocaleSet &locales_r)
Start tracking changes based on this locales_r.
Definition: Pool.cc:251
Libsolv Id queue wrapper.
Definition: Queue.h:35
detail::IdType value_type
Definition: Queue.h:38
void push(value_type val_r)
Push a value to the end off the Queue.
Definition: Queue.cc:103
Define a set of Solvables by ident and provides.
Definition: SolvableSpec.h:45
void addProvides(Capability provides_r)
A all sat::Solvable matching this provides_r.
void parseFrom(const InputStream &istr_r)
Parse file istr_r and add it's specs (one per line, #-comments).
A Solvable object within the sat Pool.
Definition: Solvable.h:54
A single step within a Transaction.
Definition: Transaction.h:219
StepType stepType() const
Type of action to perform in this step.
Definition: Transaction.cc:388
StepStage stepStage() const
Step action result.
Definition: Transaction.cc:391
Solvable satSolvable() const
Return the corresponding Solvable.
Definition: Transaction.h:243
Libsolv transaction wrapper.
Definition: Transaction.h:52
const_iterator end() const
Iterator behind the last TransactionStep.
Definition: Transaction.cc:343
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run.
Definition: Transaction.cc:358
const_iterator begin() const
Iterator to the first TransactionStep.
Definition: Transaction.cc:337
bool order()
Order transaction steps for commit.
Definition: Transaction.cc:328
@ TRANSACTION_MULTIINSTALL
[M] Install(multiversion) item (
Definition: Transaction.h:67
@ TRANSACTION_INSTALL
[+] Install(update) item
Definition: Transaction.h:66
@ TRANSACTION_IGNORE
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
Definition: Transaction.h:64
@ STEP_DONE
[OK] success
Definition: Transaction.h:74
@ STEP_ERROR
[**] error
Definition: Transaction.h:75
Target::commit helper optimizing package provision.
void setCommitList(std::vector< sat::Solvable > commitList_r)
Download(commit) sequence of solvables to compute read ahead.
bool preloaded() const
Whether preloaded hint is set.
ManagedFile get(const PoolItem &citem_r)
Provide a package.
void setData(const Data &data_r)
Store new Data.
Definition: HardLocksFile.h:73
const Data & data() const
Return the data.
Definition: HardLocksFile.h:57
pool::PoolTraits::HardLockQueries Data
Definition: HardLocksFile.h:41
Save and restore locale set from file.
const LocaleSet & locales() const
Return the loacale set.
void setLocales(const LocaleSet &locales_r)
Store a new locale set.
void tryLevel(target::rpm::InstallResolvableReport::RpmLevel level_r)
Extract and remember posttrans scripts for later execution.
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
bool executeScripts()
Execute the remembered scripts.
void discardScripts()
Discard all remembered scrips.
bool aborted() const
Returns true if removing is aborted during progress.
const Data & data() const
Return the data.
Definition: SolvIdentFile.h:53
std::unordered_set< IdString > Data
Definition: SolvIdentFile.h:37
void setData(const Data &data_r)
Store new Data.
Definition: SolvIdentFile.h:69
const Pathname & file() const
Return the file path.
Definition: SolvIdentFile.h:46
Base class for concrete Target implementations.
Definition: TargetImpl.h:55
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
Definition: TargetImpl.cc:1867
const VendorAttr & vendorAttr() const
The targets current vendor equivalence settings.
Definition: TargetImpl.h:202
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Definition: TargetImpl.cc:1861
LocaleSet requestedLocales() const
Languages to be supported by the system.
Definition: TargetImpl.h:158
void updateAutoInstalled()
Update the database of autoinstalled packages.
Definition: TargetImpl.cc:1852
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
Definition: TargetImpl.cc:1994
Pathname _root
Path to the target.
Definition: TargetImpl.h:219
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
Definition: TargetImpl.h:223
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
Definition: TargetImpl.cc:837
std::string _distributionVersion
Cache distributionVersion.
Definition: TargetImpl.h:229
std::list< PoolItem > PoolItemList
list of pool items
Definition: TargetImpl.h:60
rpm::RpmDb _rpm
RPM database.
Definition: TargetImpl.h:221
rpm::RpmDb & rpm()
The RPM database.
Definition: TargetImpl.cc:1768
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
Definition: TargetImpl.h:93
std::string distributionVersion() const
This is version attribute of the installed base product.
Definition: TargetImpl.cc:1897
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
Definition: TargetImpl.cc:815
SolvIdentFile _autoInstalledFile
user/auto installed database
Definition: TargetImpl.h:225
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Definition: TargetImpl.cc:1831
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
Definition: TargetImpl.cc:1879
virtual ~TargetImpl()
Dtor.
Definition: TargetImpl.cc:873
bool providesFile(const std::string &path_str, const std::string &name_str) const
If the package is installed and provides the file Needed to evaluate split provides during Resolver::...
Definition: TargetImpl.cc:1773
HardLocksFile _hardLocksFile
Hard-Locks database.
Definition: TargetImpl.h:227
Pathname root() const
The root set for this target.
Definition: TargetImpl.h:117
void load(bool force=true)
Definition: TargetImpl.cc:1054
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
Definition: TargetImpl.cc:1938
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
Definition: TargetImpl.cc:1983
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
Definition: TargetImpl.cc:1189
VendorAttr _vendorAttr
vendor equivalence settings.
Definition: TargetImpl.h:231
Pathname home() const
The directory to store things.
Definition: TargetImpl.h:121
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Pathname defaultSolvfilesPath() const
The systems default solv file location.
Definition: TargetImpl.cc:886
std::string anonymousUniqueId() const
anonymous unique id
Definition: TargetImpl.cc:1964
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
Definition: TargetImpl.cc:745
bool solvfilesPathIsTemp() const
Whether we're using a temp.
Definition: TargetImpl.h:97
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Definition: TargetImpl.cc:1873
Interface to the rpm program.
Definition: RpmDb.h:48
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
Definition: RpmDb.cc:1571
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
Definition: RpmDb.cc:264
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
Definition: RpmDb.cc:1766
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
Definition: RpmDb.cc:354
bool hasFile(const std::string &file_r, const std::string &name_r="") const
Return true if at least one package owns a certain file (name_r empty) Return true if package name_r ...
Definition: RpmDb.cc:965
Subclass to retrieve database content.
Definition: librpmDb.h:337
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
Definition: librpmDb.cc:743
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
Definition: PathInfo.cc:1054
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
Definition: PathInfo.cc:545
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:598
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:662
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
Definition: PathInfo.cc:704
int dirForEach(const Pathname &dir_r, function< bool(const Pathname &, const char *const)> fnc_r)
Invoke callback function fnc_r for each entry in directory dir_r.
Definition: PathInfo.cc:551
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
Definition: PathInfo.cc:1145
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition: PathInfo.cc:413
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
Definition: PathInfo.cc:1063
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
Definition: PathInfo.cc:886
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
int touch(const Pathname &path)
Change file's modification and access times.
Definition: PathInfo.cc:1196
std::string md5sum(const Pathname &file)
Compute a files md5sum.
Definition: PathInfo.cc:986
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
Definition: PathInfo.cc:817
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
std::string toJSON(void)
Definition: Json.h:136
SolvableIdType size_type
Definition: PoolMember.h:126
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
Definition: Pool.cc:286
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1023
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
Definition: String.h:1081
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:177
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
Definition: String.h:591
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:223
IMPL_PTR_TYPE(TargetImpl)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
Definition: TargetImpl.cc:730
std::string rpmDbStateHash(const Pathname &root_r)
Definition: TargetImpl.cc:73
void writeUpgradeTestcase()
Definition: TargetImpl.cc:284
static bool fileMissing(const Pathname &pathname)
helper functor
Definition: TargetImpl.cc:810
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< std::string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
Definition: TargetImpl.cc:775
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
Definition: TargetImpl.cc:91
static std::string generateRandomId()
generates a random id using uuidgen
Definition: TargetImpl.cc:764
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
std::unordered_set< Locale > LocaleSet
Definition: Locale.h:28
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
Definition: ResObject.cc:43
std::list< UpdateNotificationFile > UpdateNotifications
@ DownloadInHeaps
Similar to DownloadInAdvance, but try to split the transaction into heaps, where at the end of each h...
Definition: DownloadMode.h:29
@ DownloadOnly
Just download all packages to the local cache.
Definition: DownloadMode.h:25
@ DownloadAsNeeded
Alternating download and install.
Definition: DownloadMode.h:32
@ DownloadDefault
libzypp will decide what to do.
Definition: DownloadMode.h:24
JSON array.
Definition: Json.h:257
std::string asJSON() const
JSON representation.
Definition: Json.h:279
void add(const Value &val_r)
Push JSON Value to Array.
Definition: Json.h:271
JSON object.
Definition: Json.h:322
void add(const String &key_r, const Value &val_r)
Add key/value pair.
Definition: Json.h:336
std::string asJSON() const
JSON representation.
Definition: Json.h:344
bool isKind(const ResKind &kind_r) const
Definition: SolvableType.h:64
Solvable satSolvable() const
Return the corresponding sat::Solvable.
Definition: SolvableType.h:57
bool isNeedreboot() const
Definition: SolvableType.h:83
static PoolImpl & myPool()
Definition: PoolImpl.cc:178