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 (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
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)