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;
1290 bool systemFromSnapshot =
false;
1302 systemFromSnapshot =
true;
1315 if ( ! systemFromSnapshot )
1319 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1325 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1351 if (
PathInfo( historyFile ).isExist() )
1358 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1359 onSystemByAuto.insert( ident );
1375 sat::SolvableSpec needrebootSpec;
1376 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1377 needrebootSpec.addProvides(
Capability(
"kernel") );
1380 if (
PathInfo( needrebootFile ).isFile() )
1381 needrebootSpec.parseFrom( needrebootFile );
1384 if (
PathInfo( needrebootDir ).isDir() )
1389 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1391 if ( ! isRpmConfigBackup( str_r ) )
1393 Pathname needrebootFile { needrebootDir / str_r };
1394 if (
PathInfo( needrebootFile ).isFile() )
1395 needrebootSpec.parseFrom( needrebootFile );
1406 if ( ! hardLocks.empty() )
1416 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1428 bool explicitDryRun = policy_r.
dryRun();
1438 if (
root() ==
"/" )
1452 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1471 steps.push_back( *it );
1479 MIL <<
"Todo: " << result << endl;
1486 if ( ! policy_r.
dryRun() )
1492 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1500 if ( ! policy_r.
dryRun() )
1502 for_( it, steps.begin(), steps.end() )
1504 if ( ! it->satSolvable().isKind<
Patch>() )
1512 if ( ! patch ||patch->message().empty() )
1515 MIL <<
"Show message for " << patch << endl;
1517 if ( ! report->show( patch ) )
1519 WAR <<
"commit aborted by the user" << endl;
1526 DBG <<
"dryRun: Not checking patch messages." << endl;
1541 std::unique_ptr<CommitPackagePreloader> preloader;
1547 preloader = std::make_unique<CommitPackagePreloader>();
1548 preloader->preloadTransaction( steps );
1549 miss = preloader->missed ();
1556 for_( it, steps.begin(), steps.end() )
1558 switch ( it->stepType() )
1577 localfile = packageCache.
get( pi );
1580 catch (
const AbortRequestException & exp )
1584 WAR <<
"commit cache preload aborted by the user" << endl;
1588 catch (
const SkipRequestException & exp )
1593 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1603 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1614 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1620 if ( ! commitActiveReport->start() )
1622 WAR <<
"commit aborted: CommitActiveReport declined" << endl;
1635 if ( commitPlugins )
1636 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1641 if ( ! policy_r.
dryRun() )
1663 DBG <<
"dryRun: Not storing non-package data." << endl;
1666 if ( ! policy_r.
dryRun() )
1673 commit( policy_r, packageCache, result );
1677 preloader->cleanupCaches ();
1681 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1682 if ( explicitDryRun ) {
1696 if ( commitPlugins )
1697 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1702 if ( ! policy_r.
dryRun() )
1707 commitActiveReport->end();
1712 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1713 if ( explicitDryRun ) {
1725 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1731 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1742 struct NotifyAttemptToModify
1744 NotifyAttemptToModify(
ZYppCommitResult & result_r ) : _result( result_r ) {}
1747 {
if ( _guard ) { _result.attemptToModify(
true ); _guard =
false; } }
1750 ZYppCommitResult & _result;
1759 {
"ZYPP_SINGLE_RPMTRANS",
nullptr },
1760 {
"ZYPP_CLASSIC_RPMTRANS",
"1" },
1765 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1770 NotifyAttemptToModify attemptToModify( result_r );
1775 AssertProcMounted assertProcMounted(
_root );
1776 AssertDevMounted assertDevMounted(
_root );
1783 std::vector<sat::Solvable> successfullyInstalledPackages;
1786 for_( step, steps.begin(), steps.end() )
1791 if ( citem->isKind<
Package>() )
1795 obsoletedPackages.insert( citem->ident() );
1801 if ( citem->isKind<
Package>() )
1809 localfile = packageCache_r.
get( citem );
1811 catch (
const AbortRequestException &e )
1813 WAR <<
"commit aborted by the user" << endl;
1818 catch (
const SkipRequestException &e )
1821 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
1830 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
1839 bool success =
false;
1865 WAR <<
"commit aborted by the user" << endl;
1874 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1890 WAR <<
"dry run failed" << endl;
1897 WAR <<
"commit aborted by the user" << endl;
1902 WAR <<
"Install failed" << endl;
1908 if ( success && !policy_r.
dryRun() )
1911 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1920 bool success =
false;
1933 WAR <<
"commit aborted by the user" << endl;
1949 WAR <<
"commit aborted by the user" << endl;
1955 WAR <<
"removal of " <<
p <<
" failed";
1958 if ( success && !policy_r.
dryRun() )
1965 else if ( ! policy_r.
dryRun() )
1969 if ( ! citem.
buddy() )
1971 if ( citem->isKind<
Product>() )
1976 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1982 std::string referenceFilename(
p->referenceFilename() );
1983 if ( referenceFilename.empty() )
1985 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1989 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1990 if ( !
rpm().hasFile( referencePath.
asString() ) )
1995 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1999 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2028 if ( ! successfullyInstalledPackages.empty() )
2031 successfullyInstalledPackages, abort ) )
2033 WAR <<
"Commit aborted by the user" << endl;
2039 successfullyInstalledPackages,
2046 logPatchStatusChanges( result_r.
transaction(), *
this );
2065 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2068 data.
set(
"line", std::cref(line_r) );
2069 data.
set(
"level", level_r );
2075 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
2076 switch ( rpmlevel_r ) {
2077 case RPMLOG_EMERG: [[fallthrough]];
2078 case RPMLOG_ALERT: [[fallthrough]];
2080 return ReportType::loglevel::crt;
2082 return ReportType::loglevel::err;
2083 case RPMLOG_WARNING:
2084 return ReportType::loglevel::war;
2085 default: [[fallthrough]];
2086 case RPMLOG_NOTICE: [[fallthrough]];
2088 return ReportType::loglevel::msg;
2090 return ReportType::loglevel::dbg;
2098 { (*this)->report( userData_r ); }
2104 {
"ZYPP_SINGLE_RPMTRANS",
"1" },
2105 {
"ZYPP_CLASSIC_RPMTRANS",
nullptr },
2108 SingleTransReportLegacyWrapper _legacyWrapper;
2113 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
2118 NotifyAttemptToModify attemptToModify( result_r );
2124 AssertProcMounted assertProcMounted(
_root );
2125 AssertDevMounted assertDevMounted(
_root );
2139 proto::target::Commit
commit;
2149 for (
auto &[
_, value] : data ) {
2151 value.resetDispose();
2157 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2158 auto &step = steps[stepId];
2161 if ( citem->isKind<
Package>() )
2170 if ( citem->isKind<
Package>() ) {
2175 locCache.value()[stepId] = packageCache_r.
get( citem );
2177 proto::target::InstallStep tStep;
2178 tStep.stepId = stepId;
2179 tStep.pathname = locCache.
value()[stepId]->asString();
2180 tStep.multiversion =
p->multiversionInstall() ;
2182 commit.transactionSteps.push_back( std::move(tStep) );
2184 catch (
const AbortRequestException &e )
2186 WAR <<
"commit aborted by the user" << endl;
2191 catch (
const SkipRequestException &e )
2194 WAR <<
"Skipping package " <<
p <<
" in commit" << endl;
2203 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2209 proto::target::RemoveStep tStep;
2210 tStep.stepId = stepId;
2211 tStep.name =
p->name();
2212 tStep.version =
p->edition().version();
2213 tStep.release =
p->edition().release();
2214 tStep.arch =
p->arch().asString();
2215 commit.transactionSteps.push_back(std::move(tStep));
2226 proto::target::InstallStep tStep;
2227 tStep.stepId = stepId;
2228 tStep.pathname = locCache.value()[stepId]->asString();
2229 tStep.multiversion =
false;
2230 commit.transactionSteps.push_back(std::move(tStep));
2234 INT <<
"Unexpected Error: Skipping package " <<
p <<
" in commit" << endl;
2241 std::vector<sat::Solvable> successfullyInstalledPackages;
2243 if (
commit.transactionSteps.size() ) {
2250 const std::vector<int> interceptedSignals {
2257 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2258 unixSignals->sigReceived ().connect ([](
int signum ){
2260 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 );
2262 for(
const auto &sig : interceptedSignals )
2263 unixSignals->addSignal ( sig );
2266 for(
const auto &sig : interceptedSignals )
2267 unixSignals->removeSignal ( sig );
2274 int currentStepId = -1;
2280 bool gotEndOfScript =
false;
2283 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2284 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2285 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2286 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2287 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2290 std::optional<proto::target::TransactionError> transactionError;
2293 std::string currentScriptType;
2294 std::string currentScriptPackage;
2304 unsigned lineno = 0;
2312 zyppng::StompFrameStreamRef msgStream;
2317 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2319 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2321 if ( currentStepId >= 0 )
2322 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2323 cmdout.
set(
"line", line );
2327 if ( installreport ) {
2328 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2329 }
else if ( uninstallreport ) {
2330 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2331 }
else if ( scriptreport ) {
2332 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2333 }
else if ( transactionreport ) {
2334 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2335 }
else if ( cleanupreport ) {
2336 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2338 WAR <<
"Got rpm output without active report " << line;
2343 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2347 if ( line.back() !=
'\n' )
2353 const auto &processDataFromScriptFd = [&](){
2355 while ( scriptSource->canReadLine() ) {
2357 if ( gotEndOfScript )
2360 std::string l = scriptSource->readLine().asString();
2362 gotEndOfScript =
true;
2363 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2366 l = l.substr( 0, rawsize );
2368 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2369 sendRpmLineToReport( l );
2372 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2375 const auto &waitForScriptEnd = [&]() {
2378 if ( gotEndOfScript )
2382 processDataFromScriptFd();
2385 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2388 scriptSource->waitForReadyRead( 100 );
2392 const auto &aboutToStartNewReport = [&](){
2394 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2395 ERR <<
"There is still a running report, this is a bug" << std::endl;
2399 gotEndOfScript =
false;
2402 const auto &writeRpmMsgToHistory = [&](){
2403 if ( rpmmsg.size() == 0 )
2407 rpmmsg +=
"[truncated]\n";
2409 std::ostringstream sstr;
2410 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2415 const auto &finalizeCurrentReport = [&]() {
2418 if ( currentStepId >= 0 ) {
2419 step = &steps.at(currentStepId);
2423 if ( installreport ) {
2431 writeRpmMsgToHistory();
2435 ( *installreport)->progress( 100, resObj );
2438 if ( currentStepId >= 0 )
2439 locCache.value().erase( currentStepId );
2440 successfullyInstalledPackages.push_back( step->
satSolvable() );
2446 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2458 writeRpmMsgToHistory();
2461 if ( uninstallreport ) {
2469 writeRpmMsgToHistory();
2473 ( *uninstallreport)->progress( 100, resObj );
2483 writeRpmMsgToHistory();
2486 if ( scriptreport ) {
2488 ( *scriptreport)->progress( 100, resObj );
2491 if ( transactionreport ) {
2493 ( *transactionreport)->progress( 100 );
2496 if ( cleanupreport ) {
2498 ( *cleanupreport)->progress( 100 );
2504 currentScriptType.clear();
2505 currentScriptPackage.clear();
2506 installreport.reset();
2507 uninstallreport.reset();
2508 scriptreport.reset();
2509 transactionreport.reset();
2510 cleanupreport.reset();
2520 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2522 const char *argv[] = {
2525 zyppRpmBinary.data(),
2542 prog->addFd( messagePipe->writeFd );
2543 prog->addFd( scriptPipe->writeFd );
2546 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2549 const auto &processMessages = [&] ( ) {
2553 const auto &checkMsgWithStepId = [&steps](
auto &
p ){
2555 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2559 auto id =
p->stepId;
2560 if ( id < 0 || id >= steps.size() ) {
2561 ERR <<
"Received invalid stepId: " <<
id <<
" in " <<
p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2567 while (
const auto &m = msgStream->nextMessage() ) {
2573 const auto &mName = m->command();
2574 if ( mName == proto::target::RpmLog::typeName ) {
2576 const auto &
p = proto::target::RpmLog::fromStompMessage (*m);
2578 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2581 (
p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2582 :
p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2583 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " <<
p->level <<
"> " <<
p->line;
2586 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2587 finalizeCurrentReport();
2589 const auto &
p = proto::target::PackageBegin::fromStompMessage(*m);
2590 if ( !checkMsgWithStepId(
p ) )
2593 aboutToStartNewReport();
2595 auto & step = steps.at(
p->stepId );
2596 currentStepId =
p->stepId;
2598 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2599 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2601 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2602 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2605 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2606 const auto &
p = proto::target::PackageFinished::fromStompMessage(*m);
2607 if ( !checkMsgWithStepId(
p ) )
2614 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2615 const auto &
p = proto::target::PackageProgress::fromStompMessage(*m);
2616 if ( !checkMsgWithStepId(
p ) )
2619 if ( uninstallreport )
2620 (*uninstallreport)->progress(
p->amount,
makeResObject( steps.at(
p->stepId ) ));
2621 else if ( installreport )
2622 (*installreport)->progress(
p->amount,
makeResObject( steps.at(
p->stepId ) ));
2624 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2626 }
else if ( mName == proto::target::PackageError::typeName ) {
2627 const auto &
p = proto::target::PackageError::fromStompMessage(*m);
2628 if ( !checkMsgWithStepId(
p ) )
2631 if (
p->stepId >= 0 &&
p->stepId < steps.size() )
2634 finalizeCurrentReport();
2636 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2637 finalizeCurrentReport();
2639 const auto &
p = proto::target::ScriptBegin::fromStompMessage(*m);
2641 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2645 aboutToStartNewReport();
2648 const auto stepId =
p->stepId;
2649 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2653 currentStepId =
p->stepId;
2654 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2655 currentScriptType =
p->scriptType;
2656 currentScriptPackage =
p->scriptPackage;
2657 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2659 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2663 }
else if ( mName == proto::target::ScriptError::typeName ) {
2665 const auto &
p = proto::target::ScriptError::fromStompMessage(*m);
2667 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2672 const auto stepId =
p->stepId;
2673 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2683 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2686 writeRpmMsgToHistory();
2688 if ( !scriptreport ) {
2689 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2698 scriptreport.reset();
2701 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2702 finalizeCurrentReport();
2704 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2706 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2710 aboutToStartNewReport();
2711 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2712 (*cleanupreport)->start( beg->nvra );
2713 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2715 finalizeCurrentReport();
2717 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2718 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2720 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2724 if ( !cleanupreport ) {
2725 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2729 (*cleanupreport)->progress( prog->amount );
2731 }
else if ( mName == proto::target::TransBegin::typeName ) {
2732 finalizeCurrentReport();
2734 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2736 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2740 aboutToStartNewReport();
2741 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2742 (*transactionreport)->start( beg->name );
2743 }
else if ( mName == proto::target::TransFinished::typeName ) {
2745 finalizeCurrentReport();
2747 }
else if ( mName == proto::target::TransProgress::typeName ) {
2748 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2750 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2754 if ( !transactionreport ) {
2755 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2759 (*transactionreport)->progress( prog->amount );
2760 }
else if ( mName == proto::target::TransactionError::typeName ) {
2762 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2764 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2769 transactionError = std::move(*error);
2772 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2780 prog->sigStarted().connect( [&](){
2783 messagePipe->unrefWrite();
2784 scriptPipe->unrefWrite();
2788 while( prog->canReadLine( channel ) ) {
2789 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2795 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2801 const auto &msg =
commit.toStompMessage();
2803 std::rethrow_exception ( msg.error() );
2805 if ( !msgStream->sendMessage( *msg ) ) {
2806 prog->stop( SIGKILL );
2812 int zyppRpmExitCode = -1;
2814 zyppRpmExitCode = code;
2818 if ( !prog->start( argv ) ) {
2827 msgStream->readAllMessages();
2834 finalizeCurrentReport();
2837 bool readMsgs =
false;
2847 while ( scriptSource->canReadLine() ) {
2849 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2851 if ( scriptSource->bytesAvailable() > 0 ) {
2853 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2858 switch ( zyppRpmExitCode ) {
2860 case zypprpm::NoError:
2861 case zypprpm::RpmFinishedWithError:
2863 case zypprpm::RpmFinishedWithTransactionError: {
2865 if ( transactionError ) {
2867 std::ostringstream sstr;
2868 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2869 for (
const auto & err : transactionError->problems ) {
2870 sstr <<
" " << err <<
"\n";
2880 case zypprpm::FailedToOpenDb:
2883 case zypprpm::WrongHeaderSize:
2884 case zypprpm::WrongMessageFormat:
2887 case zypprpm::RpmInitFailed:
2890 case zypprpm::FailedToReadPackage:
2893 case zypprpm::FailedToAddStepToTransaction:
2896 case zypprpm::RpmOrderFailed:
2899 case zypprpm::FailedToCreateLock:
2904 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2905 auto &step = steps[stepId];
2917 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2921 std::string referenceFilename(
p->referenceFilename() );
2923 if ( referenceFilename.empty() ) {
2924 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2926 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2928 if ( !
rpm().hasFile( referencePath.
asString() ) ) {
2932 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2934 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2948 if ( ! successfullyInstalledPackages.empty() )
2951 successfullyInstalledPackages, abort ) )
2953 WAR <<
"Commit aborted by the user" << endl;
2959 successfullyInstalledPackages,
2966 logPatchStatusChanges( result_r.
transaction(), *
this );
2983 return _rpm.hasFile(path_str, name_str);
2994 if ( baseproduct.isFile() )
3007 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
3013 const parser::ProductFileData & cachedBaseproductdata(
const Pathname & root_r )
3015 struct CachedEntry {
3017 parser::ProductFileData data;
3019 static std::map<Pathname, CachedEntry> cache;
3020 auto & entry = cache[root_r];
3021 if ( entry.watcher.path().empty() )
3023 if ( entry.watcher.hasChanged() )
3024 entry.data = baseproductdata( root_r );
3028 inline Pathname staticGuessRoot(
const Pathname & root_r )
3030 if ( root_r.empty() )
3035 return Pathname(
"/");
3041 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
3043 std::ifstream idfile( file_r.c_str() );
3044 for( iostr::EachLine in( idfile ); in; in.next() )
3047 if ( ! line.empty() )
3050 return std::string();
3061 if (
p->isTargetDistribution() )
3069 const Pathname needroot( staticGuessRoot(root_r) );
3072 return target->requestedLocales();
3078 MIL <<
"updateAutoInstalled if changed..." << endl;
3086 {
return baseproductdata(
_root ).registerTarget(); }
3089 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3092 {
return baseproductdata(
_root ).registerRelease(); }
3095 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3098 {
return baseproductdata(
_root ).registerFlavor(); }
3101 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3133 const Pathname & needroot = staticGuessRoot(root_r);
3151 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3156 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3162 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3165 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3166 if ( ret.
empty() && root_r !=
"/" )
3169 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3177 return guessAnonymousUniqueId(
root() );
3182 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3189 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)
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.
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.
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.
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)
nullptr CURL handle void p CURLversion nullptr struct curl_slist list CURLM CURLM_INTERNAL_ERROR CURLM CURL CURLM_INTERNAL_ERROR CURLM curl_socket_t s
nullptr CURL handle void * p
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)