19 #include <sys/types.h> 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> 28 #include <zypp-core/base/UserRequestException> 33 #include <zypp/PathInfo.h> 38 #include <zypp/TmpPath.h> 40 #include <zypp/ExternalProgram.h> 56 #include <zypp/sat/detail/PoolImpl.h> 60 #include <zypp-core/base/String.h> 61 #include <zypp-core/base/StringV.h> 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> 66 #include <zypp-core/base/IOTools.h> 67 #include <zypp-core/zyppng/rpc/rpc.h> 68 #include <zypp-core/zyppng/base/private/linuxhelpers_p.h> 69 #include <zypp-core/zyppng/base/EventDispatcher> 70 #include <zypp-proto/target/commit.pb.h> 71 #include <zypp-proto/core/envelope.pb.h> 72 #include <zypp-core/zyppng/rpc/zerocopystreams.h> 79 #include "tools/zypp-rpm/errorcodes.h" 80 #include <rpm/rpmlog.h> 89 #include <solv/repo_rpmdb.h> 90 #include <solv/chksum.h> 100 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
101 ::solv_chksum_free( chk,
nullptr );
103 if ( ::rpm_hash_database_state( state, chk ) == 0 )
106 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
110 WAR <<
"rpm_hash_database_state failed" << endl;
130 inline void sigMultiversionSpecChanged()
148 for (
const Transaction::Step & step : steps_r )
150 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
160 static const std::string strType(
"type" );
161 static const std::string strStage(
"stage" );
162 static const std::string strSolvable(
"solvable" );
164 static const std::string strTypeDel(
"-" );
165 static const std::string strTypeIns(
"+" );
166 static const std::string strTypeMul(
"M" );
168 static const std::string strStageDone(
"ok" );
169 static const std::string strStageFailed(
"err" );
171 static const std::string strSolvableN(
"n" );
172 static const std::string strSolvableE(
"e" );
173 static const std::string strSolvableV(
"v" );
174 static const std::string strSolvableR(
"r" );
175 static const std::string strSolvableA(
"a" );
182 case Transaction::TRANSACTION_IGNORE:
break;
183 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
184 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
185 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
190 case Transaction::STEP_TODO:
break;
191 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
192 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
201 ident = solv.ident();
208 ident = step_r.
ident();
210 arch = step_r.
arch();
215 { strSolvableV, ed.
version() },
216 { strSolvableR, ed.
release() },
220 s.add( strSolvableE, epoch );
222 ret.
add( strSolvable, s );
236 class AssertMountedBase
248 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
249 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
257 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
269 class AssertProcMounted :
private AssertMountedBase
272 AssertProcMounted( Pathname root_r )
275 if ( ! PathInfo(root_r/
"self").isDir() ) {
276 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
278 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
282 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
290 class AssertDevMounted :
private AssertMountedBase
293 AssertDevMounted( Pathname root_r )
296 if ( ! PathInfo(root_r/
"null").isChr() ) {
297 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
302 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
306 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
323 std::ifstream infile( historyFile_r.c_str() );
324 for( iostr::EachLine in( infile ); in; in.next() )
326 const char * ch( (*in).c_str() );
328 if ( *ch <
'1' ||
'9' < *ch )
330 const char * sep1 = ::strchr( ch,
'|' );
335 bool installs =
true;
336 if ( ::strncmp( sep1,
"install|", 8 ) )
338 if ( ::strncmp( sep1,
"remove |", 8 ) )
345 const char * sep2 = ::strchr( sep1,
'|' );
346 if ( !sep2 || sep1 == sep2 )
348 (*in)[sep2-ch] =
'\0';
349 IdString pkg( sep1 );
353 onSystemByUserList.erase( pkg );
357 if ( (sep1 = ::strchr( sep2+1,
'|' ))
358 && (sep1 = ::strchr( sep1+1,
'|' ))
359 && (sep2 = ::strchr( sep1+1,
'|' )) )
361 (*in)[sep2-ch] =
'\0';
362 if ( ::strchr( sep1+1,
'@' ) )
365 onSystemByUserList.insert( pkg );
370 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
371 return onSystemByUserList;
381 return PluginFrame( command_r, json::Object {
382 {
"TransactionStepList", steps_r }
392 MIL <<
"Testcases to keep: " << toKeep << endl;
398 WAR <<
"No Target no Testcase!" << endl;
402 std::string stem(
"updateTestcase" );
403 Pathname dir( target->assertRootPrefix(
"/var/log/") );
407 std::list<std::string> content;
409 std::set<std::string> cases;
410 for_( c, content.begin(), content.end() )
415 if ( cases.size() >= toKeep )
417 unsigned toDel = cases.size() - toKeep + 1;
418 for_( c, cases.begin(), cases.end() )
427 MIL <<
"Write new testcase " << next << endl;
428 getZYpp()->resolver()->createSolverTestcase( next.asString(),
false );
445 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
455 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
460 WAR <<
"User request to abort script " << script_r << endl;
469 if ( prog.close() != 0 )
471 ret.second = report_r->problem( prog.execError() );
472 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
473 std::ostringstream sstr;
474 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
475 historylog.
comment(sstr.str(),
true);
487 bool executeScript(
const Pathname & root_r,
488 const Pathname & script_r,
489 callback::SendReport<PatchScriptReport> & report_r )
494 action = doExecuteScript( root_r, script_r, report_r );
498 switch ( action.second )
501 WAR <<
"User request to abort at script " << script_r << endl;
506 WAR <<
"User request to skip script " << script_r << endl;
516 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
525 bool RunUpdateScripts(
const Pathname & root_r,
526 const Pathname & scriptsPath_r,
527 const std::vector<sat::Solvable> & checkPackages_r,
530 if ( checkPackages_r.empty() )
533 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
535 if ( ! PathInfo( scriptsDir ).isDir() )
538 std::list<std::string> scripts;
540 if ( scripts.empty() )
548 std::map<std::string, Pathname> unify;
549 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
551 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
552 for_( sit, scripts.begin(), scripts.end() )
557 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
560 PathInfo script( scriptsDir / *sit );
561 Pathname localPath( scriptsPath_r/(*sit) );
562 std::string unifytag;
564 if ( script.isFile() )
570 else if ( ! script.isExist() )
578 if ( unifytag.empty() )
582 if ( unify[unifytag].empty() )
584 unify[unifytag] = localPath;
591 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
592 MIL <<
"Skip update script: " << msg << endl;
593 HistoryLog().comment( msg,
true );
597 if ( abort || aborting_r )
599 WAR <<
"Aborting: Skip update script " << *sit << endl;
600 HistoryLog().comment(
601 localPath.asString() +
_(
" execution skipped while aborting"),
606 MIL <<
"Found update script " << *sit << endl;
607 callback::SendReport<PatchScriptReport> report;
608 report->start( make<Package>( *it ), script.path() );
610 if ( ! executeScript( root_r, localPath, report ) )
622 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
624 std::ifstream infile( file_r.c_str() );
625 for( iostr::EachLine in( infile ); in; in.next() )
627 out_r << *in << endl;
631 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
633 std::string ret( cmd_r );
634 #define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL ) 635 SUBST_IF(
"%p", notification_r.solvable().asString() );
636 SUBST_IF(
"%P", notification_r.file().asString() );
641 void sendNotification(
const Pathname & root_r,
644 if ( notifications_r.empty() )
648 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
649 if ( cmdspec.empty() )
653 if ( pos == std::string::npos )
655 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
656 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
661 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
663 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
664 Format format = UNKNOWN;
665 if ( formatStr ==
"none" )
667 else if ( formatStr ==
"single" )
669 else if ( formatStr ==
"digest" )
671 else if ( formatStr ==
"bulk" )
675 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
676 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
684 if ( format == NONE || format == SINGLE )
686 for_( it, notifications_r.begin(), notifications_r.end() )
688 std::vector<std::string> command;
689 if ( format == SINGLE )
691 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
696 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
700 int ret = prog.close();
703 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
704 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
710 else if ( format == DIGEST || format == BULK )
712 filesystem::TmpFile tmpfile;
713 std::ofstream out( tmpfile.path().c_str() );
714 for_( it, notifications_r.begin(), notifications_r.end() )
716 if ( format == DIGEST )
718 out << it->file() << endl;
720 else if ( format == BULK )
726 std::vector<std::string> command;
727 command.push_back(
"<"+tmpfile.path().asString() );
728 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
733 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
737 int ret = prog.close();
740 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
741 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
748 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
749 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
760 void RunUpdateMessages(
const Pathname & root_r,
761 const Pathname & messagesPath_r,
762 const std::vector<sat::Solvable> & checkPackages_r,
763 ZYppCommitResult & result_r )
765 if ( checkPackages_r.empty() )
768 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
770 if ( ! PathInfo( messagesDir ).isDir() )
773 std::list<std::string> messages;
775 if ( messages.empty() )
781 HistoryLog historylog;
782 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
784 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
785 for_( sit, messages.begin(), messages.end() )
790 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
793 PathInfo message( messagesDir / *sit );
794 if ( ! message.isFile() || message.size() == 0 )
797 MIL <<
"Found update message " << *sit << endl;
798 Pathname localPath( messagesPath_r/(*sit) );
799 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
800 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
803 sendNotification( root_r, result_r.updateMessages() );
809 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
812 if ( changedPseudoInstalled.empty() )
820 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
826 HistoryLog historylog;
827 for (
const auto & el : changedPseudoInstalled )
828 historylog.patchStateChange( el.first, el.second );
837 const std::vector<sat::Solvable> & checkPackages_r,
839 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
852 , _requestedLocalesFile( home() /
"RequestedLocales" )
853 , _autoInstalledFile( home() /
"AutoInstalled" )
862 sigMultiversionSpecChanged();
863 MIL <<
"Initialized target on " <<
_root << endl;
871 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
881 boost::function<
bool ()> condition,
882 boost::function<std::string ()> value )
884 std::string val = value();
892 MIL <<
"updating '" << filename <<
"' content." << endl;
896 std::ofstream filestr;
899 filestr.open( filename.
c_str() );
901 if ( filestr.good() )
937 WAR <<
"Can't create anonymous id file" << endl;
946 Pathname flavorpath(
home() /
"LastDistributionFlavor");
952 WAR <<
"No base product, I won't create flavor cache" << endl;
956 std::string flavor = p->flavor();
968 WAR <<
"Can't create flavor cache" << endl;
981 sigMultiversionSpecChanged();
982 MIL <<
"Targets closed" << endl;
1006 Pathname rpmsolvcookie = base/
"cookie";
1008 bool build_rpm_solv =
true;
1018 MIL <<
"Read cookie: " << cookie << endl;
1023 if ( status == rpmstatus )
1024 build_rpm_solv =
false;
1025 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: " 1026 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1030 if ( build_rpm_solv )
1044 bool switchingToTmpSolvfile =
false;
1045 Exception ex(
"Failed to cache rpm database.");
1051 rpmsolv = base/
"solv";
1052 rpmsolvcookie = base/
"cookie";
1059 WAR <<
"Using a temporary solv file at " << base << endl;
1060 switchingToTmpSolvfile =
true;
1069 if ( ! switchingToTmpSolvfile )
1079 cmd.push_back(
"rpmdb2solv" );
1081 cmd.push_back(
"-r" );
1084 cmd.push_back(
"-D" );
1086 cmd.push_back(
"-X" );
1088 cmd.push_back(
"-p" );
1091 if ( ! oldSolvFile.
empty() )
1092 cmd.push_back( oldSolvFile.
asString() );
1094 cmd.push_back(
"-o" );
1098 std::string errdetail;
1101 WAR <<
" " << output;
1102 if ( errdetail.empty() ) {
1106 errdetail += output;
1109 int ret = prog.
close();
1130 if (
root() ==
"/" )
1141 if ( !
PathInfo(base/
"solv.idx").isExist() )
1144 return build_rpm_solv;
1162 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1163 ", force loading: " << (force?
"true":
"false") << endl;
1168 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1175 if ( newCache || force )
1192 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1198 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1223 if (
PathInfo( historyFile ).isExist() )
1230 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1231 onSystemByAuto.insert( ident );
1252 if (
PathInfo( needrebootFile ).isFile() )
1253 needrebootSpec.
parseFrom( needrebootFile );
1256 if (
PathInfo( needrebootDir ).isDir() )
1261 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool 1263 if ( ! isRpmConfigBackup( str_r ) )
1265 Pathname needrebootFile { needrebootDir / str_r };
1266 if (
PathInfo( needrebootFile ).isFile() )
1267 needrebootSpec.
parseFrom( needrebootFile );
1278 if ( ! hardLocks.empty() )
1287 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1299 bool explicitDryRun = policy_r.
dryRun();
1309 if (
root() ==
"/" )
1323 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1342 steps.push_back( *it );
1349 MIL <<
"Todo: " << result << endl;
1359 if ( commitPlugins )
1360 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1367 if ( ! policy_r.
dryRun() )
1373 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1380 if ( ! policy_r.
dryRun() )
1402 DBG <<
"dryRun: Not storing non-package data." << endl;
1409 if ( ! policy_r.
dryRun() )
1411 for_( it, steps.begin(), steps.end() )
1413 if ( ! it->satSolvable().isKind<
Patch>() )
1421 if ( ! patch ||patch->message().empty() )
1424 MIL <<
"Show message for " << patch << endl;
1426 if ( ! report->show( patch ) )
1428 WAR <<
"commit aborted by the user" << endl;
1435 DBG <<
"dryRun: Not checking patch messages." << endl;
1457 for_( it, steps.begin(), steps.end() )
1459 switch ( it->stepType() )
1478 localfile = packageCache.
get( pi );
1481 catch (
const AbortRequestException & exp )
1485 WAR <<
"commit cache preload aborted by the user" << endl;
1489 catch (
const SkipRequestException & exp )
1494 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1504 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1514 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1518 if ( ! policy_r.
dryRun() )
1525 commit( policy_r, packageCache, result );
1530 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1531 if ( explicitDryRun ) {
1545 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1546 if ( explicitDryRun ) {
1558 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1567 if ( commitPlugins )
1568 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1573 if ( ! policy_r.
dryRun() )
1578 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1589 struct NotifyAttemptToModify
1607 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1612 NotifyAttemptToModify attemptToModify( result_r );
1617 AssertProcMounted assertProcMounted(
_root );
1618 AssertDevMounted assertDevMounted(
_root );
1621 std::vector<sat::Solvable> successfullyInstalledPackages;
1624 for_( step, steps.begin(), steps.end() )
1646 localfile = packageCache_r.
get( citem );
1648 catch (
const AbortRequestException &e )
1650 WAR <<
"commit aborted by the user" << endl;
1655 catch (
const SkipRequestException &e )
1658 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1667 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1676 bool success =
false;
1702 if ( progress.aborted() )
1704 WAR <<
"commit aborted by the user" << endl;
1713 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1729 WAR <<
"dry run failed" << endl;
1734 if ( progress.aborted() )
1736 WAR <<
"commit aborted by the user" << endl;
1741 WAR <<
"Install failed" << endl;
1747 if ( success && !policy_r.
dryRun() )
1750 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1759 bool success =
false;
1770 if ( progress.aborted() )
1772 WAR <<
"commit aborted by the user" << endl;
1786 if ( progress.aborted() )
1788 WAR <<
"commit aborted by the user" << endl;
1794 WAR <<
"removal of " << p <<
" failed";
1797 if ( success && !policy_r.
dryRun() )
1804 else if ( ! policy_r.
dryRun() )
1808 if ( ! citem.
buddy() )
1815 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1821 std::string referenceFilename( p->referenceFilename() );
1822 if ( referenceFilename.empty() )
1824 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1828 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1829 if ( !
rpm().hasFile( referencePath.asString() ) )
1834 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1838 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1865 if ( ! successfullyInstalledPackages.empty() )
1868 successfullyInstalledPackages, abort ) )
1870 WAR <<
"Commit aborted by the user" << endl;
1876 successfullyInstalledPackages,
1883 logPatchStatusChanges( result_r.
transaction(), *this );
1902 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
1905 data.
set(
"line", std::cref(line_r) );
1906 data.set(
"level", level_r );
1912 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
1913 switch ( rpmlevel_r ) {
1914 case RPMLOG_EMERG: [[fallthrough]];
1915 case RPMLOG_ALERT: [[fallthrough]];
1917 return ReportType::loglevel::crt;
1919 return ReportType::loglevel::err;
1920 case RPMLOG_WARNING:
1921 return ReportType::loglevel::war;
1922 default: [[fallthrough]];
1923 case RPMLOG_NOTICE: [[fallthrough]];
1925 return ReportType::loglevel::msg;
1927 return ReportType::loglevel::dbg;
1935 { (*this)->report( userData_r ); }
1948 namespace zpt = zypp::proto::target;
1954 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1959 NotifyAttemptToModify attemptToModify( result_r );
1965 AssertProcMounted assertProcMounted(
_root );
1966 AssertDevMounted assertDevMounted(
_root );
1981 commit.set_flags( flags );
1990 for (
auto &[
_, value] : data ) {
1992 value.resetDispose();
1999 auto &step = steps[stepId];
2016 locCache.value()[stepId] = packageCache_r.
get( citem );
2018 zpt::TransactionStep tStep;
2019 tStep.set_stepid( stepId );
2020 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2021 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
2023 *
commit.mutable_steps()->Add( ) = std::move(tStep);
2025 catch (
const AbortRequestException &e )
2027 WAR <<
"commit aborted by the user" << endl;
2032 catch (
const SkipRequestException &e )
2035 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2044 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2050 zpt::TransactionStep tStep;
2051 tStep.set_stepid( stepId );
2052 tStep.mutable_remove()->set_name( p->name() );
2053 tStep.mutable_remove()->set_version( p->edition().version() );
2054 tStep.mutable_remove()->set_release( p->edition().release() );
2055 tStep.mutable_remove()->set_arch( p->arch().asString() );
2057 *
commit.mutable_steps()->Add() = std::move(tStep);
2068 zpt::TransactionStep tStep;
2069 tStep.set_stepid( stepId );
2070 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2071 tStep.mutable_install()->set_multiversion(
false );
2072 *
commit.mutable_steps()->Add() = std::move(tStep);
2076 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2083 std::vector<sat::Solvable> successfullyInstalledPackages;
2085 if (
commit.steps_size() ) {
2088 auto loop = zyppng::EventLoop::create();
2092 const std::vector<int> interceptedSignals {
2099 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2100 unixSignals->sigReceived ().connect ([](
int signum ){
2102 JobReport::error (
str::Format(
_(
"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it is not possible to cancel a running rpm transaction.") ) % strsignal(signum) % signum );
2104 for(
const auto &sig : interceptedSignals )
2105 unixSignals->addSignal ( sig );
2108 for(
const auto &sig : interceptedSignals )
2109 unixSignals->removeSignal ( sig );
2116 int currentStepId = -1;
2122 bool gotEndOfScript =
false;
2125 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2126 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2127 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2128 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2129 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2132 std::optional<zpt::TransactionError> transactionError;
2135 std::string currentScriptType;
2136 std::string currentScriptPackage;
2146 unsigned lineno = 0;
2149 auto msgSource = zyppng::AsyncDataSource::create();
2150 auto scriptSource = zyppng::AsyncDataSource::create();
2155 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2157 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2159 if ( currentStepId >= 0 )
2160 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2161 cmdout.
set(
"line", line );
2165 if ( installreport ) {
2167 }
else if ( uninstallreport ) {
2169 }
else if ( scriptreport ) {
2171 }
else if ( transactionreport ) {
2173 }
else if ( cleanupreport ) {
2176 WAR <<
"Got rpm output without active report " << line;
2181 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2185 if ( line.back() !=
'\n' )
2191 const auto &processDataFromScriptFd = [&](){
2193 while ( scriptSource->canReadLine() ) {
2195 if ( gotEndOfScript )
2198 std::string l = scriptSource->readLine().asString();
2200 gotEndOfScript =
true;
2204 l = l.substr( 0, rawsize );
2206 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2207 sendRpmLineToReport( l );
2210 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2213 const auto &waitForScriptEnd = [&]() {
2216 if ( gotEndOfScript )
2220 processDataFromScriptFd();
2223 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2226 scriptSource->waitForReadyRead( 100 );
2230 const auto &aboutToStartNewReport = [&](){
2232 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2233 ERR <<
"There is still a running report, this is a bug" << std::endl;
2237 gotEndOfScript =
false;
2240 const auto &writeRpmMsgToHistory = [&](){
2241 if ( rpmmsg.size() == 0 )
2245 rpmmsg +=
"[truncated]\n";
2247 std::ostringstream sstr;
2248 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2253 const auto &finalizeCurrentReport = [&]() {
2256 if ( currentStepId >= 0 ) {
2257 step = &steps.at(currentStepId);
2261 if ( installreport ) {
2269 writeRpmMsgToHistory();
2273 ( *installreport)->progress( 100, resObj );
2276 if ( currentStepId >= 0 )
2277 locCache.value().erase( currentStepId );
2278 successfullyInstalledPackages.push_back( step->
satSolvable() );
2284 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2296 writeRpmMsgToHistory();
2299 if ( uninstallreport ) {
2307 writeRpmMsgToHistory();
2311 ( *uninstallreport)->progress( 100, resObj );
2321 writeRpmMsgToHistory();
2324 if ( scriptreport ) {
2326 ( *scriptreport)->progress( 100, resObj );
2329 if ( transactionreport ) {
2331 ( *transactionreport)->progress( 100 );
2334 if ( cleanupreport ) {
2336 ( *cleanupreport)->progress( 100 );
2342 currentScriptType.clear();
2343 currentScriptPackage.clear();
2344 installreport.reset();
2345 uninstallreport.reset();
2346 scriptreport.reset();
2347 transactionreport.reset();
2348 cleanupreport.reset();
2358 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2360 const char *argv[] = {
2363 zyppRpmBinary.data(),
2366 auto prog = zyppng::Process::create();
2370 auto messagePipe = zyppng::Pipe::create();
2376 auto scriptPipe = zyppng::Pipe::create();
2380 prog->addFd( messagePipe->writeFd );
2381 prog->addFd( scriptPipe->writeFd );
2384 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2387 prog->sigStarted().connect( [&](){
2390 messagePipe->unrefWrite();
2391 scriptPipe->unrefWrite();
2394 prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&](
int channel ){
2395 while( prog->canReadLine( channel ) ) {
2396 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2402 const auto outFd = prog->stdinFd();
2409 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2410 const auto written = zyppng::eintrSafeCall( ::
write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2411 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2412 prog->stop( SIGKILL );
2416 zyppng::FileOutputStream fo ( outFd );
2417 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2418 prog->stop( SIGKILL );
2428 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd } ) )
2431 zyppng::rpc::HeaderSizeType pendingMessageSize = 0;
2432 const auto &processMessages = [&] ( ) {
2436 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2437 if ( !p.ParseFromString( m.value() ) ) {
2438 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2442 auto id = p.stepid();
2443 if ( id < 0 || id >= steps.size() ) {
2444 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2450 while ( msgSource->bytesAvailable() ) {
2452 if ( pendingMessageSize == 0 ) {
2453 if ( std::size_t(msgSource->bytesAvailable()) >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2454 msgSource->read( reinterpret_cast<char *>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2458 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2462 auto bytes = msgSource->read( pendingMessageSize );
2463 pendingMessageSize = 0;
2465 zypp::proto::Envelope m;
2466 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2469 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2477 const auto &mName = m.messagetypename();
2478 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2481 if ( !p.ParseFromString( m.value() ) ) {
2482 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2485 ( p.level() >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2486 : p.level() >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2487 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p.level() <<
"> " << p.line();
2490 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2491 finalizeCurrentReport();
2493 zpt::PackageBegin p;
2494 if ( !parseMsgWithStepId( m, p ) )
2497 aboutToStartNewReport();
2499 auto & step = steps.at( p.stepid() );
2500 currentStepId = p.stepid();
2502 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2503 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2505 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2506 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2509 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2510 zpt::PackageFinished p;
2511 if ( !parseMsgWithStepId( m, p ) )
2514 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2521 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2522 zpt::PackageProgress p;
2523 if ( !parseMsgWithStepId( m, p ) )
2526 if ( uninstallreport )
2527 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2528 else if ( installreport )
2529 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2531 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2533 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2534 zpt::PackageError p;
2535 if ( !parseMsgWithStepId( m, p ) )
2538 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2541 finalizeCurrentReport();
2543 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2544 finalizeCurrentReport();
2547 if ( !p.ParseFromString( m.value() ) ) {
2548 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2552 aboutToStartNewReport();
2555 const auto stepId = p.stepid();
2556 if ( stepId >= 0 && stepId < steps.size() ) {
2560 currentStepId = p.stepid();
2561 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2562 currentScriptType = p.scripttype();
2563 currentScriptPackage = p.scriptpackage();
2564 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2566 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2570 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2573 if ( !p.ParseFromString( m.value() ) ) {
2574 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2579 const auto stepId = p.stepid();
2580 if ( stepId >= 0 && stepId < steps.size() ) {
2590 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2593 writeRpmMsgToHistory();
2595 if ( !scriptreport ) {
2596 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2605 scriptreport.reset();
2608 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2609 finalizeCurrentReport();
2611 zpt::CleanupBegin beg;
2612 if ( !beg.ParseFromString( m.value() ) ) {
2613 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2617 aboutToStartNewReport();
2618 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2619 (*cleanupreport)->start( beg.nvra() );
2620 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2622 finalizeCurrentReport();
2624 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2625 zpt::CleanupProgress prog;
2626 if ( !prog.ParseFromString( m.value() ) ) {
2627 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2631 if ( !cleanupreport ) {
2632 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2636 (*cleanupreport)->progress( prog.amount() );
2638 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2639 finalizeCurrentReport();
2641 zpt::TransBegin beg;
2642 if ( !beg.ParseFromString( m.value() ) ) {
2643 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2647 aboutToStartNewReport();
2648 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2649 (*transactionreport)->start( beg.name() );
2650 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2652 finalizeCurrentReport();
2654 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2655 zpt::TransProgress prog;
2656 if ( !prog.ParseFromString( m.value() ) ) {
2657 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2661 if ( !transactionreport ) {
2662 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2666 (*transactionreport)->progress( prog.amount() );
2667 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2669 zpt::TransactionError error;
2670 if ( !error.ParseFromString( m.value() ) ) {
2671 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2676 transactionError = std::move(error);
2679 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2685 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2688 int zyppRpmExitCode = -1;
2689 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2690 zyppRpmExitCode = code;
2694 if ( !prog->start( argv ) ) {
2705 finalizeCurrentReport();
2708 bool readMsgs =
false;
2709 while( prog->canReadLine( zyppng::Process::StdErr ) ) {
2711 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView();
2713 while( prog->canReadLine( zyppng::Process::StdOut ) ) {
2715 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView();
2718 while ( scriptSource->canReadLine() ) {
2720 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2722 if ( scriptSource->bytesAvailable() > 0 ) {
2724 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2729 switch ( zyppRpmExitCode ) {
2731 case zypprpm::NoError:
2732 case zypprpm::RpmFinishedWithError:
2734 case zypprpm::RpmFinishedWithTransactionError: {
2736 if ( transactionError ) {
2738 std::ostringstream sstr;
2739 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2740 for (
const auto & err : transactionError->problems() ) {
2741 sstr <<
" " << err.message() <<
"\n";
2751 case zypprpm::FailedToOpenDb:
2754 case zypprpm::WrongHeaderSize:
2755 case zypprpm::WrongMessageFormat:
2758 case zypprpm::RpmInitFailed:
2761 case zypprpm::FailedToReadPackage:
2764 case zypprpm::FailedToAddStepToTransaction:
2767 case zypprpm::RpmOrderFailed:
2770 case zypprpm::FailedToCreateLock:
2776 auto &step = steps[stepId];
2788 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2792 std::string referenceFilename( p->referenceFilename() );
2794 if ( referenceFilename.empty() ) {
2795 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2797 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2799 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2803 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2805 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2819 if ( ! successfullyInstalledPackages.empty() )
2822 successfullyInstalledPackages, abort ) )
2824 WAR <<
"Commit aborted by the user" << endl;
2830 successfullyInstalledPackages,
2837 logPatchStatusChanges( result_r.
transaction(), *this );
2865 if ( baseproduct.isFile() )
2878 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2883 inline Pathname staticGuessRoot(
const Pathname & root_r )
2885 if ( root_r.empty() )
2890 return Pathname(
"/");
2896 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2898 std::ifstream idfile( file_r.c_str() );
2899 for( iostr::EachLine in( idfile ); in; in.next() )
2902 if ( ! line.empty() )
2905 return std::string();
2916 if ( p->isTargetDistribution() )
2924 const Pathname needroot( staticGuessRoot(root_r) );
2925 const Target_constPtr target( getZYpp()->getTarget() );
2926 if ( target && target->root() == needroot )
2927 return target->requestedLocales();
2933 MIL <<
"updateAutoInstalled if changed..." << endl;
2941 {
return baseproductdata(
_root ).registerTarget(); }
2944 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2947 {
return baseproductdata(
_root ).registerRelease(); }
2950 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2953 {
return baseproductdata(
_root ).registerFlavor(); }
2956 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2989 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
2996 scoped_ptr<rpm::RpmDb> tmprpmdb;
3002 tmprpmdb->initDatabase( );
3019 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3024 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3030 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3033 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3034 if ( ret.
empty() && root_r !=
"/" )
3037 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3045 return guessAnonymousUniqueId(
root() );
3050 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3057 MIL <<
"New VendorAttr: " << vendorAttr_r << endl;
std::string asString(const Patch::Category &obj)
static bool fileMissing(const Pathname &pathname)
helper functor
static const UserData::ContentType contentRpmout
"zypp-rpm/scriptsa": Additional rpm output (sent immediately).
std::string asJSON() const
JSON representation.
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
VendorAttr _vendorAttr
vendor equivalence settings.
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Interface to the rpm program.
Convenience SendReport<rpm::SingleTransReport> wrapper.
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
A Solvable object within the sat Pool.
std::vector< sat::Transaction::Step > TransactionStepList
Save and restore locale set from file.
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
Alternating download and install.
zypp::ContentType ContentType
ZYppCommitPolicy & rpmNoSignature(bool yesNo_r)
Use rpm option –nosignature (default: false)
const LocaleSet & getRequestedLocales() const
Return the requested locales.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r) const
Provide SrcPackage in a local file.
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
[M] Install(multiversion) item (
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
bool solvfilesPathIsTemp() const
Whether we're using a temp.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Solvable satSolvable() const
Return the corresponding Solvable.
Result returned from ZYpp::commit.
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...
static ZConfig & instance()
Singleton ctor.
First download all packages to the local cache.
bool isToBeInstalled() const
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
Command frame for communication with PluginScript.
Pathname _tmpSolvfilesPath
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
void setData(const Data &data_r)
Store new Data.
IMPL_PTR_TYPE(TargetImpl)
SolvIdentFile _autoInstalledFile
user/auto installed database
detail::IdType value_type
static ProductFileData scanFile(const Pathname &file_r)
Parse one file (or symlink) and return the ProductFileData parsed.
String matching (STRING|SUBSTRING|GLOB|REGEX).
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
void stampCommand()
Log info about the current process.
Target::commit helper optimizing package provision.
bool isNeedreboot() const
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
const sat::Transaction & transaction() const
The full transaction list.
void discardScripts()
Discard all remembered scrips.
StepStage stepStage() const
Step action result.
const Pathname & file() const
Return the file path.
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
ResStatus & status() const
Returns the current status.
static const UserData::ContentType contentLogline
"zypp-rpm/logline" report a line suitable to be written to the screen.
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
byKind_iterator byKindBegin(const ResKind &kind_r) const
void updateAutoInstalled()
Update the database of autoinstalled packages.
ZYppCommitPolicy & rpmExcludeDocs(bool yesNo_r)
Use rpm option –excludedocs (default: false)
const char * c_str() const
String representation.
std::string _distributionVersion
Cache distributionVersion.
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Parallel execution of stateful PluginScripts.
void setData(const Data &data_r)
Store new Data.
void setAutoInstalled(const Queue &autoInstalled_r)
Set ident list of all autoinstalled solvables.
sat::Solvable buddy() const
Return the buddy we share our status object with.
Access to the sat-pools string space.
Libsolv transaction wrapper.
Edition represents [epoch:]version[-release]
Attempts to create a lock to prevent the system from going into hibernate/shutdown.
std::string receiveLine()
Read one line from the input stream.
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
static const UserData::ContentType contentRpmout
"zypp-rpm/transactionsa": Additional rpm output (sent immediately).
Similar to DownloadInAdvance, but try to split the transaction into heaps, where at the end of each h...
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::...
TraitsType::constPtrType constPtr
const_iterator end() const
Iterator behind the last TransactionStep.
Provide a new empty temporary file and delete it when no longer needed.
unsigned epoch_t
Type of an epoch.
void writeUpgradeTestcase()
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
Class representing a patch.
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
void install(const PoolItem &pi)
Log installation (or update) of a package.
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from their initial one.
std::vector< std::string > Arguments
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
Define a set of Solvables by ident and provides.
Extract and remember posttrans scripts for later execution.
Subclass to retrieve database content.
void remember(const Exception &old_r)
Store an other Exception as history.
EstablishedStates establishedStates() const
Factory for EstablishedStates.
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
rpm::RpmDb _rpm
RPM database.
Repository systemRepo()
Return the system repository, create it if missing.
std::string distributionVersion() const
This is version attribute of the installed base product.
const LocaleSet & locales() const
Return the loacale set.
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
void initRequestedLocales(const LocaleSet &locales_r)
Start tracking changes based on this locales_r.
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run...
LocaleSet requestedLocales() const
Languages to be supported by the system.
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
bool empty() const
Test for an empty path.
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
void push(value_type val_r)
Push a value to the end off the Queue.
std::string getline(std::istream &str)
Read one line from stream.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
Store and operate on date (time_t).
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
std::string shortName() const
static Pool instance()
Singleton ctor.
const Data & data() const
Return the data.
std::string version() const
Version.
Pathname _root
Path to the target.
std::string rpmDbStateHash(const Pathname &root_r)
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::string trim(const std::string &s, const Trim trim_r)
int unlink(const Pathname &path)
Like 'unlink'.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
static const std::string & systemRepoAlias()
Reserved system repository alias .
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
static const Pathname & fname()
Get the current log file path.
bool executeScripts()
Execute the remembered scripts.
const std::string & asString() const
String representation.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
Just download all packages to the local cache.
Options and policies for ZYpp::commit.
bool isExist() const
Return whether valid stat info exists.
libzypp will decide what to do.
A single step within a Transaction.
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
void parseFrom(const InputStream &istr_r)
Parse file istr_r and add its specs (one per line, #-comments).
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
void setLocales(const LocaleSet &locales_r)
Store a new locale set.
Pathname rootDir() const
Get rootdir (for file conflicts check)
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
Pathname dirname() const
Return all but the last component od this path.
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from the established one...
std::string release() const
Release.
Interim helper class to collect global options and settings.
Definition of vendor equivalence.
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
void sendLoglineRpm(const std::string &line_r, unsigned rpmlevel_r)
Convenience to send a contentLogline translating a rpm loglevel.
std::string summary() const
bool order()
Order transaction steps for commit.
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Resolver & resolver() const
The Resolver.
Writing the zypp history fileReference counted signleton for writhing the zypp history file...
TraitsType::constPtrType constPtr
const VendorAttr & vendorAttr() const
The targets current vendor equivalence settings.
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
std::list< PoolItem > PoolItemList
list of pool items
std::string anonymousUniqueId() const
anonymous unique id
static const UserData::ContentType contentRpmout
"zypp-rpm/installpkgsa": Additional rpm output (sent immediately).
static PoolImpl & myPool()
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
const char * c_str() const
Conversion to const char *
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
std::string toLower(const std::string &s)
Return lowercase version of s.
Pathname home() const
The directory to store things.
int touch(const Pathname &path)
Change file's modification and access times.
void addProvides(Capability provides_r)
A all sat::Solvable matching this provides_r.
static std::string generateRandomId()
generates a random id using uuidgen
void resetDispose()
Set no dispose function.
ManagedFile get(const PoolItem &citem_r)
Provide a package.
HardLocksFile _hardLocksFile
Hard-Locks database.
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
int close()
Wait for the progamm to complete.
byKind_iterator byKindEnd(const ResKind &kind_r) const
void setHardLockQueries(const HardLockQueries &newLocks_r)
Set a new set of queries.
void setSingleTransactionMode(bool yesno_r)
#define SUBST_IF(PAT, VAL)
std::list< UpdateNotificationFile > UpdateNotifications
Libsolv Id queue wrapper.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
TraitsType::constPtrType constPtr
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
ZYppCommitPolicy & allMedia()
Process all media (default)
const_iterator begin() const
Iterator to the first TransactionStep.
pool::PoolTraits::HardLockQueries Data
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
void add(const Value &val_r)
Push JSON Value to Array.
StepType stepType() const
Type of action to perform in this step.
const Data & data() const
Return the data.
Base class for Exception.
bool preloaded() const
Whether preloaded hint is set.
const std::string & command() const
The command we're executing.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
Data returned by ProductFileReader.
static Date now()
Return the current time.
std::string asJSON() const
JSON representation.
void remove(const PoolItem &pi)
Log removal of a package.
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
Typesafe passing of user data via callbacks.
epoch_t epoch() const
Epoch.
std::string distroverpkg() const
Package telling the "product version" on systems not using /etc/product.d/baseproduct.
Pathname root() const
The root set for this target.
void setNeedrebootSpec(sat::SolvableSpec needrebootSpec_r)
Solvables which should trigger the reboot-needed hint if installed/updated.
virtual ~TargetImpl()
Dtor.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
void eraseFromPool()
Remove this Repository from its Pool.
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 ...
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
#define NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
TraitsType::constPtrType constPtr
static const UserData::ContentType contentRpmout
"zypp-rpm/cleanupkgsa": Additional rpm output (sent immediately).
Wrapper class for ::stat/::lstat.
bool solvablesEmpty() const
Whether Repository contains solvables.
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
sat::Transaction & rTransaction()
Manipulate transaction.
Combining sat::Solvable and ResStatus.
bool singleTransModeEnabled() const
Pathname systemRoot() const
The target root directory.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
Track changing files or directories.
std::string asString() const
Conversion to std::string
bool isKind(const ResKind &kind_r) const
const std::string & asString() const
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
static zypp::Pathname lockfileDir()
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
static const UserData::ContentType contentRpmout
"zypp-rpm/removepkgsa": Additional rpm output (sent immediately).
size_type solvablesSize() const
Number of solvables in Repository.
void commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
Commit ordered changes (internal helper)
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< IdString > Data
Pathname defaultSolvfilesPath() const
The systems default solv file location.
Solvable satSolvable() const
Return the corresponding sat::Solvable.
void add(const String &key_r, const Value &val_r)
Add key/value pair.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
void setCommitList(std::vector< sat::Solvable > commitList_r)
Download(commit) sequence of solvables to compute read ahead.
bool empty() const
Whether this is an empty object without valid data.
std::unordered_set< Locale > LocaleSet
void report(const callback::UserData &userData_r)
rpm::RpmDb & rpm()
The RPM database.
TraitsType::constPtrType constPtr
void multiversionSpecChanged()
BlockingMode setFDBlocking(int fd, bool mode)
#define MAXRPMMESSAGELINES
ZYppCommitResult & _result
Mime type like 'type/subtype' classification of content.
static ResPool instance()
Singleton ctor.
void sendLogline(const std::string &line_r, ReportType::loglevel level_r=ReportType::loglevel::msg)
Convenience to send a contentLogline.
void load(bool force=true)