28#include <zypp-core/base/UserRequestException>
62#include <zypp-core/zyppng/base/EventLoop>
63#include <zypp-core/zyppng/base/UnixSignalSource>
64#include <zypp-core/zyppng/io/AsyncDataSource>
65#include <zypp-core/zyppng/io/Process>
69#include <zypp-core/zyppng/base/EventDispatcher>
71#include <shared/commit/CommitMessages.h>
78#include "tools/zypp-rpm/errorcodes.h"
79#include <rpm/rpmlog.h>
86 static bool val = [](){
87 const char *
env = getenv(
"TRANSACTIONAL_UPDATE");
99#include <solv/repo_rpmdb.h>
100#include <solv/chksum.h>
110 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
111 ::solv_chksum_free( chk,
nullptr );
113 if ( ::rpm_hash_database_state( state, chk ) == 0 )
116 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
120 WAR <<
"rpm_hash_database_state failed" << endl;
140 inline void sigMultiversionSpecChanged()
158 for (
const Transaction::Step & step : steps_r )
160 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
170 static const std::string strType(
"type" );
171 static const std::string strStage(
"stage" );
172 static const std::string strSolvable(
"solvable" );
174 static const std::string strTypeDel(
"-" );
175 static const std::string strTypeIns(
"+" );
176 static const std::string strTypeMul(
"M" );
178 static const std::string strStageDone(
"ok" );
179 static const std::string strStageFailed(
"err" );
181 static const std::string strSolvableN(
"n" );
182 static const std::string strSolvableE(
"e" );
183 static const std::string strSolvableV(
"v" );
184 static const std::string strSolvableR(
"r" );
185 static const std::string strSolvableA(
"a" );
192 case Transaction::TRANSACTION_IGNORE:
break;
193 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
194 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
195 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
200 case Transaction::STEP_TODO:
break;
201 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
202 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
211 ident = solv.ident();
218 ident = step_r.
ident();
220 arch = step_r.
arch();
225 { strSolvableV, ed.
version() },
226 { strSolvableR, ed.
release() },
230 s.
add( strSolvableE, epoch );
232 ret.
add( strSolvable, s );
246 class AssertMountedBase
258 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
259 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
267 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
279 class AssertProcMounted :
private AssertMountedBase
282 AssertProcMounted( Pathname root_r )
285 if ( ! PathInfo(root_r/
"self").isDir() ) {
286 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
288 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
292 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
300 class AssertDevMounted :
private AssertMountedBase
303 AssertDevMounted( Pathname root_r )
306 if ( ! PathInfo(root_r/
"null").isChr() ) {
307 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
312 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
316 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
333 std::ifstream infile( historyFile_r.c_str() );
334 for( iostr::EachLine in( infile ); in; in.next() )
336 const char * ch( (*in).c_str() );
338 if ( *ch <
'1' ||
'9' < *ch )
340 const char * sep1 = ::strchr( ch,
'|' );
345 bool installs =
true;
346 if ( ::strncmp( sep1,
"install|", 8 ) )
348 if ( ::strncmp( sep1,
"remove |", 8 ) )
355 const char * sep2 = ::strchr( sep1,
'|' );
356 if ( !sep2 || sep1 == sep2 )
358 (*in)[sep2-ch] =
'\0';
363 onSystemByUserList.erase( pkg );
367 if ( (sep1 = ::strchr( sep2+1,
'|' ))
368 && (sep1 = ::strchr( sep1+1,
'|' ))
369 && (sep2 = ::strchr( sep1+1,
'|' )) )
371 (*in)[sep2-ch] =
'\0';
372 if ( ::strchr( sep1+1,
'@' ) )
375 onSystemByUserList.insert( pkg );
380 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
381 return onSystemByUserList;
391 return PluginFrame( command_r, json::Object {
392 {
"TransactionStepList", steps_r }
402 MIL <<
"Testcases to keep: " << toKeep << endl;
408 WAR <<
"No Target no Testcase!" << endl;
412 std::string stem(
"updateTestcase" );
413 Pathname dir( target->assertRootPrefix(
"/var/log/") );
417 std::list<std::string> content;
419 std::set<std::string> cases;
420 for_( c, content.begin(), content.end() )
425 if ( cases.size() >= toKeep )
427 unsigned toDel = cases.size() - toKeep + 1;
428 for_( c, cases.begin(), cases.end() )
437 MIL <<
"Write new testcase " << next << endl;
455 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
465 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
470 WAR <<
"User request to abort script " << script_r << endl;
479 if ( prog.close() != 0 )
481 ret.second = report_r->problem( prog.execError() );
482 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
483 std::ostringstream sstr;
484 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
485 historylog.
comment(sstr.str(),
true);
497 bool executeScript(
const Pathname & root_r,
498 const Pathname & script_r,
499 callback::SendReport<PatchScriptReport> & report_r )
504 action = doExecuteScript( root_r, script_r, report_r );
508 switch ( action.second )
511 WAR <<
"User request to abort at script " << script_r << endl;
516 WAR <<
"User request to skip script " << script_r << endl;
526 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
535 bool RunUpdateScripts(
const Pathname & root_r,
536 const Pathname & scriptsPath_r,
537 const std::vector<sat::Solvable> & checkPackages_r,
540 if ( checkPackages_r.empty() )
543 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
545 if ( ! PathInfo( scriptsDir ).isDir() )
548 std::list<std::string> scripts;
550 if ( scripts.empty() )
558 std::map<std::string, Pathname> unify;
559 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
561 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
562 for_( sit, scripts.begin(), scripts.end() )
567 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
570 PathInfo script( scriptsDir / *sit );
571 Pathname localPath( scriptsPath_r/(*sit) );
572 std::string unifytag;
574 if ( script.isFile() )
580 else if ( ! script.isExist() )
588 if ( unifytag.empty() )
592 if ( unify[unifytag].
empty() )
594 unify[unifytag] = localPath;
601 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
602 MIL <<
"Skip update script: " << msg << endl;
603 HistoryLog().comment( msg,
true );
607 if ( abort || aborting_r )
609 WAR <<
"Aborting: Skip update script " << *sit << endl;
610 HistoryLog().comment(
611 localPath.asString() +
_(
" execution skipped while aborting"),
616 MIL <<
"Found update script " << *sit << endl;
617 callback::SendReport<PatchScriptReport> report;
620 if ( ! executeScript( root_r, localPath, report ) )
632 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
634 std::ifstream infile( file_r.c_str() );
635 for( iostr::EachLine in( infile ); in; in.next() )
637 out_r << *in << endl;
641 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
643 std::string ret( cmd_r );
644#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
645 SUBST_IF(
"%p", notification_r.solvable().asString() );
646 SUBST_IF(
"%P", notification_r.file().asString() );
651 void sendNotification(
const Pathname & root_r,
654 if ( notifications_r.empty() )
658 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
659 if ( cmdspec.empty() )
662 std::string::size_type pos( cmdspec.find(
'|' ) );
663 if ( pos == std::string::npos )
665 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
666 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
671 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
673 enum Format {
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
675 if ( formatStr ==
"none" )
677 else if ( formatStr ==
"single" )
679 else if ( formatStr ==
"digest" )
681 else if ( formatStr ==
"bulk" )
685 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
686 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
694 if ( format == NONE || format == SINGLE )
696 for_( it, notifications_r.begin(), notifications_r.end() )
698 std::vector<std::string> command;
699 if ( format == SINGLE )
701 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
706 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
710 int ret = prog.close();
713 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
714 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
720 else if ( format == DIGEST || format == BULK )
722 filesystem::TmpFile tmpfile;
723 std::ofstream out( tmpfile.path().c_str() );
724 for_( it, notifications_r.begin(), notifications_r.end() )
726 if ( format == DIGEST )
728 out << it->file() << endl;
730 else if ( format == BULK )
736 std::vector<std::string> command;
737 command.push_back(
"<"+tmpfile.path().asString() );
738 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
743 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
747 int ret = prog.close();
750 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
751 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
758 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
759 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
770 void RunUpdateMessages(
const Pathname & root_r,
771 const Pathname & messagesPath_r,
772 const std::vector<sat::Solvable> & checkPackages_r,
773 ZYppCommitResult & result_r )
775 if ( checkPackages_r.empty() )
778 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
780 if ( ! PathInfo( messagesDir ).isDir() )
783 std::list<std::string> messages;
785 if ( messages.empty() )
791 HistoryLog historylog;
792 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
794 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
795 for_( sit, messages.begin(), messages.end() )
800 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
803 PathInfo message( messagesDir / *sit );
804 if ( ! message.isFile() || message.size() == 0 )
807 MIL <<
"Found update message " << *sit << endl;
808 Pathname localPath( messagesPath_r/(*sit) );
809 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
810 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
813 sendNotification( root_r, result_r.updateMessages() );
819 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
822 if ( changedPseudoInstalled.empty() )
830 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
833 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
836 HistoryLog historylog;
837 for (
const auto & el : changedPseudoInstalled )
838 historylog.patchStateChange( el.first, el.second );
847 const std::vector<sat::Solvable> & checkPackages_r,
849 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
862 , _requestedLocalesFile( home() /
"RequestedLocales" )
863 , _autoInstalledFile( home() /
"AutoInstalled" )
864 , _hardLocksFile(
Pathname::assertprefix( _root,
ZConfig::instance().locksFile() ) )
865 , _vendorAttr(
Pathname::assertprefix( _root,
ZConfig::instance().vendorPath() ) )
872 sigMultiversionSpecChanged();
873 MIL <<
"Initialized target on " <<
_root << endl;
881 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
891 boost::function<
bool ()> condition,
892 boost::function<std::string ()> value )
894 std::string val = value();
902 MIL <<
"updating '" << filename <<
"' content." << endl;
906 std::ofstream filestr;
909 filestr.open( filename.
c_str() );
911 if ( filestr.good() )
947 WAR <<
"Can't create anonymous id file" << endl;
956 Pathname flavorpath(
home() /
"LastDistributionFlavor");
962 WAR <<
"No base product, I won't create flavor cache" << endl;
966 std::string flavor = p->flavor();
978 WAR <<
"Can't create flavor cache" << endl;
991 sigMultiversionSpecChanged();
992 MIL <<
"Closed target on " <<
_root << endl;
1016 Pathname rpmsolvcookie = base/
"cookie";
1018 bool build_rpm_solv =
true;
1028 MIL <<
"Read cookie: " << cookie << endl;
1033 if ( status == rpmstatus )
1034 build_rpm_solv =
false;
1035 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1036 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1040 if ( build_rpm_solv )
1054 bool switchingToTmpSolvfile =
false;
1055 Exception ex(
"Failed to cache rpm database.");
1061 rpmsolv = base/
"solv";
1062 rpmsolvcookie = base/
"cookie";
1069 WAR <<
"Using a temporary solv file at " << base << endl;
1070 switchingToTmpSolvfile =
true;
1079 if ( ! switchingToTmpSolvfile )
1089#ifdef ZYPP_RPMDB2SOLV_PATH
1090 cmd.push_back( ZYPP_RPMDB2SOLV_PATH );
1092 cmd.push_back(
"rpmdb2solv" );
1095 cmd.push_back(
"-r" );
1098 cmd.push_back(
"-D" );
1100 cmd.push_back(
"-X" );
1102 cmd.push_back(
"-p" );
1105 if ( ! oldSolvFile.
empty() )
1106 cmd.push_back( oldSolvFile.
asString() );
1108 cmd.push_back(
"-o" );
1112 std::string errdetail;
1115 WAR <<
" " << output;
1116 if ( errdetail.empty() ) {
1120 errdetail += output;
1123 int ret = prog.
close();
1144 if (
root() ==
"/" )
1155 if ( !
PathInfo(base/
"solv.idx").isExist() )
1158 return build_rpm_solv;
1176 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1177 ", force loading: " << (force?
"true":
"false") << endl;
1182 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1189 if ( newCache || force )
1206 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1212 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1237 if (
PathInfo( historyFile ).isExist() )
1244 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1245 onSystemByAuto.insert( ident );
1261 sat::SolvableSpec needrebootSpec;
1262 needrebootSpec.addProvides(
Capability(
"installhint(reboot-needed)") );
1263 needrebootSpec.addProvides(
Capability(
"kernel") );
1266 if (
PathInfo( needrebootFile ).isFile() )
1267 needrebootSpec.parseFrom( needrebootFile );
1270 if (
PathInfo( needrebootDir ).isDir() )
1275 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1277 if ( ! isRpmConfigBackup( str_r ) )
1279 Pathname needrebootFile { needrebootDir / str_r };
1280 if (
PathInfo( needrebootFile ).isFile() )
1281 needrebootSpec.parseFrom( needrebootFile );
1292 if ( ! hardLocks.empty() )
1301 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1315 bool explicitDryRun = policy_r.
dryRun();
1325 if (
root() ==
"/" )
1339 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1358 steps.push_back( *it );
1365 MIL <<
"Todo: " << result << endl;
1376 if ( commitPlugins )
1377 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1384 if ( ! policy_r.
dryRun() )
1390 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1397 if ( ! policy_r.
dryRun() )
1419 DBG <<
"dryRun: Not storing non-package data." << endl;
1426 if ( ! policy_r.
dryRun() )
1428 for_( it, steps.begin(), steps.end() )
1430 if ( ! it->satSolvable().isKind<
Patch>() )
1438 if ( ! patch ||patch->message().empty() )
1441 MIL <<
"Show message for " << patch << endl;
1443 if ( ! report->show( patch ) )
1445 WAR <<
"commit aborted by the user" << endl;
1452 DBG <<
"dryRun: Not checking patch messages." << endl;
1475 for_( it, steps.begin(), steps.end() )
1477 switch ( it->stepType() )
1496 localfile = packageCache.
get( pi );
1499 catch (
const AbortRequestException & exp )
1503 WAR <<
"commit cache preload aborted by the user" << endl;
1507 catch (
const SkipRequestException & exp )
1512 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1522 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1532 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1536 if ( ! policy_r.
dryRun() )
1543 commit( policy_r, packageCache, result );
1548 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1549 if ( explicitDryRun ) {
1563 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1564 if ( explicitDryRun ) {
1576 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1585 if ( commitPlugins )
1586 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1591 if ( ! policy_r.
dryRun() )
1596 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1607 struct NotifyAttemptToModify
1612 {
if ( _guard ) {
_result.attemptToModify(
true );
_guard =
false; } }
1625 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1630 NotifyAttemptToModify attemptToModify( result_r );
1635 AssertProcMounted assertProcMounted(
_root );
1636 AssertDevMounted assertDevMounted(
_root );
1639 std::vector<sat::Solvable> successfullyInstalledPackages;
1642 for_( step, steps.begin(), steps.end() )
1647 if ( citem->isKind<
Package>() )
1656 if ( citem->isKind<
Package>() )
1664 localfile = packageCache_r.
get( citem );
1666 catch (
const AbortRequestException &e )
1668 WAR <<
"commit aborted by the user" << endl;
1673 catch (
const SkipRequestException &e )
1676 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1685 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1694 bool success =
false;
1720 WAR <<
"commit aborted by the user" << endl;
1729 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1745 WAR <<
"dry run failed" << endl;
1752 WAR <<
"commit aborted by the user" << endl;
1757 WAR <<
"Install failed" << endl;
1763 if ( success && !policy_r.
dryRun() )
1766 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1775 bool success =
false;
1788 WAR <<
"commit aborted by the user" << endl;
1804 WAR <<
"commit aborted by the user" << endl;
1810 WAR <<
"removal of " << p <<
" failed";
1813 if ( success && !policy_r.
dryRun() )
1820 else if ( ! policy_r.
dryRun() )
1824 if ( ! citem.
buddy() )
1826 if ( citem->isKind<
Product>() )
1831 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1837 std::string referenceFilename( p->referenceFilename() );
1838 if ( referenceFilename.empty() )
1840 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1844 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1845 if ( !
rpm().hasFile( referencePath.asString() ) )
1850 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1854 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1883 if ( ! successfullyInstalledPackages.empty() )
1886 successfullyInstalledPackages, abort ) )
1888 WAR <<
"Commit aborted by the user" << endl;
1894 successfullyInstalledPackages,
1901 logPatchStatusChanges( result_r.
transaction(), *
this );
1920 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
1923 data.
set(
"line", std::cref(line_r) );
1924 data.set(
"level", level_r );
1930 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
1931 switch ( rpmlevel_r ) {
1932 case RPMLOG_EMERG: [[fallthrough]];
1933 case RPMLOG_ALERT: [[fallthrough]];
1935 return ReportType::loglevel::crt;
1937 return ReportType::loglevel::err;
1938 case RPMLOG_WARNING:
1939 return ReportType::loglevel::war;
1940 default: [[fallthrough]];
1941 case RPMLOG_NOTICE: [[fallthrough]];
1943 return ReportType::loglevel::msg;
1945 return ReportType::loglevel::dbg;
1953 { (*this)->report( userData_r ); }
1970 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1975 NotifyAttemptToModify attemptToModify( result_r );
1981 AssertProcMounted assertProcMounted(
_root );
1982 AssertDevMounted assertDevMounted(
_root );
1996 proto::target::Commit
commit;
2006 for (
auto &[
_, value] : data ) {
2008 value.resetDispose();
2014 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2015 auto &step = steps[stepId];
2018 if ( citem->isKind<
Package>() )
2027 if ( citem->isKind<
Package>() ) {
2032 locCache.value()[stepId] = packageCache_r.
get( citem );
2034 proto::target::InstallStep tStep;
2035 tStep.stepId = stepId;
2036 tStep.pathname = locCache.
value()[stepId]->asString();
2037 tStep.multiversion = p->multiversionInstall() ;
2039 commit.transactionSteps.push_back( std::move(tStep) );
2041 catch (
const AbortRequestException &e )
2043 WAR <<
"commit aborted by the user" << endl;
2048 catch (
const SkipRequestException &e )
2051 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2060 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2066 proto::target::RemoveStep tStep;
2067 tStep.stepId = stepId;
2068 tStep.name = p->name();
2069 tStep.version = p->edition().version();
2070 tStep.release = p->edition().release();
2071 tStep.arch = p->arch().asString();
2072 commit.transactionSteps.push_back(std::move(tStep));
2083 proto::target::InstallStep tStep;
2084 tStep.stepId = stepId;
2085 tStep.pathname = locCache.value()[stepId]->asString();
2086 tStep.multiversion =
false;
2087 commit.transactionSteps.push_back(std::move(tStep));
2091 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2098 std::vector<sat::Solvable> successfullyInstalledPackages;
2100 if (
commit.transactionSteps.size() ) {
2107 const std::vector<int> interceptedSignals {
2114 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2115 unixSignals->sigReceived ().connect ([](
int signum ){
2117 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 );
2119 for(
const auto &sig : interceptedSignals )
2120 unixSignals->addSignal ( sig );
2123 for(
const auto &sig : interceptedSignals )
2124 unixSignals->removeSignal ( sig );
2131 int currentStepId = -1;
2137 bool gotEndOfScript =
false;
2140 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2141 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2142 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2143 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2144 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2147 std::optional<proto::target::TransactionError> transactionError;
2150 std::string currentScriptType;
2151 std::string currentScriptPackage;
2161 unsigned lineno = 0;
2169 zyppng::StompFrameStreamRef msgStream;
2174 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2176 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2178 if ( currentStepId >= 0 )
2179 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2180 cmdout.
set(
"line", line );
2184 if ( installreport ) {
2185 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2186 }
else if ( uninstallreport ) {
2187 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2188 }
else if ( scriptreport ) {
2189 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2190 }
else if ( transactionreport ) {
2191 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2192 }
else if ( cleanupreport ) {
2193 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2195 WAR <<
"Got rpm output without active report " << line;
2200 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2204 if ( line.back() !=
'\n' )
2210 const auto &processDataFromScriptFd = [&](){
2212 while ( scriptSource->canReadLine() ) {
2214 if ( gotEndOfScript )
2217 std::string l = scriptSource->readLine().asString();
2219 gotEndOfScript =
true;
2220 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2223 l = l.substr( 0, rawsize );
2225 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2226 sendRpmLineToReport( l );
2229 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2232 const auto &waitForScriptEnd = [&]() {
2235 if ( gotEndOfScript )
2239 processDataFromScriptFd();
2242 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2245 scriptSource->waitForReadyRead( 100 );
2249 const auto &aboutToStartNewReport = [&](){
2251 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2252 ERR <<
"There is still a running report, this is a bug" << std::endl;
2256 gotEndOfScript =
false;
2259 const auto &writeRpmMsgToHistory = [&](){
2260 if ( rpmmsg.size() == 0 )
2264 rpmmsg +=
"[truncated]\n";
2266 std::ostringstream sstr;
2267 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2272 const auto &finalizeCurrentReport = [&]() {
2275 if ( currentStepId >= 0 ) {
2276 step = &steps.at(currentStepId);
2280 if ( installreport ) {
2288 writeRpmMsgToHistory();
2292 ( *installreport)->progress( 100, resObj );
2295 if ( currentStepId >= 0 )
2296 locCache.value().erase( currentStepId );
2297 successfullyInstalledPackages.push_back( step->
satSolvable() );
2303 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2315 writeRpmMsgToHistory();
2318 if ( uninstallreport ) {
2326 writeRpmMsgToHistory();
2330 ( *uninstallreport)->progress( 100, resObj );
2340 writeRpmMsgToHistory();
2343 if ( scriptreport ) {
2345 ( *scriptreport)->progress( 100, resObj );
2348 if ( transactionreport ) {
2350 ( *transactionreport)->progress( 100 );
2353 if ( cleanupreport ) {
2355 ( *cleanupreport)->progress( 100 );
2361 currentScriptType.clear();
2362 currentScriptPackage.clear();
2363 installreport.reset();
2364 uninstallreport.reset();
2365 scriptreport.reset();
2366 transactionreport.reset();
2367 cleanupreport.reset();
2377 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2379 const char *argv[] = {
2382 zyppRpmBinary.data(),
2399 prog->addFd( messagePipe->writeFd );
2400 prog->addFd( scriptPipe->writeFd );
2403 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2406 const auto &processMessages = [&] ( ) {
2410 const auto &checkMsgWithStepId = [&steps](
auto &p ){
2412 ERR <<
"Failed to parse message from zypp-rpm." << std::endl;
2416 auto id = p->stepId;
2417 if ( id < 0 || id >= steps.size() ) {
2418 ERR <<
"Received invalid stepId: " <<
id <<
" in " << p->typeName <<
" message from zypp-rpm, ignoring." << std::endl;
2424 while (
const auto &m = msgStream->nextMessage() ) {
2430 const auto &mName = m->command();
2431 if ( mName == proto::target::RpmLog::typeName ) {
2433 const auto &p = proto::target::RpmLog::fromStompMessage (*m);
2435 ERR <<
"Failed to parse " << proto::target::RpmLog::typeName <<
" message from zypp-rpm." << std::endl;
2438 ( p->level >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2439 : p->level >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2440 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p->level <<
"> " << p->line;
2443 }
else if ( mName == proto::target::PackageBegin::typeName ) {
2444 finalizeCurrentReport();
2446 const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
2447 if ( !checkMsgWithStepId( p ) )
2450 aboutToStartNewReport();
2452 auto & step = steps.at( p->stepId );
2453 currentStepId = p->stepId;
2455 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2456 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2458 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2459 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2462 }
else if ( mName == proto::target::PackageFinished::typeName ) {
2463 const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
2464 if ( !checkMsgWithStepId( p ) )
2471 }
else if ( mName == proto::target::PackageProgress::typeName ) {
2472 const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
2473 if ( !checkMsgWithStepId( p ) )
2476 if ( uninstallreport )
2477 (*uninstallreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2478 else if ( installreport )
2479 (*installreport)->progress( p->amount,
makeResObject( steps.at( p->stepId ) ));
2481 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2483 }
else if ( mName == proto::target::PackageError::typeName ) {
2484 const auto &p = proto::target::PackageError::fromStompMessage(*m);
2485 if ( !checkMsgWithStepId( p ) )
2488 if ( p->stepId >= 0 && p->stepId < steps.size() )
2491 finalizeCurrentReport();
2493 }
else if ( mName == proto::target::ScriptBegin::typeName ) {
2494 finalizeCurrentReport();
2496 const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
2498 ERR <<
"Failed to parse " << proto::target::ScriptBegin::typeName <<
" message from zypp-rpm." << std::endl;
2502 aboutToStartNewReport();
2505 const auto stepId = p->stepId;
2506 if ( stepId >= 0 && stepId < steps.size() ) {
2510 currentStepId = p->stepId;
2511 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2512 currentScriptType = p->scriptType;
2513 currentScriptPackage = p->scriptPackage;
2514 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2516 }
else if ( mName == proto::target::ScriptFinished::typeName ) {
2520 }
else if ( mName == proto::target::ScriptError::typeName ) {
2522 const auto &p = proto::target::ScriptError::fromStompMessage(*m);
2524 ERR <<
"Failed to parse " << proto::target::ScriptError::typeName <<
" message from zypp-rpm." << std::endl;
2529 const auto stepId = p->stepId;
2530 if ( stepId >= 0 && stepId < steps.size() ) {
2540 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2543 writeRpmMsgToHistory();
2545 if ( !scriptreport ) {
2546 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2555 scriptreport.reset();
2558 }
else if ( mName == proto::target::CleanupBegin::typeName ) {
2559 finalizeCurrentReport();
2561 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2563 ERR <<
"Failed to parse " << proto::target::CleanupBegin::typeName <<
" message from zypp-rpm." << std::endl;
2567 aboutToStartNewReport();
2568 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2569 (*cleanupreport)->start( beg->nvra );
2570 }
else if ( mName == proto::target::CleanupFinished::typeName ) {
2572 finalizeCurrentReport();
2574 }
else if ( mName == proto::target::CleanupProgress::typeName ) {
2575 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2577 ERR <<
"Failed to parse " << proto::target::CleanupProgress::typeName <<
" message from zypp-rpm." << std::endl;
2581 if ( !cleanupreport ) {
2582 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2586 (*cleanupreport)->progress( prog->amount );
2588 }
else if ( mName == proto::target::TransBegin::typeName ) {
2589 finalizeCurrentReport();
2591 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2593 ERR <<
"Failed to parse " << proto::target::TransBegin::typeName <<
" message from zypp-rpm." << std::endl;
2597 aboutToStartNewReport();
2598 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2599 (*transactionreport)->start( beg->name );
2600 }
else if ( mName == proto::target::TransFinished::typeName ) {
2602 finalizeCurrentReport();
2604 }
else if ( mName == proto::target::TransProgress::typeName ) {
2605 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2607 ERR <<
"Failed to parse " << proto::target::TransProgress::typeName <<
" message from zypp-rpm." << std::endl;
2611 if ( !transactionreport ) {
2612 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2616 (*transactionreport)->progress( prog->amount );
2617 }
else if ( mName == proto::target::TransactionError::typeName ) {
2619 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2621 ERR <<
"Failed to parse " << proto::target::TransactionError::typeName <<
" message from zypp-rpm." << std::endl;
2626 transactionError = std::move(*error);
2629 ERR <<
"Received unexpected message from zypp-rpm: "<< m->command() <<
", ignoring" << std::endl;
2637 prog->sigStarted().connect( [&](){
2640 messagePipe->unrefWrite();
2641 scriptPipe->unrefWrite();
2645 while( prog->canReadLine( channel ) ) {
2646 L_ERR(
"zypp-rpm") << ( channel ==
zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2652 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2658 const auto &msg =
commit.toStompMessage();
2660 std::rethrow_exception ( msg.error() );
2662 if ( !msgStream->sendMessage( *msg ) ) {
2663 prog->stop( SIGKILL );
2669 int zyppRpmExitCode = -1;
2671 zyppRpmExitCode = code;
2675 if ( !prog->start( argv ) ) {
2684 msgStream->readAllMessages();
2691 finalizeCurrentReport();
2694 bool readMsgs =
false;
2704 while ( scriptSource->canReadLine() ) {
2706 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2708 if ( scriptSource->bytesAvailable() > 0 ) {
2710 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2715 switch ( zyppRpmExitCode ) {
2717 case zypprpm::NoError:
2718 case zypprpm::RpmFinishedWithError:
2720 case zypprpm::RpmFinishedWithTransactionError: {
2722 if ( transactionError ) {
2724 std::ostringstream sstr;
2725 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2726 for (
const auto & err : transactionError->problems ) {
2727 sstr <<
" " << err <<
"\n";
2737 case zypprpm::FailedToOpenDb:
2740 case zypprpm::WrongHeaderSize:
2741 case zypprpm::WrongMessageFormat:
2744 case zypprpm::RpmInitFailed:
2747 case zypprpm::FailedToReadPackage:
2750 case zypprpm::FailedToAddStepToTransaction:
2753 case zypprpm::RpmOrderFailed:
2756 case zypprpm::FailedToCreateLock:
2761 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2762 auto &step = steps[stepId];
2774 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2778 std::string referenceFilename( p->referenceFilename() );
2780 if ( referenceFilename.empty() ) {
2781 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2783 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2785 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2789 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2791 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2805 if ( ! successfullyInstalledPackages.empty() )
2808 successfullyInstalledPackages, abort ) )
2810 WAR <<
"Commit aborted by the user" << endl;
2816 successfullyInstalledPackages,
2823 logPatchStatusChanges( result_r.
transaction(), *
this );
2851 if ( baseproduct.isFile() )
2864 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2869 inline Pathname staticGuessRoot(
const Pathname & root_r )
2871 if ( root_r.empty() )
2876 return Pathname(
"/");
2882 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2884 std::ifstream idfile( file_r.c_str() );
2885 for( iostr::EachLine in( idfile ); in; in.next() )
2888 if ( ! line.empty() )
2891 return std::string();
2902 if ( p->isTargetDistribution() )
2910 const Pathname needroot( staticGuessRoot(root_r) );
2911 const Target_constPtr target(
getZYpp()->getTarget() );
2912 if ( target && target->root() == needroot )
2913 return target->requestedLocales();
2919 MIL <<
"updateAutoInstalled if changed..." << endl;
2927 {
return baseproductdata(
_root ).registerTarget(); }
2930 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2933 {
return baseproductdata(
_root ).registerRelease(); }
2936 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2939 {
return baseproductdata(
_root ).registerFlavor(); }
2942 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2975 const Pathname & needroot = staticGuessRoot(root_r);
2993 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
2998 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3004 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3007 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3008 if ( ret.
empty() && root_r !=
"/" )
3011 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3019 return guessAnonymousUniqueId(
root() );
3024 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3031 MIL <<
"New VendorAttr: " << vendorAttr_r << endl;
3062 MIL <<
"TargetImpl::predownloadPluginsHook() start" << endl;
3066 for_( it, steps.begin(), steps.end() )
3068 switch ( it->stepType() )
3086 if (!localfile->
empty())
3089 stepsNotCached.push_back(*it);
3093 using namespace std;
3094 if (stepsNotCached.empty()) {
3102 if ( plugins.
empty() ) {
3108 map<string, Url> repoUrls;
3109 map<string, list<pair<int, string> > > repoFiles;
3110 for_(it, stepsNotCached.begin(), stepsNotCached.end()) {
3113 string alias = repo.
alias();
3120 string loc = p->location().filename().asString();
3125 if (loc[0] ==
'.' && loc[1] ==
'/')
3126 loc = loc.substr(2);
3128 int sz = p->location().downloadSize();
3129 repoUrls[alias] = url;
3130 repoFiles[alias].push_back(make_pair(sz, loc));
3136 for_(it, repoUrls.begin(), repoUrls.end()) {
3137 message = it->first + string(
" ") + it->second.asString();
3138 list<pair<int, string> >& files = repoFiles[it->first];
3143 for_(i, files.rbegin(), files.rend()) {
3144 message +=
" " + i->second;
3149 if ( plugins.
empty() ) {
3165 if (pr.second < 1) {
3166 JobReport::warning(
"Predownload plugin have failed to report progress, continue without plugin" );
3172 if (pr.first < pr.second)
3182 if (!lastError.empty()) {
3184 }
else if (allgood) {
3188 MIL <<
"TargetImpl::predownloadPluginsHook() end" << endl;
#define MAXRPMMESSAGELINES
#define SUBST_IF(PAT, VAL)
ZYppCommitResult & _result
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
bool operator()(const zypp::Arch &lhs, const zypp::Arch &rhs) const
Default order for std::container based Arch::compare.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
reference value() const
Reference to the Tp object.
void resetDispose()
Set no dispose function.
Mime type like 'type/subtype' classification of content.
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
Parallel execution of stateful PluginScripts.
PluginScript first()
First plugin.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
bool empty() const
Whether no plugins are waiting.
Command frame for communication with PluginScript.
Interface to plugin scripts using a Stomp inspired communication protocol.
PluginFrame receive() const
Receive a PluginFrame.
void send(const PluginFrame &frame_r) const
Send a PluginFrame.
std::pair< int, int > Progress
const std::string & lastExecError() const
Remembers a scripts execError string after close until next open.
Progress progress() const
Send PLUGIN_PROGRESS frame and return /ref PluginScript::Progress.
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
Url url() const
Pars pro toto: The first repository url.
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.
std::string alias() const
Short unique string to identify a repo.
size_type solvablesSize() const
Number of solvables in Repository.
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
RepoInfo info() const
Return any associated RepoInfo.
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.
byKind_iterator byKindEnd(const ResKind &kind_r) const
EstablishedStates establishedStates() const
Factory for EstablishedStates.
byKind_iterator byKindBegin(const ResKind &kind_r) const
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
bool isToBeInstalled() const
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
TraitsType::constPtrType constPtr
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
Attempts to create a lock to prevent the system from going into hibernate/shutdown.
TraitsType::constPtrType constPtr
String matching (STRING|SUBSTRING|GLOB|REGEX).
bool isValid() const
Verifies the Url.
Definition of vendor equivalence.
Interim helper class to collect global options and settings.
Arch systemArchitecture() const
The system architecture zypp uses.
Pathname repoCachePath() const
Path where the caches are kept (/var/cache/zypp)
static ZConfig & instance()
Singleton ctor.
std::string distroverpkg() const
Package telling the "product version" on systems not using /etc/product.d/baseproduct.
Options and policies for ZYpp::commit.
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
bool singleTransModeEnabled() const
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.
const Pathname & root() const
Remembered root directory of the target.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
void setSingleTransactionMode(bool yesno_r)
std::vector< sat::Transaction::Step > TransactionStepList
const sat::Transaction & transaction() const
The full transaction list.
sat::Transaction & rTransaction()
Manipulate transaction.
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
static zypp::Pathname lockfileDir()
Typesafe passing of user data via callbacks.
zypp::ContentType ContentType
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.
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
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.
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.
Libsolv Id queue wrapper.
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.
ManagedFile get_from_cache(const PoolItem &citem_r)
void setData(const Data &data_r)
Store new Data.
const Data & data() const
Return the data.
pool::PoolTraits::HardLockQueries Data
Save and restore locale set from file.
const LocaleSet & locales() const
Return the loacale set.
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)
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
Pathname _tmpSolvfilesPath
std::string _distributionVersion
Cache distributionVersion.
rpm::RpmDb _rpm
RPM database.
~TargetImpl() override
Dtor.
rpm::RpmDb & rpm()
The RPM database.
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
std::string distributionVersion() const
This is version attribute of the installed base product.
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
SolvIdentFile _autoInstalledFile
user/auto installed database
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
bool providesFile(const std::string &path_str, const std::string &name_str) const
If the package is installed and provides the file Needed to evaluate split provides during Resolver::...
HardLocksFile _hardLocksFile
Hard-Locks database.
Pathname root() const
The root set for this target.
void load(bool force=true)
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
void commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
Commit ordered changes (internal helper)
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
VendorAttr _vendorAttr
vendor equivalence settings.
Pathname home() const
The directory to store things.
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Pathname defaultSolvfilesPath() const
The systems default solv file location.
std::string anonymousUniqueId() const
anonymous unique id
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
bool solvfilesPathIsTemp() const
Whether we're using a temp.
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Interface to the rpm program.
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
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.
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.
bool empty() const
Whether neither idents nor provides are set.
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
void predownloadPluginsHook(CommitPackageCache &packageCache, const ZYppCommitResult::TransactionStepList &steps)
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet
std::list< UpdateNotificationFile > UpdateNotifications
ResTraits< TRes >::PtrType make(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::string asString(const Patch::Category &obj)
ResTraits< TRes >::PtrType asKind(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
@ DownloadInHeaps
Similar to DownloadInAdvance, but try to split the transaction into heaps, where at the end of each h...
@ DownloadOnly
Just download all packages to the local cache.
@ DownloadAsNeeded
Alternating download and install.
@ DownloadInAdvance
First download all packages to the local cache.
@ DownloadDefault
libzypp will decide what to do.
static bool warning(const std::string &msg_r, const UserData &userData_r=UserData())
send warning text
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
static bool info(const std::string &msg_r, const UserData &userData_r=UserData())
send message text
std::string asJSON() const
JSON representation.
void add(const Value &val_r)
Push JSON Value to Array.
void add(const String &key_r, const Value &val_r)
Add key/value pair.
std::string asJSON() const
JSON representation.
Solvable satSolvable() const
Return the corresponding sat::Solvable.
bool isNeedreboot() const
static PoolImpl & myPool()
Convenience SendReport<rpm::SingleTransReport> wrapper.
void report(const callback::UserData &userData_r)
void sendLoglineRpm(const std::string &line_r, unsigned rpmlevel_r)
Convenience to send a contentLogline translating a rpm loglevel.
void sendLogline(const std::string &line_r, ReportType::loglevel level_r=ReportType::loglevel::msg)
Convenience to send a contentLogline.
@ RPM_NODEPS_FORCE
only this one used
static std::optional< Pipe > create(int flags=0)
#define NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define IMPL_PTR_TYPE(NAME)