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;
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;
709 if ( abort || aborting_r )
711 WAR <<
"Aborting: Skip update script " << *sit << endl;
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) );
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 ); }
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() )
1030 return !
PathInfo(pathname).isExist();
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;
1094 sigMultiversionSpecChanged();
1095 MIL <<
"Closed target on " <<
_root << endl;
1121 bool build_rpm_solv =
true;
1126 bool solvexisted =
PathInfo(rpmsolv).isExist();
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" );
1198 cmd.push_back(
"-r" );
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;
1280 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1281 ", force loading: " << (force?
"true":
"false") << endl;
1286 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1291 bool systemFromSnapshot =
false;
1300 systemFromSnapshot =
true;
1301 else if ( newCache || force )
1312 if ( ! systemFromSnapshot )
1316 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1322 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1348 if (
PathInfo( historyFile ).isExist() )
1355 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1356 onSystemByAuto.insert( ident );
1372 sat::SolvableSpec needrebootSpec;
1373 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1374 needrebootSpec.addProvides(
Capability(
"kernel") );
1377 if (
PathInfo( needrebootFile ).isFile() )
1378 needrebootSpec.parseFrom( needrebootFile );
1381 if (
PathInfo( needrebootDir ).isDir() )
1386 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1388 if ( ! isRpmConfigBackup( str_r ) )
1390 Pathname needrebootFile { needrebootDir / str_r };
1391 if (
PathInfo( needrebootFile ).isFile() )
1392 needrebootSpec.parseFrom( needrebootFile );
1403 if ( ! hardLocks.empty() )
1413 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1425 bool explicitDryRun = policy_r.
dryRun();
1435 if (
root() ==
"/" )
1449 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1468 steps.push_back( *it );
1476 MIL <<
"Todo: " << result << endl;
1483 if ( ! policy_r.
dryRun() )
1489 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1497 if ( ! policy_r.
dryRun() )
1499 for_( it, steps.begin(), steps.end() )
1501 if ( ! it->satSolvable().isKind<
Patch>() )
1509 if ( ! patch ||patch->message().empty() )
1512 MIL <<
"Show message for " << patch << endl;
1514 if ( ! report->show( patch ) )
1516 WAR <<
"commit aborted by the user" << endl;
1523 DBG <<
"dryRun: Not checking patch messages." << endl;
1538 std::unique_ptr<CommitPackagePreloader> preloader;
1544 preloader = std::make_unique<CommitPackagePreloader>();
1545 preloader->preloadTransaction( steps );
1546 miss = preloader->missed ();
1553 for_( it, steps.begin(), steps.end() )
1555 switch ( it->stepType() )
1574 localfile = packageCache.
get( pi );
1577 catch (
const AbortRequestException & exp )
1581 WAR <<
"commit cache preload aborted by the user" << endl;
1585 catch (
const SkipRequestException & exp )
1590 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1600 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1611 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1617 if ( ! commitActiveReport->start() )
1619 WAR <<
"commit aborted: CommitActiveReport declined" << endl;
1632 if ( commitPlugins )
1633 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1638 if ( ! policy_r.
dryRun() )
1660 DBG <<
"dryRun: Not storing non-package data." << endl;
1663 if ( ! policy_r.
dryRun() )
1670 commit( policy_r, packageCache, result );
1674 preloader->cleanupCaches ();
1678 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1679 if ( explicitDryRun ) {
1693 if ( commitPlugins )
1694 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1699 if ( ! policy_r.
dryRun() )
1704 commitActiveReport->end();
1709 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1710 if ( explicitDryRun ) {
1722 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1728 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1739 struct NotifyAttemptToModify
1741 NotifyAttemptToModify(
ZYppCommitResult & result_r ) : _result( result_r ) {}
1744 {
if ( _guard ) { _result.attemptToModify(
true ); _guard =
false; } }
1747 ZYppCommitResult & _result;
1756 {
"ZYPP_SINGLE_RPMTRANS",
nullptr },
1757 {
"ZYPP_CLASSIC_RPMTRANS",
"1" },
1762 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1767 NotifyAttemptToModify attemptToModify( result_r );
1772 AssertProcMounted assertProcMounted(
_root );
1773 AssertDevMounted assertDevMounted(
_root );
1780 std::vector<sat::Solvable> successfullyInstalledPackages;
1783 for_( step, steps.begin(), steps.end() )
1788 if ( citem->isKind<
Package>() )
1792 obsoletedPackages.insert( citem->ident() );
1798 if ( citem->isKind<
Package>() )
1806 localfile = packageCache_r.
get( citem );
1808 catch (
const AbortRequestException &e )
1810 WAR <<
"commit aborted by the user" << endl;
1815 catch (
const SkipRequestException &e )
1818 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
1827 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
1836 bool success =
false;
1862 WAR <<
"commit aborted by the user" << endl;
1871 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1887 WAR <<
"dry run failed" << endl;
1894 WAR <<
"commit aborted by the user" << endl;
1899 WAR <<
"Install failed" << endl;
1905 if ( success && !policy_r.
dryRun() )
1908 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1917 bool success =
false;
1930 WAR <<
"commit aborted by the user" << endl;
1946 WAR <<
"commit aborted by the user" << endl;
1952 WAR <<
"removal of " <<
p <<
" failed";
1955 if ( success && !policy_r.
dryRun() )
1962 else if ( ! policy_r.
dryRun() )
1966 if ( ! citem.
buddy() )
1968 if ( citem->isKind<
Product>() )
1973 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1979 std::string referenceFilename(
p->referenceFilename() );
1980 if ( referenceFilename.empty() )
1982 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1986 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1987 if ( !
rpm().hasFile( referencePath.
asString() ) )
1992 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1996 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2025 if ( ! successfullyInstalledPackages.empty() )
2028 successfullyInstalledPackages, abort ) )
2030 WAR <<
"Commit aborted by the user" << endl;
2036 successfullyInstalledPackages,
2043 logPatchStatusChanges( result_r.
transaction(), *
this );
2047 HistoryLog().comment(
"Commit was aborted." );
2062 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2065 data.
set(
"line", std::cref(line_r) );
2066 data.
set(
"level", level_r );
2072 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
2073 switch ( rpmlevel_r ) {
2074 case RPMLOG_EMERG: [[fallthrough]];
2075 case RPMLOG_ALERT: [[fallthrough]];
2077 return ReportType::loglevel::crt;
2079 return ReportType::loglevel::err;
2080 case RPMLOG_WARNING:
2081 return ReportType::loglevel::war;
2082 default: [[fallthrough]];
2083 case RPMLOG_NOTICE: [[fallthrough]];
2085 return ReportType::loglevel::msg;
2087 return ReportType::loglevel::dbg;
2095 { (*this)->report( userData_r ); }
2101 {
"ZYPP_SINGLE_RPMTRANS",
"1" },
2102 {
"ZYPP_CLASSIC_RPMTRANS",
nullptr },
2105 SingleTransReportLegacyWrapper _legacyWrapper;
2110 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
2115 NotifyAttemptToModify attemptToModify( result_r );
2121 AssertProcMounted assertProcMounted(
_root );
2122 AssertDevMounted assertDevMounted(
_root );
2136 proto::target::Commit
commit;
2146 for (
auto &[
_, value] : data ) {
2148 value.resetDispose();
2154 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2155 auto &step = steps[stepId];
2158 if ( citem->isKind<
Package>() )
2167 if ( citem->isKind<
Package>() ) {
2172 locCache.value()[stepId] = packageCache_r.
get( citem );
2174 proto::target::InstallStep tStep;
2175 tStep.stepId = stepId;
2176 tStep.pathname = locCache.
value()[stepId]->asString();
2177 tStep.multiversion =
p->multiversionInstall() ;
2179 commit.transactionSteps.push_back( std::move(tStep) );
2181 catch (
const AbortRequestException &e )
2183 WAR <<
"commit aborted by the user" << endl;
2188 catch (
const SkipRequestException &e )
2191 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
2200 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2206 proto::target::RemoveStep tStep;
2207 tStep.stepId = stepId;
2208 tStep.name =
p->name();
2209 tStep.version =
p->edition().version();
2210 tStep.release =
p->edition().release();
2211 tStep.arch =
p->arch().asString();
2212 commit.transactionSteps.push_back(std::move(tStep));
2223 proto::target::InstallStep tStep;
2224 tStep.stepId = stepId;
2225 tStep.pathname = locCache.value()[stepId]->asString();
2226 tStep.multiversion =
false;
2227 commit.transactionSteps.push_back(std::move(tStep));
2231 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2238 std::vector<sat::Solvable> successfullyInstalledPackages;
2240 if (
commit.transactionSteps.size() ) {
2247 const std::vector<int> interceptedSignals {
2254 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2255 unixSignals->sigReceived ().connect ([](
int signum ){
2257 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 );
2259 for(
const auto &sig : interceptedSignals )
2260 unixSignals->addSignal ( sig );
2263 for(
const auto &sig : interceptedSignals )
2264 unixSignals->removeSignal ( sig );
2271 int currentStepId = -1;
2277 bool gotEndOfScript =
false;
2280 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2281 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2282 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2283 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2284 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2287 std::optional<proto::target::TransactionError> transactionError;
2290 std::string currentScriptType;
2291 std::string currentScriptPackage;
2301 unsigned lineno = 0;
2309 zyppng::StompFrameStreamRef msgStream;
2314 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2316 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2318 if ( currentStepId >= 0 )
2319 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2320 cmdout.
set(
"line", line );
2324 if ( installreport ) {
2325 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2326 }
else if ( uninstallreport ) {
2327 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2328 }
else if ( scriptreport ) {
2329 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2330 }
else if ( transactionreport ) {
2331 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2332 }
else if ( cleanupreport ) {
2333 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2335 WAR <<
"Got rpm output without active report " << line;
2340 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2344 if ( line.back() !=
'\n' )
2350 const auto &processDataFromScriptFd = [&](){
2352 while ( scriptSource->canReadLine() ) {
2354 if ( gotEndOfScript )
2357 std::string l = scriptSource->readLine().asString();
2359 gotEndOfScript =
true;
2360 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2363 l = l.substr( 0, rawsize );
2365 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2366 sendRpmLineToReport( l );
2369 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2372 const auto &waitForScriptEnd = [&]() {
2375 if ( gotEndOfScript )
2379 processDataFromScriptFd();
2382 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2385 scriptSource->waitForReadyRead( 100 );
2389 const auto &aboutToStartNewReport = [&](){
2391 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2392 ERR <<
"There is still a running report, this is a bug" << std::endl;
2396 gotEndOfScript =
false;
2399 const auto &writeRpmMsgToHistory = [&](){
2400 if ( rpmmsg.size() == 0 )
2404 rpmmsg +=
"[truncated]\n";
2406 std::ostringstream sstr;
2407 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2412 const auto &finalizeCurrentReport = [&]() {
2415 if ( currentStepId >= 0 ) {
2416 step = &steps.at(currentStepId);
2420 if ( installreport ) {
2428 writeRpmMsgToHistory();
2432 ( *installreport)->progress( 100, resObj );
2435 if ( currentStepId >= 0 )
2436 locCache.value().erase( currentStepId );
2437 successfullyInstalledPackages.push_back( step->
satSolvable() );
2443 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2455 writeRpmMsgToHistory();
2458 if ( uninstallreport ) {
2466 writeRpmMsgToHistory();
2470 ( *uninstallreport)->progress( 100, resObj );
2480 writeRpmMsgToHistory();
2483 if ( scriptreport ) {
2485 ( *scriptreport)->progress( 100, resObj );
2488 if ( transactionreport ) {
2490 ( *transactionreport)->progress( 100 );
2493 if ( cleanupreport ) {
2495 ( *cleanupreport)->progress( 100 );
2501 currentScriptType.clear();
2502 currentScriptPackage.clear();
2503 installreport.reset();
2504 uninstallreport.reset();
2505 scriptreport.reset();
2506 transactionreport.reset();
2507 cleanupreport.reset();
2517 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2519 const char *argv[] = {
2522 zyppRpmBinary.data(),
2539 prog->addFd( messagePipe->writeFd );
2540 prog->addFd( scriptPipe->writeFd );
2543 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2546 const auto &processMessages = [&] ( ) {
2550 const auto &checkMsgWithStepId = [&steps](
auto &
p ){
2552 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2556 auto id =
p->stepId;
2557 if ( id < 0 || id >= steps.size() ) {
2558 ERR <<
"Received invalid stepId: " <<
id <<
" in " <<
p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2564 while (
const auto &m = msgStream->nextMessage() ) {
2570 const auto &mName = m->command();
2571 if ( mName == proto::target::RpmLog::typeName ) {
2573 const auto &
p = proto::target::RpmLog::fromStompMessage (*m);
2575 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2578 (
p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2579 :
p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2580 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " <<
p->level <<
"> " <<
p->line;
2583 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2584 finalizeCurrentReport();
2586 const auto &
p = proto::target::PackageBegin::fromStompMessage(*m);
2587 if ( !checkMsgWithStepId(
p ) )
2590 aboutToStartNewReport();
2592 auto & step = steps.at(
p->stepId );
2593 currentStepId =
p->stepId;
2595 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2596 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2598 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2599 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2602 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2603 const auto &
p = proto::target::PackageFinished::fromStompMessage(*m);
2604 if ( !checkMsgWithStepId(
p ) )
2611 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2612 const auto &
p = proto::target::PackageProgress::fromStompMessage(*m);
2613 if ( !checkMsgWithStepId(
p ) )
2616 if ( uninstallreport )
2617 (*uninstallreport)->progress(
p->amount,
makeResObject( steps.at(
p->stepId ) ));
2618 else if ( installreport )
2619 (*installreport)->progress(
p->amount,
makeResObject( steps.at(
p->stepId ) ));
2621 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2623 }
else if ( mName == proto::target::PackageError::typeName ) {
2624 const auto &
p = proto::target::PackageError::fromStompMessage(*m);
2625 if ( !checkMsgWithStepId(
p ) )
2628 if (
p->stepId >= 0 &&
p->stepId < steps.size() )
2631 finalizeCurrentReport();
2633 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2634 finalizeCurrentReport();
2636 const auto &
p = proto::target::ScriptBegin::fromStompMessage(*m);
2638 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2642 aboutToStartNewReport();
2645 const auto stepId =
p->stepId;
2646 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2650 currentStepId =
p->stepId;
2651 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2652 currentScriptType =
p->scriptType;
2653 currentScriptPackage =
p->scriptPackage;
2654 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2656 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2660 }
else if ( mName == proto::target::ScriptError::typeName ) {
2662 const auto &
p = proto::target::ScriptError::fromStompMessage(*m);
2664 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2669 const auto stepId =
p->stepId;
2670 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2680 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2683 writeRpmMsgToHistory();
2685 if ( !scriptreport ) {
2686 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2695 scriptreport.reset();
2698 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2699 finalizeCurrentReport();
2701 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2703 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2707 aboutToStartNewReport();
2708 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2709 (*cleanupreport)->start( beg->nvra );
2710 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2712 finalizeCurrentReport();
2714 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2715 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2717 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2721 if ( !cleanupreport ) {
2722 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2726 (*cleanupreport)->progress( prog->amount );
2728 }
else if ( mName == proto::target::TransBegin::typeName ) {
2729 finalizeCurrentReport();
2731 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2733 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2737 aboutToStartNewReport();
2738 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2739 (*transactionreport)->start( beg->name );
2740 }
else if ( mName == proto::target::TransFinished::typeName ) {
2742 finalizeCurrentReport();
2744 }
else if ( mName == proto::target::TransProgress::typeName ) {
2745 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2747 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2751 if ( !transactionreport ) {
2752 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2756 (*transactionreport)->progress( prog->amount );
2757 }
else if ( mName == proto::target::TransactionError::typeName ) {
2759 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2761 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2766 transactionError = std::move(*error);
2769 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2777 prog->sigStarted().connect( [&](){
2780 messagePipe->unrefWrite();
2781 scriptPipe->unrefWrite();
2785 while( prog->canReadLine( channel ) ) {
2786 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2792 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2798 const auto &msg =
commit.toStompMessage();
2800 std::rethrow_exception ( msg.error() );
2802 if ( !msgStream->sendMessage( *msg ) ) {
2803 prog->stop( SIGKILL );
2809 int zyppRpmExitCode = -1;
2811 zyppRpmExitCode = code;
2815 if ( !prog->start( argv ) ) {
2816 HistoryLog().comment(
"Commit was aborted, failed to run zypp-rpm" );
2824 msgStream->readAllMessages();
2831 finalizeCurrentReport();
2834 bool readMsgs =
false;
2844 while ( scriptSource->canReadLine() ) {
2846 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2848 if ( scriptSource->bytesAvailable() > 0 ) {
2850 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2855 switch ( zyppRpmExitCode ) {
2857 case zypprpm::NoError:
2858 case zypprpm::RpmFinishedWithError:
2860 case zypprpm::RpmFinishedWithTransactionError: {
2862 if ( transactionError ) {
2864 std::ostringstream sstr;
2865 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2866 for (
const auto & err : transactionError->problems ) {
2867 sstr <<
" " << err <<
"\n";
2877 case zypprpm::FailedToOpenDb:
2880 case zypprpm::WrongHeaderSize:
2881 case zypprpm::WrongMessageFormat:
2884 case zypprpm::RpmInitFailed:
2887 case zypprpm::FailedToReadPackage:
2890 case zypprpm::FailedToAddStepToTransaction:
2893 case zypprpm::RpmOrderFailed:
2896 case zypprpm::FailedToCreateLock:
2901 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2902 auto &step = steps[stepId];
2914 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2918 std::string referenceFilename(
p->referenceFilename() );
2920 if ( referenceFilename.empty() ) {
2921 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2923 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2925 if ( !
rpm().hasFile( referencePath.
asString() ) ) {
2929 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2931 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2945 if ( ! successfullyInstalledPackages.empty() )
2948 successfullyInstalledPackages, abort ) )
2950 WAR <<
"Commit aborted by the user" << endl;
2956 successfullyInstalledPackages,
2963 logPatchStatusChanges( result_r.
transaction(), *
this );
2966 HistoryLog().comment(
"Commit was aborted." );
2991 if ( baseproduct.isFile() )
3004 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
3010 const parser::ProductFileData & cachedBaseproductdata(
const Pathname & root_r )
3012 struct CachedEntry {
3014 parser::ProductFileData data;
3016 static std::map<Pathname, CachedEntry> cache;
3017 auto & entry = cache[root_r];
3018 if ( entry.watcher.path().empty() )
3020 if ( entry.watcher.hasChanged() )
3021 entry.data = baseproductdata( root_r );
3025 inline Pathname staticGuessRoot(
const Pathname & root_r )
3027 if ( root_r.empty() )
3038 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
3040 std::ifstream idfile( file_r.c_str() );
3041 for( iostr::EachLine in( idfile ); in; in.next() )
3044 if ( ! line.empty() )
3047 return std::string();
3058 if (
p->isTargetDistribution() )
3066 const Pathname needroot( staticGuessRoot(root_r) );
3069 return target->requestedLocales();
3075 MIL <<
"updateAutoInstalled if changed..." << endl;
3083 {
return baseproductdata(
_root ).registerTarget(); }
3086 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3089 {
return baseproductdata(
_root ).registerRelease(); }
3092 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3095 {
return baseproductdata(
_root ).registerFlavor(); }
3098 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3130 const Pathname & needroot = staticGuessRoot(root_r);
3148 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3153 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3159 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3162 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3163 if ( ret.
empty() && root_r !=
"/" )
3166 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3174 return guessAnonymousUniqueId(
root() );
3179 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3186 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.
Capability()
Default ctor, Empty capability.
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.
HistoryLog(const HistoryLog &)
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
static const Pathname & fname()
Get the current log file path.
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.
constexpr IdString()
Default ctor, empty string.
@ REGEX
Regular Expression.
TraitsType::constPtrType constPtr
Class representing a patch.
TraitsType::constPtrType constPtr
Pathname()
Default ctor: an empty path.
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Unless path_r does not already denote a path below root_r, combine them.
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.
PluginFrame()
Default ctor (empty frame).
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.
RepoStatus()
Default ctor.
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).
UpdateNotificationFile(sat::Solvable solvable_r, Pathname file_r)
Definition of vendor equivalence.
Remember a files attributes to detect content changes.
WatchFile(const Pathname &path_r=Pathname(), Initial mode=INIT)
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.
static bool snapshotMapped()
Whether mapSnapshot succeeded in this process.
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.
void setData(const Data &data_r)
Store new Data.
const Data & data() const
Return the data.
pool::PoolTraits::HardLockQueries Data
const LocaleSet & locales() const
Return the loacale set.
RequestedLocalesFile(Pathname file_r)
Ctor taking the file to read/write.
void setLocales(const LocaleSet &locales_r)
Store a new locale 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.
const Data & data() const
Return the data.
std::unordered_set< IdString > Data
void setData(const Data &data_r)
Store new Data.
const Pathname & file() const
Return the file path.
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
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
const Pathname & root() const
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
const Pathname & dbPath() const
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
bool hasFile(const std::string &file_r, const std::string &name_r="") const
Return true if at least one package owns a certain file (name_r empty) Return true if package name_r ...
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)
CURL handle void p CURLversion age struct curl_slist list CURLM multi CURLM CURL handle CURLM curl_socket_t s
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)
IMPL_PTR_TYPE(TargetImpl)
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)