28#include <zypp-core/base/UserRequestException>
64#include <zypp-core/ng/base/EventLoop>
65#include <zypp-core/ng/base/UnixSignalSource>
66#include <zypp-core/ng/io/AsyncDataSource>
67#include <zypp-core/ng/io/Process>
71#include <zypp-core/ng/base/EventDispatcher>
73#include <shared/commit/CommitMessages.h>
80#include "tools/zypp-rpm/errorcodes.h"
81#include <rpm/rpmlog.h>
88 static bool val = [](){
89 const char *
env = getenv(
"TRANSACTIONAL_UPDATE");
101#include <solv/repo_rpmdb.h>
102#include <solv/chksum.h>
112 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
113 ::solv_chksum_free( chk,
nullptr );
115 if ( ::rpm_hash_database_state( state, chk ) == 0 )
118 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
122 WAR <<
"rpm_hash_database_state failed" << endl;
142 inline void sigMultiversionSpecChanged()
159 static const std::string strType(
"type" );
160 static const std::string strStage(
"stage" );
161 static const std::string strSolvable(
"solvable" );
163 static const std::string strTypeDel(
"-" );
164 static const std::string strTypeIns(
"+" );
165 static const std::string strTypeMul(
"M" );
167 static const std::string strStageDone(
"ok" );
168 static const std::string strStageFailed(
"err" );
170 static const std::string strSolvableN(
"n" );
171 static const std::string strSolvableE(
"e" );
172 static const std::string strSolvableV(
"v" );
173 static const std::string strSolvableR(
"r" );
174 static const std::string strSolvableA(
"a" );
181 case Transaction::TRANSACTION_IGNORE:
break;
182 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
183 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
184 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
189 case Transaction::STEP_TODO:
break;
190 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
191 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
200 ident = solv.ident();
207 ident = step_r.
ident();
209 arch = step_r.
arch();
214 { strSolvableV, ed.
version() },
215 { strSolvableR, ed.
release() },
219 s.
add( strSolvableE, epoch );
221 ret.
add( strSolvable, s );
233 for (
const Transaction::Step & step : steps_r )
235 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
250 struct InstallResolvableSAReportReceiver :
public callback::ReceiveReport<rpm::InstallResolvableReportSA>
252 using ReportType = callback::SendReport<rpm::InstallResolvableReport>;
254 InstallResolvableSAReportReceiver()
255 : _report {
std::make_unique<ReportType>() }
259 { (*_report)->start( resolvable ); }
262 { (*_report)->progress( value, resolvable ); }
268 std::unique_ptr<ReportType> _report;
271 struct RemoveResolvableSAReportReceiver :
public callback::ReceiveReport<rpm::RemoveResolvableReportSA>
273 using ReportType = callback::SendReport<rpm::RemoveResolvableReport>;
275 RemoveResolvableSAReportReceiver()
276 : _report { std::make_unique<ReportType>() }
280 { (*_report)->start( resolvable ); }
283 { (*_report)->progress( value, resolvable ); }
289 std::unique_ptr<ReportType> _report;
297 struct SingleTransReportLegacyWrapper
302 SingleTransReportLegacyWrapper()
304 if ( not singleTransReportsConnected() and legacyReportsConnected() )
306 WAR <<
"Activating SingleTransReportLegacyWrapper! The application does not listen to the singletrans reports :(" << endl;
307 _installResolvableSAReportReceiver = InstallResolvableSAReportReceiver();
308 _removeResolvableSAReportReceiver = RemoveResolvableSAReportReceiver();
309 _installResolvableSAReportReceiver->connect();
310 _removeResolvableSAReportReceiver->connect();
315 ~SingleTransReportLegacyWrapper()
319 bool singleTransReportsConnected()
const
330 bool legacyReportsConnected()
const
338 std::optional<InstallResolvableSAReportReceiver> _installResolvableSAReportReceiver;
339 std::optional<RemoveResolvableSAReportReceiver> _removeResolvableSAReportReceiver;
347 class AssertMountedBase
357 if ( ! _mountpoint.empty() ) {
359 MIL <<
"We mounted " << _mountpoint <<
" so we unmount it" << endl;
360 execute({
"umount",
"-R",
"-l", _mountpoint.asString() });
368 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
374 Pathname _mountpoint;
380 class AssertProcMounted :
private AssertMountedBase
383 AssertProcMounted( Pathname root_r )
386 if ( ! PathInfo(root_r/
"self").isDir() ) {
387 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
389 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
390 _mountpoint = std::move(root_r);
393 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
401 class AssertDevMounted :
private AssertMountedBase
404 AssertDevMounted( Pathname root_r )
407 if ( ! PathInfo(root_r/
"null").isChr() ) {
408 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
413 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
414 _mountpoint = std::move(root_r);
417 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
434 std::ifstream infile( historyFile_r.c_str() );
435 for( iostr::EachLine in( infile ); in; in.next() )
437 const char * ch( (*in).c_str() );
439 if ( *ch <
'1' ||
'9' < *ch )
441 const char * sep1 = ::strchr( ch,
'|' );
446 bool installs =
true;
447 if ( ::strncmp( sep1,
"install|", 8 ) )
449 if ( ::strncmp( sep1,
"remove |", 8 ) )
456 const char * sep2 = ::strchr( sep1,
'|' );
457 if ( !sep2 || sep1 == sep2 )
459 (*in)[sep2-ch] =
'\0';
464 onSystemByUserList.erase( pkg );
468 if ( (sep1 = ::strchr( sep2+1,
'|' ))
469 && (sep1 = ::strchr( sep1+1,
'|' ))
470 && (sep2 = ::strchr( sep1+1,
'|' )) )
472 (*in)[sep2-ch] =
'\0';
473 if ( ::strchr( sep1+1,
'@' ) )
476 onSystemByUserList.insert( pkg );
481 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
482 return onSystemByUserList;
492 return PluginFrame( command_r, json::Object {
503 MIL <<
"Testcases to keep: " << toKeep << endl;
509 WAR <<
"No Target no Testcase!" << endl;
513 std::string stem(
"updateTestcase" );
518 std::list<std::string> content;
520 std::set<std::string> cases;
521 for_( c, content.begin(), content.end() )
526 if ( cases.size() >= toKeep )
528 unsigned toDel = cases.size() - toKeep + 1;
529 for_( c, cases.begin(), cases.end() )
538 MIL <<
"Write new testcase " << next << endl;
556 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
566 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
571 WAR <<
"User request to abort script " << script_r << endl;
580 if ( prog.close() != 0 )
582 ret.second = report_r->problem( prog.execError() );
583 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
584 std::ostringstream sstr;
585 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
586 historylog.
comment(sstr.str(),
true);
598 bool executeScript(
const Pathname & root_r,
599 const Pathname & script_r,
600 callback::SendReport<PatchScriptReport> & report_r )
605 action = doExecuteScript( root_r, script_r, report_r );
609 switch ( action.second )
612 WAR <<
"User request to abort at script " << script_r << endl;
617 WAR <<
"User request to skip script " << script_r << endl;
627 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
636 bool RunUpdateScripts(
const Pathname & root_r,
637 const Pathname & scriptsPath_r,
638 const std::vector<sat::Solvable> & checkPackages_r,
641 if ( checkPackages_r.empty() )
644 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
646 if ( ! PathInfo( scriptsDir ).isDir() )
649 std::list<std::string> scripts;
651 if ( scripts.empty() )
659 std::map<std::string, Pathname> unify;
660 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
662 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
663 for_( sit, scripts.begin(), scripts.end() )
668 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
671 PathInfo script( scriptsDir / *sit );
672 Pathname localPath( scriptsPath_r/(*sit) );
673 std::string unifytag;
675 if ( script.isFile() )
681 else if ( ! script.isExist() )
689 if ( unifytag.empty() )
693 if ( unify[unifytag].
empty() )
695 unify[unifytag] = localPath;
702 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
703 MIL <<
"Skip update script: " << msg << endl;
704 HistoryLog().comment( msg,
true );
708 if ( abort || aborting_r )
710 WAR <<
"Aborting: Skip update script " << *sit << endl;
711 HistoryLog().comment(
712 localPath.asString() +
_(
" execution skipped while aborting"),
717 MIL <<
"Found update script " << *sit << endl;
718 callback::SendReport<PatchScriptReport> report;
721 if ( ! executeScript( root_r, localPath, report ) )
733 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
735 std::ifstream infile( file_r.c_str() );
736 for( iostr::EachLine in( infile ); in; in.next() )
738 out_r << *in << endl;
742 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
744 std::string ret( cmd_r );
745#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
746 SUBST_IF(
"%p", notification_r.solvable().asString() );
747 SUBST_IF(
"%P", notification_r.file().asString() );
752 void sendNotification(
const Pathname & root_r,
755 if ( notifications_r.empty() )
759 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
760 if ( cmdspec.empty() )
763 std::string::size_type pos( cmdspec.find(
'|' ) );
764 if ( pos == std::string::npos )
766 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
767 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
772 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
774 enum Format {
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
776 if ( formatStr ==
"none" )
778 else if ( formatStr ==
"single" )
780 else if ( formatStr ==
"digest" )
782 else if ( formatStr ==
"bulk" )
786 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
787 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
795 if ( format == NONE || format == SINGLE )
797 for_( it, notifications_r.begin(), notifications_r.end() )
799 std::vector<std::string> command;
800 if ( format == SINGLE )
802 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
807 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
811 int ret = prog.close();
814 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
815 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
821 else if ( format == DIGEST || format == BULK )
823 filesystem::TmpFile tmpfile;
824 std::ofstream out( tmpfile.path().c_str() );
825 for_( it, notifications_r.begin(), notifications_r.end() )
827 if ( format == DIGEST )
829 out << it->file() << endl;
831 else if ( format == BULK )
837 std::vector<std::string> command;
838 command.push_back(
"<"+tmpfile.path().asString() );
839 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
844 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
848 int ret = prog.close();
851 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
852 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
859 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
860 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
871 void RunUpdateMessages(
const Pathname & root_r,
872 const Pathname & messagesPath_r,
873 const std::vector<sat::Solvable> & checkPackages_r,
874 ZYppCommitResult & result_r )
876 if ( checkPackages_r.empty() )
879 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
881 if ( ! PathInfo( messagesDir ).isDir() )
884 std::list<std::string> messages;
886 if ( messages.empty() )
892 HistoryLog historylog;
893 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
895 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
896 for_( sit, messages.begin(), messages.end() )
901 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
904 PathInfo message( messagesDir / *sit );
905 if ( ! message.isFile() || message.size() == 0 )
908 MIL <<
"Found update message " << *sit << endl;
909 Pathname localPath( messagesPath_r/(*sit) );
910 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
911 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
914 sendNotification( root_r, result_r.updateMessages() );
920 void logPatchStatusChanges(
const sat::Transaction & transaction_r,
TargetImpl & target_r )
923 if ( changedPseudoInstalled.empty() )
931 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
934 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
937 HistoryLog historylog;
938 for (
const auto & el : changedPseudoInstalled )
939 historylog.patchStateChange( el.first, el.second );
948 const std::vector<sat::Solvable> & checkPackages_r,
950 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
968 _rpm.initDatabase( root_r, doRebuild_r );
973 sigMultiversionSpecChanged();
974 MIL <<
"Initialized target on " <<
_root << endl;
982 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
992 boost::function<
bool ()> condition,
993 boost::function<std::string ()> value )
995 std::string val = value();
1003 MIL <<
"updating '" << filename <<
"' content." << endl;
1007 std::ofstream filestr;
1010 filestr.open( filename.
c_str() );
1012 if ( filestr.good() )
1034 if (
root() !=
"/" )
1048 WAR <<
"Can't create anonymous id file" << endl;
1057 Pathname flavorpath(
home() /
"LastDistributionFlavor");
1063 WAR <<
"No base product, I won't create flavor cache" << endl;
1067 std::string flavor = p->flavor();
1079 WAR <<
"Can't create flavor cache" << endl;
1091 _rpm.closeDatabase();
1092 sigMultiversionSpecChanged();
1093 MIL <<
"Closed target on " <<
_root << endl;
1119 bool build_rpm_solv =
true;
1129 MIL <<
"Read cookie: " << cookie << endl;
1134 if ( status == rpmstatus )
1135 build_rpm_solv =
false;
1136 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1137 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1141 if ( build_rpm_solv )
1155 bool switchingToTmpSolvfile =
false;
1156 Exception ex(
"Failed to cache rpm database.");
1162 rpmsolv =
base/
"solv";
1163 rpmsolvcookie =
base/
"cookie";
1170 WAR <<
"Using a temporary solv file at " <<
base << endl;
1171 switchingToTmpSolvfile =
true;
1180 if ( ! switchingToTmpSolvfile )
1190#ifdef ZYPP_RPMDB2SOLV_PATH
1191 cmd.push_back( ZYPP_RPMDB2SOLV_PATH );
1193 cmd.push_back(
"rpmdb2solv" );
1195 if ( !
_root.empty() ) {
1196 cmd.push_back(
"-r" );
1197 cmd.push_back(
_root.asString() );
1199 cmd.push_back(
"-D" );
1201 cmd.push_back(
"-X" );
1203 cmd.push_back(
"-p" );
1206 if ( ! oldSolvFile.
empty() )
1207 cmd.push_back( oldSolvFile.
asString() );
1209 cmd.push_back(
"-o" );
1213 std::string errdetail;
1216 WAR <<
" " << output;
1217 if ( errdetail.empty() ) {
1221 errdetail += output;
1224 int ret = prog.
close();
1245 if (
root() ==
"/" )
1259 return build_rpm_solv;
1277 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1278 ", force loading: " << (force?
"true":
"false") << endl;
1283 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1290 if ( newCache || force )
1307 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1313 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1338 if (
PathInfo( historyFile ).isExist() )
1345 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1346 onSystemByAuto.insert( ident );
1362 sat::SolvableSpec needrebootSpec;
1363 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1364 needrebootSpec.addProvides(
Capability(
"kernel") );
1367 if (
PathInfo( needrebootFile ).isFile() )
1368 needrebootSpec.parseFrom( needrebootFile );
1371 if (
PathInfo( needrebootDir ).isDir() )
1376 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1378 if ( ! isRpmConfigBackup( str_r ) )
1380 Pathname needrebootFile { needrebootDir / str_r };
1381 if (
PathInfo( needrebootFile ).isFile() )
1382 needrebootSpec.parseFrom( needrebootFile );
1393 if ( ! hardLocks.empty() )
1402 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1414 bool explicitDryRun = policy_r.
dryRun();
1424 if (
root() ==
"/" )
1438 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1457 steps.push_back( *it );
1464 MIL <<
"Todo: " << result << endl;
1475 if ( commitPlugins )
1476 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1483 if ( ! policy_r.
dryRun() )
1489 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1496 if ( ! policy_r.
dryRun() )
1518 DBG <<
"dryRun: Not storing non-package data." << endl;
1525 if ( ! policy_r.
dryRun() )
1527 for_( it, steps.begin(), steps.end() )
1529 if ( ! it->satSolvable().isKind<
Patch>() )
1537 if ( ! patch ||patch->message().empty() )
1540 MIL <<
"Show message for " << patch << endl;
1542 if ( ! report->show( patch ) )
1544 WAR <<
"commit aborted by the user" << endl;
1551 DBG <<
"dryRun: Not checking patch messages." << endl;
1566 std::unique_ptr<CommitPackagePreloader> preloader;
1572 preloader = std::make_unique<CommitPackagePreloader>();
1573 preloader->preloadTransaction( steps );
1574 miss = preloader->missed ();
1581 for_( it, steps.begin(), steps.end() )
1583 switch ( it->stepType() )
1602 localfile = packageCache.
get( pi );
1605 catch (
const AbortRequestException & exp )
1609 WAR <<
"commit cache preload aborted by the user" << endl;
1613 catch (
const SkipRequestException & exp )
1618 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1628 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1639 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1643 if ( ! policy_r.
dryRun() )
1651 commit( policy_r, packageCache, result );
1655 preloader->cleanupCaches ();
1659 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1660 if ( explicitDryRun ) {
1674 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1675 if ( explicitDryRun ) {
1687 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1696 if ( commitPlugins )
1697 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1702 if ( ! policy_r.
dryRun() )
1707 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1718 struct NotifyAttemptToModify
1720 NotifyAttemptToModify(
ZYppCommitResult & result_r ) : _result( result_r ) {}
1723 {
if ( _guard ) { _result.attemptToModify(
true ); _guard =
false; } }
1726 ZYppCommitResult & _result;
1735 {
"ZYPP_SINGLE_RPMTRANS",
nullptr },
1736 {
"ZYPP_CLASSIC_RPMTRANS",
"1" },
1741 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1746 NotifyAttemptToModify attemptToModify( result_r );
1751 AssertProcMounted assertProcMounted(
_root );
1752 AssertDevMounted assertDevMounted(
_root );
1759 std::vector<sat::Solvable> successfullyInstalledPackages;
1762 for_( step, steps.begin(), steps.end() )
1767 if ( citem->isKind<
Package>() )
1771 obsoletedPackages.insert( citem->ident() );
1777 if ( citem->isKind<
Package>() )
1785 localfile = packageCache_r.
get( citem );
1787 catch (
const AbortRequestException &e )
1789 WAR <<
"commit aborted by the user" << endl;
1794 catch (
const SkipRequestException &e )
1797 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1806 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1815 bool success =
false;
1841 WAR <<
"commit aborted by the user" << endl;
1850 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1866 WAR <<
"dry run failed" << endl;
1873 WAR <<
"commit aborted by the user" << endl;
1878 WAR <<
"Install failed" << endl;
1884 if ( success && !policy_r.
dryRun() )
1887 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1896 bool success =
false;
1909 WAR <<
"commit aborted by the user" << endl;
1925 WAR <<
"commit aborted by the user" << endl;
1931 WAR <<
"removal of " << p <<
" failed";
1934 if ( success && !policy_r.
dryRun() )
1941 else if ( ! policy_r.
dryRun() )
1945 if ( ! citem.
buddy() )
1947 if ( citem->isKind<
Product>() )
1952 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1958 std::string referenceFilename( p->referenceFilename() );
1959 if ( referenceFilename.empty() )
1961 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1965 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1966 if ( !
rpm().hasFile( referencePath.
asString() ) )
1971 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1975 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2004 if ( ! successfullyInstalledPackages.empty() )
2007 successfullyInstalledPackages, abort ) )
2009 WAR <<
"Commit aborted by the user" << endl;
2015 successfullyInstalledPackages,
2022 logPatchStatusChanges( result_r.
transaction(), *
this );
2041 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2044 data.
set(
"line", std::cref(line_r) );
2045 data.
set(
"level", level_r );
2051 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
2052 switch ( rpmlevel_r ) {
2053 case RPMLOG_EMERG: [[fallthrough]];
2054 case RPMLOG_ALERT: [[fallthrough]];
2056 return ReportType::loglevel::crt;
2058 return ReportType::loglevel::err;
2059 case RPMLOG_WARNING:
2060 return ReportType::loglevel::war;
2061 default: [[fallthrough]];
2062 case RPMLOG_NOTICE: [[fallthrough]];
2064 return ReportType::loglevel::msg;
2066 return ReportType::loglevel::dbg;
2074 { (*this)->report( userData_r ); }
2080 {
"ZYPP_SINGLE_RPMTRANS",
"1" },
2081 {
"ZYPP_CLASSIC_RPMTRANS",
nullptr },
2084 SingleTransReportLegacyWrapper _legacyWrapper;
2089 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
2094 NotifyAttemptToModify attemptToModify( result_r );
2100 AssertProcMounted assertProcMounted(
_root );
2101 AssertDevMounted assertDevMounted(
_root );
2115 proto::target::Commit
commit;
2125 for (
auto &[
_, value] : data ) {
2127 value.resetDispose();
2133 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2134 auto &step = steps[stepId];
2137 if ( citem->isKind<
Package>() )
2146 if ( citem->isKind<
Package>() ) {
2151 locCache.value()[stepId] = packageCache_r.
get( citem );
2153 proto::target::InstallStep tStep;
2154 tStep.stepId = stepId;
2155 tStep.pathname = locCache.
value()[stepId]->asString();
2156 tStep.multiversion = p->multiversionInstall() ;
2158 commit.transactionSteps.push_back( std::move(tStep) );
2160 catch (
const AbortRequestException &e )
2162 WAR <<
"commit aborted by the user" << endl;
2167 catch (
const SkipRequestException &e )
2170 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2179 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2185 proto::target::RemoveStep tStep;
2186 tStep.stepId = stepId;
2187 tStep.name = p->name();
2188 tStep.version = p->edition().version();
2189 tStep.release = p->edition().release();
2190 tStep.arch = p->arch().asString();
2191 commit.transactionSteps.push_back(std::move(tStep));
2202 proto::target::InstallStep tStep;
2203 tStep.stepId = stepId;
2204 tStep.pathname = locCache.value()[stepId]->asString();
2205 tStep.multiversion =
false;
2206 commit.transactionSteps.push_back(std::move(tStep));
2210 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2217 std::vector<sat::Solvable> successfullyInstalledPackages;
2219 if (
commit.transactionSteps.size() ) {
2226 const std::vector<int> interceptedSignals {
2233 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2234 unixSignals->sigReceived ().connect ([](
int signum ){
2236 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 );
2238 for(
const auto &sig : interceptedSignals )
2239 unixSignals->addSignal ( sig );
2242 for(
const auto &sig : interceptedSignals )
2243 unixSignals->removeSignal ( sig );
2250 int currentStepId = -1;
2256 bool gotEndOfScript =
false;
2259 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2260 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2261 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2262 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2263 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2266 std::optional<proto::target::TransactionError> transactionError;
2269 std::string currentScriptType;
2270 std::string currentScriptPackage;
2280 unsigned lineno = 0;
2288 zyppng::StompFrameStreamRef msgStream;
2293 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2295 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2297 if ( currentStepId >= 0 )
2298 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2299 cmdout.
set(
"line", line );
2303 if ( installreport ) {
2304 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2305 }
else if ( uninstallreport ) {
2306 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2307 }
else if ( scriptreport ) {
2308 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2309 }
else if ( transactionreport ) {
2310 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2311 }
else if ( cleanupreport ) {
2312 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2314 WAR <<
"Got rpm output without active report " << line;
2319 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2323 if ( line.back() !=
'\n' )
2329 const auto &processDataFromScriptFd = [&](){
2331 while ( scriptSource->canReadLine() ) {
2333 if ( gotEndOfScript )
2336 std::string l = scriptSource->readLine().asString();
2338 gotEndOfScript =
true;
2339 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2342 l = l.substr( 0, rawsize );
2344 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2345 sendRpmLineToReport( l );
2348 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2351 const auto &waitForScriptEnd = [&]() {
2354 if ( gotEndOfScript )
2358 processDataFromScriptFd();
2361 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2364 scriptSource->waitForReadyRead( 100 );
2368 const auto &aboutToStartNewReport = [&](){
2370 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2371 ERR <<
"There is still a running report, this is a bug" << std::endl;
2375 gotEndOfScript =
false;
2378 const auto &writeRpmMsgToHistory = [&](){
2379 if ( rpmmsg.size() == 0 )
2383 rpmmsg +=
"[truncated]\n";
2385 std::ostringstream sstr;
2386 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2391 const auto &finalizeCurrentReport = [&]() {
2394 if ( currentStepId >= 0 ) {
2395 step = &steps.at(currentStepId);
2399 if ( installreport ) {
2407 writeRpmMsgToHistory();
2411 ( *installreport)->progress( 100, resObj );
2414 if ( currentStepId >= 0 )
2415 locCache.value().erase( currentStepId );
2416 successfullyInstalledPackages.push_back( step->
satSolvable() );
2422 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2434 writeRpmMsgToHistory();
2437 if ( uninstallreport ) {
2445 writeRpmMsgToHistory();
2449 ( *uninstallreport)->progress( 100, resObj );
2459 writeRpmMsgToHistory();
2462 if ( scriptreport ) {
2464 ( *scriptreport)->progress( 100, resObj );
2467 if ( transactionreport ) {
2469 ( *transactionreport)->progress( 100 );
2472 if ( cleanupreport ) {
2474 ( *cleanupreport)->progress( 100 );
2480 currentScriptType.clear();
2481 currentScriptPackage.clear();
2482 installreport.reset();
2483 uninstallreport.reset();
2484 scriptreport.reset();
2485 transactionreport.reset();
2486 cleanupreport.reset();
2496 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2498 const char *argv[] = {
2501 zyppRpmBinary.data(),
2518 prog->addFd( messagePipe->writeFd );
2519 prog->addFd( scriptPipe->writeFd );
2522 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2525 const auto &processMessages = [&] ( ) {
2529 const auto &checkMsgWithStepId = [&steps](
auto &p ){
2531 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2535 auto id = p->stepId;
2536 if ( id < 0 || id >= steps.size() ) {
2537 ERR <<
"Received invalid stepId: " <<
id <<
" in " << p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2543 while (
const auto &m = msgStream->nextMessage() ) {
2549 const auto &mName = m->command();
2550 if ( mName == proto::target::RpmLog::typeName ) {
2552 const auto &p = proto::target::RpmLog::fromStompMessage (*m);
2554 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2557 ( p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2558 : p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2559 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p->level <<
"> " << p->line;
2562 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2563 finalizeCurrentReport();
2565 const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
2566 if ( !checkMsgWithStepId( p ) )
2569 aboutToStartNewReport();
2571 auto & step = steps.at( p->stepId );
2572 currentStepId = p->stepId;
2574 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2575 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2577 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2578 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2581 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2582 const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
2583 if ( !checkMsgWithStepId( p ) )
2590 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2591 const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
2592 if ( !checkMsgWithStepId( p ) )
2595 if ( uninstallreport )
2596 (*uninstallreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2597 else if ( installreport )
2598 (*installreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2600 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2602 }
else if ( mName == proto::target::PackageError::typeName ) {
2603 const auto &p = proto::target::PackageError::fromStompMessage(*m);
2604 if ( !checkMsgWithStepId( p ) )
2607 if ( p->stepId >= 0 && p->stepId < steps.size() )
2610 finalizeCurrentReport();
2612 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2613 finalizeCurrentReport();
2615 const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
2617 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2621 aboutToStartNewReport();
2624 const auto stepId = p->stepId;
2625 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2629 currentStepId = p->stepId;
2630 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2631 currentScriptType = p->scriptType;
2632 currentScriptPackage = p->scriptPackage;
2633 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2635 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2639 }
else if ( mName == proto::target::ScriptError::typeName ) {
2641 const auto &p = proto::target::ScriptError::fromStompMessage(*m);
2643 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2648 const auto stepId = p->stepId;
2649 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2659 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2662 writeRpmMsgToHistory();
2664 if ( !scriptreport ) {
2665 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2674 scriptreport.reset();
2677 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2678 finalizeCurrentReport();
2680 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2682 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2686 aboutToStartNewReport();
2687 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2688 (*cleanupreport)->start( beg->nvra );
2689 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2691 finalizeCurrentReport();
2693 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2694 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2696 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2700 if ( !cleanupreport ) {
2701 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2705 (*cleanupreport)->progress( prog->amount );
2707 }
else if ( mName == proto::target::TransBegin::typeName ) {
2708 finalizeCurrentReport();
2710 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2712 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2716 aboutToStartNewReport();
2717 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2718 (*transactionreport)->start( beg->name );
2719 }
else if ( mName == proto::target::TransFinished::typeName ) {
2721 finalizeCurrentReport();
2723 }
else if ( mName == proto::target::TransProgress::typeName ) {
2724 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2726 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2730 if ( !transactionreport ) {
2731 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2735 (*transactionreport)->progress( prog->amount );
2736 }
else if ( mName == proto::target::TransactionError::typeName ) {
2738 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2740 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2745 transactionError = std::move(*error);
2748 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2756 prog->sigStarted().connect( [&](){
2759 messagePipe->unrefWrite();
2760 scriptPipe->unrefWrite();
2764 while( prog->canReadLine( channel ) ) {
2765 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2771 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2777 const auto &msg =
commit.toStompMessage();
2779 std::rethrow_exception ( msg.error() );
2781 if ( !msgStream->sendMessage( *msg ) ) {
2782 prog->stop( SIGKILL );
2788 int zyppRpmExitCode = -1;
2790 zyppRpmExitCode = code;
2794 if ( !prog->start( argv ) ) {
2803 msgStream->readAllMessages();
2810 finalizeCurrentReport();
2813 bool readMsgs =
false;
2823 while ( scriptSource->canReadLine() ) {
2825 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2827 if ( scriptSource->bytesAvailable() > 0 ) {
2829 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2834 switch ( zyppRpmExitCode ) {
2836 case zypprpm::NoError:
2837 case zypprpm::RpmFinishedWithError:
2839 case zypprpm::RpmFinishedWithTransactionError: {
2841 if ( transactionError ) {
2843 std::ostringstream sstr;
2844 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2845 for (
const auto & err : transactionError->problems ) {
2846 sstr <<
" " << err <<
"\n";
2856 case zypprpm::FailedToOpenDb:
2859 case zypprpm::WrongHeaderSize:
2860 case zypprpm::WrongMessageFormat:
2863 case zypprpm::RpmInitFailed:
2866 case zypprpm::FailedToReadPackage:
2869 case zypprpm::FailedToAddStepToTransaction:
2872 case zypprpm::RpmOrderFailed:
2875 case zypprpm::FailedToCreateLock:
2880 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2881 auto &step = steps[stepId];
2893 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2897 std::string referenceFilename( p->referenceFilename() );
2899 if ( referenceFilename.empty() ) {
2900 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2902 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2904 if ( !
rpm().hasFile( referencePath.
asString() ) ) {
2908 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2910 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2924 if ( ! successfullyInstalledPackages.empty() )
2927 successfullyInstalledPackages, abort ) )
2929 WAR <<
"Commit aborted by the user" << endl;
2935 successfullyInstalledPackages,
2942 logPatchStatusChanges( result_r.
transaction(), *
this );
2959 return _rpm.hasFile(path_str, name_str);
2970 if ( baseproduct.isFile() )
2983 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2988 inline Pathname staticGuessRoot(
const Pathname & root_r )
2990 if ( root_r.empty() )
2995 return Pathname(
"/");
3001 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
3003 std::ifstream idfile( file_r.c_str() );
3004 for( iostr::EachLine in( idfile ); in; in.next() )
3007 if ( ! line.empty() )
3010 return std::string();
3021 if ( p->isTargetDistribution() )
3029 const Pathname needroot( staticGuessRoot(root_r) );
3032 return target->requestedLocales();
3038 MIL <<
"updateAutoInstalled if changed..." << endl;
3046 {
return baseproductdata(
_root ).registerTarget(); }
3049 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3052 {
return baseproductdata(
_root ).registerRelease(); }
3055 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3058 {
return baseproductdata(
_root ).registerFlavor(); }
3061 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3094 const Pathname & needroot = staticGuessRoot(root_r);
3112 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3117 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3123 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3126 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3127 if ( ret.
empty() && root_r !=
"/" )
3130 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3138 return guessAnonymousUniqueId(
root() );
3143 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3150 MIL <<
"New VendorAttr: " << vendorAttr_r << endl;
#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 MAXRPMMESSAGELINES
#define SUBST_IF(PAT, VAL)
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
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.
Store and operate on date (time_t).
static Date now()
Return the current time.
Edition represents [epoch:]version[-release].
std::string version() const
Version.
unsigned int epoch_t
Type of an epoch.
std::string release() const
Release.
epoch_t epoch() const
Epoch.
Base class for Exception.
void remember(const Exception &old_r)
Store an other Exception as history.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
int close() override
Wait for the progamm to complete.
const std::string & command() const
The command we're executing.
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.
const char * c_str() const
Conversion to const char *.
std::string asString() const
Conversion to std::string.
@ REGEX
Regular Expression.
TraitsType::constPtrType constPtr
Class representing a patch.
TraitsType::constPtrType constPtr
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Parallel execution of stateful PluginScripts.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Command frame for communication with PluginScript.
Combining sat::Solvable and ResStatus.
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
ResStatus & status() const
Returns the current status.
sat::Solvable buddy() const
Return the buddy we share our status object with.
TraitsType::constPtrType constPtr
Track changing files or directories.
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
bool solvablesEmpty() const
Whether Repository contains solvables.
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
size_type solvablesSize() const
Number of solvables in Repository.
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
void eraseFromPool()
Remove this Repository from its Pool.
static ResPool instance()
Singleton ctor.
void setHardLockQueries(const HardLockQueries &newLocks_r)
Set a new set of queries.
Resolver & resolver() const
The Resolver.
const LocaleSet & getRequestedLocales() const
Return the requested locales.
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from their initial one.
EstablishedStates establishedStates() const
Factory for EstablishedStates.
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
bool isToBeInstalled() const
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
TraitsType::constPtrType constPtr
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
TraitsType::constPtrType constPtr
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition of vendor equivalence.
Interim helper class to collect global options and settings.
Arch systemArchitecture() const
The system architecture zypp uses.
static ZConfig & instance()
Singleton ctor.
Options and policies for ZYpp::commit.
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
bool singleTransModeEnabled() const
Whether the single_rpmtrans backend is enabled (or the classic_rpmtrans).
ZYppCommitPolicy & rpmExcludeDocs(bool yesNo_r)
Use rpm option –excludedocs (default: false).
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
ZYppCommitPolicy & allMedia()
Process all media (default).
ZYppCommitPolicy & rpmNoSignature(bool yesNo_r)
Use rpm option –nosignature (default: false).
Result returned from ZYpp::commit.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
void setSingleTransactionMode(bool yesno_r)
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).
std::string receiveLine()
Read one line from the input stream.
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.
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.
void add(Value val_r)
Push JSON Value to Array.
void add(String key_r, Value val_r)
Add key/value pair.
Data returned by ProductFileReader.
bool empty() const
Whether this is an empty object without valid data.
std::string summary() const
std::string shortName() const
static ProductFileData scanFile(const Pathname &file_r)
Parse one file (or symlink) and return the ProductFileData parsed.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r) const
Provide SrcPackage in a local file.
void setAutoInstalled(const Queue &autoInstalled_r)
Set ident list of all autoinstalled solvables.
Pathname rootDir() const
Get rootdir (for file conflicts check).
static Pool instance()
Singleton ctor.
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
void setNeedrebootSpec(sat::SolvableSpec needrebootSpec_r)
Solvables which should trigger the reboot-needed hint if installed/updated.
Repository systemRepo()
Return the system repository, create it if missing.
void initRequestedLocales(const LocaleSet &locales_r)
Start tracking changes based on this locales_r.
detail::IdType value_type
void push(value_type val_r)
Push a value to the end off the Queue.
A Solvable object within the sat Pool.
A single step within a Transaction.
StepType stepType() const
Type of action to perform in this step.
StepStage stepStage() const
Step action result.
Solvable satSolvable() const
Return the corresponding Solvable.
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
void multiversionSpecChanged()
Target::commit helper optimizing package provision.
void setCommitList(std::vector< sat::Solvable > commitList_r)
Download(commit) sequence of solvables to compute read ahead.
bool preloaded() const
Whether preloaded hint is set.
ManagedFile get(const PoolItem &citem_r)
Provide a package.
pool::PoolTraits::HardLockQueries Data
Save and restore locale set from file.
const LocaleSet & locales() const
Return the loacale set.
void tryLevel(target::rpm::InstallResolvableReport::RpmLevel level_r)
Extract and remember posttrans scripts for later execution.
void executeScripts(rpm::RpmDb &rpm_r, const IdStringSet &obsoletedPackages_r)
Execute the remembered scripts and/or or dump_posttrans lines.
void discardScripts()
Discard all remembered scripts and/or or dump_posttrans lines.
bool aborted() const
Returns true if removing is aborted during progress.
std::unordered_set< IdString > Data
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
const Pathname & root() const
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
const Pathname & dbPath() const
Subclass to retrieve rpm database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
static Ptr create(GMainContext *ctx=nullptr)
SignalProxy< void(uint)> sigChannelReadyRead()
SignalProxy< void(int)> sigFinished()
SignalProxy< void()> sigMessageReceived()
static Ptr create(IODevice::Ptr iostr)
Namespace intended to collect all environment variables we use.
bool TRANSACTIONAL_UPDATE()
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB ).
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
int unlink(const Pathname &path)
Like 'unlink'.
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
int touch(const Pathname &path)
Change file's modification and access times.
std::string getline(std::istream &str)
Read one line from stream.
json::Value toJSON(const sat::Transaction::Step &step_r)
See COMMITBEGIN (added in v1) on page Commit plugin for the specs.
bool empty() const
Whether neither idents nor provides are set.
Queue StringQueue
Queue with String ids.
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
ZYpp::Ptr getZYpp()
relates: ZYppFactory Convenience to get the Pointer to the ZYpp instance.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
std::list< UpdateNotificationFile > UpdateNotifications
std::unordered_set< IdString > IdStringSet
ResTraits< TRes >::PtrType make(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
ResTraits< TRes >::PtrType asKind(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
DefaultIntegral< bool, true > TrueBool
relates: DefaultIntegral true initialized bool
@ DownloadDefault
libzypp will decide what to do.
zypp::callback::UserData UserData
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
Temporarily set/unset an environment variable.
Solvable satSolvable() const
Return the corresponding sat::Solvable.
bool isNeedreboot() const
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 IMPL_PTR_TYPE(NAME)