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>
70#include <zypp-proto/target/commit.pb.h>
71#include <zypp-proto/core/envelope.pb.h>
79#include "tools/zypp-rpm/errorcodes.h"
80#include <rpm/rpmlog.h>
87 static bool val = [](){
88 const char *
env =
getenv(
"TRANSACTIONAL_UPDATE");
100#include <solv/repo_rpmdb.h>
101#include <solv/chksum.h>
112 ::solv_chksum_free(
chk,
nullptr );
114 if ( ::rpm_hash_database_state( state,
chk ) == 0 )
117 const unsigned char * md5 = ::solv_chksum_get(
chk, &
md5l );
121 WAR <<
"rpm_hash_database_state failed" << endl;
141 inline void sigMultiversionSpecChanged()
161 if (
step.stepType() != Transaction::TRANSACTION_IGNORE )
171 static const std::string
strType(
"type" );
172 static const std::string
strStage(
"stage" );
173 static const std::string
strSolvable(
"solvable" );
191 switch (
step_r.stepType() )
193 case Transaction::TRANSACTION_IGNORE:
break;
199 switch (
step_r.stepStage() )
201 case Transaction::STEP_TODO:
break;
212 ident =
solv.ident();
247 class AssertMountedBase
259 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
260 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
268 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
280 class AssertProcMounted :
private AssertMountedBase
283 AssertProcMounted( Pathname root_r )
286 if ( ! PathInfo(root_r/
"self").isDir() ) {
287 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
289 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
293 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
301 class AssertDevMounted :
private AssertMountedBase
304 AssertDevMounted( Pathname root_r )
307 if ( ! PathInfo(root_r/
"null").isChr() ) {
308 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
313 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
317 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
334 std::ifstream infile( historyFile_r.c_str() );
335 for( iostr::EachLine in( infile ); in; in.next() )
337 const char * ch( (*in).c_str() );
339 if ( *ch <
'1' ||
'9' < *ch )
341 const char * sep1 = ::strchr( ch,
'|' );
346 bool installs =
true;
347 if ( ::strncmp( sep1,
"install|", 8 ) )
349 if ( ::strncmp( sep1,
"remove |", 8 ) )
356 const char * sep2 = ::strchr( sep1,
'|' );
357 if ( !sep2 || sep1 == sep2 )
359 (*in)[sep2-ch] =
'\0';
364 onSystemByUserList.erase( pkg );
368 if ( (sep1 = ::strchr( sep2+1,
'|' ))
369 && (sep1 = ::strchr( sep1+1,
'|' ))
370 && (sep2 = ::strchr( sep1+1,
'|' )) )
372 (*in)[sep2-ch] =
'\0';
373 if ( ::strchr( sep1+1,
'@' ) )
376 onSystemByUserList.insert( pkg );
381 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
382 return onSystemByUserList;
392 return PluginFrame( command_r, json::Object {
393 {
"TransactionStepList", steps_r }
403 MIL <<
"Testcases to keep: " <<
toKeep << endl;
409 WAR <<
"No Target no Testcase!" << endl;
413 std::string
stem(
"updateTestcase" );
414 Pathname dir( target->assertRootPrefix(
"/var/log/") );
418 std::list<std::string> content;
420 std::set<std::string>
cases;
421 for_(
c, content.begin(), content.end() )
438 MIL <<
"Write new testcase " << next << endl;
439 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
471 WAR <<
"User request to abort script " <<
script_r << endl;
480 if ( prog.close() != 0 )
482 ret.second = report_r->problem( prog.execError() );
483 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
484 std::ostringstream sstr;
485 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
486 historylog.
comment(sstr.str(),
true);
498 bool executeScript(
const Pathname & root_r,
499 const Pathname & script_r,
500 callback::SendReport<PatchScriptReport> & report_r )
505 action = doExecuteScript( root_r, script_r, report_r );
509 switch ( action.second )
512 WAR <<
"User request to abort at script " << script_r << endl;
517 WAR <<
"User request to skip script " << script_r << endl;
527 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
536 bool RunUpdateScripts(
const Pathname & root_r,
537 const Pathname & scriptsPath_r,
538 const std::vector<sat::Solvable> & checkPackages_r,
541 if ( checkPackages_r.empty() )
544 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
546 if ( ! PathInfo( scriptsDir ).isDir() )
549 std::list<std::string> scripts;
551 if ( scripts.empty() )
559 std::map<std::string, Pathname> unify;
560 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
562 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
563 for_( sit, scripts.begin(), scripts.end() )
568 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
571 PathInfo script( scriptsDir / *sit );
572 Pathname localPath( scriptsPath_r/(*sit) );
573 std::string unifytag;
575 if ( script.isFile() )
581 else if ( ! script.isExist() )
589 if ( unifytag.empty() )
593 if ( unify[unifytag].empty() )
595 unify[unifytag] = localPath;
602 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
603 MIL <<
"Skip update script: " << msg << endl;
604 HistoryLog().comment( msg,
true );
608 if ( abort || aborting_r )
610 WAR <<
"Aborting: Skip update script " << *sit << endl;
611 HistoryLog().comment(
612 localPath.asString() +
_(
" execution skipped while aborting"),
617 MIL <<
"Found update script " << *sit << endl;
618 callback::SendReport<PatchScriptReport> report;
619 report->start( make<Package>( *it ), script.path() );
621 if ( ! executeScript( root_r, localPath, report ) )
633 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
635 std::ifstream infile( file_r.c_str() );
636 for( iostr::EachLine in( infile ); in; in.next() )
638 out_r << *in << endl;
642 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
644 std::string ret( cmd_r );
645#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
646 SUBST_IF(
"%p", notification_r.solvable().asString() );
647 SUBST_IF(
"%P", notification_r.file().asString() );
652 void sendNotification(
const Pathname & root_r,
655 if ( notifications_r.empty() )
659 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
660 if ( cmdspec.empty() )
663 std::string::size_type pos( cmdspec.find(
'|' ) );
664 if ( pos == std::string::npos )
666 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
667 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
672 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
674 enum Format {
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
676 if ( formatStr ==
"none" )
678 else if ( formatStr ==
"single" )
680 else if ( formatStr ==
"digest" )
682 else if ( formatStr ==
"bulk" )
686 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
687 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
695 if ( format == NONE || format == SINGLE )
697 for_( it, notifications_r.begin(), notifications_r.end() )
699 std::vector<std::string> command;
700 if ( format == SINGLE )
702 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
707 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
711 int ret = prog.close();
714 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
715 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
721 else if ( format == DIGEST || format == BULK )
723 filesystem::TmpFile tmpfile;
724 std::ofstream out( tmpfile.path().c_str() );
725 for_( it, notifications_r.begin(), notifications_r.end() )
727 if ( format == DIGEST )
729 out << it->file() << endl;
731 else if ( format == BULK )
737 std::vector<std::string> command;
738 command.push_back(
"<"+tmpfile.path().asString() );
739 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
744 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
748 int ret = prog.close();
751 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
752 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
759 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
760 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
771 void RunUpdateMessages(
const Pathname & root_r,
772 const Pathname & messagesPath_r,
773 const std::vector<sat::Solvable> & checkPackages_r,
774 ZYppCommitResult & result_r )
776 if ( checkPackages_r.empty() )
779 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
781 if ( ! PathInfo( messagesDir ).isDir() )
784 std::list<std::string> messages;
786 if ( messages.empty() )
792 HistoryLog historylog;
793 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
795 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
796 for_( sit, messages.begin(), messages.end() )
801 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
804 PathInfo message( messagesDir / *sit );
805 if ( ! message.isFile() || message.size() == 0 )
808 MIL <<
"Found update message " << *sit << endl;
809 Pathname localPath( messagesPath_r/(*sit) );
810 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
811 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
814 sendNotification( root_r, result_r.updateMessages() );
820 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
823 if ( changedPseudoInstalled.empty() )
831 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
832 ResPool::EstablishedStates establishedStates{
ResPool::instance().establishedStates() };
834 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
837 HistoryLog historylog;
838 for (
const auto & el : changedPseudoInstalled )
839 historylog.patchStateChange( el.first, el.second );
863 , _requestedLocalesFile( home() /
"RequestedLocales" )
864 , _autoInstalledFile( home() /
"AutoInstalled" )
865 , _hardLocksFile(
Pathname::assertprefix( _root,
ZConfig::instance().locksFile() ) )
866 , _vendorAttr(
Pathname::assertprefix( _root,
ZConfig::instance().vendorPath() ) )
874 MIL <<
"Initialized target on " <<
_root << endl;
882 std::ifstream
uuidprovider(
"/proc/sys/kernel/random/uuid" );
893 boost::function<std::string ()> value )
895 std::string val = value();
903 MIL <<
"updating '" << filename <<
"' content." << endl;
948 WAR <<
"Can't create anonymous id file" << endl;
963 WAR <<
"No base product, I won't create flavor cache" << endl;
967 std::string flavor =
p->flavor();
979 WAR <<
"Can't create flavor cache" << endl;
993 MIL <<
"Closed target on " <<
_root << endl;
1029 MIL <<
"Read cookie: " <<
cookie << endl;
1057 ex.remember(
str::form(
"Cannot create temporary file under %s.", base.
c_str()));
1070 WAR <<
"Using a temporary solv file at " << base << endl;
1076 ex.remember(
str::form(
"Cannot create temporary file under %s.", base.
c_str()));
1090 cmd.push_back(
"rpmdb2solv" );
1092 cmd.push_back(
"-r" );
1095 cmd.push_back(
"-D" );
1097 cmd.push_back(
"-X" );
1099 cmd.push_back(
"-p" );
1105 cmd.push_back(
"-o" );
1141 if (
root() ==
"/" )
1152 if ( !
PathInfo(base/
"solv.idx").isExist() )
1173 MIL <<
"New cache built: " << (
newCache?
"true":
"false") <<
1174 ", force loading: " << (
force?
"true":
"false") << endl;
1179 MIL <<
"adding " <<
rpmsolv <<
" to pool(" << satpool.systemRepoAlias() <<
")" << endl;
1198 system = satpool.systemRepo();
1203 MIL <<
"adding " <<
rpmsolv <<
" to system" << endl;
1209 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1215 satpool.rootDir(
_root );
1241 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1242 onSystemByAuto.insert( ident );
1253 satpool.setAutoInstalled(
q );
1263 if (
PathInfo( needrebootFile ).isFile() )
1277 if (
PathInfo( needrebootFile ).isFile() )
1298 MIL <<
"Target loaded: " <<
system.solvablesSize() <<
" resolvables" << endl;
1316 if (
policy_r.restrictToMedia() > 1 )
1320 if (
root() ==
"/" )
1323 if (
policy_r.singleTransModeEnabled() )
1334 MIL <<
"TargetImpl::commit(<pool>, " <<
policy_r <<
")" << endl;
1348 MIL <<
"Restrict to media number " <<
policy_r.restrictToMedia() << endl;
1353 steps.push_back( *
it );
1360 MIL <<
"Todo: " << result << endl;
1377 if (
pool_r.resolver().upgradeMode() ||
pool_r.resolver().upgradingRepos() )
1385 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1414 DBG <<
"dryRun: Not storing non-package data." << endl;
1423 for_(
it, steps.begin(), steps.end() )
1425 if ( !
it->satSolvable().isKind<
Patch>() )
1429 if ( !
pi.status().isToBeInstalled() )
1433 if ( ! patch ||patch->message().empty() )
1436 MIL <<
"Show message for " << patch << endl;
1438 if ( ! report->show( patch ) )
1440 WAR <<
"commit aborted by the user" << endl;
1447 DBG <<
"dryRun: Not checking patch messages." << endl;
1461 packageCache.setCommitList( steps.begin(), steps.end() );
1469 for_(
it, steps.begin(), steps.end() )
1471 switch (
it->stepType() )
1497 WAR <<
"commit cache preload aborted by the user" << endl;
1506 WAR <<
"Skipping cache preload package " <<
pi->asKind<
Package>() <<
" in commit" << endl;
1516 INT <<
"Unexpected Error: Skipping cache preload package " <<
pi->asKind<
Package>() <<
" in commit" << endl;
1526 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1532 if (
policy_r.singleTransModeEnabled() ) {
1542 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1544 if (
policy_r.singleTransModeEnabled() ) {
1557 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1570 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1590 MIL <<
"TargetImpl::commit(<pool>, " <<
policy_r <<
") returns: " << result << endl;
1601 struct NotifyAttemptToModify
1606 {
if ( _guard ) {
_result.attemptToModify(
true );
_guard =
false; } }
1619 MIL <<
"TargetImpl::commit(<list>" <<
policy_r <<
")" << steps.size() << endl;
1624 NotifyAttemptToModify attemptToModify(
result_r );
1636 for_(
step, steps.begin(), steps.end() )
1653 if (
citem.status().isToBeInstalled() )
1662 WAR <<
"commit aborted by the user" << endl;
1670 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
1679 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
1688 bool success =
false;
1714 WAR <<
"commit aborted by the user" << endl;
1722 if (
citem.isNeedreboot() ) {
1739 WAR <<
"dry run failed" << endl;
1746 WAR <<
"commit aborted by the user" << endl;
1751 WAR <<
"Install failed" << endl;
1757 if ( success && !
policy_r.dryRun() )
1769 bool success =
false;
1782 WAR <<
"commit aborted by the user" << endl;
1798 WAR <<
"commit aborted by the user" << endl;
1804 WAR <<
"removal of " <<
p <<
" failed";
1807 if ( success && !
policy_r.dryRun() )
1818 if ( !
citem.buddy() )
1823 if (
citem.status().isToBeInstalled() )
1825 ERR <<
"Can't install orphan product without release-package! " <<
citem << endl;
1831 std::string referenceFilename(
p->referenceFilename() );
1832 if ( referenceFilename.empty() )
1834 ERR <<
"Can't remove orphan product without 'referenceFilename'! " <<
citem << endl;
1848 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1882 WAR <<
"Commit aborted by the user" << endl;
1929 return ReportType::loglevel::crt;
1931 return ReportType::loglevel::err;
1933 return ReportType::loglevel::war;
1937 return ReportType::loglevel::msg;
1939 return ReportType::loglevel::dbg;
1960 namespace zpt = zypp::proto::target;
1966 MIL <<
"TargetImpl::commit(<list>" <<
policy_r <<
")" << steps.size() << endl;
1971 NotifyAttemptToModify attemptToModify(
result_r );
1974 result_r.setSingleTransactionMode(
true );
1984 rpm::RpmInstFlags flags(
policy_r.rpmInstFlags()
1993 commit.set_flags( flags );
2002 for (
auto &[
_, value] : data ) {
2004 value.resetDispose();
2010 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)
stepId < steps.size() && !abort ; ++
stepId ) {
2025 if (
citem.status().isToBeInstalled() )
2030 zpt::TransactionStep
tStep;
2033 tStep.mutable_install()->set_multiversion(
p->multiversionInstall() );
2035 *
commit.mutable_steps()->Add( ) = std::move(
tStep);
2039 WAR <<
"commit aborted by the user" << endl;
2047 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
2056 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2062 zpt::TransactionStep
tStep;
2064 tStep.mutable_remove()->set_name(
p->name() );
2065 tStep.mutable_remove()->set_version(
p->edition().version() );
2066 tStep.mutable_remove()->set_release(
p->edition().release() );
2067 tStep.mutable_remove()->set_arch(
p->arch().asString() );
2069 *
commit.mutable_steps()->Add() = std::move(
tStep);
2080 zpt::TransactionStep
tStep;
2083 tStep.mutable_install()->set_multiversion(
false );
2084 *
commit.mutable_steps()->Add() = std::move(
tStep);
2088 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2097 if (
commit.steps_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;
2188 WAR <<
"Got rpm output without active report " <<
line;
2193 if (
line.find(
" scriptlet failed, " ) == std::string::npos )
2197 if (
line.back() !=
'\n' )
2218 L_DBG(
"zypp-rpm") <<
"[rpm> " <<
l;
2245 ERR <<
"There is still a running report, this is a bug" << std::endl;
2253 if (
rpmmsg.size() == 0 )
2257 rpmmsg +=
"[truncated]\n";
2259 std::ostringstream
sstr;
2260 sstr <<
"rpm output:" << endl <<
rpmmsg << endl;
2285 ( *installreport)->progress( 100,
resObj );
2295 if (
citem.isNeedreboot() ) {
2323 ( *uninstallreport)->progress( 100,
resObj );
2338 ( *scriptreport)->progress( 100,
resObj );
2343 ( *transactionreport)->progress( 100 );
2348 ( *cleanupreport)->progress( 100 );
2372 const char *
argv[] = {
2396 if ( !
scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2399 prog->sigStarted().connect( [&](){
2407 while(
prog->canReadLine( channel ) ) {
2408 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2429 if ( !
commit.SerializeToZeroCopyStream( &
fo ) ) {
2440 if ( !
msgSource->openFds( std::vector<int>{ messagePipe->readFd } ) )
2449 if ( !
p.ParseFromString(
m.
value() ) ) {
2450 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2454 auto id =
p.stepid();
2456 ERR <<
"Received invalid stepId: " <<
id <<
" in " <<
m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2477 zypp::proto::Envelope
m;
2478 if (!
m.ParseFromArray(
bytes.data(),
bytes.size() ) ) {
2481 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2489 const auto &
mName =
m.messagetypename();
2490 if (
mName ==
"zypp.proto.target.RpmLog" ) {
2493 if ( !
p.ParseFromString(
m.
value() ) ) {
2494 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2499 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " <<
p.level() <<
"> " <<
p.line();
2502 }
else if (
mName ==
"zypp.proto.target.PackageBegin" ) {
2505 zpt::PackageBegin
p;
2511 auto &
step = steps.at(
p.stepid() );
2514 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2517 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2521 }
else if (
mName ==
"zypp.proto.target.PackageFinished" ) {
2522 zpt::PackageFinished
p;
2526 if (
p.stepid() < 0 ||
p.stepid() > steps.size() )
2533 }
else if (
mName ==
"zypp.proto.target.PackageProgress" ) {
2534 zpt::PackageProgress
p;
2539 (*uninstallreport)->progress(
p.amount(),
makeResObject( steps.at(
p.stepid() ) ));
2541 (*installreport)->progress(
p.amount(),
makeResObject( steps.at(
p.stepid() ) ));
2543 ERR <<
"Received a " <<
mName <<
" message but there is no corresponding report running." << std::endl;
2545 }
else if (
mName ==
"zypp.proto.target.PackageError" ) {
2546 zpt::PackageError
p;
2550 if (
p.stepid() >= 0 &&
p.stepid() < steps.size() )
2555 }
else if (
mName ==
"zypp.proto.target.ScriptBegin" ) {
2559 if ( !
p.ParseFromString(
m.
value() ) ) {
2560 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2567 const auto stepId =
p.stepid();
2573 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2576 (*scriptreport)->start(
p.scripttype(),
p.scriptpackage(),
resPtr );
2578 }
else if (
mName ==
"zypp.proto.target.ScriptFinished" ) {
2582 }
else if (
mName ==
"zypp.proto.target.ScriptError" ) {
2585 if ( !
p.ParseFromString(
m.
value() ) ) {
2586 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2591 const auto stepId =
p.stepid();
2608 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2620 }
else if (
mName ==
"zypp.proto.target.CleanupBegin" ) {
2623 zpt::CleanupBegin
beg;
2624 if ( !
beg.ParseFromString(
m.
value() ) ) {
2625 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2630 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2631 (*cleanupreport)->start(
beg.nvra() );
2632 }
else if (
mName ==
"zypp.proto.target.CleanupFinished" ) {
2636 }
else if (
mName ==
"zypp.proto.target.CleanupProgress" ) {
2637 zpt::CleanupProgress
prog;
2639 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2644 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2648 (*cleanupreport)->progress(
prog.amount() );
2650 }
else if (
mName ==
"zypp.proto.target.TransBegin" ) {
2653 zpt::TransBegin
beg;
2654 if ( !
beg.ParseFromString(
m.
value() ) ) {
2655 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2660 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2661 (*transactionreport)->start(
beg.name() );
2662 }
else if (
mName ==
"zypp.proto.target.TransFinished" ) {
2666 }
else if (
mName ==
"zypp.proto.target.TransProgress" ) {
2667 zpt::TransProgress
prog;
2669 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2674 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2678 (*transactionreport)->progress(
prog.amount() );
2679 }
else if (
mName ==
"zypp.proto.target.TransactionError" ) {
2681 zpt::TransactionError error;
2682 if ( !error.ParseFromString(
m.
value() ) ) {
2683 ERR <<
"Failed to parse " <<
m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2691 ERR <<
"Received unexpected message from zypp-rpm: "<<
m.messagetypename() <<
", ignoring" << std::endl;
2743 case zypprpm::NoError:
2744 case zypprpm::RpmFinishedWithError:
2746 case zypprpm::RpmFinishedWithTransactionError: {
2750 std::ostringstream
sstr;
2751 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2753 sstr <<
" " << err.message() <<
"\n";
2763 case zypprpm::FailedToOpenDb:
2766 case zypprpm::WrongHeaderSize:
2767 case zypprpm::WrongMessageFormat:
2770 case zypprpm::RpmInitFailed:
2773 case zypprpm::FailedToReadPackage:
2776 case zypprpm::FailedToAddStepToTransaction:
2779 case zypprpm::RpmOrderFailed:
2782 case zypprpm::FailedToCreateLock:
2787 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)
stepId < steps.size() && !abort; ++
stepId ) {
2799 if (
citem.status().isToBeInstalled() ) {
2800 ERR <<
"Can't install orphan product without release-package! " <<
citem << endl;
2804 std::string referenceFilename(
p->referenceFilename() );
2806 if ( referenceFilename.empty() ) {
2807 ERR <<
"Can't remove orphan product without 'referenceFilename'! " <<
citem << endl;
2817 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2836 WAR <<
"Commit aborted by the user" << endl;
2890 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2895 inline Pathname staticGuessRoot(
const Pathname & root_r )
2897 if ( root_r.empty() )
2902 return Pathname(
"/");
2908 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2910 std::ifstream idfile( file_r.c_str() );
2911 for( iostr::EachLine in( idfile ); in; in.next() )
2914 if ( ! line.empty() )
2917 return std::string();
2928 if (
p->isTargetDistribution() )
2938 if ( target && target->root() ==
needroot )
2939 return target->requestedLocales();
2945 MIL <<
"updateAutoInstalled if changed..." << endl;
3021 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.
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.
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
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()> sigReadyRead()
SignalProxy< void(int)> sigFinished()
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.
BlockingMode setFDBlocking(int fd, bool mode)
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.
auto eintrSafeCall(Fun &&function, Args &&... args)
google::protobuf::io::FileOutputStream FileOutputStream
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)