29#include <zypp-core/base/UserRequestException>
65#include <zypp-core/ng/base/EventLoop>
66#include <zypp-core/ng/base/UnixSignalSource>
67#include <zypp-core/ng/io/AsyncDataSource>
68#include <zypp-core/ng/io/Process>
72#include <zypp-core/ng/base/EventDispatcher>
74#include <shared/commit/CommitMessages.h>
81#include "tools/zypp-rpm/errorcodes.h"
82#include <rpm/rpmlog.h>
89 static bool val = [](){
90 const char *
env = getenv(
"TRANSACTIONAL_UPDATE");
102#include <solv/repo_rpmdb.h>
103#include <solv/chksum.h>
113 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
114 ::solv_chksum_free( chk,
nullptr );
116 if ( ::rpm_hash_database_state( state, chk ) == 0 )
119 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
123 WAR <<
"rpm_hash_database_state failed" << endl;
143 inline void sigMultiversionSpecChanged()
160 static const std::string strType(
"type" );
161 static const std::string strStage(
"stage" );
162 static const std::string strSolvable(
"solvable" );
164 static const std::string strTypeDel(
"-" );
165 static const std::string strTypeIns(
"+" );
166 static const std::string strTypeMul(
"M" );
168 static const std::string strStageDone(
"ok" );
169 static const std::string strStageFailed(
"err" );
171 static const std::string strSolvableN(
"n" );
172 static const std::string strSolvableE(
"e" );
173 static const std::string strSolvableV(
"v" );
174 static const std::string strSolvableR(
"r" );
175 static const std::string strSolvableA(
"a" );
182 case Transaction::TRANSACTION_IGNORE:
break;
183 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
184 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
185 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
190 case Transaction::STEP_TODO:
break;
191 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
192 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
201 ident = solv.ident();
208 ident = step_r.
ident();
210 arch = step_r.
arch();
215 { strSolvableV, ed.
version() },
216 { strSolvableR, ed.
release() },
220 s.
add( strSolvableE, epoch );
222 ret.
add( strSolvable, s );
234 for (
const Transaction::Step & step : steps_r )
236 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
251 struct InstallResolvableSAReportReceiver :
public callback::ReceiveReport<rpm::InstallResolvableReportSA>
253 using ReportType = callback::SendReport<rpm::InstallResolvableReport>;
255 InstallResolvableSAReportReceiver()
256 : _report {
std::make_unique<ReportType>() }
260 { (*_report)->start( resolvable ); }
263 { (*_report)->progress( value, resolvable ); }
269 std::unique_ptr<ReportType> _report;
272 struct RemoveResolvableSAReportReceiver :
public callback::ReceiveReport<rpm::RemoveResolvableReportSA>
274 using ReportType = callback::SendReport<rpm::RemoveResolvableReport>;
276 RemoveResolvableSAReportReceiver()
277 : _report { std::make_unique<ReportType>() }
281 { (*_report)->start( resolvable ); }
284 { (*_report)->progress( value, resolvable ); }
290 std::unique_ptr<ReportType> _report;
298 struct SingleTransReportLegacyWrapper
303 SingleTransReportLegacyWrapper()
305 if ( not singleTransReportsConnected() and legacyReportsConnected() )
307 WAR <<
"Activating SingleTransReportLegacyWrapper! The application does not listen to the singletrans reports :(" << endl;
308 _installResolvableSAReportReceiver = InstallResolvableSAReportReceiver();
309 _removeResolvableSAReportReceiver = RemoveResolvableSAReportReceiver();
310 _installResolvableSAReportReceiver->connect();
311 _removeResolvableSAReportReceiver->connect();
316 ~SingleTransReportLegacyWrapper()
320 bool singleTransReportsConnected()
const
331 bool legacyReportsConnected()
const
339 std::optional<InstallResolvableSAReportReceiver> _installResolvableSAReportReceiver;
340 std::optional<RemoveResolvableSAReportReceiver> _removeResolvableSAReportReceiver;
348 class AssertMountedBase
358 if ( ! _mountpoint.empty() ) {
360 MIL <<
"We mounted " << _mountpoint <<
" so we unmount it" << endl;
361 execute({
"umount",
"-R",
"-l", _mountpoint.asString() });
369 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
375 Pathname _mountpoint;
381 class AssertProcMounted :
private AssertMountedBase
384 AssertProcMounted( Pathname root_r )
387 if ( ! PathInfo(root_r/
"self").isDir() ) {
388 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
390 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
391 _mountpoint = std::move(root_r);
394 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
402 class AssertDevMounted :
private AssertMountedBase
405 AssertDevMounted( Pathname root_r )
408 if ( ! PathInfo(root_r/
"null").isChr() ) {
409 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
414 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
415 _mountpoint = std::move(root_r);
418 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
435 std::ifstream infile( historyFile_r.c_str() );
436 for( iostr::EachLine in( infile ); in; in.next() )
438 const char * ch( (*in).c_str() );
440 if ( *ch <
'1' ||
'9' < *ch )
442 const char * sep1 = ::strchr( ch,
'|' );
447 bool installs =
true;
448 if ( ::strncmp( sep1,
"install|", 8 ) )
450 if ( ::strncmp( sep1,
"remove |", 8 ) )
457 const char * sep2 = ::strchr( sep1,
'|' );
458 if ( !sep2 || sep1 == sep2 )
460 (*in)[sep2-ch] =
'\0';
465 onSystemByUserList.erase( pkg );
469 if ( (sep1 = ::strchr( sep2+1,
'|' ))
470 && (sep1 = ::strchr( sep1+1,
'|' ))
471 && (sep2 = ::strchr( sep1+1,
'|' )) )
473 (*in)[sep2-ch] =
'\0';
474 if ( ::strchr( sep1+1,
'@' ) )
477 onSystemByUserList.insert( pkg );
482 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
483 return onSystemByUserList;
493 return PluginFrame( command_r, json::Object {
504 MIL <<
"Testcases to keep: " << toKeep << endl;
510 WAR <<
"No Target no Testcase!" << endl;
514 std::string stem(
"updateTestcase" );
519 std::list<std::string> content;
521 std::set<std::string> cases;
522 for_( c, content.begin(), content.end() )
527 if ( cases.size() >= toKeep )
529 unsigned toDel = cases.size() - toKeep + 1;
530 for_( c, cases.begin(), cases.end() )
539 MIL <<
"Write new testcase " << next << endl;
557 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
567 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
572 WAR <<
"User request to abort script " << script_r << endl;
581 if ( prog.close() != 0 )
583 ret.second = report_r->problem( prog.execError() );
584 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
585 std::ostringstream sstr;
586 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
587 historylog.
comment(sstr.str(),
true);
599 bool executeScript(
const Pathname & root_r,
600 const Pathname & script_r,
601 callback::SendReport<PatchScriptReport> & report_r )
606 action = doExecuteScript( root_r, script_r, report_r );
610 switch ( action.second )
613 WAR <<
"User request to abort at script " << script_r << endl;
618 WAR <<
"User request to skip script " << script_r << endl;
628 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
637 bool RunUpdateScripts(
const Pathname & root_r,
638 const Pathname & scriptsPath_r,
639 const std::vector<sat::Solvable> & checkPackages_r,
642 if ( checkPackages_r.empty() )
645 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
647 if ( ! PathInfo( scriptsDir ).isDir() )
650 std::list<std::string> scripts;
652 if ( scripts.empty() )
660 std::map<std::string, Pathname> unify;
661 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
663 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
664 for_( sit, scripts.begin(), scripts.end() )
669 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
672 PathInfo script( scriptsDir / *sit );
673 Pathname localPath( scriptsPath_r/(*sit) );
674 std::string unifytag;
676 if ( script.isFile() )
682 else if ( ! script.isExist() )
690 if ( unifytag.empty() )
694 if ( unify[unifytag].
empty() )
696 unify[unifytag] = localPath;
703 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
704 MIL <<
"Skip update script: " << msg << endl;
705 HistoryLog().comment( msg,
true );
709 if ( abort || aborting_r )
711 WAR <<
"Aborting: Skip update script " << *sit << endl;
712 HistoryLog().comment(
713 localPath.asString() +
_(
" execution skipped while aborting"),
718 MIL <<
"Found update script " << *sit << endl;
719 callback::SendReport<PatchScriptReport> report;
722 if ( ! executeScript( root_r, localPath, report ) )
734 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
736 std::ifstream infile( file_r.c_str() );
737 for( iostr::EachLine in( infile ); in; in.next() )
739 out_r << *in << endl;
743 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
745 std::string ret( cmd_r );
746#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
747 SUBST_IF(
"%p", notification_r.solvable().asString() );
748 SUBST_IF(
"%P", notification_r.file().asString() );
753 void sendNotification(
const Pathname & root_r,
756 if ( notifications_r.empty() )
760 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
761 if ( cmdspec.empty() )
764 std::string::size_type pos( cmdspec.find(
'|' ) );
765 if ( pos == std::string::npos )
767 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
768 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
773 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
775 enum Format {
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
777 if ( formatStr ==
"none" )
779 else if ( formatStr ==
"single" )
781 else if ( formatStr ==
"digest" )
783 else if ( formatStr ==
"bulk" )
787 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
788 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
796 if ( format == NONE || format == SINGLE )
798 for_( it, notifications_r.begin(), notifications_r.end() )
800 std::vector<std::string> command;
801 if ( format == SINGLE )
803 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
808 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
812 int ret = prog.close();
815 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
816 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
822 else if ( format == DIGEST || format == BULK )
824 filesystem::TmpFile tmpfile;
825 std::ofstream out( tmpfile.path().c_str() );
826 for_( it, notifications_r.begin(), notifications_r.end() )
828 if ( format == DIGEST )
830 out << it->file() << endl;
832 else if ( format == BULK )
838 std::vector<std::string> command;
839 command.push_back(
"<"+tmpfile.path().asString() );
840 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
845 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
849 int ret = prog.close();
852 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
853 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
860 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
861 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
872 void RunUpdateMessages(
const Pathname & root_r,
873 const Pathname & messagesPath_r,
874 const std::vector<sat::Solvable> & checkPackages_r,
875 ZYppCommitResult & result_r )
877 if ( checkPackages_r.empty() )
880 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
882 if ( ! PathInfo( messagesDir ).isDir() )
885 std::list<std::string> messages;
887 if ( messages.empty() )
893 HistoryLog historylog;
894 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
896 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
897 for_( sit, messages.begin(), messages.end() )
902 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
905 PathInfo message( messagesDir / *sit );
906 if ( ! message.isFile() || message.size() == 0 )
909 MIL <<
"Found update message " << *sit << endl;
910 Pathname localPath( messagesPath_r/(*sit) );
911 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
912 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
915 sendNotification( root_r, result_r.updateMessages() );
921 void logPatchStatusChanges(
const sat::Transaction & transaction_r,
TargetImpl & target_r )
924 if ( changedPseudoInstalled.empty() )
932 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
935 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
938 HistoryLog historylog;
939 for (
const auto & el : changedPseudoInstalled )
940 historylog.patchStateChange( el.first, el.second );
949 const std::vector<sat::Solvable> & checkPackages_r,
951 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
970 _rpm.initDatabase( root_r, doRebuild_r );
975 sigMultiversionSpecChanged();
976 MIL <<
"Initialized target on " <<
_root << endl;
984 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
994 boost::function<
bool ()> condition,
995 boost::function<std::string ()> value )
997 std::string val = value();
1005 MIL <<
"updating '" << filename <<
"' content." << endl;
1009 std::ofstream filestr;
1012 filestr.open( filename.
c_str() );
1014 if ( filestr.good() )
1036 if (
root() !=
"/" )
1050 WAR <<
"Can't create anonymous id file" << endl;
1059 Pathname flavorpath(
home() /
"LastDistributionFlavor");
1065 WAR <<
"No base product, I won't create flavor cache" << endl;
1069 std::string flavor = p->flavor();
1081 WAR <<
"Can't create flavor cache" << endl;
1093 _rpm.closeDatabase();
1094 sigMultiversionSpecChanged();
1095 MIL <<
"Closed target on " <<
_root << endl;
1121 bool build_rpm_solv =
true;
1131 MIL <<
"Read cookie: " << cookie << endl;
1136 if ( status == rpmstatus )
1137 build_rpm_solv =
false;
1138 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1139 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1143 if ( build_rpm_solv )
1157 bool switchingToTmpSolvfile =
false;
1158 Exception ex(
"Failed to cache rpm database.");
1164 rpmsolv =
base/
"solv";
1165 rpmsolvcookie =
base/
"cookie";
1172 WAR <<
"Using a temporary solv file at " <<
base << endl;
1173 switchingToTmpSolvfile =
true;
1182 if ( ! switchingToTmpSolvfile )
1192#ifdef ZYPP_RPMDB2SOLV_PATH
1193 cmd.push_back( ZYPP_RPMDB2SOLV_PATH );
1195 cmd.push_back(
"rpmdb2solv" );
1197 if ( !
_root.empty() ) {
1198 cmd.push_back(
"-r" );
1199 cmd.push_back(
_root.asString() );
1201 cmd.push_back(
"-D" );
1203 cmd.push_back(
"-X" );
1205 cmd.push_back(
"-p" );
1208 if ( ! oldSolvFile.
empty() )
1209 cmd.push_back( oldSolvFile.
asString() );
1211 cmd.push_back(
"-o" );
1215 std::string errdetail;
1218 WAR <<
" " << output;
1219 if ( errdetail.empty() ) {
1223 errdetail += output;
1226 int ret = prog.
close();
1247 if (
root() ==
"/" )
1261 return build_rpm_solv;
1279 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1280 ", force loading: " << (force?
"true":
"false") << endl;
1285 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1292 if ( newCache || force )
1309 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1315 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1340 if (
PathInfo( historyFile ).isExist() )
1347 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1348 onSystemByAuto.insert( ident );
1364 sat::SolvableSpec needrebootSpec;
1365 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1366 needrebootSpec.addProvides(
Capability(
"kernel") );
1369 if (
PathInfo( needrebootFile ).isFile() )
1370 needrebootSpec.parseFrom( needrebootFile );
1373 if (
PathInfo( needrebootDir ).isDir() )
1378 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1380 if ( ! isRpmConfigBackup( str_r ) )
1382 Pathname needrebootFile { needrebootDir / str_r };
1383 if (
PathInfo( needrebootFile ).isFile() )
1384 needrebootSpec.parseFrom( needrebootFile );
1395 if ( ! hardLocks.empty() )
1404 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1416 bool explicitDryRun = policy_r.
dryRun();
1426 if (
root() ==
"/" )
1440 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1459 steps.push_back( *it );
1466 MIL <<
"Todo: " << result << endl;
1477 if ( commitPlugins )
1478 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1485 if ( ! policy_r.
dryRun() )
1491 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1498 if ( ! policy_r.
dryRun() )
1520 DBG <<
"dryRun: Not storing non-package data." << endl;
1527 if ( ! policy_r.
dryRun() )
1529 for_( it, steps.begin(), steps.end() )
1531 if ( ! it->satSolvable().isKind<
Patch>() )
1539 if ( ! patch ||patch->message().empty() )
1542 MIL <<
"Show message for " << patch << endl;
1544 if ( ! report->show( patch ) )
1546 WAR <<
"commit aborted by the user" << endl;
1553 DBG <<
"dryRun: Not checking patch messages." << endl;
1568 std::unique_ptr<CommitPackagePreloader> preloader;
1574 preloader = std::make_unique<CommitPackagePreloader>();
1575 preloader->preloadTransaction( steps );
1576 miss = preloader->missed ();
1583 for_( it, steps.begin(), steps.end() )
1585 switch ( it->stepType() )
1604 localfile = packageCache.
get( pi );
1607 catch (
const AbortRequestException & exp )
1611 WAR <<
"commit cache preload aborted by the user" << endl;
1615 catch (
const SkipRequestException & exp )
1620 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1630 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1641 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1645 if ( ! policy_r.
dryRun() )
1653 commit( policy_r, packageCache, result );
1657 preloader->cleanupCaches ();
1661 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1662 if ( explicitDryRun ) {
1676 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1677 if ( explicitDryRun ) {
1689 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1698 if ( commitPlugins )
1699 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1704 if ( ! policy_r.
dryRun() )
1709 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1720 struct NotifyAttemptToModify
1722 NotifyAttemptToModify(
ZYppCommitResult & result_r ) : _result( result_r ) {}
1725 {
if ( _guard ) { _result.attemptToModify(
true ); _guard =
false; } }
1728 ZYppCommitResult & _result;
1737 {
"ZYPP_SINGLE_RPMTRANS",
nullptr },
1738 {
"ZYPP_CLASSIC_RPMTRANS",
"1" },
1743 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1748 NotifyAttemptToModify attemptToModify( result_r );
1753 AssertProcMounted assertProcMounted(
_root );
1754 AssertDevMounted assertDevMounted(
_root );
1761 std::vector<sat::Solvable> successfullyInstalledPackages;
1764 for_( step, steps.begin(), steps.end() )
1769 if ( citem->isKind<
Package>() )
1773 obsoletedPackages.insert( citem->ident() );
1779 if ( citem->isKind<
Package>() )
1787 localfile = packageCache_r.
get( citem );
1789 catch (
const AbortRequestException &e )
1791 WAR <<
"commit aborted by the user" << endl;
1796 catch (
const SkipRequestException &e )
1799 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1808 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1817 bool success =
false;
1843 WAR <<
"commit aborted by the user" << endl;
1852 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1868 WAR <<
"dry run failed" << endl;
1875 WAR <<
"commit aborted by the user" << endl;
1880 WAR <<
"Install failed" << endl;
1886 if ( success && !policy_r.
dryRun() )
1889 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1898 bool success =
false;
1911 WAR <<
"commit aborted by the user" << endl;
1927 WAR <<
"commit aborted by the user" << endl;
1933 WAR <<
"removal of " << p <<
" failed";
1936 if ( success && !policy_r.
dryRun() )
1943 else if ( ! policy_r.
dryRun() )
1947 if ( ! citem.
buddy() )
1949 if ( citem->isKind<
Product>() )
1954 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1960 std::string referenceFilename( p->referenceFilename() );
1961 if ( referenceFilename.empty() )
1963 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1967 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1968 if ( !
rpm().hasFile( referencePath.
asString() ) )
1973 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1977 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2006 if ( ! successfullyInstalledPackages.empty() )
2009 successfullyInstalledPackages, abort ) )
2011 WAR <<
"Commit aborted by the user" << endl;
2017 successfullyInstalledPackages,
2024 logPatchStatusChanges( result_r.
transaction(), *
this );
2043 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2046 data.
set(
"line", std::cref(line_r) );
2047 data.
set(
"level", level_r );
2053 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
2054 switch ( rpmlevel_r ) {
2055 case RPMLOG_EMERG: [[fallthrough]];
2056 case RPMLOG_ALERT: [[fallthrough]];
2058 return ReportType::loglevel::crt;
2060 return ReportType::loglevel::err;
2061 case RPMLOG_WARNING:
2062 return ReportType::loglevel::war;
2063 default: [[fallthrough]];
2064 case RPMLOG_NOTICE: [[fallthrough]];
2066 return ReportType::loglevel::msg;
2068 return ReportType::loglevel::dbg;
2076 { (*this)->report( userData_r ); }
2082 {
"ZYPP_SINGLE_RPMTRANS",
"1" },
2083 {
"ZYPP_CLASSIC_RPMTRANS",
nullptr },
2086 SingleTransReportLegacyWrapper _legacyWrapper;
2091 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
2096 NotifyAttemptToModify attemptToModify( result_r );
2102 AssertProcMounted assertProcMounted(
_root );
2103 AssertDevMounted assertDevMounted(
_root );
2117 proto::target::Commit
commit;
2127 for (
auto &[
_, value] : data ) {
2129 value.resetDispose();
2135 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2136 auto &step = steps[stepId];
2139 if ( citem->isKind<
Package>() )
2148 if ( citem->isKind<
Package>() ) {
2153 locCache.value()[stepId] = packageCache_r.
get( citem );
2155 proto::target::InstallStep tStep;
2156 tStep.stepId = stepId;
2157 tStep.pathname = locCache.
value()[stepId]->asString();
2158 tStep.multiversion = p->multiversionInstall() ;
2160 commit.transactionSteps.push_back( std::move(tStep) );
2162 catch (
const AbortRequestException &e )
2164 WAR <<
"commit aborted by the user" << endl;
2169 catch (
const SkipRequestException &e )
2172 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2181 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2187 proto::target::RemoveStep tStep;
2188 tStep.stepId = stepId;
2189 tStep.name = p->name();
2190 tStep.version = p->edition().version();
2191 tStep.release = p->edition().release();
2192 tStep.arch = p->arch().asString();
2193 commit.transactionSteps.push_back(std::move(tStep));
2204 proto::target::InstallStep tStep;
2205 tStep.stepId = stepId;
2206 tStep.pathname = locCache.value()[stepId]->asString();
2207 tStep.multiversion =
false;
2208 commit.transactionSteps.push_back(std::move(tStep));
2212 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2219 std::vector<sat::Solvable> successfullyInstalledPackages;
2221 if (
commit.transactionSteps.size() ) {
2228 const std::vector<int> interceptedSignals {
2235 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2236 unixSignals->sigReceived ().connect ([](
int signum ){
2238 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 );
2240 for(
const auto &sig : interceptedSignals )
2241 unixSignals->addSignal ( sig );
2244 for(
const auto &sig : interceptedSignals )
2245 unixSignals->removeSignal ( sig );
2252 int currentStepId = -1;
2258 bool gotEndOfScript =
false;
2261 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2262 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2263 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2264 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2265 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2268 std::optional<proto::target::TransactionError> transactionError;
2271 std::string currentScriptType;
2272 std::string currentScriptPackage;
2282 unsigned lineno = 0;
2290 zyppng::StompFrameStreamRef msgStream;
2295 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2297 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2299 if ( currentStepId >= 0 )
2300 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2301 cmdout.
set(
"line", line );
2305 if ( installreport ) {
2306 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2307 }
else if ( uninstallreport ) {
2308 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2309 }
else if ( scriptreport ) {
2310 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2311 }
else if ( transactionreport ) {
2312 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2313 }
else if ( cleanupreport ) {
2314 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2316 WAR <<
"Got rpm output without active report " << line;
2321 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2325 if ( line.back() !=
'\n' )
2331 const auto &processDataFromScriptFd = [&](){
2333 while ( scriptSource->canReadLine() ) {
2335 if ( gotEndOfScript )
2338 std::string l = scriptSource->readLine().asString();
2340 gotEndOfScript =
true;
2341 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2344 l = l.substr( 0, rawsize );
2346 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2347 sendRpmLineToReport( l );
2350 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2353 const auto &waitForScriptEnd = [&]() {
2356 if ( gotEndOfScript )
2360 processDataFromScriptFd();
2363 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2366 scriptSource->waitForReadyRead( 100 );
2370 const auto &aboutToStartNewReport = [&](){
2372 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2373 ERR <<
"There is still a running report, this is a bug" << std::endl;
2377 gotEndOfScript =
false;
2380 const auto &writeRpmMsgToHistory = [&](){
2381 if ( rpmmsg.size() == 0 )
2385 rpmmsg +=
"[truncated]\n";
2387 std::ostringstream sstr;
2388 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2393 const auto &finalizeCurrentReport = [&]() {
2396 if ( currentStepId >= 0 ) {
2397 step = &steps.at(currentStepId);
2401 if ( installreport ) {
2409 writeRpmMsgToHistory();
2413 ( *installreport)->progress( 100, resObj );
2416 if ( currentStepId >= 0 )
2417 locCache.value().erase( currentStepId );
2418 successfullyInstalledPackages.push_back( step->
satSolvable() );
2424 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2436 writeRpmMsgToHistory();
2439 if ( uninstallreport ) {
2447 writeRpmMsgToHistory();
2451 ( *uninstallreport)->progress( 100, resObj );
2461 writeRpmMsgToHistory();
2464 if ( scriptreport ) {
2466 ( *scriptreport)->progress( 100, resObj );
2469 if ( transactionreport ) {
2471 ( *transactionreport)->progress( 100 );
2474 if ( cleanupreport ) {
2476 ( *cleanupreport)->progress( 100 );
2482 currentScriptType.clear();
2483 currentScriptPackage.clear();
2484 installreport.reset();
2485 uninstallreport.reset();
2486 scriptreport.reset();
2487 transactionreport.reset();
2488 cleanupreport.reset();
2498 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2500 const char *argv[] = {
2503 zyppRpmBinary.data(),
2520 prog->addFd( messagePipe->writeFd );
2521 prog->addFd( scriptPipe->writeFd );
2524 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2527 const auto &processMessages = [&] ( ) {
2531 const auto &checkMsgWithStepId = [&steps](
auto &p ){
2533 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2537 auto id = p->stepId;
2538 if ( id < 0 || id >= steps.size() ) {
2539 ERR <<
"Received invalid stepId: " <<
id <<
" in " << p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2545 while (
const auto &m = msgStream->nextMessage() ) {
2551 const auto &mName = m->command();
2552 if ( mName == proto::target::RpmLog::typeName ) {
2554 const auto &p = proto::target::RpmLog::fromStompMessage (*m);
2556 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2559 ( p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2560 : p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2561 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p->level <<
"> " << p->line;
2564 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2565 finalizeCurrentReport();
2567 const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
2568 if ( !checkMsgWithStepId( p ) )
2571 aboutToStartNewReport();
2573 auto & step = steps.at( p->stepId );
2574 currentStepId = p->stepId;
2576 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2577 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2579 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2580 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2583 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2584 const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
2585 if ( !checkMsgWithStepId( p ) )
2592 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2593 const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
2594 if ( !checkMsgWithStepId( p ) )
2597 if ( uninstallreport )
2598 (*uninstallreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2599 else if ( installreport )
2600 (*installreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2602 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2604 }
else if ( mName == proto::target::PackageError::typeName ) {
2605 const auto &p = proto::target::PackageError::fromStompMessage(*m);
2606 if ( !checkMsgWithStepId( p ) )
2609 if ( p->stepId >= 0 && p->stepId < steps.size() )
2612 finalizeCurrentReport();
2614 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2615 finalizeCurrentReport();
2617 const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
2619 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2623 aboutToStartNewReport();
2626 const auto stepId = p->stepId;
2627 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2631 currentStepId = p->stepId;
2632 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2633 currentScriptType = p->scriptType;
2634 currentScriptPackage = p->scriptPackage;
2635 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2637 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2641 }
else if ( mName == proto::target::ScriptError::typeName ) {
2643 const auto &p = proto::target::ScriptError::fromStompMessage(*m);
2645 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2650 const auto stepId = p->stepId;
2651 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2661 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2664 writeRpmMsgToHistory();
2666 if ( !scriptreport ) {
2667 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2676 scriptreport.reset();
2679 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2680 finalizeCurrentReport();
2682 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2684 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2688 aboutToStartNewReport();
2689 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2690 (*cleanupreport)->start( beg->nvra );
2691 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2693 finalizeCurrentReport();
2695 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2696 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2698 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2702 if ( !cleanupreport ) {
2703 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2707 (*cleanupreport)->progress( prog->amount );
2709 }
else if ( mName == proto::target::TransBegin::typeName ) {
2710 finalizeCurrentReport();
2712 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2714 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2718 aboutToStartNewReport();
2719 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2720 (*transactionreport)->start( beg->name );
2721 }
else if ( mName == proto::target::TransFinished::typeName ) {
2723 finalizeCurrentReport();
2725 }
else if ( mName == proto::target::TransProgress::typeName ) {
2726 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2728 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2732 if ( !transactionreport ) {
2733 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2737 (*transactionreport)->progress( prog->amount );
2738 }
else if ( mName == proto::target::TransactionError::typeName ) {
2740 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2742 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2747 transactionError = std::move(*error);
2750 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2758 prog->sigStarted().connect( [&](){
2761 messagePipe->unrefWrite();
2762 scriptPipe->unrefWrite();
2766 while( prog->canReadLine( channel ) ) {
2767 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2773 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2779 const auto &msg =
commit.toStompMessage();
2781 std::rethrow_exception ( msg.error() );
2783 if ( !msgStream->sendMessage( *msg ) ) {
2784 prog->stop( SIGKILL );
2790 int zyppRpmExitCode = -1;
2792 zyppRpmExitCode = code;
2796 if ( !prog->start( argv ) ) {
2805 msgStream->readAllMessages();
2812 finalizeCurrentReport();
2815 bool readMsgs =
false;
2825 while ( scriptSource->canReadLine() ) {
2827 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2829 if ( scriptSource->bytesAvailable() > 0 ) {
2831 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2836 switch ( zyppRpmExitCode ) {
2838 case zypprpm::NoError:
2839 case zypprpm::RpmFinishedWithError:
2841 case zypprpm::RpmFinishedWithTransactionError: {
2843 if ( transactionError ) {
2845 std::ostringstream sstr;
2846 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2847 for (
const auto & err : transactionError->problems ) {
2848 sstr <<
" " << err <<
"\n";
2858 case zypprpm::FailedToOpenDb:
2861 case zypprpm::WrongHeaderSize:
2862 case zypprpm::WrongMessageFormat:
2865 case zypprpm::RpmInitFailed:
2868 case zypprpm::FailedToReadPackage:
2871 case zypprpm::FailedToAddStepToTransaction:
2874 case zypprpm::RpmOrderFailed:
2877 case zypprpm::FailedToCreateLock:
2882 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2883 auto &step = steps[stepId];
2895 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2899 std::string referenceFilename( p->referenceFilename() );
2901 if ( referenceFilename.empty() ) {
2902 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2904 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2906 if ( !
rpm().hasFile( referencePath.
asString() ) ) {
2910 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2912 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2926 if ( ! successfullyInstalledPackages.empty() )
2929 successfullyInstalledPackages, abort ) )
2931 WAR <<
"Commit aborted by the user" << endl;
2937 successfullyInstalledPackages,
2944 logPatchStatusChanges( result_r.
transaction(), *
this );
2961 return _rpm.hasFile(path_str, name_str);
2972 if ( baseproduct.isFile() )
2985 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2991 const parser::ProductFileData & cachedBaseproductdata(
const Pathname & root_r )
2993 struct CachedEntry {
2995 parser::ProductFileData data;
2997 static std::map<Pathname, CachedEntry> cache;
2998 auto & entry = cache[root_r];
2999 if ( entry.watcher.path().empty() )
3001 if ( entry.watcher.hasChanged() )
3002 entry.data = baseproductdata( root_r );
3006 inline Pathname staticGuessRoot(
const Pathname & root_r )
3008 if ( root_r.empty() )
3013 return Pathname(
"/");
3019 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
3021 std::ifstream idfile( file_r.c_str() );
3022 for( iostr::EachLine in( idfile ); in; in.next() )
3025 if ( ! line.empty() )
3028 return std::string();
3039 if ( p->isTargetDistribution() )
3047 const Pathname needroot( staticGuessRoot(root_r) );
3050 return target->requestedLocales();
3056 MIL <<
"updateAutoInstalled if changed..." << endl;
3064 {
return baseproductdata(
_root ).registerTarget(); }
3067 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3070 {
return baseproductdata(
_root ).registerRelease(); }
3073 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3076 {
return baseproductdata(
_root ).registerFlavor(); }
3079 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3111 const Pathname & needroot = staticGuessRoot(root_r);
3129 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3134 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3140 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3143 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3144 if ( ret.
empty() && root_r !=
"/" )
3147 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3155 return guessAnonymousUniqueId(
root() );
3160 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3167 MIL <<
"New VendorAttr: " << vendorAttr_r << endl;
#define NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define MAXRPMMESSAGELINES
#define SUBST_IF(PAT, VAL)
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
reference value() const
Reference to the Tp object.
void resetDispose()
Set no dispose function.
Store and operate on date (time_t).
static Date now()
Return the current time.
Edition represents [epoch:]version[-release]
std::string version() const
Version.
unsigned int epoch_t
Type of an epoch.
std::string release() const
Release.
epoch_t epoch() const
Epoch.
Base class for Exception.
void remember(const Exception &old_r)
Store an other Exception as history.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
int close() override
Wait for the progamm to complete.
const std::string & command() const
The command we're executing.
std::vector< std::string > Arguments
Writing the zypp history file.
void stampCommand()
Log info about the current process.
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
void remove(const PoolItem &pi)
Log removal of a package.
static const Pathname & fname()
Get the current log file path.
void install(const PoolItem &pi)
Log installation (or update) of a package.
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Access to the sat-pools string space.
const char * c_str() const
Conversion to const char *
std::string asString() const
Conversion to std::string
@ REGEX
Regular Expression.
TraitsType::constPtrType constPtr
Class representing a patch.
TraitsType::constPtrType constPtr
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Parallel execution of stateful PluginScripts.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Command frame for communication with PluginScript.
Combining sat::Solvable and ResStatus.
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
ResStatus & status() const
Returns the current status.
sat::Solvable buddy() const
Return the buddy we share our status object with.
TraitsType::constPtrType constPtr
Track changing files or directories.
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
bool solvablesEmpty() const
Whether Repository contains solvables.
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
size_type solvablesSize() const
Number of solvables in Repository.
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
void eraseFromPool()
Remove this Repository from its Pool.
static ResPool instance()
Singleton ctor.
void setHardLockQueries(const HardLockQueries &newLocks_r)
Set a new set of queries.
Resolver & resolver() const
The Resolver.
const LocaleSet & getRequestedLocales() const
Return the requested locales.
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from their initial one.
EstablishedStates establishedStates() const
Factory for EstablishedStates.
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
bool isToBeInstalled() const
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
TraitsType::constPtrType constPtr
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
TraitsType::constPtrType constPtr
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition of vendor equivalence.
Remember a files attributes to detect content changes.
Interim helper class to collect global options and settings.
Arch systemArchitecture() const
The system architecture zypp uses.
static ZConfig & instance()
Singleton ctor.
Options and policies for ZYpp::commit.
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
bool singleTransModeEnabled() const
Whether the single_rpmtrans backend is enabled (or the classic_rpmtrans)
ZYppCommitPolicy & rpmExcludeDocs(bool yesNo_r)
Use rpm option –excludedocs (default: false)
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
ZYppCommitPolicy & allMedia()
Process all media (default)
ZYppCommitPolicy & rpmNoSignature(bool yesNo_r)
Use rpm option –nosignature (default: false)
Result returned from ZYpp::commit.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
void setSingleTransactionMode(bool yesno_r)
std::vector< sat::Transaction::Step > TransactionStepList
const sat::Transaction & transaction() const
The full transaction list.
sat::Transaction & rTransaction()
Manipulate transaction.
static zypp::Pathname lockfileDir()
Typesafe passing of user data via callbacks.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
Pathname dirname() const
Return all but the last component od this path.
const char * c_str() const
String representation.
const std::string & asString() const
String representation.
bool empty() const
Test for an empty path.
Provide a new empty temporary file and delete it when no longer needed.
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
void add(Value val_r)
Push JSON Value to Array.
void add(String key_r, Value val_r)
Add key/value pair.
Data returned by ProductFileReader.
bool empty() const
Whether this is an empty object without valid data.
std::string summary() const
std::string shortName() const
static ProductFileData scanFile(const Pathname &file_r)
Parse one file (or symlink) and return the ProductFileData parsed.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r) const
Provide SrcPackage in a local file.
void setAutoInstalled(const Queue &autoInstalled_r)
Set ident list of all autoinstalled solvables.
Pathname rootDir() const
Get rootdir (for file conflicts check)
static Pool instance()
Singleton ctor.
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
void setNeedrebootSpec(sat::SolvableSpec needrebootSpec_r)
Solvables which should trigger the reboot-needed hint if installed/updated.
Repository systemRepo()
Return the system repository, create it if missing.
void initRequestedLocales(const LocaleSet &locales_r)
Start tracking changes based on this locales_r.
detail::IdType value_type
void push(value_type val_r)
Push a value to the end off the Queue.
A Solvable object within the sat Pool.
A single step within a Transaction.
StepType stepType() const
Type of action to perform in this step.
StepStage stepStage() const
Step action result.
Solvable satSolvable() const
Return the corresponding Solvable.
Libsolv transaction wrapper.
const_iterator end() const
Iterator behind the last TransactionStep.
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run.
const_iterator begin() const
Iterator to the first TransactionStep.
bool order()
Order transaction steps for commit.
@ TRANSACTION_MULTIINSTALL
[M] Install(multiversion) item (
@ TRANSACTION_INSTALL
[+] Install(update) item
@ TRANSACTION_IGNORE
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
@ TRANSACTION_ERASE
[-] Delete item
@ STEP_TODO
[__] unprocessed
void multiversionSpecChanged()
Target::commit helper optimizing package provision.
void setCommitList(std::vector< sat::Solvable > commitList_r)
Download(commit) sequence of solvables to compute read ahead.
bool preloaded() const
Whether preloaded hint is set.
ManagedFile get(const PoolItem &citem_r)
Provide a package.
pool::PoolTraits::HardLockQueries Data
Save and restore locale set from file.
const LocaleSet & locales() const
Return the loacale set.
void tryLevel(target::rpm::InstallResolvableReport::RpmLevel level_r)
Extract and remember posttrans scripts for later execution.
void executeScripts(rpm::RpmDb &rpm_r, const IdStringSet &obsoletedPackages_r)
Execute the remembered scripts and/or or dump_posttrans lines.
void discardScripts()
Discard all remembered scripts and/or or dump_posttrans lines.
bool aborted() const
Returns true if removing is aborted during progress.
std::unordered_set< IdString > Data
Base class for concrete Target implementations.
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
const VendorAttr & vendorAttr() const
The targets current vendor equivalence settings.
std::string targetDistribution() const
This is register.target attribute of the installed base product.
std::list< PoolItem > PoolItemList
list of pool items
LocaleSet requestedLocales() const
Languages to be supported by the system.
void updateAutoInstalled()
Update the database of autoinstalled packages.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
Pathname _root
Path to the target.
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
WatchFile _baseproductWatcher
Cache distributionVersion.
Pathname _tmpSolvfilesPath
std::string _distributionVersion
rpm::RpmDb _rpm
RPM database.
~TargetImpl() override
Dtor.
rpm::RpmDb & rpm()
The RPM database.
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
std::string distributionVersion() const
This is version attribute of the installed base product.
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
SolvIdentFile _autoInstalledFile
user/auto installed database
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
bool providesFile(const std::string &path_str, const std::string &name_str) const
If the package is installed and provides the file Needed to evaluate split provides during Resolver::...
HardLocksFile _hardLocksFile
Hard-Locks database.
Pathname root() const
The root set for this target.
void load(bool force=true)
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
void commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
Commit ordered changes (internal helper)
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
VendorAttr _vendorAttr
vendor equivalence settings.
Pathname home() const
The directory to store things.
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Pathname defaultSolvfilesPath() const
The systems default solv file location.
std::string anonymousUniqueId() const
anonymous unique id
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
bool solvfilesPathIsTemp() const
Whether we're using a temp.
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Interface to the rpm program.
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
const Pathname & root() const
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
const Pathname & dbPath() const
Subclass to retrieve rpm database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
static Ptr create(GMainContext *ctx=nullptr)
SignalProxy< void(uint)> sigChannelReadyRead()
SignalProxy< void(int)> sigFinished()
SignalProxy< void()> sigMessageReceived()
static Ptr create(IODevice::Ptr iostr)
Namespace intended to collect all environment variables we use.
bool TRANSACTIONAL_UPDATE()
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
int unlink(const Pathname &path)
Like 'unlink'.
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
int touch(const Pathname &path)
Change file's modification and access times.
std::string getline(std::istream &str)
Read one line from stream.
json::Value toJSON(const sat::Transaction::Step &step_r)
See COMMITBEGIN (added in v1) on page Commit plugin for the specs.
bool empty() const
Whether neither idents nor provides are set.
Queue StringQueue
Queue with String ids.
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
std::string toLower(const std::string &s)
Return lowercase version of s.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
std::string trim(const std::string &s, const Trim trim_r)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
std::string rpmDbStateHash(const Pathname &root_r)
void writeUpgradeTestcase()
static bool fileMissing(const Pathname &pathname)
helper functor
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< std::string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
static std::string generateRandomId()
generates a random id using uuidgen
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet
ZYpp::Ptr getZYpp()
relates: ZYppFactory Convenience to get the Pointer to the ZYpp instance.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
std::list< UpdateNotificationFile > UpdateNotifications
std::unordered_set< IdString > IdStringSet
ResTraits< TRes >::PtrType make(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
ResTraits< TRes >::PtrType asKind(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
DefaultIntegral< bool, true > TrueBool
relates: DefaultIntegral true initialized bool
@ DownloadDefault
libzypp will decide what to do.
zypp::callback::UserData UserData
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
Temporarily set/unset an environment variable.
Solvable satSolvable() const
Return the corresponding sat::Solvable.
bool isNeedreboot() const
static PoolImpl & myPool()
Convenience SendReport<rpm::SingleTransReport> wrapper.
void report(const callback::UserData &userData_r)
void sendLoglineRpm(const std::string &line_r, unsigned rpmlevel_r)
Convenience to send a contentLogline translating a rpm loglevel.
void sendLogline(const std::string &line_r, ReportType::loglevel level_r=ReportType::loglevel::msg)
Convenience to send a contentLogline.
@ RPM_NODEPS_FORCE
only this one used
static std::optional< Pipe > create(int flags=0)
#define IMPL_PTR_TYPE(NAME)