28#include <zypp-core/base/UserRequestException>
64#include <zypp-core/zyppng/base/EventLoop>
65#include <zypp-core/zyppng/base/UnixSignalSource>
66#include <zypp-core/zyppng/io/AsyncDataSource>
67#include <zypp-core/zyppng/io/Process>
71#include <zypp-core/zyppng/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()
158 static const std::string strType(
"type" );
159 static const std::string strStage(
"stage" );
160 static const std::string strSolvable(
"solvable" );
162 static const std::string strTypeDel(
"-" );
163 static const std::string strTypeIns(
"+" );
164 static const std::string strTypeMul(
"M" );
166 static const std::string strStageDone(
"ok" );
167 static const std::string strStageFailed(
"err" );
169 static const std::string strSolvableN(
"n" );
170 static const std::string strSolvableE(
"e" );
171 static const std::string strSolvableV(
"v" );
172 static const std::string strSolvableR(
"r" );
173 static const std::string strSolvableA(
"a" );
180 case Transaction::TRANSACTION_IGNORE:
break;
181 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
182 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
183 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
188 case Transaction::STEP_TODO:
break;
189 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
190 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
199 ident = solv.ident();
206 ident = step_r.
ident();
208 arch = step_r.
arch();
213 { strSolvableV, ed.
version() },
214 { strSolvableR, ed.
release() },
218 s.
add( strSolvableE, epoch );
220 ret.
add( strSolvable, s );
232 for (
const Transaction::Step & step : steps_r )
234 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
249 struct InstallResolvableSAReportReceiver :
public callback::ReceiveReport<rpm::InstallResolvableReportSA>
251 using ReportType = callback::SendReport<rpm::InstallResolvableReport>;
253 InstallResolvableSAReportReceiver()
254 : _report {
std::make_unique<ReportType>() }
258 { (*_report)->start( resolvable ); }
261 { (*_report)->progress( value, resolvable ); }
267 std::unique_ptr<ReportType> _report;
270 struct RemoveResolvableSAReportReceiver :
public callback::ReceiveReport<rpm::RemoveResolvableReportSA>
272 using ReportType = callback::SendReport<rpm::RemoveResolvableReport>;
274 RemoveResolvableSAReportReceiver()
275 : _report { std::make_unique<ReportType>() }
279 { (*_report)->start( resolvable ); }
282 { (*_report)->progress( value, resolvable ); }
288 std::unique_ptr<ReportType> _report;
296 struct SingleTransReportLegacyWrapper
301 SingleTransReportLegacyWrapper()
303 if ( not singleTransReportsConnected() and legacyReportsConnected() )
305 WAR <<
"Activating SingleTransReportLegacyWrapper! The application does not listen to the singletrans reports :(" << endl;
306 _installResolvableSAReportReceiver = InstallResolvableSAReportReceiver();
307 _removeResolvableSAReportReceiver = RemoveResolvableSAReportReceiver();
308 _installResolvableSAReportReceiver->connect();
309 _removeResolvableSAReportReceiver->connect();
314 ~SingleTransReportLegacyWrapper()
318 bool singleTransReportsConnected()
const
329 bool legacyReportsConnected()
const
337 std::optional<InstallResolvableSAReportReceiver> _installResolvableSAReportReceiver;
338 std::optional<RemoveResolvableSAReportReceiver> _removeResolvableSAReportReceiver;
346 class AssertMountedBase
356 if ( ! _mountpoint.empty() ) {
358 MIL <<
"We mounted " << _mountpoint <<
" so we unmount it" << endl;
359 execute({
"umount",
"-R",
"-l", _mountpoint.asString() });
367 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
373 Pathname _mountpoint;
379 class AssertProcMounted :
private AssertMountedBase
382 AssertProcMounted( Pathname root_r )
385 if ( ! PathInfo(root_r/
"self").isDir() ) {
386 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
388 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
389 _mountpoint = std::move(root_r);
392 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
400 class AssertDevMounted :
private AssertMountedBase
403 AssertDevMounted( Pathname root_r )
406 if ( ! PathInfo(root_r/
"null").isChr() ) {
407 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
412 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
413 _mountpoint = std::move(root_r);
416 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
433 std::ifstream infile( historyFile_r.c_str() );
434 for( iostr::EachLine in( infile ); in; in.next() )
436 const char * ch( (*in).c_str() );
438 if ( *ch <
'1' ||
'9' < *ch )
440 const char * sep1 = ::strchr( ch,
'|' );
445 bool installs =
true;
446 if ( ::strncmp( sep1,
"install|", 8 ) )
448 if ( ::strncmp( sep1,
"remove |", 8 ) )
455 const char * sep2 = ::strchr( sep1,
'|' );
456 if ( !sep2 || sep1 == sep2 )
458 (*in)[sep2-ch] =
'\0';
463 onSystemByUserList.erase( pkg );
467 if ( (sep1 = ::strchr( sep2+1,
'|' ))
468 && (sep1 = ::strchr( sep1+1,
'|' ))
469 && (sep2 = ::strchr( sep1+1,
'|' )) )
471 (*in)[sep2-ch] =
'\0';
472 if ( ::strchr( sep1+1,
'@' ) )
475 onSystemByUserList.insert( pkg );
480 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
481 return onSystemByUserList;
491 return PluginFrame( command_r, json::Object {
502 MIL <<
"Testcases to keep: " << toKeep << endl;
508 WAR <<
"No Target no Testcase!" << endl;
512 std::string stem(
"updateTestcase" );
517 std::list<std::string> content;
519 std::set<std::string> cases;
520 for_( c, content.begin(), content.end() )
525 if ( cases.size() >= toKeep )
527 unsigned toDel = cases.size() - toKeep + 1;
528 for_( c, cases.begin(), cases.end() )
537 MIL <<
"Write new testcase " << next << endl;
555 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
565 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
570 WAR <<
"User request to abort script " << script_r << endl;
579 if ( prog.close() != 0 )
581 ret.second = report_r->problem( prog.execError() );
582 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
583 std::ostringstream sstr;
584 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
585 historylog.
comment(sstr.str(),
true);
597 bool executeScript(
const Pathname & root_r,
598 const Pathname & script_r,
599 callback::SendReport<PatchScriptReport> & report_r )
604 action = doExecuteScript( root_r, script_r, report_r );
608 switch ( action.second )
611 WAR <<
"User request to abort at script " << script_r << endl;
616 WAR <<
"User request to skip script " << script_r << endl;
626 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
635 bool RunUpdateScripts(
const Pathname & root_r,
636 const Pathname & scriptsPath_r,
637 const std::vector<sat::Solvable> & checkPackages_r,
640 if ( checkPackages_r.empty() )
643 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
645 if ( ! PathInfo( scriptsDir ).isDir() )
648 std::list<std::string> scripts;
650 if ( scripts.empty() )
658 std::map<std::string, Pathname> unify;
659 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
661 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
662 for_( sit, scripts.begin(), scripts.end() )
667 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
670 PathInfo script( scriptsDir / *sit );
671 Pathname localPath( scriptsPath_r/(*sit) );
672 std::string unifytag;
674 if ( script.isFile() )
680 else if ( ! script.isExist() )
688 if ( unifytag.empty() )
692 if ( unify[unifytag].
empty() )
694 unify[unifytag] = localPath;
701 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
702 MIL <<
"Skip update script: " << msg << endl;
703 HistoryLog().comment( msg,
true );
707 if ( abort || aborting_r )
709 WAR <<
"Aborting: Skip update script " << *sit << endl;
710 HistoryLog().comment(
711 localPath.asString() +
_(
" execution skipped while aborting"),
716 MIL <<
"Found update script " << *sit << endl;
717 callback::SendReport<PatchScriptReport> report;
720 if ( ! executeScript( root_r, localPath, report ) )
732 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
734 std::ifstream infile( file_r.c_str() );
735 for( iostr::EachLine in( infile ); in; in.next() )
737 out_r << *in << endl;
741 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
743 std::string ret( cmd_r );
744#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
745 SUBST_IF(
"%p", notification_r.solvable().asString() );
746 SUBST_IF(
"%P", notification_r.file().asString() );
751 void sendNotification(
const Pathname & root_r,
754 if ( notifications_r.empty() )
758 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
759 if ( cmdspec.empty() )
762 std::string::size_type pos( cmdspec.find(
'|' ) );
763 if ( pos == std::string::npos )
765 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
766 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
771 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
773 enum Format {
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
775 if ( formatStr ==
"none" )
777 else if ( formatStr ==
"single" )
779 else if ( formatStr ==
"digest" )
781 else if ( formatStr ==
"bulk" )
785 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
786 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
794 if ( format == NONE || format == SINGLE )
796 for_( it, notifications_r.begin(), notifications_r.end() )
798 std::vector<std::string> command;
799 if ( format == SINGLE )
801 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
806 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
810 int ret = prog.close();
813 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
814 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
820 else if ( format == DIGEST || format == BULK )
822 filesystem::TmpFile tmpfile;
823 std::ofstream out( tmpfile.path().c_str() );
824 for_( it, notifications_r.begin(), notifications_r.end() )
826 if ( format == DIGEST )
828 out << it->file() << endl;
830 else if ( format == BULK )
836 std::vector<std::string> command;
837 command.push_back(
"<"+tmpfile.path().asString() );
838 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
843 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
847 int ret = prog.close();
850 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
851 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
858 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
859 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
870 void RunUpdateMessages(
const Pathname & root_r,
871 const Pathname & messagesPath_r,
872 const std::vector<sat::Solvable> & checkPackages_r,
873 ZYppCommitResult & result_r )
875 if ( checkPackages_r.empty() )
878 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
880 if ( ! PathInfo( messagesDir ).isDir() )
883 std::list<std::string> messages;
885 if ( messages.empty() )
891 HistoryLog historylog;
892 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
894 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
895 for_( sit, messages.begin(), messages.end() )
900 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
903 PathInfo message( messagesDir / *sit );
904 if ( ! message.isFile() || message.size() == 0 )
907 MIL <<
"Found update message " << *sit << endl;
908 Pathname localPath( messagesPath_r/(*sit) );
909 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
910 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
913 sendNotification( root_r, result_r.updateMessages() );
919 void logPatchStatusChanges(
const sat::Transaction & transaction_r,
TargetImpl & target_r )
922 if ( changedPseudoInstalled.empty() )
930 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
933 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
936 HistoryLog historylog;
937 for (
const auto & el : changedPseudoInstalled )
938 historylog.patchStateChange( el.first, el.second );
947 const std::vector<sat::Solvable> & checkPackages_r,
949 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
967 _rpm.initDatabase( root_r, doRebuild_r );
972 sigMultiversionSpecChanged();
973 MIL <<
"Initialized target on " <<
_root << endl;
981 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
991 boost::function<
bool ()> condition,
992 boost::function<std::string ()> value )
994 std::string val = value();
1002 MIL <<
"updating '" << filename <<
"' content." << endl;
1006 std::ofstream filestr;
1009 filestr.open( filename.
c_str() );
1011 if ( filestr.good() )
1033 if (
root() !=
"/" )
1047 WAR <<
"Can't create anonymous id file" << endl;
1056 Pathname flavorpath(
home() /
"LastDistributionFlavor");
1062 WAR <<
"No base product, I won't create flavor cache" << endl;
1066 std::string flavor = p->flavor();
1078 WAR <<
"Can't create flavor cache" << endl;
1090 _rpm.closeDatabase();
1091 sigMultiversionSpecChanged();
1092 MIL <<
"Closed target on " <<
_root << endl;
1118 bool build_rpm_solv =
true;
1128 MIL <<
"Read cookie: " << cookie << endl;
1133 if ( status == rpmstatus )
1134 build_rpm_solv =
false;
1135 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1136 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1140 if ( build_rpm_solv )
1154 bool switchingToTmpSolvfile =
false;
1155 Exception ex(
"Failed to cache rpm database.");
1161 rpmsolv =
base/
"solv";
1162 rpmsolvcookie =
base/
"cookie";
1169 WAR <<
"Using a temporary solv file at " <<
base << endl;
1170 switchingToTmpSolvfile =
true;
1179 if ( ! switchingToTmpSolvfile )
1189#ifdef ZYPP_RPMDB2SOLV_PATH
1190 cmd.push_back( ZYPP_RPMDB2SOLV_PATH );
1192 cmd.push_back(
"rpmdb2solv" );
1194 if ( !
_root.empty() ) {
1195 cmd.push_back(
"-r" );
1196 cmd.push_back(
_root.asString() );
1198 cmd.push_back(
"-D" );
1200 cmd.push_back(
"-X" );
1202 cmd.push_back(
"-p" );
1205 if ( ! oldSolvFile.
empty() )
1206 cmd.push_back( oldSolvFile.
asString() );
1208 cmd.push_back(
"-o" );
1212 std::string errdetail;
1215 WAR <<
" " << output;
1216 if ( errdetail.empty() ) {
1220 errdetail += output;
1223 int ret = prog.
close();
1244 if (
root() ==
"/" )
1258 return build_rpm_solv;
1276 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1277 ", force loading: " << (force?
"true":
"false") << endl;
1282 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1289 if ( newCache || force )
1306 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1312 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1337 if (
PathInfo( historyFile ).isExist() )
1344 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1345 onSystemByAuto.insert( ident );
1361 sat::SolvableSpec needrebootSpec;
1362 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1363 needrebootSpec.addProvides(
Capability(
"kernel") );
1366 if (
PathInfo( needrebootFile ).isFile() )
1367 needrebootSpec.parseFrom( needrebootFile );
1370 if (
PathInfo( needrebootDir ).isDir() )
1375 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1377 if ( ! isRpmConfigBackup( str_r ) )
1379 Pathname needrebootFile { needrebootDir / str_r };
1380 if (
PathInfo( needrebootFile ).isFile() )
1381 needrebootSpec.parseFrom( needrebootFile );
1392 if ( ! hardLocks.empty() )
1401 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1413 bool explicitDryRun = policy_r.
dryRun();
1423 if (
root() ==
"/" )
1437 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1456 steps.push_back( *it );
1463 MIL <<
"Todo: " << result << endl;
1474 if ( commitPlugins )
1475 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1482 if ( ! policy_r.
dryRun() )
1488 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1495 if ( ! policy_r.
dryRun() )
1517 DBG <<
"dryRun: Not storing non-package data." << endl;
1524 if ( ! policy_r.
dryRun() )
1526 for_( it, steps.begin(), steps.end() )
1528 if ( ! it->satSolvable().isKind<
Patch>() )
1536 if ( ! patch ||patch->message().empty() )
1539 MIL <<
"Show message for " << patch << endl;
1541 if ( ! report->show( patch ) )
1543 WAR <<
"commit aborted by the user" << endl;
1550 DBG <<
"dryRun: Not checking patch messages." << endl;
1565 std::unique_ptr<CommitPackagePreloader> preloader;
1571 preloader = std::make_unique<CommitPackagePreloader>();
1572 preloader->preloadTransaction( steps );
1573 miss = preloader->missed ();
1580 for_( it, steps.begin(), steps.end() )
1582 switch ( it->stepType() )
1601 localfile = packageCache.
get( pi );
1604 catch (
const AbortRequestException & exp )
1608 WAR <<
"commit cache preload aborted by the user" << endl;
1612 catch (
const SkipRequestException & exp )
1617 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1627 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1638 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1642 if ( ! policy_r.
dryRun() )
1650 commit( policy_r, packageCache, result );
1654 preloader->cleanupCaches ();
1658 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1659 if ( explicitDryRun ) {
1673 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1674 if ( explicitDryRun ) {
1686 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1695 if ( commitPlugins )
1696 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1701 if ( ! policy_r.
dryRun() )
1706 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1717 struct NotifyAttemptToModify
1719 NotifyAttemptToModify(
ZYppCommitResult & result_r ) : _result( result_r ) {}
1722 {
if ( _guard ) { _result.attemptToModify(
true ); _guard =
false; } }
1725 ZYppCommitResult & _result;
1734 {
"ZYPP_SINGLE_RPMTRANS",
nullptr },
1735 {
"ZYPP_CLASSIC_RPMTRANS",
"1" },
1740 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1745 NotifyAttemptToModify attemptToModify( result_r );
1750 AssertProcMounted assertProcMounted(
_root );
1751 AssertDevMounted assertDevMounted(
_root );
1758 std::vector<sat::Solvable> successfullyInstalledPackages;
1761 for_( step, steps.begin(), steps.end() )
1766 if ( citem->isKind<
Package>() )
1770 obsoletedPackages.insert( citem->ident() );
1776 if ( citem->isKind<
Package>() )
1784 localfile = packageCache_r.
get( citem );
1786 catch (
const AbortRequestException &e )
1788 WAR <<
"commit aborted by the user" << endl;
1793 catch (
const SkipRequestException &e )
1796 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1805 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1814 bool success =
false;
1840 WAR <<
"commit aborted by the user" << endl;
1849 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1865 WAR <<
"dry run failed" << endl;
1872 WAR <<
"commit aborted by the user" << endl;
1877 WAR <<
"Install failed" << endl;
1883 if ( success && !policy_r.
dryRun() )
1886 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1895 bool success =
false;
1908 WAR <<
"commit aborted by the user" << endl;
1924 WAR <<
"commit aborted by the user" << endl;
1930 WAR <<
"removal of " << p <<
" failed";
1933 if ( success && !policy_r.
dryRun() )
1940 else if ( ! policy_r.
dryRun() )
1944 if ( ! citem.
buddy() )
1946 if ( citem->isKind<
Product>() )
1951 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1957 std::string referenceFilename( p->referenceFilename() );
1958 if ( referenceFilename.empty() )
1960 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1964 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1965 if ( !
rpm().hasFile( referencePath.
asString() ) )
1970 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1974 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2003 if ( ! successfullyInstalledPackages.empty() )
2006 successfullyInstalledPackages, abort ) )
2008 WAR <<
"Commit aborted by the user" << endl;
2014 successfullyInstalledPackages,
2021 logPatchStatusChanges( result_r.
transaction(), *
this );
2040 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2043 data.
set(
"line", std::cref(line_r) );
2044 data.
set(
"level", level_r );
2050 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
2051 switch ( rpmlevel_r ) {
2052 case RPMLOG_EMERG: [[fallthrough]];
2053 case RPMLOG_ALERT: [[fallthrough]];
2055 return ReportType::loglevel::crt;
2057 return ReportType::loglevel::err;
2058 case RPMLOG_WARNING:
2059 return ReportType::loglevel::war;
2060 default: [[fallthrough]];
2061 case RPMLOG_NOTICE: [[fallthrough]];
2063 return ReportType::loglevel::msg;
2065 return ReportType::loglevel::dbg;
2073 { (*this)->report( userData_r ); }
2079 {
"ZYPP_SINGLE_RPMTRANS",
"1" },
2080 {
"ZYPP_CLASSIC_RPMTRANS",
nullptr },
2083 SingleTransReportLegacyWrapper _legacyWrapper;
2088 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
2093 NotifyAttemptToModify attemptToModify( result_r );
2099 AssertProcMounted assertProcMounted(
_root );
2100 AssertDevMounted assertDevMounted(
_root );
2114 proto::target::Commit
commit;
2124 for (
auto &[
_, value] : data ) {
2126 value.resetDispose();
2132 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2133 auto &step = steps[stepId];
2136 if ( citem->isKind<
Package>() )
2145 if ( citem->isKind<
Package>() ) {
2150 locCache.value()[stepId] = packageCache_r.
get( citem );
2152 proto::target::InstallStep tStep;
2153 tStep.stepId = stepId;
2154 tStep.pathname = locCache.
value()[stepId]->asString();
2155 tStep.multiversion = p->multiversionInstall() ;
2157 commit.transactionSteps.push_back( std::move(tStep) );
2159 catch (
const AbortRequestException &e )
2161 WAR <<
"commit aborted by the user" << endl;
2166 catch (
const SkipRequestException &e )
2169 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2178 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2184 proto::target::RemoveStep tStep;
2185 tStep.stepId = stepId;
2186 tStep.name = p->name();
2187 tStep.version = p->edition().version();
2188 tStep.release = p->edition().release();
2189 tStep.arch = p->arch().asString();
2190 commit.transactionSteps.push_back(std::move(tStep));
2201 proto::target::InstallStep tStep;
2202 tStep.stepId = stepId;
2203 tStep.pathname = locCache.value()[stepId]->asString();
2204 tStep.multiversion =
false;
2205 commit.transactionSteps.push_back(std::move(tStep));
2209 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2216 std::vector<sat::Solvable> successfullyInstalledPackages;
2218 if (
commit.transactionSteps.size() ) {
2225 const std::vector<int> interceptedSignals {
2232 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2233 unixSignals->sigReceived ().connect ([](
int signum ){
2235 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 );
2237 for(
const auto &sig : interceptedSignals )
2238 unixSignals->addSignal ( sig );
2241 for(
const auto &sig : interceptedSignals )
2242 unixSignals->removeSignal ( sig );
2249 int currentStepId = -1;
2255 bool gotEndOfScript =
false;
2258 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2259 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2260 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2261 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2262 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2265 std::optional<proto::target::TransactionError> transactionError;
2268 std::string currentScriptType;
2269 std::string currentScriptPackage;
2279 unsigned lineno = 0;
2287 zyppng::StompFrameStreamRef msgStream;
2292 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2294 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2296 if ( currentStepId >= 0 )
2297 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2298 cmdout.
set(
"line", line );
2302 if ( installreport ) {
2303 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2304 }
else if ( uninstallreport ) {
2305 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2306 }
else if ( scriptreport ) {
2307 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2308 }
else if ( transactionreport ) {
2309 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2310 }
else if ( cleanupreport ) {
2311 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2313 WAR <<
"Got rpm output without active report " << line;
2318 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2322 if ( line.back() !=
'\n' )
2328 const auto &processDataFromScriptFd = [&](){
2330 while ( scriptSource->canReadLine() ) {
2332 if ( gotEndOfScript )
2335 std::string l = scriptSource->readLine().asString();
2337 gotEndOfScript =
true;
2338 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2341 l = l.substr( 0, rawsize );
2343 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2344 sendRpmLineToReport( l );
2347 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2350 const auto &waitForScriptEnd = [&]() {
2353 if ( gotEndOfScript )
2357 processDataFromScriptFd();
2360 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2363 scriptSource->waitForReadyRead( 100 );
2367 const auto &aboutToStartNewReport = [&](){
2369 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2370 ERR <<
"There is still a running report, this is a bug" << std::endl;
2374 gotEndOfScript =
false;
2377 const auto &writeRpmMsgToHistory = [&](){
2378 if ( rpmmsg.size() == 0 )
2382 rpmmsg +=
"[truncated]\n";
2384 std::ostringstream sstr;
2385 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2390 const auto &finalizeCurrentReport = [&]() {
2393 if ( currentStepId >= 0 ) {
2394 step = &steps.at(currentStepId);
2398 if ( installreport ) {
2406 writeRpmMsgToHistory();
2410 ( *installreport)->progress( 100, resObj );
2413 if ( currentStepId >= 0 )
2414 locCache.value().erase( currentStepId );
2415 successfullyInstalledPackages.push_back( step->
satSolvable() );
2421 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2433 writeRpmMsgToHistory();
2436 if ( uninstallreport ) {
2444 writeRpmMsgToHistory();
2448 ( *uninstallreport)->progress( 100, resObj );
2458 writeRpmMsgToHistory();
2461 if ( scriptreport ) {
2463 ( *scriptreport)->progress( 100, resObj );
2466 if ( transactionreport ) {
2468 ( *transactionreport)->progress( 100 );
2471 if ( cleanupreport ) {
2473 ( *cleanupreport)->progress( 100 );
2479 currentScriptType.clear();
2480 currentScriptPackage.clear();
2481 installreport.reset();
2482 uninstallreport.reset();
2483 scriptreport.reset();
2484 transactionreport.reset();
2485 cleanupreport.reset();
2495 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2497 const char *argv[] = {
2500 zyppRpmBinary.data(),
2517 prog->addFd( messagePipe->writeFd );
2518 prog->addFd( scriptPipe->writeFd );
2521 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2524 const auto &processMessages = [&] ( ) {
2528 const auto &checkMsgWithStepId = [&steps](
auto &p ){
2530 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2534 auto id = p->stepId;
2535 if ( id < 0 || id >= steps.size() ) {
2536 ERR <<
"Received invalid stepId: " <<
id <<
" in " << p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2542 while (
const auto &m = msgStream->nextMessage() ) {
2548 const auto &mName = m->command();
2549 if ( mName == proto::target::RpmLog::typeName ) {
2551 const auto &p = proto::target::RpmLog::fromStompMessage (*m);
2553 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2556 ( p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2557 : p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2558 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p->level <<
"> " << p->line;
2561 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2562 finalizeCurrentReport();
2564 const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
2565 if ( !checkMsgWithStepId( p ) )
2568 aboutToStartNewReport();
2570 auto & step = steps.at( p->stepId );
2571 currentStepId = p->stepId;
2573 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2574 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2576 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2577 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2580 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2581 const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
2582 if ( !checkMsgWithStepId( p ) )
2589 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2590 const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
2591 if ( !checkMsgWithStepId( p ) )
2594 if ( uninstallreport )
2595 (*uninstallreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2596 else if ( installreport )
2597 (*installreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2599 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2601 }
else if ( mName == proto::target::PackageError::typeName ) {
2602 const auto &p = proto::target::PackageError::fromStompMessage(*m);
2603 if ( !checkMsgWithStepId( p ) )
2606 if ( p->stepId >= 0 && p->stepId < steps.size() )
2609 finalizeCurrentReport();
2611 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2612 finalizeCurrentReport();
2614 const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
2616 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2620 aboutToStartNewReport();
2623 const auto stepId = p->stepId;
2624 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2628 currentStepId = p->stepId;
2629 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2630 currentScriptType = p->scriptType;
2631 currentScriptPackage = p->scriptPackage;
2632 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2634 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2638 }
else if ( mName == proto::target::ScriptError::typeName ) {
2640 const auto &p = proto::target::ScriptError::fromStompMessage(*m);
2642 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2647 const auto stepId = p->stepId;
2648 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2658 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2661 writeRpmMsgToHistory();
2663 if ( !scriptreport ) {
2664 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2673 scriptreport.reset();
2676 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2677 finalizeCurrentReport();
2679 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2681 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2685 aboutToStartNewReport();
2686 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2687 (*cleanupreport)->start( beg->nvra );
2688 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2690 finalizeCurrentReport();
2692 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2693 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2695 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2699 if ( !cleanupreport ) {
2700 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2704 (*cleanupreport)->progress( prog->amount );
2706 }
else if ( mName == proto::target::TransBegin::typeName ) {
2707 finalizeCurrentReport();
2709 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2711 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2715 aboutToStartNewReport();
2716 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2717 (*transactionreport)->start( beg->name );
2718 }
else if ( mName == proto::target::TransFinished::typeName ) {
2720 finalizeCurrentReport();
2722 }
else if ( mName == proto::target::TransProgress::typeName ) {
2723 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2725 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2729 if ( !transactionreport ) {
2730 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2734 (*transactionreport)->progress( prog->amount );
2735 }
else if ( mName == proto::target::TransactionError::typeName ) {
2737 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2739 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2744 transactionError = std::move(*error);
2747 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2755 prog->sigStarted().connect( [&](){
2758 messagePipe->unrefWrite();
2759 scriptPipe->unrefWrite();
2763 while( prog->canReadLine( channel ) ) {
2764 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2770 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2776 const auto &msg =
commit.toStompMessage();
2778 std::rethrow_exception ( msg.error() );
2780 if ( !msgStream->sendMessage( *msg ) ) {
2781 prog->stop( SIGKILL );
2787 int zyppRpmExitCode = -1;
2789 zyppRpmExitCode = code;
2793 if ( !prog->start( argv ) ) {
2802 msgStream->readAllMessages();
2809 finalizeCurrentReport();
2812 bool readMsgs =
false;
2822 while ( scriptSource->canReadLine() ) {
2824 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2826 if ( scriptSource->bytesAvailable() > 0 ) {
2828 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2833 switch ( zyppRpmExitCode ) {
2835 case zypprpm::NoError:
2836 case zypprpm::RpmFinishedWithError:
2838 case zypprpm::RpmFinishedWithTransactionError: {
2840 if ( transactionError ) {
2842 std::ostringstream sstr;
2843 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2844 for (
const auto & err : transactionError->problems ) {
2845 sstr <<
" " << err <<
"\n";
2855 case zypprpm::FailedToOpenDb:
2858 case zypprpm::WrongHeaderSize:
2859 case zypprpm::WrongMessageFormat:
2862 case zypprpm::RpmInitFailed:
2865 case zypprpm::FailedToReadPackage:
2868 case zypprpm::FailedToAddStepToTransaction:
2871 case zypprpm::RpmOrderFailed:
2874 case zypprpm::FailedToCreateLock:
2879 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2880 auto &step = steps[stepId];
2892 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2896 std::string referenceFilename( p->referenceFilename() );
2898 if ( referenceFilename.empty() ) {
2899 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2901 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2903 if ( !
rpm().hasFile( referencePath.
asString() ) ) {
2907 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2909 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2923 if ( ! successfullyInstalledPackages.empty() )
2926 successfullyInstalledPackages, abort ) )
2928 WAR <<
"Commit aborted by the user" << endl;
2934 successfullyInstalledPackages,
2941 logPatchStatusChanges( result_r.
transaction(), *
this );
2958 return _rpm.hasFile(path_str, name_str);
2969 if ( baseproduct.isFile() )
2982 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2987 inline Pathname staticGuessRoot(
const Pathname & root_r )
2989 if ( root_r.empty() )
2994 return Pathname(
"/");
3000 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
3002 std::ifstream idfile( file_r.c_str() );
3003 for( iostr::EachLine in( idfile ); in; in.next() )
3006 if ( ! line.empty() )
3009 return std::string();
3020 if ( p->isTargetDistribution() )
3028 const Pathname needroot( staticGuessRoot(root_r) );
3031 return target->requestedLocales();
3037 MIL <<
"updateAutoInstalled if changed..." << endl;
3045 {
return baseproductdata(
_root ).registerTarget(); }
3048 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3051 {
return baseproductdata(
_root ).registerRelease(); }
3054 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3057 {
return baseproductdata(
_root ).registerFlavor(); }
3060 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3093 const Pathname & needroot = staticGuessRoot(root_r);
3111 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3116 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3122 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3125 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3126 if ( ret.
empty() && root_r !=
"/" )
3129 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3137 return guessAnonymousUniqueId(
root() );
3142 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3149 MIL <<
"New VendorAttr: " << vendorAttr_r << endl;
#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.
bool operator()(const zypp::Arch &lhs, const zypp::Arch &rhs) const
Default order for std::container based Arch::compare.
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.
Attempts to create a lock to prevent the system from going into hibernate/shutdown.
TraitsType::constPtrType constPtr
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition of vendor equivalence.
Interim helper class to collect global options and settings.
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.
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
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.
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 on page plugin-commit 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
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)
ResTraits< TRes >::PtrType asKind(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
@ 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 NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define IMPL_PTR_TYPE(NAME)