28#include <zypp-core/base/UserRequestException>
62#include <zypp-core/zyppng/base/EventLoop>
63#include <zypp-core/zyppng/base/UnixSignalSource>
64#include <zypp-core/zyppng/io/AsyncDataSource>
65#include <zypp-core/zyppng/io/Process>
69#include <zypp-core/zyppng/base/EventDispatcher>
71#include <shared/commit/CommitMessages.h>
78#include "tools/zypp-rpm/errorcodes.h"
79#include <rpm/rpmlog.h>
86 static bool val = [](){
87 const char *
env =
getenv(
"TRANSACTIONAL_UPDATE");
99#include <solv/repo_rpmdb.h>
100#include <solv/chksum.h>
111 ::solv_chksum_free(
chk,
nullptr );
113 if ( ::rpm_hash_database_state( state,
chk ) == 0 )
116 const unsigned char * md5 = ::solv_chksum_get(
chk, &
md5l );
120 WAR <<
"rpm_hash_database_state failed" << endl;
140 inline void sigMultiversionSpecChanged()
160 if (
step.stepType() != Transaction::TRANSACTION_IGNORE )
170 static const std::string
strType(
"type" );
171 static const std::string
strStage(
"stage" );
172 static const std::string
strSolvable(
"solvable" );
190 switch (
step_r.stepType() )
192 case Transaction::TRANSACTION_IGNORE:
break;
198 switch (
step_r.stepStage() )
200 case Transaction::STEP_TODO:
break;
211 ident =
solv.ident();
246 class AssertMountedBase
258 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
259 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
267 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
279 class AssertProcMounted :
private AssertMountedBase
282 AssertProcMounted( Pathname root_r )
285 if ( ! PathInfo(root_r/
"self").isDir() ) {
286 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
288 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
292 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
300 class AssertDevMounted :
private AssertMountedBase
303 AssertDevMounted( Pathname root_r )
306 if ( ! PathInfo(root_r/
"null").isChr() ) {
307 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
312 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
316 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
333 std::ifstream infile( historyFile_r.c_str() );
334 for( iostr::EachLine in( infile ); in; in.next() )
336 const char * ch( (*in).c_str() );
338 if ( *ch <
'1' ||
'9' < *ch )
340 const char * sep1 = ::strchr( ch,
'|' );
345 bool installs =
true;
346 if ( ::strncmp( sep1,
"install|", 8 ) )
348 if ( ::strncmp( sep1,
"remove |", 8 ) )
355 const char * sep2 = ::strchr( sep1,
'|' );
356 if ( !sep2 || sep1 == sep2 )
358 (*in)[sep2-ch] =
'\0';
363 onSystemByUserList.erase( pkg );
367 if ( (sep1 = ::strchr( sep2+1,
'|' ))
368 && (sep1 = ::strchr( sep1+1,
'|' ))
369 && (sep2 = ::strchr( sep1+1,
'|' )) )
371 (*in)[sep2-ch] =
'\0';
372 if ( ::strchr( sep1+1,
'@' ) )
375 onSystemByUserList.insert( pkg );
380 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
381 return onSystemByUserList;
391 return PluginFrame( command_r, json::Object {
392 {
"TransactionStepList", steps_r }
402 MIL <<
"Testcases to keep: " <<
toKeep << endl;
408 WAR <<
"No Target no Testcase!" << endl;
412 std::string
stem(
"updateTestcase" );
413 Pathname dir( target->assertRootPrefix(
"/var/log/") );
417 std::list<std::string> content;
419 std::set<std::string>
cases;
420 for_(
c, content.begin(), content.end() )
437 MIL <<
"Write new testcase " << next << endl;
438 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
470 WAR <<
"User request to abort script " <<
script_r << endl;
479 if ( prog.close() != 0 )
481 ret.second = report_r->problem( prog.execError() );
482 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
483 std::ostringstream sstr;
484 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
485 historylog.
comment(sstr.str(),
true);
497 bool executeScript(
const Pathname & root_r,
498 const Pathname & script_r,
499 callback::SendReport<PatchScriptReport> & report_r )
504 action = doExecuteScript( root_r, script_r, report_r );
508 switch ( action.second )
511 WAR <<
"User request to abort at script " << script_r << endl;
516 WAR <<
"User request to skip script " << script_r << endl;
526 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
535 bool RunUpdateScripts(
const Pathname & root_r,
536 const Pathname & scriptsPath_r,
537 const std::vector<sat::Solvable> & checkPackages_r,
540 if ( checkPackages_r.empty() )
543 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
545 if ( ! PathInfo( scriptsDir ).isDir() )
548 std::list<std::string> scripts;
550 if ( scripts.empty() )
558 std::map<std::string, Pathname> unify;
559 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
561 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
562 for_( sit, scripts.begin(), scripts.end() )
567 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
570 PathInfo script( scriptsDir / *sit );
571 Pathname localPath( scriptsPath_r/(*sit) );
572 std::string unifytag;
574 if ( script.isFile() )
580 else if ( ! script.isExist() )
588 if ( unifytag.empty() )
592 if ( unify[unifytag].empty() )
594 unify[unifytag] = localPath;
601 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
602 MIL <<
"Skip update script: " << msg << endl;
603 HistoryLog().comment( msg,
true );
607 if ( abort || aborting_r )
609 WAR <<
"Aborting: Skip update script " << *sit << endl;
610 HistoryLog().comment(
611 localPath.asString() +
_(
" execution skipped while aborting"),
616 MIL <<
"Found update script " << *sit << endl;
617 callback::SendReport<PatchScriptReport> report;
618 report->start( make<Package>( *it ), script.path() );
620 if ( ! executeScript( root_r, localPath, report ) )
632 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
634 std::ifstream infile( file_r.c_str() );
635 for( iostr::EachLine in( infile ); in; in.next() )
637 out_r << *in << endl;
641 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
643 std::string ret( cmd_r );
644#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
645 SUBST_IF(
"%p", notification_r.solvable().asString() );
646 SUBST_IF(
"%P", notification_r.file().asString() );
651 void sendNotification(
const Pathname & root_r,
654 if ( notifications_r.empty() )
658 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
659 if ( cmdspec.empty() )
662 std::string::size_type pos( cmdspec.find(
'|' ) );
663 if ( pos == std::string::npos )
665 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
666 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
671 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
673 enum Format {
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
675 if ( formatStr ==
"none" )
677 else if ( formatStr ==
"single" )
679 else if ( formatStr ==
"digest" )
681 else if ( formatStr ==
"bulk" )
685 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
686 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
694 if ( format == NONE || format == SINGLE )
696 for_( it, notifications_r.begin(), notifications_r.end() )
698 std::vector<std::string> command;
699 if ( format == SINGLE )
701 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
706 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
710 int ret = prog.close();
713 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
714 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
720 else if ( format == DIGEST || format == BULK )
722 filesystem::TmpFile tmpfile;
723 std::ofstream out( tmpfile.path().c_str() );
724 for_( it, notifications_r.begin(), notifications_r.end() )
726 if ( format == DIGEST )
728 out << it->file() << endl;
730 else if ( format == BULK )
736 std::vector<std::string> command;
737 command.push_back(
"<"+tmpfile.path().asString() );
738 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
743 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
747 int ret = prog.close();
750 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
751 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
758 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
759 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
770 void RunUpdateMessages(
const Pathname & root_r,
771 const Pathname & messagesPath_r,
772 const std::vector<sat::Solvable> & checkPackages_r,
773 ZYppCommitResult & result_r )
775 if ( checkPackages_r.empty() )
778 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
780 if ( ! PathInfo( messagesDir ).isDir() )
783 std::list<std::string> messages;
785 if ( messages.empty() )
791 HistoryLog historylog;
792 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
794 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
795 for_( sit, messages.begin(), messages.end() )
800 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
803 PathInfo message( messagesDir / *sit );
804 if ( ! message.isFile() || message.size() == 0 )
807 MIL <<
"Found update message " << *sit << endl;
808 Pathname localPath( messagesPath_r/(*sit) );
809 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
810 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
813 sendNotification( root_r, result_r.updateMessages() );
819 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
822 if ( changedPseudoInstalled.empty() )
830 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
831 ResPool::EstablishedStates establishedStates{
ResPool::instance().establishedStates() };
833 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
836 HistoryLog historylog;
837 for (
const auto & el : changedPseudoInstalled )
838 historylog.patchStateChange( el.first, el.second );
862 , _requestedLocalesFile( home() /
"RequestedLocales" )
863 , _autoInstalledFile( home() /
"AutoInstalled" )
864 , _hardLocksFile(
Pathname::assertprefix( _root,
ZConfig::instance().locksFile() ) )
865 , _vendorAttr(
Pathname::assertprefix( _root,
ZConfig::instance().vendorPath() ) )
873 MIL <<
"Initialized target on " <<
_root << endl;
881 std::ifstream
uuidprovider(
"/proc/sys/kernel/random/uuid" );
892 boost::function<std::string ()> value )
894 std::string val = value();
902 MIL <<
"updating '" << filename <<
"' content." << endl;
947 WAR <<
"Can't create anonymous id file" << endl;
962 WAR <<
"No base product, I won't create flavor cache" << endl;
966 std::string flavor =
p->flavor();
978 WAR <<
"Can't create flavor cache" << endl;
992 MIL <<
"Closed target on " <<
_root << endl;
1028 MIL <<
"Read cookie: " <<
cookie << endl;
1056 ex.remember(
str::form(
"Cannot create temporary file under %s.", base.
c_str()));
1069 WAR <<
"Using a temporary solv file at " << base << endl;
1075 ex.remember(
str::form(
"Cannot create temporary file under %s.", base.
c_str()));
1089#ifdef ZYPP_RPMDB2SOLV_PATH
1092 cmd.push_back(
"rpmdb2solv" );
1095 cmd.push_back(
"-r" );
1098 cmd.push_back(
"-D" );
1100 cmd.push_back(
"-X" );
1102 cmd.push_back(
"-p" );
1108 cmd.push_back(
"-o" );
1144 if (
root() ==
"/" )
1155 if ( !
PathInfo(base/
"solv.idx").isExist() )
1176 MIL <<
"New cache built: " << (
newCache?
"true":
"false") <<
1177 ", force loading: " << (
force?
"true":
"false") << endl;
1182 MIL <<
"adding " <<
rpmsolv <<
" to pool(" << satpool.systemRepoAlias() <<
")" << endl;
1201 system = satpool.systemRepo();
1206 MIL <<
"adding " <<
rpmsolv <<
" to system" << endl;
1212 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1218 satpool.rootDir(
_root );
1244 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1245 onSystemByAuto.insert( ident );
1256 satpool.setAutoInstalled(
q );
1266 if (
PathInfo( needrebootFile ).isFile() )
1280 if (
PathInfo( needrebootFile ).isFile() )
1301 MIL <<
"Target loaded: " <<
system.solvablesSize() <<
" resolvables" << endl;
1319 if (
policy_r.restrictToMedia() > 1 )
1323 if (
root() ==
"/" )
1326 if (
policy_r.singleTransModeEnabled() )
1337 MIL <<
"TargetImpl::commit(<pool>, " <<
policy_r <<
")" << endl;
1351 MIL <<
"Restrict to media number " <<
policy_r.restrictToMedia() << endl;
1356 steps.push_back( *
it );
1363 MIL <<
"Todo: " << result << endl;
1380 if (
pool_r.resolver().upgradeMode() ||
pool_r.resolver().upgradingRepos() )
1388 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1417 DBG <<
"dryRun: Not storing non-package data." << endl;
1426 for_(
it, steps.begin(), steps.end() )
1428 if ( !
it->satSolvable().isKind<
Patch>() )
1432 if ( !
pi.status().isToBeInstalled() )
1436 if ( ! patch ||patch->message().empty() )
1439 MIL <<
"Show message for " << patch << endl;
1441 if ( ! report->show( patch ) )
1443 WAR <<
"commit aborted by the user" << endl;
1450 DBG <<
"dryRun: Not checking patch messages." << endl;
1464 packageCache.setCommitList( steps.begin(), steps.end() );
1472 for_(
it, steps.begin(), steps.end() )
1474 switch (
it->stepType() )
1500 WAR <<
"commit cache preload aborted by the user" << endl;
1509 WAR <<
"Skipping cache preload package " <<
pi->asKind<
Package>() <<
" in commit" << endl;
1519 INT <<
"Unexpected Error: Skipping cache preload package " <<
pi->asKind<
Package>() <<
" in commit" << endl;
1529 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1535 if (
policy_r.singleTransModeEnabled() ) {
1545 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1547 if (
policy_r.singleTransModeEnabled() ) {
1560 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1573 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1593 MIL <<
"TargetImpl::commit(<pool>, " <<
policy_r <<
") returns: " << result << endl;
1604 struct NotifyAttemptToModify
1609 {
if ( _guard ) {
_result.attemptToModify(
true );
_guard =
false; } }
1622 MIL <<
"TargetImpl::commit(<list>" <<
policy_r <<
")" << steps.size() << endl;
1627 NotifyAttemptToModify attemptToModify(
result_r );
1639 for_(
step, steps.begin(), steps.end() )
1656 if (
citem.status().isToBeInstalled() )
1665 WAR <<
"commit aborted by the user" << endl;
1673 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
1682 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
1691 bool success =
false;
1717 WAR <<
"commit aborted by the user" << endl;
1725 if (
citem.isNeedreboot() ) {
1742 WAR <<
"dry run failed" << endl;
1749 WAR <<
"commit aborted by the user" << endl;
1754 WAR <<
"Install failed" << endl;
1760 if ( success && !
policy_r.dryRun() )
1772 bool success =
false;
1785 WAR <<
"commit aborted by the user" << endl;
1801 WAR <<
"commit aborted by the user" << endl;
1807 WAR <<
"removal of " <<
p <<
" failed";
1810 if ( success && !
policy_r.dryRun() )
1821 if ( !
citem.buddy() )
1826 if (
citem.status().isToBeInstalled() )
1828 ERR <<
"Can't install orphan product without release-package! " <<
citem << endl;
1834 std::string referenceFilename(
p->referenceFilename() );
1835 if ( referenceFilename.empty() )
1837 ERR <<
"Can't remove orphan product without 'referenceFilename'! " <<
citem << endl;
1851 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1885 WAR <<
"Commit aborted by the user" << endl;
1932 return ReportType::loglevel::crt;
1934 return ReportType::loglevel::err;
1936 return ReportType::loglevel::war;
1940 return ReportType::loglevel::msg;
1942 return ReportType::loglevel::dbg;
1967 MIL <<
"TargetImpl::commit(<list>" <<
policy_r <<
")" << steps.size() << endl;
1972 NotifyAttemptToModify attemptToModify(
result_r );
1975 result_r.setSingleTransactionMode(
true );
1985 rpm::RpmInstFlags flags(
policy_r.rpmInstFlags()
1993 proto::target::Commit
commit;
2003 for (
auto &[
_, value] : data ) {
2005 value.resetDispose();
2011 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)
stepId < steps.size() && !abort ; ++
stepId ) {
2026 if (
citem.status().isToBeInstalled() )
2031 proto::target::InstallStep
tStep;
2034 tStep.multiversion =
p->multiversionInstall() ;
2036 commit.transactionSteps.push_back( std::move(
tStep) );
2040 WAR <<
"commit aborted by the user" << endl;
2048 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
2057 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2063 proto::target::RemoveStep
tStep;
2066 tStep.version =
p->edition().version();
2067 tStep.release =
p->edition().release();
2068 tStep.arch =
p->arch().asString();
2069 commit.transactionSteps.push_back(std::move(
tStep));
2080 proto::target::InstallStep
tStep;
2083 tStep.multiversion =
false;
2084 commit.transactionSteps.push_back(std::move(
tStep));
2088 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2097 if (
commit.transactionSteps.size() ) {
2137 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>>
transactionreport;
2138 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>>
installreport;
2139 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>>
uninstallreport;
2140 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>>
scriptreport;
2141 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>>
cleanupreport;
2192 WAR <<
"Got rpm output without active report " <<
line;
2197 if (
line.find(
" scriptlet failed, " ) == std::string::npos )
2201 if (
line.back() !=
'\n' )
2222 L_DBG(
"zypp-rpm") <<
"[rpm> " <<
l;
2249 ERR <<
"There is still a running report, this is a bug" << std::endl;
2257 if (
rpmmsg.size() == 0 )
2261 rpmmsg +=
"[truncated]\n";
2263 std::ostringstream
sstr;
2264 sstr <<
"rpm output:" << endl <<
rpmmsg << endl;
2289 ( *installreport)->progress( 100,
resObj );
2299 if (
citem.isNeedreboot() ) {
2327 ( *uninstallreport)->progress( 100,
resObj );
2342 ( *scriptreport)->progress( 100,
resObj );
2347 ( *transactionreport)->progress( 100 );
2352 ( *cleanupreport)->progress( 100 );
2376 const char *
argv[] = {
2400 if ( !
scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2409 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2413 auto id =
p->stepId;
2415 ERR <<
"Received invalid stepId: " <<
id <<
" in " <<
p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2421 while (
const auto &
m =
msgStream->nextMessage() ) {
2427 const auto &
mName =
m->command();
2428 if (
mName == proto::target::RpmLog::typeName ) {
2430 const auto &
p = proto::target::RpmLog::fromStompMessage (*
m);
2432 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2437 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " <<
p->level <<
"> " <<
p->line;
2440 }
else if (
mName == proto::target::PackageBegin::typeName ) {
2443 const auto &
p = proto::target::PackageBegin::fromStompMessage(*
m);
2449 auto &
step = steps.at(
p->stepId );
2452 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2455 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2459 }
else if (
mName == proto::target::PackageFinished::typeName ) {
2460 const auto &
p = proto::target::PackageFinished::fromStompMessage(*
m);
2468 }
else if (
mName == proto::target::PackageProgress::typeName ) {
2469 const auto &
p = proto::target::PackageProgress::fromStompMessage(*
m);
2474 (*uninstallreport)->progress(
p->amount,
makeResObject( steps.at(
p->stepId ) ));
2476 (*installreport)->progress(
p->amount,
makeResObject( steps.at(
p->stepId ) ));
2478 ERR <<
"Received a " <<
mName <<
" message but there is no corresponding report running." << std::endl;
2480 }
else if (
mName == proto::target::PackageError::typeName ) {
2481 const auto &
p = proto::target::PackageError::fromStompMessage(*
m);
2485 if (
p->stepId >= 0 &&
p->stepId < steps.size() )
2490 }
else if (
mName == proto::target::ScriptBegin::typeName ) {
2493 const auto &
p = proto::target::ScriptBegin::fromStompMessage(*
m);
2495 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2502 const auto stepId =
p->stepId;
2508 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2513 }
else if (
mName == proto::target::ScriptFinished::typeName ) {
2517 }
else if (
mName == proto::target::ScriptError::typeName ) {
2519 const auto &
p = proto::target::ScriptError::fromStompMessage(*
m);
2521 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2526 const auto stepId =
p->stepId;
2543 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2555 }
else if (
mName == proto::target::CleanupBegin::typeName ) {
2558 const auto &
beg = proto::target::CleanupBegin::fromStompMessage(*
m);
2560 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2565 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2566 (*cleanupreport)->start(
beg->nvra );
2567 }
else if (
mName == proto::target::CleanupFinished::typeName ) {
2571 }
else if (
mName == proto::target::CleanupProgress::typeName ) {
2572 const auto &
prog = proto::target::CleanupProgress::fromStompMessage(*
m);
2574 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2579 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2583 (*cleanupreport)->progress(
prog->amount );
2585 }
else if (
mName == proto::target::TransBegin::typeName ) {
2588 const auto &
beg = proto::target::TransBegin::fromStompMessage(*
m);
2590 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2595 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2596 (*transactionreport)->start(
beg->name );
2597 }
else if (
mName == proto::target::TransFinished::typeName ) {
2601 }
else if (
mName == proto::target::TransProgress::typeName ) {
2602 const auto &
prog = proto::target::TransProgress::fromStompMessage(*
m);
2604 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2609 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2613 (*transactionreport)->progress(
prog->amount );
2614 }
else if (
mName == proto::target::TransactionError::typeName ) {
2616 const auto &error = proto::target::TransactionError::fromStompMessage(*
m);
2618 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2626 ERR <<
"Received unexpected message from zypp-rpm: "<<
m->command() <<
", ignoring" << std::endl;
2634 prog->sigStarted().connect( [&](){
2642 while(
prog->canReadLine( channel ) ) {
2643 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2649 if ( !
msgSource->openFds( std::vector<int>{ messagePipe->readFd },
prog->stdinFd() ) )
2655 const auto &msg =
commit.toStompMessage();
2657 std::rethrow_exception ( msg.error() );
2659 if ( !
msgStream->sendMessage( *msg ) ) {
2714 case zypprpm::NoError:
2715 case zypprpm::RpmFinishedWithError:
2717 case zypprpm::RpmFinishedWithTransactionError: {
2721 std::ostringstream
sstr;
2722 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2724 sstr <<
" " << err <<
"\n";
2734 case zypprpm::FailedToOpenDb:
2737 case zypprpm::WrongHeaderSize:
2738 case zypprpm::WrongMessageFormat:
2741 case zypprpm::RpmInitFailed:
2744 case zypprpm::FailedToReadPackage:
2747 case zypprpm::FailedToAddStepToTransaction:
2750 case zypprpm::RpmOrderFailed:
2753 case zypprpm::FailedToCreateLock:
2758 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)
stepId < steps.size() && !abort; ++
stepId ) {
2770 if (
citem.status().isToBeInstalled() ) {
2771 ERR <<
"Can't install orphan product without release-package! " <<
citem << endl;
2775 std::string referenceFilename(
p->referenceFilename() );
2777 if ( referenceFilename.empty() ) {
2778 ERR <<
"Can't remove orphan product without 'referenceFilename'! " <<
citem << endl;
2788 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2807 WAR <<
"Commit aborted by the user" << endl;
2861 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2866 inline Pathname staticGuessRoot(
const Pathname & root_r )
2868 if ( root_r.empty() )
2873 return Pathname(
"/");
2879 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2881 std::ifstream idfile( file_r.c_str() );
2882 for( iostr::EachLine in( idfile ); in; in.next() )
2885 if ( ! line.empty() )
2888 return std::string();
2899 if (
p->isTargetDistribution() )
2909 if ( target && target->root() ==
needroot )
2910 return target->requestedLocales();
2916 MIL <<
"updateAutoInstalled if changed..." << endl;
2992 rpm::librpmDb::db_const_iterator
it;
#define MAXRPMMESSAGELINES
#define SUBST_IF(PAT, VAL)
ZYppCommitResult & _result
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
reference value() const
Reference to the Tp object.
void resetDispose()
Set no dispose function.
void reset()
Reset to default Ctor values.
Mime type like 'type/subtype' classification of content.
Store and operate on date (time_t).
static Date now()
Return the current time.
Edition represents [epoch:]version[-release]
std::string version() const
Version.
std::string release() const
Release.
epoch_t epoch() const
Epoch.
Base class for Exception.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::vector< std::string > Arguments
Writing the zypp history file.
void stampCommand()
Log info about the current process.
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
void remove(const PoolItem &pi)
Log removal of a package.
static const Pathname & fname()
Get the current log file path.
void install(const PoolItem &pi)
Log installation (or update) of a package.
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Access to the sat-pools string space.
std::string asString() const
Conversion to std::string
@ REGEX
Regular Expression.
TraitsType::constPtrType constPtr
Class representing a patch.
TraitsType::constPtrType constPtr
Parallel execution of stateful PluginScripts.
Command frame for communication with PluginScript.
Combining sat::Solvable and ResStatus.
TraitsType::constPtrType constPtr
Track changing files or directories.
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
static ResPool instance()
Singleton ctor.
byKind_iterator byKindEnd(const ResKind &kind_r) const
byKind_iterator byKindBegin(const ResKind &kind_r) const
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
TraitsType::constPtrType constPtr
Attempts to create a lock to prevent the system from going into hibernate/shutdown.
TraitsType::constPtrType constPtr
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition of vendor equivalence.
Interim helper class to collect global options and settings.
static ZConfig & instance()
Singleton ctor.
Options and policies for ZYpp::commit.
Result returned from ZYpp::commit.
const Pathname & root() const
Remembered root directory of the target.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
std::vector< sat::Transaction::Step > TransactionStepList
const sat::Transaction & transaction() const
The full transaction list.
sat::Transaction & rTransaction()
Manipulate transaction.
static zypp::Pathname lockfileDir()
Typesafe passing of user data via callbacks.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
zypp::ContentType ContentType
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
Pathname dirname() const
Return all but the last component od this path.
const char * c_str() const
String representation.
const std::string & asString() const
String representation.
bool empty() const
Test for an empty path.
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Provide a new empty temporary file and delete it when no longer needed.
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
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.
static Pool instance()
Singleton ctor.
Libsolv Id queue wrapper.
detail::IdType value_type
Define a set of Solvables by ident and provides.
A Solvable object within the sat Pool.
A single step within a Transaction.
Libsolv transaction wrapper.
const_iterator end() const
Iterator behind the last TransactionStep.
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run.
const_iterator begin() const
Iterator to the first TransactionStep.
bool order()
Order transaction steps for commit.
@ TRANSACTION_MULTIINSTALL
[M] Install(multiversion) item (
@ TRANSACTION_INSTALL
[+] Install(update) item
@ TRANSACTION_IGNORE
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
@ TRANSACTION_ERASE
[-] Delete item
@ STEP_TODO
[__] unprocessed
Target::commit helper optimizing package provision.
void setData(const Data &data_r)
Store new Data.
const Data & data() const
Return the data.
pool::PoolTraits::HardLockQueries Data
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 aborted() const
Returns true if removing is aborted during progress.
const Data & data() const
Return the data.
std::unordered_set< IdString > Data
void setData(const Data &data_r)
Store new Data.
const Pathname & file() const
Return the file path.
Base class for concrete Target implementations.
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
const VendorAttr & vendorAttr() const
The targets current vendor equivalence settings.
std::string targetDistribution() const
This is register.target attribute of the installed base product.
std::list< PoolItem > PoolItemList
list of pool items
LocaleSet requestedLocales() const
Languages to be supported by the system.
void updateAutoInstalled()
Update the database of autoinstalled packages.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
Pathname _root
Path to the target.
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
Pathname _tmpSolvfilesPath
std::string _distributionVersion
Cache distributionVersion.
rpm::RpmDb _rpm
RPM database.
~TargetImpl() override
Dtor.
rpm::RpmDb & rpm()
The RPM database.
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
std::string distributionVersion() const
This is version attribute of the installed base product.
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
SolvIdentFile _autoInstalledFile
user/auto installed database
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
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::...
HardLocksFile _hardLocksFile
Hard-Locks database.
Pathname root() const
The root set for this target.
void load(bool force=true)
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
void commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
Commit ordered changes (internal helper)
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
VendorAttr _vendorAttr
vendor equivalence settings.
Pathname home() const
The directory to store things.
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.
std::string anonymousUniqueId() const
anonymous unique id
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
bool solvfilesPathIsTemp() const
Whether we're using a temp.
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Interface to the rpm program.
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
const Pathname & root() const
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
const Pathname & dbPath() const
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
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 ...
SignalProxy< void(uint)> sigChannelReadyRead()
SignalProxy< void(int)> sigFinished()
SignalProxy< void()> sigMessageReceived()
static Ptr create(IODevice::Ptr iostr)
Namespace intended to collect all environment variables we use.
bool TRANSACTIONAL_UPDATE()
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
int unlink(const Pathname &path)
Like 'unlink'.
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
int touch(const Pathname &path)
Change file's modification and access times.
std::string getline(std::istream &str)
Read one line from stream.
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
std::string toLower(const std::string &s)
Return lowercase version of s.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
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.
std::string trim(const std::string &s, const Trim trim_r)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
std::string rpmDbStateHash(const Pathname &root_r)
void writeUpgradeTestcase()
static bool fileMissing(const Pathname &pathname)
helper functor
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...
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
static std::string generateRandomId()
generates a random id using uuidgen
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::list< UpdateNotificationFile > UpdateNotifications
std::string asString(const Patch::Category &obj)
@ DownloadInHeaps
Similar to DownloadInAdvance, but try to split the transaction into heaps, where at the end of each h...
@ DownloadOnly
Just download all packages to the local cache.
@ DownloadAsNeeded
Alternating download and install.
@ DownloadInAdvance
First download all packages to the local cache.
@ DownloadDefault
libzypp will decide what to do.
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
static PoolImpl & myPool()
Convenience SendReport<rpm::SingleTransReport> wrapper.
void report(const callback::UserData &userData_r)
void sendLoglineRpm(const std::string &line_r, unsigned rpmlevel_r)
Convenience to send a contentLogline translating a rpm loglevel.
void sendLogline(const std::string &line_r, ReportType::loglevel level_r=ReportType::loglevel::msg)
Convenience to send a contentLogline.
@ RPM_NODEPS_FORCE
only this one used
static std::optional< Pipe > create(int flags=0)
#define NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define IMPL_PTR_TYPE(NAME)