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;
1279 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1280 ", force loading: " << (force?
"true":
"false") << endl;
1285 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1292 if ( newCache || force )
1309 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1315 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1340 if (
PathInfo( historyFile ).isExist() )
1347 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1348 onSystemByAuto.insert( ident );
1364 sat::SolvableSpec needrebootSpec;
1365 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1366 needrebootSpec.addProvides(
Capability(
"kernel") );
1369 if (
PathInfo( needrebootFile ).isFile() )
1370 needrebootSpec.parseFrom( needrebootFile );
1373 if (
PathInfo( needrebootDir ).isDir() )
1378 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1380 if ( ! isRpmConfigBackup( str_r ) )
1382 Pathname needrebootFile { needrebootDir / str_r };
1383 if (
PathInfo( needrebootFile ).isFile() )
1384 needrebootSpec.parseFrom( needrebootFile );
1395 if ( ! hardLocks.empty() )
1404 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1416 bool explicitDryRun = policy_r.
dryRun();
1426 if (
root() ==
"/" )
1440 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1459 steps.push_back( *it );
1467 MIL <<
"Todo: " << result << endl;
1474 if ( ! policy_r.
dryRun() )
1480 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1488 if ( ! policy_r.
dryRun() )
1490 for_( it, steps.begin(), steps.end() )
1492 if ( ! it->satSolvable().isKind<
Patch>() )
1500 if ( ! patch ||patch->message().empty() )
1503 MIL <<
"Show message for " << patch << endl;
1505 if ( ! report->show( patch ) )
1507 WAR <<
"commit aborted by the user" << endl;
1514 DBG <<
"dryRun: Not checking patch messages." << endl;
1529 std::unique_ptr<CommitPackagePreloader> preloader;
1535 preloader = std::make_unique<CommitPackagePreloader>();
1536 preloader->preloadTransaction( steps );
1537 miss = preloader->missed ();
1544 for_( it, steps.begin(), steps.end() )
1546 switch ( it->stepType() )
1565 localfile = packageCache.
get( pi );
1568 catch (
const AbortRequestException & exp )
1572 WAR <<
"commit cache preload aborted by the user" << endl;
1576 catch (
const SkipRequestException & exp )
1581 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1591 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1602 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1608 if ( ! commitActiveReport->start() )
1610 WAR <<
"commit aborted: CommitActiveReport declined" << endl;
1623 if ( commitPlugins )
1624 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1629 if ( ! policy_r.
dryRun() )
1651 DBG <<
"dryRun: Not storing non-package data." << endl;
1654 if ( ! policy_r.
dryRun() )
1661 commit( policy_r, packageCache, result );
1665 preloader->cleanupCaches ();
1669 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1670 if ( explicitDryRun ) {
1684 if ( commitPlugins )
1685 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1690 if ( ! policy_r.
dryRun() )
1695 commitActiveReport->end();
1700 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1701 if ( explicitDryRun ) {
1713 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1719 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1730 struct NotifyAttemptToModify
1732 NotifyAttemptToModify(
ZYppCommitResult & result_r ) : _result( result_r ) {}
1735 {
if ( _guard ) { _result.attemptToModify(
true ); _guard =
false; } }
1738 ZYppCommitResult & _result;
1747 {
"ZYPP_SINGLE_RPMTRANS",
nullptr },
1748 {
"ZYPP_CLASSIC_RPMTRANS",
"1" },
1753 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1758 NotifyAttemptToModify attemptToModify( result_r );
1763 AssertProcMounted assertProcMounted(
_root );
1764 AssertDevMounted assertDevMounted(
_root );
1771 std::vector<sat::Solvable> successfullyInstalledPackages;
1774 for_( step, steps.begin(), steps.end() )
1779 if ( citem->isKind<
Package>() )
1783 obsoletedPackages.insert( citem->ident() );
1789 if ( citem->isKind<
Package>() )
1797 localfile = packageCache_r.
get( citem );
1799 catch (
const AbortRequestException &e )
1801 WAR <<
"commit aborted by the user" << endl;
1806 catch (
const SkipRequestException &e )
1809 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1818 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1827 bool success =
false;
1853 WAR <<
"commit aborted by the user" << endl;
1862 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1878 WAR <<
"dry run failed" << endl;
1885 WAR <<
"commit aborted by the user" << endl;
1890 WAR <<
"Install failed" << endl;
1896 if ( success && !policy_r.
dryRun() )
1899 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1908 bool success =
false;
1921 WAR <<
"commit aborted by the user" << endl;
1937 WAR <<
"commit aborted by the user" << endl;
1943 WAR <<
"removal of " << p <<
" failed";
1946 if ( success && !policy_r.
dryRun() )
1953 else if ( ! policy_r.
dryRun() )
1957 if ( ! citem.
buddy() )
1959 if ( citem->isKind<
Product>() )
1964 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1970 std::string referenceFilename( p->referenceFilename() );
1971 if ( referenceFilename.empty() )
1973 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1977 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1978 if ( !
rpm().hasFile( referencePath.
asString() ) )
1983 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1987 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2016 if ( ! successfullyInstalledPackages.empty() )
2019 successfullyInstalledPackages, abort ) )
2021 WAR <<
"Commit aborted by the user" << endl;
2027 successfullyInstalledPackages,
2034 logPatchStatusChanges( result_r.
transaction(), *
this );
2038 HistoryLog().comment(
"Commit was aborted." );
2053 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2056 data.
set(
"line", std::cref(line_r) );
2057 data.
set(
"level", level_r );
2063 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
2064 switch ( rpmlevel_r ) {
2065 case RPMLOG_EMERG: [[fallthrough]];
2066 case RPMLOG_ALERT: [[fallthrough]];
2068 return ReportType::loglevel::crt;
2070 return ReportType::loglevel::err;
2071 case RPMLOG_WARNING:
2072 return ReportType::loglevel::war;
2073 default: [[fallthrough]];
2074 case RPMLOG_NOTICE: [[fallthrough]];
2076 return ReportType::loglevel::msg;
2078 return ReportType::loglevel::dbg;
2086 { (*this)->report( userData_r ); }
2092 {
"ZYPP_SINGLE_RPMTRANS",
"1" },
2093 {
"ZYPP_CLASSIC_RPMTRANS",
nullptr },
2096 SingleTransReportLegacyWrapper _legacyWrapper;
2101 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
2106 NotifyAttemptToModify attemptToModify( result_r );
2112 AssertProcMounted assertProcMounted(
_root );
2113 AssertDevMounted assertDevMounted(
_root );
2127 proto::target::Commit
commit;
2137 for (
auto &[
_, value] : data ) {
2139 value.resetDispose();
2145 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2146 auto &step = steps[stepId];
2149 if ( citem->isKind<
Package>() )
2158 if ( citem->isKind<
Package>() ) {
2163 locCache.value()[stepId] = packageCache_r.
get( citem );
2165 proto::target::InstallStep tStep;
2166 tStep.stepId = stepId;
2167 tStep.pathname = locCache.
value()[stepId]->asString();
2168 tStep.multiversion = p->multiversionInstall() ;
2170 commit.transactionSteps.push_back( std::move(tStep) );
2172 catch (
const AbortRequestException &e )
2174 WAR <<
"commit aborted by the user" << endl;
2179 catch (
const SkipRequestException &e )
2182 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2191 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2197 proto::target::RemoveStep tStep;
2198 tStep.stepId = stepId;
2199 tStep.name = p->name();
2200 tStep.version = p->edition().version();
2201 tStep.release = p->edition().release();
2202 tStep.arch = p->arch().asString();
2203 commit.transactionSteps.push_back(std::move(tStep));
2214 proto::target::InstallStep tStep;
2215 tStep.stepId = stepId;
2216 tStep.pathname = locCache.value()[stepId]->asString();
2217 tStep.multiversion =
false;
2218 commit.transactionSteps.push_back(std::move(tStep));
2222 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2229 std::vector<sat::Solvable> successfullyInstalledPackages;
2231 if (
commit.transactionSteps.size() ) {
2238 const std::vector<int> interceptedSignals {
2245 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2246 unixSignals->sigReceived ().connect ([](
int signum ){
2248 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 );
2250 for(
const auto &sig : interceptedSignals )
2251 unixSignals->addSignal ( sig );
2254 for(
const auto &sig : interceptedSignals )
2255 unixSignals->removeSignal ( sig );
2262 int currentStepId = -1;
2268 bool gotEndOfScript =
false;
2271 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2272 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2273 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2274 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2275 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2278 std::optional<proto::target::TransactionError> transactionError;
2281 std::string currentScriptType;
2282 std::string currentScriptPackage;
2292 unsigned lineno = 0;
2300 zyppng::StompFrameStreamRef msgStream;
2305 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2307 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2309 if ( currentStepId >= 0 )
2310 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2311 cmdout.
set(
"line", line );
2315 if ( installreport ) {
2316 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2317 }
else if ( uninstallreport ) {
2318 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2319 }
else if ( scriptreport ) {
2320 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2321 }
else if ( transactionreport ) {
2322 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2323 }
else if ( cleanupreport ) {
2324 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2326 WAR <<
"Got rpm output without active report " << line;
2331 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2335 if ( line.back() !=
'\n' )
2341 const auto &processDataFromScriptFd = [&](){
2343 while ( scriptSource->canReadLine() ) {
2345 if ( gotEndOfScript )
2348 std::string l = scriptSource->readLine().asString();
2350 gotEndOfScript =
true;
2351 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2354 l = l.substr( 0, rawsize );
2356 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2357 sendRpmLineToReport( l );
2360 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2363 const auto &waitForScriptEnd = [&]() {
2366 if ( gotEndOfScript )
2370 processDataFromScriptFd();
2373 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2376 scriptSource->waitForReadyRead( 100 );
2380 const auto &aboutToStartNewReport = [&](){
2382 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2383 ERR <<
"There is still a running report, this is a bug" << std::endl;
2387 gotEndOfScript =
false;
2390 const auto &writeRpmMsgToHistory = [&](){
2391 if ( rpmmsg.size() == 0 )
2395 rpmmsg +=
"[truncated]\n";
2397 std::ostringstream sstr;
2398 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2403 const auto &finalizeCurrentReport = [&]() {
2406 if ( currentStepId >= 0 ) {
2407 step = &steps.at(currentStepId);
2411 if ( installreport ) {
2419 writeRpmMsgToHistory();
2423 ( *installreport)->progress( 100, resObj );
2426 if ( currentStepId >= 0 )
2427 locCache.value().erase( currentStepId );
2428 successfullyInstalledPackages.push_back( step->
satSolvable() );
2434 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2446 writeRpmMsgToHistory();
2449 if ( uninstallreport ) {
2457 writeRpmMsgToHistory();
2461 ( *uninstallreport)->progress( 100, resObj );
2471 writeRpmMsgToHistory();
2474 if ( scriptreport ) {
2476 ( *scriptreport)->progress( 100, resObj );
2479 if ( transactionreport ) {
2481 ( *transactionreport)->progress( 100 );
2484 if ( cleanupreport ) {
2486 ( *cleanupreport)->progress( 100 );
2492 currentScriptType.clear();
2493 currentScriptPackage.clear();
2494 installreport.reset();
2495 uninstallreport.reset();
2496 scriptreport.reset();
2497 transactionreport.reset();
2498 cleanupreport.reset();
2508 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2510 const char *argv[] = {
2513 zyppRpmBinary.data(),
2530 prog->addFd( messagePipe->writeFd );
2531 prog->addFd( scriptPipe->writeFd );
2534 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2537 const auto &processMessages = [&] ( ) {
2541 const auto &checkMsgWithStepId = [&steps](
auto &p ){
2543 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2547 auto id = p->stepId;
2548 if ( id < 0 || id >= steps.size() ) {
2549 ERR <<
"Received invalid stepId: " <<
id <<
" in " << p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2555 while (
const auto &m = msgStream->nextMessage() ) {
2561 const auto &mName = m->command();
2562 if ( mName == proto::target::RpmLog::typeName ) {
2564 const auto &p = proto::target::RpmLog::fromStompMessage (*m);
2566 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2569 ( p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2570 : p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2571 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p->level <<
"> " << p->line;
2574 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2575 finalizeCurrentReport();
2577 const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
2578 if ( !checkMsgWithStepId( p ) )
2581 aboutToStartNewReport();
2583 auto & step = steps.at( p->stepId );
2584 currentStepId = p->stepId;
2586 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2587 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2589 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2590 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2593 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2594 const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
2595 if ( !checkMsgWithStepId( p ) )
2602 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2603 const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
2604 if ( !checkMsgWithStepId( p ) )
2607 if ( uninstallreport )
2608 (*uninstallreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2609 else if ( installreport )
2610 (*installreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2612 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2614 }
else if ( mName == proto::target::PackageError::typeName ) {
2615 const auto &p = proto::target::PackageError::fromStompMessage(*m);
2616 if ( !checkMsgWithStepId( p ) )
2619 if ( p->stepId >= 0 && p->stepId < steps.size() )
2622 finalizeCurrentReport();
2624 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2625 finalizeCurrentReport();
2627 const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
2629 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2633 aboutToStartNewReport();
2636 const auto stepId = p->stepId;
2637 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2641 currentStepId = p->stepId;
2642 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2643 currentScriptType = p->scriptType;
2644 currentScriptPackage = p->scriptPackage;
2645 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2647 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2651 }
else if ( mName == proto::target::ScriptError::typeName ) {
2653 const auto &p = proto::target::ScriptError::fromStompMessage(*m);
2655 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2660 const auto stepId = p->stepId;
2661 if ( stepId >= 0 &&
static_cast<size_t>(stepId) < steps.size() ) {
2671 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2674 writeRpmMsgToHistory();
2676 if ( !scriptreport ) {
2677 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2686 scriptreport.reset();
2689 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2690 finalizeCurrentReport();
2692 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2694 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2698 aboutToStartNewReport();
2699 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2700 (*cleanupreport)->start( beg->nvra );
2701 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2703 finalizeCurrentReport();
2705 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2706 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2708 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2712 if ( !cleanupreport ) {
2713 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2717 (*cleanupreport)->progress( prog->amount );
2719 }
else if ( mName == proto::target::TransBegin::typeName ) {
2720 finalizeCurrentReport();
2722 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2724 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2728 aboutToStartNewReport();
2729 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2730 (*transactionreport)->start( beg->name );
2731 }
else if ( mName == proto::target::TransFinished::typeName ) {
2733 finalizeCurrentReport();
2735 }
else if ( mName == proto::target::TransProgress::typeName ) {
2736 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2738 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2742 if ( !transactionreport ) {
2743 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2747 (*transactionreport)->progress( prog->amount );
2748 }
else if ( mName == proto::target::TransactionError::typeName ) {
2750 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2752 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2757 transactionError = std::move(*error);
2760 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2768 prog->sigStarted().connect( [&](){
2771 messagePipe->unrefWrite();
2772 scriptPipe->unrefWrite();
2776 while( prog->canReadLine( channel ) ) {
2777 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2783 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2789 const auto &msg =
commit.toStompMessage();
2791 std::rethrow_exception ( msg.error() );
2793 if ( !msgStream->sendMessage( *msg ) ) {
2794 prog->stop( SIGKILL );
2800 int zyppRpmExitCode = -1;
2802 zyppRpmExitCode = code;
2806 if ( !prog->start( argv ) ) {
2807 HistoryLog().comment(
"Commit was aborted, failed to run zypp-rpm" );
2815 msgStream->readAllMessages();
2822 finalizeCurrentReport();
2825 bool readMsgs =
false;
2835 while ( scriptSource->canReadLine() ) {
2837 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2839 if ( scriptSource->bytesAvailable() > 0 ) {
2841 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2846 switch ( zyppRpmExitCode ) {
2848 case zypprpm::NoError:
2849 case zypprpm::RpmFinishedWithError:
2851 case zypprpm::RpmFinishedWithTransactionError: {
2853 if ( transactionError ) {
2855 std::ostringstream sstr;
2856 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2857 for (
const auto & err : transactionError->problems ) {
2858 sstr <<
" " << err <<
"\n";
2868 case zypprpm::FailedToOpenDb:
2871 case zypprpm::WrongHeaderSize:
2872 case zypprpm::WrongMessageFormat:
2875 case zypprpm::RpmInitFailed:
2878 case zypprpm::FailedToReadPackage:
2881 case zypprpm::FailedToAddStepToTransaction:
2884 case zypprpm::RpmOrderFailed:
2887 case zypprpm::FailedToCreateLock:
2892 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2893 auto &step = steps[stepId];
2905 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2909 std::string referenceFilename( p->referenceFilename() );
2911 if ( referenceFilename.empty() ) {
2912 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2914 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2916 if ( !
rpm().hasFile( referencePath.
asString() ) ) {
2920 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2922 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2936 if ( ! successfullyInstalledPackages.empty() )
2939 successfullyInstalledPackages, abort ) )
2941 WAR <<
"Commit aborted by the user" << endl;
2947 successfullyInstalledPackages,
2954 logPatchStatusChanges( result_r.
transaction(), *
this );
2957 HistoryLog().comment(
"Commit was aborted." );
2982 if ( baseproduct.isFile() )
2995 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
3001 const parser::ProductFileData & cachedBaseproductdata(
const Pathname & root_r )
3003 struct CachedEntry {
3005 parser::ProductFileData data;
3007 static std::map<Pathname, CachedEntry> cache;
3008 auto & entry = cache[root_r];
3009 if ( entry.watcher.path().empty() )
3011 if ( entry.watcher.hasChanged() )
3012 entry.data = baseproductdata( root_r );
3016 inline Pathname staticGuessRoot(
const Pathname & root_r )
3018 if ( root_r.empty() )
3029 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
3031 std::ifstream idfile( file_r.c_str() );
3032 for( iostr::EachLine in( idfile ); in; in.next() )
3035 if ( ! line.empty() )
3038 return std::string();
3049 if ( p->isTargetDistribution() )
3057 const Pathname needroot( staticGuessRoot(root_r) );
3060 return target->requestedLocales();
3066 MIL <<
"updateAutoInstalled if changed..." << endl;
3074 {
return baseproductdata(
_root ).registerTarget(); }
3077 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3080 {
return baseproductdata(
_root ).registerRelease(); }
3083 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3086 {
return baseproductdata(
_root ).registerFlavor(); }
3089 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3121 const Pathname & needroot = staticGuessRoot(root_r);
3139 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3144 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3150 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3153 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3154 if ( ret.
empty() && root_r !=
"/" )
3157 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3165 return guessAnonymousUniqueId(
root() );
3170 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3177 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.
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)
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)